[PATCH weston 10/13] gl-renderer: Add stereoscopy support.
Emmanuel Gil Peyrot
linkmauve at linkmauve.fr
Tue Nov 14 15:05:57 UTC 2017
Signed-off-by: Emmanuel Gil Peyrot <linkmauve at 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
More information about the wayland-devel
mailing list