summaryrefslogtreecommitdiff
path: root/src/gl-renderer.c
diff options
context:
space:
mode:
authorJason Ekstrand <jason@jlekstrand.net>2014-02-04 21:36:39 -0600
committerKristian Høgsberg <krh@bitplanet.net>2014-02-05 17:16:37 -0800
commit8e96f9eb6ae51f75d199fb5b805e8c470d12ecfa (patch)
tree723fbf6ba088c46def8a38c26d0712c971529d47 /src/gl-renderer.c
parente5512d4014c56a5f82fe17a27f018aadb74fcb12 (diff)
downloadweston-8e96f9eb6ae51f75d199fb5b805e8c470d12ecfa.tar.gz
gl-renderer: Use eglSwapBuffersWithDamageEXT when available
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
Diffstat (limited to 'src/gl-renderer.c')
-rw-r--r--src/gl-renderer.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index c8dfa4b7..d03bce64 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -124,6 +124,10 @@ struct gl_renderer {
PFNEGLCREATEIMAGEKHRPROC create_image;
PFNEGLDESTROYIMAGEKHRPROC destroy_image;
+#ifdef EGL_EXT_swap_buffers_with_damage
+ PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
+#endif
+
int has_unpack_subimage;
PFNEGLBINDWAYLANDDISPLAYWL bind_display;
@@ -677,6 +681,17 @@ draw_output_border_texture(struct gl_output_state *go,
glDisableVertexAttribArray(0);
}
+static int
+output_has_borders(struct weston_output *output)
+{
+ struct gl_output_state *go = get_output_state(output);
+
+ return go->borders[GL_RENDERER_BORDER_TOP].data ||
+ go->borders[GL_RENDERER_BORDER_RIGHT].data ||
+ go->borders[GL_RENDERER_BORDER_BOTTOM].data ||
+ go->borders[GL_RENDERER_BORDER_LEFT].data;
+}
+
static void
draw_output_borders(struct weston_output *output,
enum gl_border_status border_status)
@@ -732,6 +747,43 @@ draw_output_borders(struct weston_output *output,
}
static void
+output_get_border_damage(struct weston_output *output,
+ enum gl_border_status border_status,
+ pixman_region32_t *damage)
+{
+ struct gl_output_state *go = get_output_state(output);
+ struct gl_border_image *top, *bottom, *left, *right;
+ int full_width, full_height;
+
+ if (border_status == BORDER_STATUS_CLEAN)
+ return; /* Clean. Nothing to do. */
+
+ top = &go->borders[GL_RENDERER_BORDER_TOP];
+ bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
+ left = &go->borders[GL_RENDERER_BORDER_LEFT];
+ right = &go->borders[GL_RENDERER_BORDER_RIGHT];
+
+ full_width = output->current_mode->width + left->width + right->width;
+ full_height = output->current_mode->height + top->height + bottom->height;
+ if (border_status & BORDER_TOP_DIRTY)
+ pixman_region32_union_rect(damage, damage,
+ 0, 0,
+ full_width, top->height);
+ if (border_status & BORDER_LEFT_DIRTY)
+ pixman_region32_union_rect(damage, damage,
+ 0, top->height,
+ left->width, output->current_mode->height);
+ if (border_status & BORDER_RIGHT_DIRTY)
+ pixman_region32_union_rect(damage, damage,
+ full_width - right->width, top->height,
+ right->width, output->current_mode->height);
+ if (border_status & BORDER_BOTTOM_DIRTY)
+ pixman_region32_union_rect(damage, damage,
+ 0, full_height - bottom->height,
+ full_width, bottom->height);
+}
+
+static void
output_get_damage(struct weston_output *output,
pixman_region32_t *buffer_damage, uint32_t *border_damage)
{
@@ -802,6 +854,11 @@ gl_renderer_repaint_output(struct weston_output *output,
struct gl_renderer *gr = get_renderer(compositor);
EGLBoolean ret;
static int errored;
+#ifdef EGL_EXT_swap_buffers_with_damage
+ int i, nrects, buffer_height;
+ EGLint *egl_damage, *d;
+ pixman_box32_t *rects;
+#endif
pixman_region32_t buffer_damage, total_damage;
enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
@@ -847,7 +904,48 @@ gl_renderer_repaint_output(struct weston_output *output,
pixman_region32_copy(&output->previous_damage, output_damage);
wl_signal_emit(&output->frame_signal, output);
+#ifdef EGL_EXT_swap_buffers_with_damage
+ if (gr->swap_buffers_with_damage) {
+ pixman_region32_init(&buffer_damage);
+ weston_transformed_region(output->width, output->height,
+ output->transform,
+ output->current_scale,
+ output_damage, &buffer_damage);
+
+ if (output_has_borders(output)) {
+ pixman_region32_translate(&buffer_damage,
+ go->borders[GL_RENDERER_BORDER_LEFT].width,
+ go->borders[GL_RENDERER_BORDER_TOP].height);
+ output_get_border_damage(output, go->border_status,
+ &buffer_damage);
+ }
+
+ rects = pixman_region32_rectangles(&buffer_damage, &nrects);
+ egl_damage = malloc(nrects * 4 * sizeof(EGLint));
+
+ buffer_height = go->borders[GL_RENDERER_BORDER_TOP].height +
+ output->current_mode->height +
+ go->borders[GL_RENDERER_BORDER_BOTTOM].height;
+
+ d = egl_damage;
+ for (i = 0; i < nrects; ++i) {
+ *d++ = rects[i].x1;
+ *d++ = buffer_height - rects[i].y2;
+ *d++ = rects[i].x2 - rects[i].x1;
+ *d++ = rects[i].y2 - rects[i].y1;
+ }
+ ret = gr->swap_buffers_with_damage(gr->egl_display,
+ go->egl_surface,
+ egl_damage, nrects);
+ free(egl_damage);
+ pixman_region32_fini(&buffer_damage);
+ } else {
+ ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
+ }
+#else /* ! defined EGL_EXT_swap_buffers_with_damage */
ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
+#endif
+
if (ret == EGL_FALSE && !errored) {
errored = 1;
weston_log("Failed in eglSwapBuffers.\n");
@@ -1958,6 +2056,15 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
weston_log("warning: EGL_EXT_buffer_age not supported. "
"Performance could be affected.\n");
+#ifdef EGL_EXT_swap_buffers_with_damage
+ if (strstr(extensions, "EGL_EXT_swap_buffers_with_damage"))
+ gr->swap_buffers_with_damage =
+ (void *) eglGetProcAddress("eglSwapBuffersWithDamageEXT");
+ else
+ weston_log("warning: EGL_EXT_swap_buffers_with_damage not "
+ "supported. Performance could be affected.\n");
+#endif
+
glActiveTexture(GL_TEXTURE0);
if (compile_shaders(ec))