scene: add scene_buffer_set_buffer_and_texture()

This commit is contained in:
Simon Ser 2024-03-06 16:47:54 +01:00
parent 95c2308928
commit 119c634d94
3 changed files with 63 additions and 16 deletions

View file

@ -7,4 +7,8 @@ struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
void scene_surface_set_clip(struct wlr_scene_surface *surface, struct wlr_box *clip); void scene_surface_set_clip(struct wlr_scene_surface *surface, struct wlr_box *clip);
void scene_buffer_set_buffer_and_texture(struct wlr_scene_buffer *scene_buffer,
struct wlr_buffer *buffer, struct wlr_texture *texture,
const pixman_region32_t *damage);
#endif #endif

View file

@ -184,6 +184,7 @@ struct wlr_scene_buffer {
uint64_t active_outputs; uint64_t active_outputs;
struct wlr_texture *texture; struct wlr_texture *texture;
bool own_texture;
struct wlr_linux_dmabuf_feedback_v1_init_options prev_feedback_options; struct wlr_linux_dmabuf_feedback_v1_init_options prev_feedback_options;
bool own_buffer; bool own_buffer;
@ -191,6 +192,7 @@ struct wlr_scene_buffer {
bool buffer_is_opaque; bool buffer_is_opaque;
struct wl_listener buffer_release; struct wl_listener buffer_release;
struct wl_listener texture_destroy;
}; };
/** A viewport for an output in the scene-graph */ /** A viewport for an output in the scene-graph */

View file

@ -112,7 +112,9 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
} }
} }
wlr_texture_destroy(scene_buffer->texture); if (scene_buffer->own_texture) {
wlr_texture_destroy(scene_buffer->texture);
}
scene_buffer_set_buffer(scene_buffer, NULL); scene_buffer_set_buffer(scene_buffer, NULL);
pixman_region32_fini(&scene_buffer->opaque_region); pixman_region32_fini(&scene_buffer->opaque_region);
} else if (node->type == WLR_SCENE_NODE_TREE) { } else if (node->type == WLR_SCENE_NODE_TREE) {
@ -635,6 +637,37 @@ static void scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer,
wl_signal_add(&buffer->events.release, &scene_buffer->buffer_release); wl_signal_add(&buffer->events.release, &scene_buffer->buffer_release);
} }
static void scene_buffer_set_texture(struct wlr_scene_buffer *scene_buffer,
struct wlr_texture *texture, bool own_texture);
static void scene_buffer_handle_texture_destroy(struct wl_listener *listener,
void *data) {
struct wlr_scene_buffer *scene_buffer =
wl_container_of(listener, scene_buffer, texture_destroy);
scene_buffer_set_texture(scene_buffer, NULL, false);
}
static void scene_buffer_set_texture(struct wlr_scene_buffer *scene_buffer,
struct wlr_texture *texture, bool own_texture) {
wl_list_remove(&scene_buffer->texture_destroy.link);
wl_list_init(&scene_buffer->texture_destroy.link);
if (scene_buffer->own_texture) {
wlr_texture_destroy(scene_buffer->texture);
}
scene_buffer->texture = NULL;
scene_buffer->own_texture = false;
if (!texture) {
return;
}
scene_buffer->own_texture = own_texture;
scene_buffer->texture = texture;
scene_buffer->texture_destroy.notify = scene_buffer_handle_texture_destroy;
wl_signal_add(&texture->events.destroy, &scene_buffer->texture_destroy);
}
struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent,
struct wlr_buffer *buffer) { struct wlr_buffer *buffer) {
struct wlr_scene_buffer *scene_buffer = calloc(1, sizeof(*scene_buffer)); struct wlr_scene_buffer *scene_buffer = calloc(1, sizeof(*scene_buffer));
@ -659,20 +692,28 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent,
return scene_buffer; return scene_buffer;
} }
void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer, void scene_buffer_set_buffer_and_texture(struct wlr_scene_buffer *scene_buffer,
struct wlr_buffer *buffer, const pixman_region32_t *damage) { struct wlr_buffer *buffer, struct wlr_texture *texture,
const pixman_region32_t *damage) {
// specifying a region for a NULL buffer doesn't make sense. We need to know // specifying a region for a NULL buffer doesn't make sense. We need to know
// about the buffer to scale the buffer local coordinates down to scene // about the buffer to scale the buffer local coordinates down to scene
// coordinates. // coordinates.
assert(buffer || !damage); assert(buffer || texture || !damage);
int buffer_width = 0, buffer_height = 0; int buffer_width = 0, buffer_height = 0;
if (buffer != NULL && texture != NULL) {
assert(buffer->width == (int)texture->width &&
buffer->height == (int)texture->height);
}
if (buffer != NULL) { if (buffer != NULL) {
buffer_width = buffer->width; buffer_width = buffer->width;
buffer_height = buffer->height; buffer_height = buffer->height;
} else if (texture != NULL) {
buffer_width = texture->width;
buffer_height = texture->height;
} }
bool mapped = buffer != NULL; bool mapped = buffer != NULL || texture != NULL;
bool prev_mapped = scene_buffer->buffer != NULL || scene_buffer->texture != NULL; bool prev_mapped = scene_buffer->buffer != NULL || scene_buffer->texture != NULL;
// if this node used to not be mapped or its previous displayed // if this node used to not be mapped or its previous displayed
@ -684,10 +725,10 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff
scene_buffer->buffer_height != buffer_height; scene_buffer->buffer_height != buffer_height;
} }
wlr_texture_destroy(scene_buffer->texture);
scene_buffer->texture = NULL;
scene_buffer_set_buffer(scene_buffer, buffer); scene_buffer_set_buffer(scene_buffer, buffer);
scene_buffer_set_texture(scene_buffer, texture, false);
scene_buffer->buffer_width = buffer_width;
scene_buffer->buffer_height = buffer_height;
if (update) { if (update) {
scene_node_update(&scene_buffer->node, NULL); scene_node_update(&scene_buffer->node, NULL);
@ -786,6 +827,11 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff
pixman_region32_fini(&fallback_damage); pixman_region32_fini(&fallback_damage);
} }
void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer,
struct wlr_buffer *buffer, const pixman_region32_t *damage) {
scene_buffer_set_buffer_and_texture(scene_buffer, buffer, NULL, damage);
}
void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer,
struct wlr_buffer *buffer) { struct wlr_buffer *buffer) {
wlr_scene_buffer_set_buffer_with_damage(scene_buffer, buffer, NULL); wlr_scene_buffer_set_buffer_with_damage(scene_buffer, buffer, NULL);
@ -880,15 +926,10 @@ static struct wlr_texture *scene_buffer_get_texture(
return scene_buffer->texture; return scene_buffer->texture;
} }
struct wlr_client_buffer *client_buffer = struct wlr_texture *texture =
wlr_client_buffer_get(scene_buffer->buffer);
if (client_buffer != NULL) {
return client_buffer->texture;
}
scene_buffer->texture =
wlr_texture_from_buffer(renderer, scene_buffer->buffer); wlr_texture_from_buffer(renderer, scene_buffer->buffer);
if (scene_buffer->texture != NULL && scene_buffer->own_buffer) { scene_buffer_set_texture(scene_buffer, texture, true);
if (texture != NULL && scene_buffer->own_buffer) {
scene_buffer->own_buffer = false; scene_buffer->own_buffer = false;
wlr_buffer_unlock(scene_buffer->buffer); wlr_buffer_unlock(scene_buffer->buffer);
} }