Signed-off-by: Emmanuel Gil Peyrot <linkma...@linkmauve.fr> --- libweston/compositor.c | 5 +- libweston/gl-renderer.c | 135 ++++++++++++++++++++++++++++++++++++++++++------ libweston/gl-renderer.h | 6 +++ 3 files changed, 128 insertions(+), 18 deletions(-)
diff --git a/libweston/compositor.c b/libweston/compositor.c index 9343bdbf..723dec02 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -5187,10 +5187,13 @@ destroy_stereoscopy_description(struct wl_resource *resource) struct weston_surface *surface = wl_resource_get_user_data(resource); + bool was_stereo = surface->pending.buffer_viewport.buffer.stereoscopy_layout != + ZWP_STEREOSCOPY_V1_LAYOUT_NONE; + surface->stereoscopy_description_resource = NULL; surface->pending.buffer_viewport.buffer.stereoscopy_layout = ZWP_STEREOSCOPY_V1_LAYOUT_NONE; surface->pending.buffer_viewport.surface.default_side = ZWP_STEREOSCOPY_DESCRIPTION_V1_SIDE_DEFAULT; - surface->pending.buffer_viewport.changed = 1; + surface->pending.buffer_viewport.changed |= was_stereo; } static void diff --git a/libweston/gl-renderer.c b/libweston/gl-renderer.c index 244ce309..73b0d358 100644 --- a/libweston/gl-renderer.c +++ b/libweston/gl-renderer.c @@ -54,6 +54,7 @@ #include "vertex-clipping.h" #include "linux-dmabuf.h" #include "linux-dmabuf-unstable-v1-server-protocol.h" +#include "stereoscopy-unstable-v1-server-protocol.h" #include "shared/helpers.h" #include "shared/platform.h" @@ -771,7 +772,8 @@ triangle_fan_debug(struct weston_view *view, int first, int count) static void repaint_region(struct weston_view *ev, pixman_region32_t *region, - pixman_region32_t *surf_region) + pixman_region32_t *surf_region, + enum gl_renderer_stereoscopy_side side) { struct weston_compositor *ec = ev->surface->compositor; struct gl_renderer *gr = get_renderer(ec); @@ -792,6 +794,36 @@ repaint_region(struct weston_view *ev, pixman_region32_t *region, v = gr->vertices.data; vtxcnt = gr->vtxcnt.data; + assert(side == GL_RENDERER_SIDE_LEFT || side == GL_RENDERER_SIDE_RIGHT); + switch (ev->surface->buffer_viewport.buffer.stereoscopy_layout) { + case ZWP_STEREOSCOPY_V1_LAYOUT_NONE: + break; + case ZWP_STEREOSCOPY_V1_LAYOUT_FRAME_PACKING: + for (i = 0; i < nfans * 4; i++) { + if (side == GL_RENDERER_SIDE_RIGHT) + v[i * 4 + 3] += 25. / 24.; + } + break; + case ZWP_STEREOSCOPY_V1_LAYOUT_SIDE_BY_SIDE: + for (i = 0; i < nfans * 4; i++) { + v[i * 4 + 2] *= 0.5; + if (side == GL_RENDERER_SIDE_RIGHT) + v[i * 4 + 2] += 0.5; + } + break; + case ZWP_STEREOSCOPY_V1_LAYOUT_TOP_AND_BOTTOM: + for (i = 0; i < nfans * 4; i++) { + v[i * 4 + 3] *= 0.5; + if (side == GL_RENDERER_SIDE_RIGHT) + v[i * 4 + 3] += 0.5; + } + break; + default: + /* We currently only support side-by-side and + * top-and-bottom layouts for client buffers. */ + assert(0); + } + /* position: */ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]); glEnableVertexAttribArray(0); @@ -881,7 +913,8 @@ shader_uniforms(struct gl_shader *shader, static void draw_view(struct weston_view *ev, struct weston_output *output, - pixman_region32_t *damage) /* in global coordinates */ + pixman_region32_t *damage, /* in global coordinates */ + enum gl_renderer_stereoscopy_side side) { struct weston_compositor *ec = ev->surface->compositor; struct gl_renderer *gr = get_renderer(ec); @@ -920,11 +953,22 @@ draw_view(struct weston_view *ev, struct weston_output *output, shader_uniforms(gs->shader, ev, output); if (ev->transform.enabled || output->zoom.active || - output->current_scale != ev->surface->buffer_viewport.buffer.scale) + output->current_scale != ev->surface->buffer_viewport.buffer.scale || + (output->stereoscopy_layout != ZWP_STEREOSCOPY_V1_LAYOUT_NONE && + output->stereoscopy_layout != ZWP_STEREOSCOPY_V1_LAYOUT_FRAME_PACKING) || + ev->surface->buffer_viewport.buffer.stereoscopy_layout != ZWP_STEREOSCOPY_V1_LAYOUT_NONE) filter = GL_LINEAR; else filter = GL_NEAREST; + if (output->stereoscopy_layout == ZWP_STEREOSCOPY_V1_LAYOUT_NONE && + side == GL_RENDERER_SIDE_DEFAULT) { + if (ev->surface->buffer_viewport.surface.default_side == ZWP_STEREOSCOPY_DESCRIPTION_V1_SIDE_DEFAULT) + side = GL_RENDERER_SIDE_LEFT; + else + side = ev->surface->buffer_viewport.surface.default_side; + } + for (i = 0; i < gs->num_textures; i++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(gs->target, gs->textures[i]); @@ -966,13 +1010,13 @@ draw_view(struct weston_view *ev, struct weston_output *output, else glDisable(GL_BLEND); - repaint_region(ev, &repaint, &surface_opaque); + repaint_region(ev, &repaint, &surface_opaque, side); } if (pixman_region32_not_empty(&surface_blend)) { use_shader(gr, gs->shader); glEnable(GL_BLEND); - repaint_region(ev, &repaint, &surface_blend); + repaint_region(ev, &repaint, &surface_blend, side); } pixman_region32_fini(&surface_blend); @@ -983,14 +1027,15 @@ out: } static void -repaint_views(struct weston_output *output, pixman_region32_t *damage) +repaint_views(struct weston_output *output, pixman_region32_t *damage, + enum gl_renderer_stereoscopy_side side) { struct weston_compositor *compositor = output->compositor; struct weston_view *view; wl_list_for_each_reverse(view, &compositor->view_list, link) if (view->plane == &compositor->primary_plane) - draw_view(view, output, damage); + draw_view(view, output, damage, side); } static void @@ -1248,14 +1293,6 @@ gl_renderer_repaint_output(struct weston_output *output, if (use_output(output) < 0) return; - begin_render_sync = timeline_create_render_sync(gr); - - /* Calculate the viewport */ - glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width, - go->borders[GL_RENDERER_BORDER_BOTTOM].height, - output->current_mode->width, - output->current_mode->height); - /* Calculate the global GL matrix */ go->output_matrix = output->matrix; weston_matrix_translate(&go->output_matrix, @@ -1274,7 +1311,7 @@ gl_renderer_repaint_output(struct weston_output *output, pixman_region32_subtract(&undamaged, &output->region, output_damage); gr->fan_debug = 0; - repaint_views(output, &undamaged); + repaint_views(output, &undamaged, GL_RENDERER_SIDE_DEFAULT); gr->fan_debug = 1; pixman_region32_fini(&undamaged); } @@ -1288,7 +1325,71 @@ gl_renderer_repaint_output(struct weston_output *output, pixman_region32_union(&total_damage, &buffer_damage, output_damage); border_damage |= go->border_status; - repaint_views(output, &total_damage); + begin_render_sync = timeline_create_render_sync(gr); + + switch (output->stereoscopy_layout) { + case ZWP_STEREOSCOPY_V1_LAYOUT_NONE: + glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width, + go->borders[GL_RENDERER_BORDER_BOTTOM].height, + output->current_mode->width, + output->current_mode->height); + + repaint_views(output, &total_damage, GL_RENDERER_SIDE_DEFAULT); + break; + case ZWP_STEREOSCOPY_V1_LAYOUT_SIDE_BY_SIDE: + /* Left eye */ + glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width, + go->borders[GL_RENDERER_BORDER_BOTTOM].height, + output->current_mode->width / 2, + output->current_mode->height); + + repaint_views(output, &total_damage, GL_RENDERER_SIDE_LEFT); + + /* Right eye */ + glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width + output->current_mode->width / 2, + go->borders[GL_RENDERER_BORDER_BOTTOM].height, + output->current_mode->width / 2, + output->current_mode->height); + + repaint_views(output, &total_damage, GL_RENDERER_SIDE_RIGHT); + break; + case ZWP_STEREOSCOPY_V1_LAYOUT_TOP_AND_BOTTOM: + /* Left eye */ + glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width, + go->borders[GL_RENDERER_BORDER_BOTTOM].height, + output->current_mode->width, + output->current_mode->height / 2); + + repaint_views(output, &total_damage, GL_RENDERER_SIDE_LEFT); + + /* Right eye */ + glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width, + go->borders[GL_RENDERER_BORDER_BOTTOM].height + output->current_mode->height / 2, + output->current_mode->width, + output->current_mode->height / 2); + + repaint_views(output, &total_damage, GL_RENDERER_SIDE_RIGHT); + break; + case ZWP_STEREOSCOPY_V1_LAYOUT_FRAME_PACKING: + /* Left eye */ + glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width, + go->borders[GL_RENDERER_BORDER_BOTTOM].height, + output->current_mode->width, + output->current_mode->height); + + repaint_views(output, &total_damage, GL_RENDERER_SIDE_LEFT); + + /* Right eye, with 1/24th of the height unused in the middle. */ + glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width, + go->borders[GL_RENDERER_BORDER_BOTTOM].height + output->current_mode->height * 25.0 / 24.0, + output->current_mode->width, + output->current_mode->height); + + repaint_views(output, &total_damage, GL_RENDERER_SIDE_RIGHT); + break; + default: + assert(0); + } pixman_region32_fini(&total_damage); pixman_region32_fini(&buffer_damage); diff --git a/libweston/gl-renderer.h b/libweston/gl-renderer.h index b47ea07f..0469417f 100644 --- a/libweston/gl-renderer.h +++ b/libweston/gl-renderer.h @@ -56,6 +56,12 @@ enum gl_renderer_border_side { GL_RENDERER_BORDER_BOTTOM = 3, }; +enum gl_renderer_stereoscopy_side { + GL_RENDERER_SIDE_DEFAULT = 0, + GL_RENDERER_SIDE_LEFT = 1, + GL_RENDERER_SIDE_RIGHT = 2, +}; + struct gl_renderer_interface { const EGLint *opaque_attribs; const EGLint *alpha_attribs; -- 2.15.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel