[PATCH 2/2] gl-renderer: Use eglSwapBuffersWithDamageEXT when available

Jason Ekstrand jason at jlekstrand.net
Thu Jan 16 21:16:26 PST 2014


Never mind, the first one was correct. I misunderstood buffer age.
--Jason
On Jan 16, 2014 10:52 PM, "Jason Ekstrand" <jason at jlekstrand.net> wrote:

> Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
> ---
>
> The second version properly sets the EGL_SWAP_BEHAVIOR surface attribute to
> EGL_BUFFER_PRESERVED.
>
>  src/gl-renderer.c | 104
> +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 103 insertions(+), 1 deletion(-)
>
> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index c8dfa4b..eddf481 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -124,6 +124,8 @@ struct gl_renderer {
>         PFNEGLCREATEIMAGEKHRPROC create_image;
>         PFNEGLDESTROYIMAGEKHRPROC destroy_image;
>
> +       PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
> +
>         int has_unpack_subimage;
>
>         PFNEGLBINDWAYLANDDISPLAYWL bind_display;
> @@ -677,6 +679,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 +745,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 +852,9 @@ gl_renderer_repaint_output(struct weston_output
> *output,
>         struct gl_renderer *gr = get_renderer(compositor);
>         EGLBoolean ret;
>         static int errored;
> +       int i, nrects, buffer_height;
> +       EGLint *egl_damage, *d;
> +       pixman_box32_t *rects;
>         pixman_region32_t buffer_damage, total_damage;
>         enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
>
> @@ -847,7 +900,44 @@ gl_renderer_repaint_output(struct weston_output
> *output,
>         pixman_region32_copy(&output->previous_damage, output_damage);
>         wl_signal_emit(&output->frame_signal, output);
>
> -       ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
> +       if (gr->swap_buffers_with_damage && gr->has_egl_buffer_age) {
> +               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);
> +       }
> +
>         if (ret == EGL_FALSE && !errored) {
>                 errored = 1;
>                 weston_log("Failed in eglSwapBuffers.\n");
> @@ -1618,6 +1708,11 @@ gl_renderer_output_create(struct weston_output
> *output,
>                         return -1;
>                 }
>
> +       if (gr->swap_buffers_with_damage && gr->has_egl_buffer_age) {
> +               eglSurfaceAttrib(gr->egl_display, go->egl_surface,
> +                                EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
> +       }
> +
>         for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
>                 pixman_region32_init(&go->buffer_damage[i]);
>
> @@ -1958,6 +2053,13 @@ gl_renderer_setup(struct weston_compositor *ec,
> EGLSurface egl_surface)
>                 weston_log("warning: EGL_EXT_buffer_age not supported. "
>                            "Performance could be affected.\n");
>
> +       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");
> +
>         glActiveTexture(GL_TEXTURE0);
>
>         if (compile_shaders(ec))
> --
> 1.8.4.2
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20140116/dfd2255f/attachment-0001.html>


More information about the wayland-devel mailing list