From fb003d3457a7a39ed17d96373974295932363c13 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Tue, 4 Dec 2012 15:58:13 +0200 Subject: [PATCH] gl: take, hold, and release a buffer reference 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 --- src/gl-renderer.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/gl-renderer.c b/src/gl-renderer.c index f5814822..4ab8b0ce 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); }