mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-17 06:46:39 -04:00
Replace wlr_client_buffer with wlr_surface_texture
wlr_client_buffer has a bad design: just because it needs some ref'counting functionality, it's implemented as a wlr_buffer. Its purpose is to allow compositors to obtain a frozen wlr_texture to keep painting an old representation of the surface for an arbitrary amount of time (e.g. during layout reconfigurations). However a wlr_buffer lock means something else entirely, and abusing it for ref'counting a texture leads to various issues. In particular, wlr_surface checks the wlr_client_buffer lock count to decide whether to mutate a texture on commit. This falls apart if the buffer is locked for another purpose than freezing a surface texture (e.g. locked by another wlroots helper). Additionally, wlr_client_buffer forces backends to re-import and re-check the buffer each time the client commits, since DMA-BUF wlr_client_buffers are destroyed and re-created on each commit. wlr_client_buffer also doesn't properly forward all wlr_buffer operations to the source buffer: some are unimplemented, and the source buffer is not locked by wlr_client_buffer thus may be destroyed anytime. To fix all of this mess, introduce a new struct wlr_surface_texture whose purpose is just to track whether a wlr_texture is frozen. Compositors can lock the texture to freeze it. The wlr_buffer can be accessed from wlr_surface_texture.buffer, or at surface commit time from wlr_surface.current.buffer.
This commit is contained in:
parent
119c634d94
commit
5f6b9e5620
3 changed files with 107 additions and 53 deletions
|
|
@ -72,28 +72,6 @@ static void scene_surface_handle_surface_destroy(
|
|||
wlr_scene_node_destroy(&surface->buffer->node);
|
||||
}
|
||||
|
||||
// This is used for wlr_scene where it unconditionally locks buffers preventing
|
||||
// reuse of the existing texture for shm clients. With the usage pattern of
|
||||
// wlr_scene surface handling, we can mark its locked buffer as safe
|
||||
// for mutation.
|
||||
static void client_buffer_mark_next_can_damage(struct wlr_client_buffer *buffer) {
|
||||
buffer->n_ignore_locks++;
|
||||
}
|
||||
|
||||
static void scene_buffer_unmark_client_buffer(struct wlr_scene_buffer *scene_buffer) {
|
||||
if (!scene_buffer->buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_client_buffer *buffer = wlr_client_buffer_get(scene_buffer->buffer);
|
||||
if (!buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(buffer->n_ignore_locks > 0);
|
||||
buffer->n_ignore_locks--;
|
||||
}
|
||||
|
||||
static int min(int a, int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
|
@ -148,13 +126,10 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
|
|||
wlr_scene_buffer_set_dest_size(scene_buffer, width, height);
|
||||
wlr_scene_buffer_set_transform(scene_buffer, state->transform);
|
||||
|
||||
scene_buffer_unmark_client_buffer(scene_buffer);
|
||||
|
||||
if (surface->buffer) {
|
||||
client_buffer_mark_next_can_damage(surface->buffer);
|
||||
|
||||
wlr_scene_buffer_set_buffer_with_damage(scene_buffer,
|
||||
&surface->buffer->base, &surface->buffer_damage);
|
||||
if (surface->texture) {
|
||||
scene_buffer_set_buffer_and_texture(scene_buffer,
|
||||
surface->texture->buffer, surface->texture->texture,
|
||||
&surface->buffer_damage);
|
||||
} else {
|
||||
wlr_scene_buffer_set_buffer(scene_buffer, NULL);
|
||||
}
|
||||
|
|
@ -198,7 +173,7 @@ static bool scene_buffer_point_accepts_input(struct wlr_scene_buffer *scene_buff
|
|||
static void surface_addon_destroy(struct wlr_addon *addon) {
|
||||
struct wlr_scene_surface *surface = wl_container_of(addon, surface, addon);
|
||||
|
||||
scene_buffer_unmark_client_buffer(surface->buffer);
|
||||
wlr_scene_buffer_set_buffer(surface->buffer, NULL);
|
||||
|
||||
wlr_addon_finish(&surface->addon);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue