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 <ppaalanen@gmail.com>
Pekka Paalanen 12 years ago committed by Kristian Høgsberg
parent de685b8843
commit fb003d3457
  1. 19
      src/gl-renderer.c

@ -62,6 +62,8 @@ struct gl_surface_state {
EGLImageKHR images[3]; EGLImageKHR images[3];
GLenum target; GLenum target;
int num_images; int num_images;
struct weston_buffer_reference buffer_ref;
}; };
struct gl_renderer { 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_renderer *gr = get_renderer(surface->compositor);
struct gl_surface_state *gs = get_surface_state(surface); 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 #ifdef GL_UNPACK_ROW_LENGTH
pixman_box32_t *rectangles; pixman_box32_t *rectangles;
@ -1049,14 +1051,19 @@ gl_renderer_flush_damage(struct weston_surface *surface)
pixman_region32_union(&surface->texture_damage, pixman_region32_union(&surface->texture_damage,
&surface->texture_damage, &surface->damage); &surface->texture_damage, &surface->damage);
if (!buffer)
return;
/* Avoid upload, if the texture won't be used this time. /* 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) if (surface->plane != &surface->compositor->primary_plane)
return; return;
if (!pixman_region32_not_empty(&surface->texture_damage)) if (!pixman_region32_not_empty(&surface->texture_damage))
return; goto done;
glBindTexture(GL_TEXTURE_2D, gs->textures[0]); glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
@ -1090,6 +1097,8 @@ gl_renderer_flush_damage(struct weston_surface *surface)
done: done:
pixman_region32_fini(&surface->texture_damage); pixman_region32_fini(&surface->texture_damage);
pixman_region32_init(&surface->texture_damage); pixman_region32_init(&surface->texture_damage);
weston_buffer_reference(&gs->buffer_ref, NULL);
} }
static void static void
@ -1121,6 +1130,8 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
EGLint attribs[3], format; EGLint attribs[3], format;
int i, num_planes; int i, num_planes;
weston_buffer_reference(&gs->buffer_ref, buffer);
if (!buffer) { if (!buffer) {
for (i = 0; i < gs->num_images; i++) { for (i = 0; i < gs->num_images; i++) {
gr->destroy_image(gr->egl_display, gs->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; es->pitch = buffer->width;
} else { } else {
weston_log("unhandled buffer type!\n"); 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++) for (i = 0; i < gs->num_images; i++)
gr->destroy_image(gr->egl_display, gs->images[i]); gr->destroy_image(gr->egl_display, gs->images[i]);
weston_buffer_reference(&gs->buffer_ref, NULL);
free(gs); free(gs);
} }

Loading…
Cancel
Save