[PATCH weston 4/4] gl-renderer: Use EXT_buffer_age and don't assume double buffering

Kristian Høgsberg krh at bitplanet.net
Wed Mar 6 05:43:17 PST 2013


EGL_BUFFER_PRESERVED is what you get when buffer_age is 1.  I'm sure
we can clip the redraw to just the damage region when that happens.

Kristian

On Wed, Mar 6, 2013 at 3:24 AM, Pekka Paalanen <ppaalanen at gmail.com> wrote:
> On Tue,  5 Mar 2013 17:30:30 +0200
> Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
> wrote:
>
>> Now that we have EXT_buffer_age in mesa, we should stop assuming double
>> buffering and use the buffer age instead.
>>
>> Note: this will cause system without the extension to repaint the whole
>> screen every frame.
>
> Ok, that might hurt the rpi backend when it is using GL to composite.
> It makes the extra step to set EGL_SWAP_BEHAVIOR to
> EGL_BUFFER_PRESERVED, so it can support the old double-buffering assumption.
> I do not recall if it has EXT_buffer_age, but I would assume it doesn't.
>
> Would it be easy to add a flag to get the strictly double-buffered
> behaviour if a backend wishes so?
>
> If not, then don't worry about it.
>
>
> Thanks,
> pq
>
>> ---
>>  src/gl-renderer.c |   86 ++++++++++++++++++++++++++++++++++++++++-------------
>>  1 file changed, 66 insertions(+), 20 deletions(-)
>>
>> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
>> index 4c1bc23..fdde9ae 100644
>> --- a/src/gl-renderer.c
>> +++ b/src/gl-renderer.c
>> @@ -46,10 +46,11 @@ struct gl_shader {
>>       GLint color_uniform;
>>  };
>>
>> +#define BUFFER_DAMAGE_COUNT 2
>> +
>>  struct gl_output_state {
>>       EGLSurface egl_surface;
>> -     int current_buffer;
>> -     pixman_region32_t buffer_damage[2];
>> +     pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
>>  };
>>
>>  struct gl_surface_state {
>> @@ -95,6 +96,8 @@ struct gl_renderer {
>>
>>       int has_egl_image_external;
>>
>> +     int has_egl_buffer_age;
>> +
>>       struct gl_shader texture_shader_rgba;
>>       struct gl_shader texture_shader_rgbx;
>>       struct gl_shader texture_shader_egl_external;
>> @@ -742,12 +745,10 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
>>       struct weston_compositor *ec = es->compositor;
>>       struct gl_renderer *gr = get_renderer(ec);
>>       struct gl_surface_state *gs = get_surface_state(es);
>> -     struct gl_output_state *go = get_output_state(output);
>>       /* repaint bounding region in global coordinates: */
>>       pixman_region32_t repaint;
>>       /* non-opaque region in surface coordinates: */
>>       pixman_region32_t surface_blend;
>> -     pixman_region32_t *buffer_damage;
>>       GLint filter;
>>       int i;
>>
>> @@ -759,9 +760,6 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
>>       if (!pixman_region32_not_empty(&repaint))
>>               goto out;
>>
>> -     buffer_damage = &go->buffer_damage[go->current_buffer];
>> -     pixman_region32_subtract(buffer_damage, buffer_damage, &repaint);
>> -
>>       glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
>>
>>       if (ec->fan_debug) {
>> @@ -948,6 +946,51 @@ draw_border(struct weston_output *output)
>>  }
>>
>>  static void
>> +output_get_buffer_damage(struct weston_output *output,
>> +                      pixman_region32_t *buffer_damage)
>> +{
>> +     struct gl_output_state *go = get_output_state(output);
>> +     struct gl_renderer *gr = get_renderer(output->compositor);
>> +     EGLint buffer_age = 0;
>> +     EGLBoolean ret;
>> +     int i;
>> +
>> +     if (gr->has_egl_buffer_age) {
>> +             ret = eglQuerySurface(gr->egl_display, go->egl_surface,
>> +                                   EGL_BUFFER_AGE_EXT, &buffer_age);
>> +             if (ret == EGL_FALSE) {
>> +                     weston_log("buffer age query failed.\n");
>> +                     gl_renderer_print_egl_error_state();
>> +             }
>> +     }
>> +
>> +     if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT)
>> +             pixman_region32_copy(buffer_damage, &output->region);
>> +     else
>> +             for (i = 0; i < buffer_age - 1; i++)
>> +                     pixman_region32_union(buffer_damage, buffer_damage,
>> +                                           &go->buffer_damage[i]);
>> +}
>> +
>> +static void
>> +output_rotate_damage(struct weston_output *output,
>> +                  pixman_region32_t *output_damage)
>> +{
>> +     struct gl_output_state *go = get_output_state(output);
>> +     struct gl_renderer *gr = get_renderer(output->compositor);
>> +     int i;
>> +
>> +     if (!gr->has_egl_buffer_age)
>> +             return;
>> +
>> +     for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--)
>> +             pixman_region32_copy(&go->buffer_damage[i],
>> +                                  &go->buffer_damage[i - 1]);
>> +
>> +     pixman_region32_copy(&go->buffer_damage[0], output_damage);
>> +}
>> +
>> +static void
>>  gl_renderer_repaint_output(struct weston_output *output,
>>                             pixman_region32_t *output_damage)
>>  {
>> @@ -956,8 +999,8 @@ gl_renderer_repaint_output(struct weston_output *output,
>>       struct gl_renderer *gr = get_renderer(compositor);
>>       EGLBoolean ret;
>>       static int errored;
>> -     int32_t width, height, i;
>> -     pixman_region32_t total_damage;
>> +     int32_t width, height;
>> +     pixman_region32_t buffer_damage, total_damage;
>>
>>       width = output->current->width +
>>               output->border.left + output->border.right;
>> @@ -983,18 +1026,18 @@ gl_renderer_repaint_output(struct weston_output *output,
>>               pixman_region32_fini(&undamaged);
>>       }
>>
>> -     for (i = 0; i < 2; i++)
>> -             pixman_region32_union(&go->buffer_damage[i],
>> -                                   &go->buffer_damage[i],
>> -                                   output_damage);
>> -
>>       pixman_region32_init(&total_damage);
>> -     pixman_region32_copy(&total_damage,
>> -                          &go->buffer_damage[go->current_buffer]);
>> +     pixman_region32_init(&buffer_damage);
>> +
>> +     output_get_buffer_damage(output, &buffer_damage);
>> +     output_rotate_damage(output, output_damage);
>> +
>> +     pixman_region32_union(&total_damage, &buffer_damage, output_damage);
>>
>>       repaint_surfaces(output, &total_damage);
>>
>>       pixman_region32_fini(&total_damage);
>> +     pixman_region32_fini(&buffer_damage);
>>
>>       if (gr->border.texture)
>>               draw_border(output);
>> @@ -1009,8 +1052,6 @@ gl_renderer_repaint_output(struct weston_output *output,
>>               gl_renderer_print_egl_error_state();
>>       }
>>
>> -     go->current_buffer ^= 1;
>> -
>>  }
>>
>>  static int
>> @@ -1620,8 +1661,7 @@ gl_renderer_output_create(struct weston_output *output,
>>                       return -1;
>>               }
>>
>> -     go->current_buffer = 0;
>> -     for (i = 0; i < 2; i++)
>> +     for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
>>               pixman_region32_init(&go->buffer_damage[i]);
>>
>>       output->renderer_state = go;
>> @@ -1931,6 +1971,12 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
>>                       gr->has_bind_display = 0;
>>       }
>>
>> +     if (strstr(extensions, "EGL_EXT_buffer_age"))
>> +             gr->has_egl_buffer_age = 1;
>> +     else
>> +             weston_log("warning: EGL_EXT_buffer_age not supported. "
>> +                        "Performance could be affected.\n");
>> +
>>       glActiveTexture(GL_TEXTURE0);
>>
>>       if (compile_shaders(ec))
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list