render saved buffer on fade-out

This commit is contained in:
William McKinnon 2024-02-01 01:26:49 -05:00
parent d7cf2986fa
commit a27fa243ad
9 changed files with 32 additions and 99 deletions

View file

@ -8,7 +8,6 @@
#include "sway/desktop/fx_renderer/fx_framebuffer.h" #include "sway/desktop/fx_renderer/fx_framebuffer.h"
#include "sway/desktop/fx_renderer/fx_texture.h" #include "sway/desktop/fx_renderer/fx_texture.h"
#include "sway/tree/view.h"
enum corner_location { TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, ALL, NONE }; enum corner_location { TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, ALL, NONE };
@ -125,8 +124,6 @@ struct fx_renderer {
struct wlr_output *wlr_output; struct wlr_output *wlr_output;
struct wlr_egl *wlr_egl;
// The framebuffer used by wlroots // The framebuffer used by wlroots
struct fx_framebuffer wlr_buffer; struct fx_framebuffer wlr_buffer;
// Contains the blurred background for tiled windows // Contains the blurred background for tiled windows
@ -217,8 +214,4 @@ void fx_render_blur(struct fx_renderer *renderer, const float matrix[static 9],
struct fx_framebuffer **buffer, struct blur_shader *shader, const struct wlr_box *box, struct fx_framebuffer **buffer, struct blur_shader *shader, const struct wlr_box *box,
int blur_radius); int blur_radius);
void fx_create_container_snapshot(struct fx_renderer *renderer, struct sway_container *con);
void fx_render_container_snapshot(struct fx_renderer *renderer, struct sway_container *con);
#endif #endif

View file

@ -185,9 +185,6 @@ void render_rounded_rect(struct sway_output *output,
float color[static 4], int corner_radius, float color[static 4], int corner_radius,
enum corner_location corner_location); enum corner_location corner_location);
void render_container(struct sway_output *output,
pixman_region32_t *damage, struct sway_container *con, bool parent_focused);
void premultiply_alpha(float color[4], float opacity); void premultiply_alpha(float color[4], float opacity);
void scale_box(struct wlr_box *box, float scale); void scale_box(struct wlr_box *box, float scale);

View file

@ -380,7 +380,4 @@ void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx);
bool gaps_to_edge(struct sway_view *view); bool gaps_to_edge(struct sway_view *view);
void view_container_cleanup(struct sway_view *view);
#endif #endif

View file

@ -273,7 +273,6 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl, struct wlr_output *w
sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not make EGL current"); sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not make EGL current");
return NULL; return NULL;
} }
renderer->wlr_egl = egl;
renderer->wlr_buffer = fx_framebuffer_create(); renderer->wlr_buffer = fx_framebuffer_create();
renderer->blur_buffer = fx_framebuffer_create(); renderer->blur_buffer = fx_framebuffer_create();
@ -877,57 +876,3 @@ void fx_render_blur(struct fx_renderer *renderer, const float matrix[static 9],
glDisableVertexAttribArray(shader->pos_attrib); glDisableVertexAttribArray(shader->pos_attrib);
glDisableVertexAttribArray(shader->tex_attrib); glDisableVertexAttribArray(shader->tex_attrib);
} }
void fx_render_container_snapshot(struct fx_renderer *renderer, struct sway_container *con) {
// TODO: move create_deco_data
// TODO: render without blur?
struct decoration_data deco_data = {
.alpha = 1.0f,
.dim = 0.0f,
.dim_color = config->dim_inactive_colors.unfocused,
.corner_radius = 0,
.saturation = 1.0f,
.has_titlebar = false,
.blur = false,
.discard_transparent = false,
.shadow = false,
};
struct sway_output *output = con->pending.workspace->output;
struct wlr_box dst_box = { 0, 0, output->width, output->height };
enum wl_output_transform transform = wlr_output_transform_invert(output->wlr_output->transform);
float matrix[9];
wlr_matrix_project_box(matrix, &dst_box, transform, 0.0, output->wlr_output->transform_matrix);
fx_render_texture_with_matrix(renderer, &con->close_animation_fb.texture, &dst_box, matrix, deco_data);
}
void fx_create_container_snapshot(struct fx_renderer *renderer, struct sway_container *con) {
assert(con);
// TODO: move to function? used in creation too
if (!eglMakeCurrent(wlr_egl_get_display(renderer->wlr_egl), EGL_NO_SURFACE, EGL_NO_SURFACE,
wlr_egl_get_context(renderer->wlr_egl))) {
sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not make EGL current");
return;
}
struct sway_output *output = con->pending.workspace->output;
fx_framebuffer_update(&con->close_animation_fb, output->width, output->height);
fx_framebuffer_bind(&con->close_animation_fb);
// damage whole output to ensure full container is rendered
// (temporary, render_container will only render container area)
struct wlr_box box = { 0, 0, output->width, output->height };
scale_box(&box, output->wlr_output->scale);
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_union_rect(&damage, &damage, box.x, box.y, box.width, box.height);
// render container instead?
fx_render_container_snapshot(renderer, con);
// rebind the main fb
fx_framebuffer_bind(&renderer->wlr_buffer);
printf("snapshot created\n");
}

