From 06ad734e70227ad0527fe11b88ad37e93005ce0c Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 27 Apr 2023 10:25:40 +0200 Subject: scene_graph: Port view saved buffers --- sway/tree/view.c | 88 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 31 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/view.c b/sway/tree/view.c index ee25faf1..402fa179 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -56,7 +56,6 @@ bool view_init(struct sway_view *view, enum sway_view_type type, view->type = type; view->impl = impl; view->executed_criteria = create_list(); - wl_list_init(&view->saved_buffers); view->allow_request_urgent = true; view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; wl_signal_init(&view->events.unmap); @@ -77,9 +76,6 @@ void view_destroy(struct sway_view *view) { return; } wl_list_remove(&view->events.unmap.listener_list); - if (!wl_list_empty(&view->saved_buffers)) { - view_remove_saved_buffer(view); - } list_free(view->executed_criteria); view_assign_ctx(view, NULL); @@ -931,10 +927,10 @@ void view_center_surface(struct sway_view *view) { struct sway_container *con = view->container; // We always center the current coordinates rather than the next, as the // geometry immediately affects the currently active rendering. - con->surface_x = fmax(con->current.content_x, con->current.content_x + - (con->current.content_width - view->geometry.width) / 2); - con->surface_y = fmax(con->current.content_y, con->current.content_y + - (con->current.content_height - view->geometry.height) / 2); + int x = (int) fmax(0, (con->current.content_width - view->geometry.width) / 2); + int y = (int) fmax(0, (con->current.content_height - view->geometry.height) / 2); + + wlr_scene_node_set_position(&view->content_tree->node, x, y); } struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { @@ -1161,40 +1157,54 @@ bool view_is_urgent(struct sway_view *view) { } void view_remove_saved_buffer(struct sway_view *view) { - if (!sway_assert(!wl_list_empty(&view->saved_buffers), "Expected a saved buffer")) { + if (!sway_assert(view->saved_surface_tree, "Expected a saved buffer")) { return; } - struct sway_saved_buffer *saved_buf, *tmp; - wl_list_for_each_safe(saved_buf, tmp, &view->saved_buffers, link) { - wlr_buffer_unlock(&saved_buf->buffer->base); - wl_list_remove(&saved_buf->link); - free(saved_buf); - } + + wlr_scene_node_destroy(&view->saved_surface_tree->node); + view->saved_surface_tree = NULL; + wlr_scene_node_set_enabled(&view->content_tree->node, true); } -static void view_save_buffer_iterator(struct wlr_surface *surface, +static void view_save_buffer_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *data) { - struct sway_view *view = data; - - if (surface && surface->buffer) { - wlr_buffer_lock(&surface->buffer->base); - struct sway_saved_buffer *saved_buffer = calloc(1, sizeof(struct sway_saved_buffer)); - saved_buffer->buffer = surface->buffer; - saved_buffer->width = surface->current.width; - saved_buffer->height = surface->current.height; - saved_buffer->x = view->container->surface_x + sx; - saved_buffer->y = view->container->surface_y + sy; - saved_buffer->transform = surface->current.transform; - wlr_surface_get_buffer_source_box(surface, &saved_buffer->source_box); - wl_list_insert(view->saved_buffers.prev, &saved_buffer->link); + struct wlr_scene_tree *tree = data; + + struct wlr_scene_buffer *sbuf = wlr_scene_buffer_create(tree, NULL); + if (!sbuf) { + sway_log(SWAY_ERROR, "Could not allocate a scene buffer when saving a surface"); + return; } + + wlr_scene_buffer_set_dest_size(sbuf, + buffer->dst_width, buffer->dst_height); + wlr_scene_buffer_set_opaque_region(sbuf, &buffer->opaque_region); + wlr_scene_buffer_set_source_box(sbuf, &buffer->src_box); + wlr_scene_node_set_position(&sbuf->node, sx, sy); + wlr_scene_buffer_set_transform(sbuf, buffer->transform); + wlr_scene_buffer_set_buffer(sbuf, buffer->buffer); } void view_save_buffer(struct sway_view *view) { - if (!sway_assert(wl_list_empty(&view->saved_buffers), "Didn't expect saved buffer")) { + if (!sway_assert(!view->saved_surface_tree, "Didn't expect saved buffer")) { view_remove_saved_buffer(view); } - view_for_each_surface(view, view_save_buffer_iterator, view); + + view->saved_surface_tree = wlr_scene_tree_create(view->scene_tree); + if (!view->saved_surface_tree) { + sway_log(SWAY_ERROR, "Could not allocate a scene tree node when saving a surface"); + return; + } + + // Enable and disable the saved surface tree like so to atomitaclly update + // the tree. This will prevent over damaging or other weirdness. + wlr_scene_node_set_enabled(&view->saved_surface_tree->node, false); + + wlr_scene_node_for_each_buffer(&view->content_tree->node, + view_save_buffer_iterator, view->saved_surface_tree); + + wlr_scene_node_set_enabled(&view->content_tree->node, false); + wlr_scene_node_set_enabled(&view->saved_surface_tree->node, true); } bool view_is_transient_for(struct sway_view *child, @@ -1202,3 +1212,19 @@ bool view_is_transient_for(struct sway_view *child, return child->impl->is_transient_for && child->impl->is_transient_for(child, ancestor); } + +static void send_frame_done_iterator(struct wlr_scene_buffer *scene_buffer, + int x, int y, void *data) { + struct timespec *when = data; + wl_signal_emit_mutable(&scene_buffer->events.frame_done, when); +} + +void view_send_frame_done(struct sway_view *view) { + struct timespec when; + clock_gettime(CLOCK_MONOTONIC, &when); + + struct wlr_scene_node *node; + wl_list_for_each(node, &view->content_tree->children, link) { + wlr_scene_node_for_each_buffer(node, send_frame_done_iterator, &when); + } +} -- cgit v1.2.3-54-g00ecf