Instead of relying on the compositor core to keep the wl_buffer around
and unreleased, take a new reference to it in gl-renderer. This makes
sure in the future, that the gl-renderer always has the buffer at hand,
client misbehaviour excluded.

The reference is taken in the attach callback, and released in the
flush_damage callback after copy to texture, or when the next attach
callback with a different buffer occurs.

If the surface is not on the primary plane, the buffer is not released
in flush_damage. This ensures, that the buffer stays valid in case the
surface migrates to the primary plane later.

Signed-off-by: Pekka Paalanen <[email protected]>
---
 src/gl-renderer.c |   19 ++++++++++++++++---
 1 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index f581482..4ab8b0c 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -62,6 +62,8 @@ struct gl_surface_state {
        EGLImageKHR images[3];
        GLenum target;
        int num_images;
+
+       struct weston_buffer_reference buffer_ref;
 };
 
 struct gl_renderer {
@@ -1038,7 +1040,7 @@ gl_renderer_flush_damage(struct weston_surface *surface)
 {
        struct gl_renderer *gr = get_renderer(surface->compositor);
        struct gl_surface_state *gs = get_surface_state(surface);
-       struct wl_buffer *buffer = surface->buffer_ref.buffer;
+       struct wl_buffer *buffer = gs->buffer_ref.buffer;
 
 #ifdef GL_UNPACK_ROW_LENGTH
        pixman_box32_t *rectangles;
@@ -1049,14 +1051,19 @@ gl_renderer_flush_damage(struct weston_surface *surface)
        pixman_region32_union(&surface->texture_damage,
                              &surface->texture_damage, &surface->damage);
 
+       if (!buffer)
+               return;
+
        /* Avoid upload, if the texture won't be used this time.
-        * We still accumulate the damage in texture_damage.
+        * We still accumulate the damage in texture_damage, and
+        * hold the reference to the buffer, in case the surface
+        * migrates back to the primary plane.
         */
        if (surface->plane != &surface->compositor->primary_plane)
                return;
 
        if (!pixman_region32_not_empty(&surface->texture_damage))
-               return;
+               goto done;
 
        glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
 
@@ -1090,6 +1097,8 @@ gl_renderer_flush_damage(struct weston_surface *surface)
 done:
        pixman_region32_fini(&surface->texture_damage);
        pixman_region32_init(&surface->texture_damage);
+
+       weston_buffer_reference(&gs->buffer_ref, NULL);
 }
 
 static void
@@ -1121,6 +1130,8 @@ gl_renderer_attach(struct weston_surface *es, struct 
wl_buffer *buffer)
        EGLint attribs[3], format;
        int i, num_planes;
 
+       weston_buffer_reference(&gs->buffer_ref, buffer);
+
        if (!buffer) {
                for (i = 0; i < gs->num_images; i++) {
                        gr->destroy_image(gr->egl_display, gs->images[i]);
@@ -1201,6 +1212,7 @@ gl_renderer_attach(struct weston_surface *es, struct 
wl_buffer *buffer)
                es->pitch = buffer->width;
        } else {
                weston_log("unhandled buffer type!\n");
+               weston_buffer_reference(&gs->buffer_ref, NULL);
        }
 }
 
@@ -1246,6 +1258,7 @@ gl_renderer_destroy_surface(struct weston_surface 
*surface)
        for (i = 0; i < gs->num_images; i++)
                gr->destroy_image(gr->egl_display, gs->images[i]);
 
+       weston_buffer_reference(&gs->buffer_ref, NULL);
        free(gs);
 }
 
-- 
1.7.8.6

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to