View file

@ -765,6 +765,7 @@ static void render_view_popups(struct sway_view *view, struct sway_output *outpu
static void render_saved_view(struct sway_view *view, struct sway_output *output, static void render_saved_view(struct sway_view *view, struct sway_output *output,
pixman_region32_t *damage, struct decoration_data deco_data) { pixman_region32_t *damage, struct decoration_data deco_data) {
printf("rendering saved view\n");
struct wlr_output *wlr_output = output->wlr_output; struct wlr_output *wlr_output = output->wlr_output;
if (wl_list_empty(&view->saved_buffers)) { if (wl_list_empty(&view->saved_buffers)) {
@ -873,8 +874,11 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
// render view // render view
if (!wl_list_empty(&view->saved_buffers)) { if (!wl_list_empty(&view->saved_buffers)) {
printf("rendering saved view\n");
render_saved_view(view, output, damage, deco_data); render_saved_view(view, output, damage, deco_data);
} else if (view->surface) { } else if (view->surface) {
printf("rendering view toplevels\n");
render_view_toplevels(view, output, damage, deco_data); render_view_toplevels(view, output, damage, deco_data);
} }
@ -1398,6 +1402,9 @@ struct parent_data {
struct sway_container *active_child; struct sway_container *active_child;
}; };
static void render_container(struct sway_output *output,
pixman_region32_t *damage, struct sway_container *con, bool parent_focused);
/** /**
* Render a container's children using a L_HORIZ or L_VERT layout. * Render a container's children using a L_HORIZ or L_VERT layout.
* *
@ -1684,12 +1691,6 @@ static void render_containers(struct sway_output *output,
void render_container(struct sway_output *output, void render_container(struct sway_output *output,
pixman_region32_t *damage, struct sway_container *con, bool focused) { pixman_region32_t *damage, struct sway_container *con, bool focused) {
if (con->is_fading_out) {
printf("rendering snapshot\n");
fx_render_container_snapshot(output->renderer, con);
return;
}
struct parent_data data = { struct parent_data data = {
.layout = con->current.layout, .layout = con->current.layout,
.box = { .box = {
@ -1805,6 +1806,7 @@ void output_render(struct sway_output *output, struct timespec *when,
struct wlr_output *wlr_output = output->wlr_output; struct wlr_output *wlr_output = output->wlr_output;
struct fx_renderer *renderer = output->renderer; struct fx_renderer *renderer = output->renderer;
printf("rendering output\n");
struct sway_workspace *workspace = output->current.active_workspace; struct sway_workspace *workspace = output->current.active_workspace;
if (workspace == NULL) { if (workspace == NULL) {
return; return;
@ -1983,6 +1985,7 @@ void output_render(struct sway_output *output, struct timespec *when,
render_output_blur(output, damage); render_output_blur(output, damage);
} }
printf("rendering workspace\n");
render_workspace(output, damage, workspace, workspace->current.focused); render_workspace(output, damage, workspace, workspace->current.focused);
render_floating(output, damage); render_floating(output, damage);
#if HAVE_XWAYLAND #if HAVE_XWAYLAND

View file

@ -256,7 +256,7 @@ static void apply_container_state(struct sway_container *container,
memcpy(&container->current, state, sizeof(struct sway_container_state)); memcpy(&container->current, state, sizeof(struct sway_container_state));
if (view && !wl_list_empty(&view->saved_buffers)) { if (view && !wl_list_empty(&view->saved_buffers) && !container->is_fading_out) {
if (!container->node.destroying || container->node.ntxnrefs == 1) { if (!container->node.destroying || container->node.ntxnrefs == 1) {
view_remove_saved_buffer(view); view_remove_saved_buffer(view);
} }
@ -401,6 +401,7 @@ static void transaction_commit(struct sway_transaction *transaction) {
for (int i = 0; i < transaction->instructions->length; ++i) { for (int i = 0; i < transaction->instructions->length; ++i) {
struct sway_transaction_instruction *instruction = struct sway_transaction_instruction *instruction =
transaction->instructions->items[i]; transaction->instructions->items[i];
printf("processing instruction for %s\n", instruction->node->sway_container->title);
struct sway_node *node = instruction->node; struct sway_node *node = instruction->node;
bool hidden = node_is_view(node) && !node->destroying && bool hidden = node_is_view(node) && !node->destroying &&
!view_is_visible(node->sway_container->view); !view_is_visible(node->sway_container->view);
@ -426,6 +427,7 @@ static void transaction_commit(struct sway_transaction *transaction) {
} }
if (!hidden && node_is_view(node) && if (!hidden && node_is_view(node) &&
wl_list_empty(&node->sway_container->view->saved_buffers)) { wl_list_empty(&node->sway_container->view->saved_buffers)) {
printf("saving buffer\n");
view_save_buffer(node->sway_container->view); view_save_buffer(node->sway_container->view);
memcpy(&node->sway_container->view->saved_geometry, memcpy(&node->sway_container->view->saved_geometry,
&node->sway_container->view->geometry, &node->sway_container->view->geometry,
@ -523,6 +525,7 @@ void transaction_notify_view_ready_by_geometry(struct sway_view *view,
static void _transaction_commit_dirty(bool server_request) { static void _transaction_commit_dirty(bool server_request) {
if (!server.dirty_nodes->length) { if (!server.dirty_nodes->length) {
printf("no dirty nodes\n");
return; return;
} }
@ -540,6 +543,7 @@ static void _transaction_commit_dirty(bool server_request) {
} }
server.dirty_nodes->length = 0; server.dirty_nodes->length = 0;
printf("committing pending transaction\n");
transaction_commit_pending(); transaction_commit_pending();
} }

View file

@ -507,6 +507,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
} }
static void handle_destroy(struct wl_listener *listener, void *data) { static void handle_destroy(struct wl_listener *listener, void *data) {
/*
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, destroy); wl_container_of(listener, xdg_shell_view, destroy);
struct sway_view *view = &xdg_shell_view->view; struct sway_view *view = &xdg_shell_view->view;
@ -521,6 +522,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
view->xdg_decoration->view = NULL; view->xdg_decoration->view = NULL;
} }
view_begin_destroy(view); view_begin_destroy(view);
*/
} }
struct sway_view *view_from_wlr_xdg_surface( struct sway_view *view_from_wlr_xdg_surface(

View file

@ -52,8 +52,7 @@ static int animation_timer(void *data) {
wl_event_source_timer_update(con->animation_present_timer, fastest_output_refresh_s * 1000); wl_event_source_timer_update(con->animation_present_timer, fastest_output_refresh_s * 1000);
} else if (is_closing) { // equal to target and closing } else if (is_closing) { // equal to target and closing
printf("done animation; clean up view\n"); printf("done animation; clean up view\n");
con->is_fading_out = false; //con->is_fading_out = false;
view_container_cleanup(con->view);
return 1; return 1;
} }
@ -130,13 +129,10 @@ void container_destroy(struct sway_container *con) {
wl_event_source_remove(con->animation_present_timer); wl_event_source_remove(con->animation_present_timer);
printf("alive 0\n");
if (con->view && con->view->container == con) { if (con->view && con->view->container == con) {
con->view->container = NULL; con->view->container = NULL;
if (con->view->destroying) { if (con->view->destroying) {
printf("alive\n");
view_destroy(con->view); view_destroy(con->view);
printf("alive 2\n");
} }
} }
@ -145,7 +141,6 @@ void container_destroy(struct sway_container *con) {
void container_begin_destroy(struct sway_container *con) { void container_begin_destroy(struct sway_container *con) {
printf("container begin destroy\n"); printf("container begin destroy\n");
// TODO; better way of deleting view
if (con->view && !con->is_fading_out) { if (con->view && !con->is_fading_out) {
ipc_event_window(con, "close"); ipc_event_window(con, "close");
} }
@ -158,8 +153,6 @@ void container_begin_destroy(struct sway_container *con) {
container_fullscreen_disable(con); container_fullscreen_disable(con);
} }
// TODO: problem here
printf("about to emit signal\n");
wl_signal_emit_mutable(&con->node.events.destroy, &con->node); wl_signal_emit_mutable(&con->node.events.destroy, &con->node);
container_end_mouse_operation(con); container_end_mouse_operation(con);
@ -236,6 +229,9 @@ static struct sway_container *surface_at_view(struct sway_container *con, double
return NULL; return NULL;
} }
struct sway_view *view = con->view; struct sway_view *view = con->view;
if (con->is_fading_out) {
return NULL;
}
double view_sx = lx - con->surface_x + view->geometry.x; double view_sx = lx - con->surface_x + view->geometry.x;
double view_sy = ly - con->surface_y + view->geometry.y; double view_sy = ly - con->surface_y + view->geometry.y;

View file

@ -46,6 +46,7 @@ void view_init(struct sway_view *view, enum sway_view_type type,
} }
void view_destroy(struct sway_view *view) { void view_destroy(struct sway_view *view) {
printf("view destroy\n");
if (!sway_assert(view->surface == NULL, "Tried to free mapped view")) { if (!sway_assert(view->surface == NULL, "Tried to free mapped view")) {
return; return;
} }
@ -76,6 +77,7 @@ void view_destroy(struct sway_view *view) {
} }
void view_begin_destroy(struct sway_view *view) { void view_begin_destroy(struct sway_view *view) {
printf("view begin destroy\n");
if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) { if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) {
return; return;
} }
@ -906,9 +908,13 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
} }
} }
void view_container_cleanup(struct sway_view *view) { void view_unmap(struct sway_view *view) {
printf("unmapping view\n");
wl_signal_emit_mutable(&view->events.unmap, view);
wl_list_remove(&view->surface_new_subsurface.link); wl_list_remove(&view->surface_new_subsurface.link);
/*
if (view->urgent_timer) { if (view->urgent_timer) {
wl_event_source_remove(view->urgent_timer); wl_event_source_remove(view->urgent_timer);
view->urgent_timer = NULL; view->urgent_timer = NULL;
@ -935,7 +941,7 @@ void view_container_cleanup(struct sway_view *view) {
arrange_workspace(ws); arrange_workspace(ws);
workspace_detect_urgent(ws); workspace_detect_urgent(ws);
} }
*/
struct sway_seat *seat; struct sway_seat *seat;
wl_list_for_each(seat, &server.input->seats, link) { wl_list_for_each(seat, &server.input->seats, link) {
seat->cursor->image_surface = NULL; seat->cursor->image_surface = NULL;
@ -949,24 +955,14 @@ void view_container_cleanup(struct sway_view *view) {
seat_consider_warp_to_focus(seat); seat_consider_warp_to_focus(seat);
} }
node_set_dirty(&view->container->node);
view->container->is_fading_out = true;
view->container->target_alpha = 0;
wl_event_source_timer_update(view->container->animation_present_timer, 50);
transaction_commit_dirty(); transaction_commit_dirty();
view->surface = NULL; view->surface = NULL;
} }
void view_unmap(struct sway_view *view) {
wl_signal_emit_mutable(&view->events.unmap, view);
struct sway_workspace *ws = view->container->pending.workspace;
if (ws && config->animation_duration > 0) {
printf("starting fade out animation\n");
view->container->is_fading_out = true;
fx_render_container_snapshot(ws->output->renderer, view->container);
view->container->target_alpha = 0;
wl_event_source_timer_update(view->container->animation_present_timer, 50);
} else {
view_container_cleanup(view);
}
}
void view_update_size(struct sway_view *view) { void view_update_size(struct sway_view *view) {
struct sway_container *con = view->container; struct sway_container *con = view->container;
con->pending.content_width = view->geometry.width; con->pending.content_width = view->geometry.width;