diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index bcfbc72f9..2fa1d6b46 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -35,6 +35,7 @@ struct wlr_xdg_surface; struct wlr_layer_surface_v1; struct wlr_drag_icon; struct wlr_surface; +struct wlr_raster; struct wlr_scene_node; struct wlr_scene_buffer; @@ -158,6 +159,7 @@ struct wlr_scene_buffer { // May be NULL struct wlr_buffer *buffer; + struct wlr_raster *raster; struct { struct wl_signal outputs_update; // struct wlr_scene_outputs_update_event @@ -188,15 +190,9 @@ struct wlr_scene_buffer { // private state uint64_t active_outputs; - struct wlr_texture *texture; struct wlr_linux_dmabuf_feedback_v1_init_options prev_feedback_options; bool own_buffer; - int buffer_width, buffer_height; - bool buffer_is_opaque; - - struct wlr_drm_syncobj_timeline *wait_timeline; - uint64_t wait_point; struct wl_listener buffer_release; struct wl_listener renderer_destroy; @@ -427,7 +423,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, struct wlr_buffer *buffer); /** - * Sets the buffer's backing buffer. + * Sets the buffer's backing raster. * * If the buffer is NULL, the buffer node will not be displayed. */ @@ -435,7 +431,7 @@ void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, struct wlr_buffer *buffer); /** - * Sets the buffer's backing buffer with a custom damage region. + * Sets the buffer's backing raster with a custom damage region. * * The damage region is in buffer-local coordinates. If the region is NULL, * the whole buffer node will be damaged. diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index b5863f476..7e0bca307 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -91,8 +92,6 @@ struct highlight_region { static void scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, struct wlr_buffer *buffer); -static void scene_buffer_set_texture(struct wlr_scene_buffer *scene_buffer, - struct wlr_texture *texture); void wlr_scene_node_destroy(struct wlr_scene_node *node) { if (node == NULL) { @@ -123,9 +122,8 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { } scene_buffer_set_buffer(scene_buffer, NULL); - scene_buffer_set_texture(scene_buffer, NULL); + wlr_raster_unlock(scene_buffer->raster); pixman_region32_fini(&scene_buffer->opaque_region); - wlr_drm_syncobj_timeline_unref(scene_buffer->wait_timeline); } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node); @@ -259,7 +257,7 @@ static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y, } else if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - if (!scene_buffer->buffer) { + if (!scene_buffer->raster) { return; } @@ -267,7 +265,7 @@ static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y, return; } - if (!scene_buffer->buffer_is_opaque) { + if (!scene_buffer->raster->opaque) { pixman_region32_copy(opaque, &scene_buffer->opaque_region); pixman_region32_intersect_rect(opaque, opaque, 0, 0, width, height); pixman_region32_translate(opaque, x, y); @@ -755,9 +753,6 @@ static void scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, wlr_buffer_unlock(scene_buffer->buffer); } scene_buffer->buffer = NULL; - scene_buffer->own_buffer = false; - scene_buffer->buffer_width = scene_buffer->buffer_height = 0; - scene_buffer->buffer_is_opaque = false; if (!buffer) { return; @@ -765,46 +760,11 @@ static void scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, scene_buffer->own_buffer = true; scene_buffer->buffer = wlr_buffer_lock(buffer); - scene_buffer->buffer_width = buffer->width; - scene_buffer->buffer_height = buffer->height; - scene_buffer->buffer_is_opaque = buffer_is_opaque(buffer); scene_buffer->buffer_release.notify = scene_buffer_handle_buffer_release; wl_signal_add(&buffer->events.release, &scene_buffer->buffer_release); } -static void scene_buffer_handle_renderer_destroy(struct wl_listener *listener, - void *data) { - struct wlr_scene_buffer *scene_buffer = wl_container_of(listener, scene_buffer, renderer_destroy); - scene_buffer_set_texture(scene_buffer, NULL); -} - -static void scene_buffer_set_texture(struct wlr_scene_buffer *scene_buffer, - struct wlr_texture *texture) { - wl_list_remove(&scene_buffer->renderer_destroy.link); - wlr_texture_destroy(scene_buffer->texture); - scene_buffer->texture = texture; - - if (texture != NULL) { - scene_buffer->renderer_destroy.notify = scene_buffer_handle_renderer_destroy; - wl_signal_add(&texture->renderer->events.destroy, &scene_buffer->renderer_destroy); - } else { - wl_list_init(&scene_buffer->renderer_destroy.link); - } -} - -static void scene_buffer_set_wait_timeline(struct wlr_scene_buffer *scene_buffer, - struct wlr_drm_syncobj_timeline *timeline, uint64_t point) { - wlr_drm_syncobj_timeline_unref(scene_buffer->wait_timeline); - if (timeline != NULL) { - scene_buffer->wait_timeline = wlr_drm_syncobj_timeline_ref(timeline); - scene_buffer->wait_point = point; - } else { - scene_buffer->wait_timeline = NULL; - scene_buffer->wait_point = 0; - } -} - struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, struct wlr_buffer *buffer) { struct wlr_scene_buffer *scene_buffer = calloc(1, sizeof(*scene_buffer)); @@ -823,6 +783,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, wl_list_init(&scene_buffer->buffer_release.link); wl_list_init(&scene_buffer->renderer_destroy.link); scene_buffer->opacity = 1; + scene_buffer->raster = buffer ? wlr_raster_create(buffer, NULL) : NULL; scene_buffer_set_buffer(scene_buffer, buffer); scene_node_update(&scene_buffer->node, NULL); @@ -843,7 +804,7 @@ void wlr_scene_buffer_set_buffer_with_options(struct wlr_scene_buffer *scene_buf assert(buffer || !options->damage); bool mapped = buffer != NULL; - bool prev_mapped = scene_buffer->buffer != NULL || scene_buffer->texture != NULL; + bool prev_mapped = scene_buffer->raster != NULL; if (!mapped && !prev_mapped) { // unmapping already unmapped buffer - noop @@ -855,14 +816,20 @@ void wlr_scene_buffer_set_buffer_with_options(struct wlr_scene_buffer *scene_buf // produce we need to update the node. bool update = mapped != prev_mapped; if (buffer != NULL && scene_buffer->dst_width == 0 && scene_buffer->dst_height == 0) { - update = update || scene_buffer->buffer_width != buffer->width || - scene_buffer->buffer_height != buffer->height; + update = update || (int)scene_buffer->raster->width != buffer->width || + (int)scene_buffer->raster->height != buffer->height; } + wlr_raster_unlock(scene_buffer->raster); + scene_buffer->raster = NULL; + scene_buffer_set_buffer(scene_buffer, buffer); - scene_buffer_set_texture(scene_buffer, NULL); - scene_buffer_set_wait_timeline(scene_buffer, - options->wait_timeline, options->wait_point); + if (buffer) { + scene_buffer->raster = wlr_raster_create(buffer, &(struct wlr_raster_create_options) { + .wait_timeline = options->wait_timeline, + .wait_point = options->wait_point, + }); + } if (update) { scene_node_update(&scene_buffer->node, NULL); @@ -1057,28 +1024,6 @@ void wlr_scene_buffer_set_filter_mode(struct wlr_scene_buffer *scene_buffer, scene_node_update(&scene_buffer->node, NULL); } -static struct wlr_texture *scene_buffer_get_texture( - struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) { - if (scene_buffer->buffer == NULL || scene_buffer->texture != NULL) { - return scene_buffer->texture; - } - - struct wlr_client_buffer *client_buffer = - wlr_client_buffer_get(scene_buffer->buffer); - if (client_buffer != NULL) { - return client_buffer->texture; - } - - struct wlr_texture *texture = - wlr_texture_from_buffer(renderer, scene_buffer->buffer); - if (texture != NULL && scene_buffer->own_buffer) { - scene_buffer->own_buffer = false; - wlr_buffer_unlock(scene_buffer->buffer); - } - scene_buffer_set_texture(scene_buffer, texture); - return texture; -} - static void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height) { *width = 0; @@ -1097,9 +1042,9 @@ static void scene_node_get_size(struct wlr_scene_node *node, if (scene_buffer->dst_width > 0 && scene_buffer->dst_height > 0) { *width = scene_buffer->dst_width; *height = scene_buffer->dst_height; - } else { - *width = scene_buffer->buffer_width; - *height = scene_buffer->buffer_height; + } else if (scene_buffer->raster) { + *width = scene_buffer->raster->width; + *height = scene_buffer->raster->height; wlr_output_transform_coords(scene_buffer->transform, width, height); } break; @@ -1368,8 +1313,12 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - struct wlr_texture *texture = scene_buffer_get_texture(scene_buffer, - data->output->output->renderer); + struct wlr_texture *texture = NULL; + if (scene_buffer->raster) { + texture = wlr_raster_obtain_texture(scene_buffer->raster, + data->output->output->renderer); + } + if (texture == NULL) { scene_output_damage(data->output, &render_region); break; @@ -1390,8 +1339,8 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren .blend_mode = !data->output->scene->calculate_visibility || pixman_region32_not_empty(&opaque) ? WLR_RENDER_BLEND_MODE_PREMULTIPLIED : WLR_RENDER_BLEND_MODE_NONE, - .wait_timeline = scene_buffer->wait_timeline, - .wait_point = scene_buffer->wait_point, + .wait_timeline = scene_buffer->raster->wait_timeline, + .wait_point = scene_buffer->raster->wait_point, }); struct wlr_scene_output_sample_event sample_event = { @@ -1702,7 +1651,7 @@ static bool scene_node_invisible(struct wlr_scene_node *node) { } else if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); - return buffer->buffer == NULL && buffer->texture == NULL; + return buffer->raster == NULL; } return false; @@ -1825,8 +1774,8 @@ static bool scene_entry_try_direct_scanout(struct render_list_entry *entry, return false; } - int default_width = buffer->buffer->width; - int default_height = buffer->buffer->height; + int default_width = buffer->raster->width; + int default_height = buffer->raster->height; wlr_output_transform_coords(buffer->transform, &default_width, &default_height); struct wlr_fbox default_box = { .width = default_width, @@ -1866,8 +1815,9 @@ static bool scene_entry_try_direct_scanout(struct render_list_entry *entry, } wlr_output_state_set_buffer(&pending, buffer->buffer); - if (buffer->wait_timeline != NULL) { - wlr_output_state_set_wait_timeline(&pending, buffer->wait_timeline, buffer->wait_point); + if (buffer->raster->wait_timeline != NULL) { + wlr_output_state_set_wait_timeline(&pending, + buffer->raster->wait_timeline, buffer->raster->wait_point); } if (!wlr_output_test_state(scene_output->output, &pending)) {