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>
This commit is contained in:
committed by
Kristian Høgsberg
parent
de685b8843
commit
fb003d3457
+16
-3
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user