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

Reply via email to