render/gles2: fix texture cleanup on destroy

When importing a DMA-BUF wlr_buffer as a wlr_texture, the GLES2
renderer caches the result, in case the buffer is used for texturing
again in the future. When the wlr_texture is destroyed by the caller,
the wlr_buffer is unref'ed, but the wlr_gles2_texture is kept around.
This is fine because wlr_gles2_texture listens for wlr_buffer's destroy
event to avoid any use-after-free.

However, with this logic wlr_texture_destroy doesn't "really" destroy
the wlr_gles2_texture. It just decrements the wlr_buffer ref'count.
Each wlr_texture_destroy call must have a matching prior
wlr_texture_create_from_buffer call or the ref'counting will go south.

Wehn destroying the renderer, we don't want to decrement any wlr_buffer
ref'count. Instead, we want to go through any cached wlr_gles2_texture
and destroy our GL state. So instead of calling wlr_texture_destroy, we
need to call our internal gles2_texture_destroy function.

Closes: https://github.com/swaywm/wlroots/issues/2941
This commit is contained in:
Simon Ser 2021-05-29 10:25:25 +02:00 committed by Simon Zeni
parent d0560e2597
commit abf527b075
3 changed files with 3 additions and 2 deletions

View file

@ -128,6 +128,7 @@ struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer,
struct wlr_dmabuf_attributes *attribs); struct wlr_dmabuf_attributes *attribs);
struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer, struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer,
struct wlr_buffer *buffer); struct wlr_buffer *buffer);
void gles2_texture_destroy(struct wlr_gles2_texture *texture);
void push_gles2_debug_(struct wlr_gles2_renderer *renderer, void push_gles2_debug_(struct wlr_gles2_renderer *renderer,
const char *file, const char *func); const char *file, const char *func);

View file

@ -546,7 +546,7 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) {
struct wlr_gles2_texture *tex, *tex_tmp; struct wlr_gles2_texture *tex, *tex_tmp;
wl_list_for_each_safe(tex, tex_tmp, &renderer->textures, link) { wl_list_for_each_safe(tex, tex_tmp, &renderer->textures, link) {
wlr_texture_destroy(&tex->wlr_texture); gles2_texture_destroy(tex);
} }
push_gles2_debug(renderer); push_gles2_debug(renderer);

View file

@ -125,7 +125,7 @@ static bool gles2_texture_invalidate(struct wlr_gles2_texture *texture) {
return true; return true;
} }
static void gles2_texture_destroy(struct wlr_gles2_texture *texture) { void gles2_texture_destroy(struct wlr_gles2_texture *texture) {
wl_list_remove(&texture->link); wl_list_remove(&texture->link);
wl_list_remove(&texture->buffer_destroy.link); wl_list_remove(&texture->buffer_destroy.link);