diff --git a/include/scenefx/types/fx/blur_data.h b/include/scenefx/types/fx/blur_data.h index 5afda75..e6a7c29 100644 --- a/include/scenefx/types/fx/blur_data.h +++ b/include/scenefx/types/fx/blur_data.h @@ -15,8 +15,6 @@ struct blur_data { struct blur_data blur_data_get_default(void); -bool scene_buffer_should_blur(bool backdrop_blur, struct blur_data *blur_data); - bool blur_data_should_parameters_blur_effects(struct blur_data *blur_data); bool blur_data_cmp(struct blur_data *a, struct blur_data *b); diff --git a/include/scenefx/types/fx/shadow_data.h b/include/scenefx/types/fx/shadow_data.h index 4982078..d96a084 100644 --- a/include/scenefx/types/fx/shadow_data.h +++ b/include/scenefx/types/fx/shadow_data.h @@ -1,5 +1,5 @@ -#ifndef TYPES_FX_SHADOW_DATA_H -#define TYPES_FX_SHADOW_DATA_H +#ifndef TYPES_DECORATION_DATA +#define TYPES_DECORATION_DATA #include #include diff --git a/include/scenefx/types/wlr_scene.h b/include/scenefx/types/wlr_scene.h index 4af8a7f..5925931 100644 --- a/include/scenefx/types/wlr_scene.h +++ b/include/scenefx/types/wlr_scene.h @@ -21,7 +21,6 @@ #include #include "scenefx/types/fx/shadow_data.h" -#include "scenefx/types/fx/blur_data.h" #include #include #include @@ -112,8 +111,6 @@ struct wlr_scene { enum wlr_scene_debug_damage_option debug_damage_option; bool direct_scanout; bool calculate_visibility; - - struct blur_data blur_data; }; /** A scene-graph node displaying a single surface. */ @@ -179,13 +176,10 @@ struct wlr_scene_buffer { */ struct wlr_scene_output *primary_output; + float opacity; int corner_radius; struct shadow_data shadow_data; - bool backdrop_blur; - bool backdrop_blur_optimized; - bool backdrop_blur_ignore_transparent; - float opacity; enum wlr_scale_filter_mode filter_mode; struct wlr_fbox src_box; int dst_width, dst_height; @@ -320,9 +314,6 @@ struct wlr_scene *wlr_scene_create(void); void wlr_scene_set_presentation(struct wlr_scene *scene, struct wlr_presentation *presentation); -/** Sets the global blur parameters */ -void wlr_scene_set_blur_data(struct wlr_scene *scene, struct blur_data blur_data); - /** * Handles linux_dmabuf_v1 feedback for all surfaces in the scene. * @@ -471,34 +462,6 @@ void wlr_scene_buffer_set_corner_radius(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_set_shadow_data(struct wlr_scene_buffer *scene_buffer, struct shadow_data shadow_data); -/** -* Sets the whether or not the buffer should render backdrop blur -*/ -void wlr_scene_buffer_set_backdrop_blur(struct wlr_scene_buffer *scene_buffer, - bool enabled); - -/** -* Sets the whether the backdrop blur should use optimized blur or not -*/ -void wlr_scene_buffer_set_backdrop_blur_optimized(struct wlr_scene_buffer *scene_buffer, - bool enabled); - -/** -* Sets the whether the backdrop blur should not render in fully transparent -* segments. -*/ -void wlr_scene_buffer_set_backdrop_blur_ignore_transparent( - struct wlr_scene_buffer *scene_buffer, bool enabled); - -/** - * Tells the renderer to re-render the optimized blur. Very expensive so should - * only be called when needed. - * - * An example use would be to call this when a "static" node changes, like a - * wallpaper. - */ -void wlr_scene_optimized_blur_mark_dirty(struct wlr_scene *scene); - /** * Calls the buffer's frame_done signal. */ diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 32488f6..994574f 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -557,6 +557,50 @@ static void server_cursor_frame(struct wl_listener *listener, void *data) { wlr_seat_pointer_notify_frame(server->seat); } +static void output_configure_scene(struct wlr_scene_node *node, + struct tinywl_toplevel *toplevel) { + if (!node->enabled) { + return; + } + + struct tinywl_toplevel *_toplevel = node->data; + if (_toplevel) { + toplevel = _toplevel; + } + + if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); + + struct wlr_scene_surface * scene_surface = + wlr_scene_surface_try_from_buffer(buffer); + if (!scene_surface) { + return; + } + + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); + + if (toplevel && + xdg_surface && + xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { + // TODO: Be able to set whole decoration_data instead of calling + // each individually? + wlr_scene_buffer_set_opacity(buffer, toplevel->opacity); + + if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { + wlr_scene_buffer_set_corner_radius(buffer, toplevel->corner_radius); + wlr_scene_buffer_set_shadow_data(buffer, toplevel->shadow_data); + } + } + } else if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *tree = wl_container_of(node, tree, node); + struct wlr_scene_node *node; + wl_list_for_each(node, &tree->children, link) { + output_configure_scene(node, toplevel); + } + } +} + static void output_frame(struct wl_listener *listener, void *data) { /* This function is called every time an output is ready to display a frame, * generally at the output's refresh rate (e.g. 60Hz). */ @@ -566,6 +610,8 @@ static void output_frame(struct wl_listener *listener, void *data) { struct wlr_scene_output *scene_output = wlr_scene_get_scene_output( scene, output->wlr_output); + output_configure_scene(&scene_output->scene->tree.node, NULL); + /* Render the scene if needed and commit the output */ wlr_scene_output_commit(scene_output, NULL); @@ -657,42 +703,10 @@ static void server_new_output(struct wl_listener *listener, void *data) { wlr_scene_output_layout_add_output(server->scene_layout, l_output, scene_output); } -static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, - int sy, void *user_data) { - struct tinywl_toplevel *toplevel = user_data; - - struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); - if (!scene_surface) { - return; - } - - struct wlr_xdg_surface *xdg_surface = - wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); - if (toplevel && - xdg_surface && - xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { - // TODO: Be able to set whole decoration_data instead of calling - // each individually? - wlr_scene_buffer_set_opacity(buffer, toplevel->opacity); - - if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { - wlr_scene_buffer_set_corner_radius(buffer, toplevel->corner_radius); - wlr_scene_buffer_set_shadow_data(buffer, toplevel->shadow_data); - - wlr_scene_buffer_set_backdrop_blur(buffer, true); - wlr_scene_buffer_set_backdrop_blur_optimized(buffer, false); - wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true); - } - } -} - static void xdg_toplevel_map(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, map); - wlr_scene_node_for_each_buffer(&toplevel->scene_tree->node, - iter_xdg_scene_buffers, toplevel); - wl_list_insert(&toplevel->server->toplevels, &toplevel->link); focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface); diff --git a/types/fx/blur_data.c b/types/fx/blur_data.c index 0458cea..3aa618b 100644 --- a/types/fx/blur_data.c +++ b/types/fx/blur_data.c @@ -11,10 +11,6 @@ struct blur_data blur_data_get_default(void) { }; } -bool scene_buffer_should_blur(bool backdrop_blur, struct blur_data *blur_data) { - return backdrop_blur && blur_data->radius > 0 && blur_data->num_passes > 0; -} - bool blur_data_should_parameters_blur_effects(struct blur_data *blur_data) { return blur_data->brightness != 1.0f || blur_data->saturation != 1.0f diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 2121a27..f0f00c3 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -17,8 +17,6 @@ #include #include "render/pass.h" -#include "render/fx_renderer/fx_renderer.h" -#include "scenefx/types/fx/blur_data.h" #include "scenefx/types/fx/shadow_data.h" #include "types/wlr_buffer.h" #include "types/wlr_output.h" @@ -178,8 +176,6 @@ struct wlr_scene *wlr_scene_create(void) { scene->direct_scanout = !env_parse_bool("WLR_SCENE_DISABLE_DIRECT_SCANOUT"); scene->calculate_visibility = !env_parse_bool("WLR_SCENE_DISABLE_VISIBILITY"); - scene->blur_data = blur_data_get_default(); - return scene; } @@ -648,12 +644,8 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, wl_signal_init(&scene_buffer->events.frame_done); pixman_region32_init(&scene_buffer->opaque_region); scene_buffer->opacity = 1; - scene_buffer->corner_radius = 0; scene_buffer->shadow_data = shadow_data_get_default(); - scene_buffer->backdrop_blur = false; - scene_buffer->backdrop_blur_optimized = false; - scene_buffer->backdrop_blur_ignore_transparent = true; scene_node_update(&scene_buffer->node, NULL); @@ -901,45 +893,6 @@ void wlr_scene_buffer_set_shadow_data(struct wlr_scene_buffer *scene_buffer, scene_node_update(&scene_buffer->node, NULL); } -void wlr_scene_buffer_set_backdrop_blur(struct wlr_scene_buffer *scene_buffer, - bool enabled) { - if (scene_buffer->backdrop_blur != enabled) { - scene_buffer->backdrop_blur = enabled; - wlr_scene_optimized_blur_mark_dirty(scene_node_get_root(&scene_buffer->node)); - } -} - -void wlr_scene_buffer_set_backdrop_blur_optimized(struct wlr_scene_buffer *scene_buffer, - bool enabled) { - if (scene_buffer->backdrop_blur_optimized != enabled) { - scene_buffer->backdrop_blur_optimized = enabled; - wlr_scene_optimized_blur_mark_dirty(scene_node_get_root(&scene_buffer->node)); - } -} - -void wlr_scene_buffer_set_backdrop_blur_ignore_transparent( - struct wlr_scene_buffer *scene_buffer, bool enabled) { - if (scene_buffer->backdrop_blur_ignore_transparent != enabled) { - scene_buffer->backdrop_blur_ignore_transparent = enabled; - wlr_scene_optimized_blur_mark_dirty(scene_node_get_root(&scene_buffer->node)); - } -} - -static void output_optimized_blur_mark_dirty(struct wlr_output *output) { - struct fx_renderer *renderer = fx_get_renderer(output->renderer); - renderer->blur_buffer_dirty = true; -} - -void wlr_scene_optimized_blur_mark_dirty(struct wlr_scene *scene) { - // Mark the blur buffers as dirty - struct wlr_scene_output *current_output; - wl_list_for_each(current_output, &scene->outputs, link) { - struct wlr_output *output = current_output->output; - output_optimized_blur_mark_dirty(output); - } - scene_node_update(&scene->tree.node, NULL); -} - static struct wlr_texture *scene_buffer_get_texture( struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) { struct wlr_client_buffer *client_buffer = @@ -1221,8 +1174,7 @@ static void clip_xdg(struct wlr_scene_node *node, // Don't clip if the scene buffer doesn't have any effects if (!scene_buffer || (scene_buffer->corner_radius == 0 && - !scene_buffer_has_shadow(&scene_buffer->shadow_data) && - !scene_buffer->backdrop_blur)) { + !scene_buffer_has_shadow(&scene_buffer->shadow_data))) { return; } @@ -1348,51 +1300,6 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren .discard_transparent = false, }; - // Blur - struct wlr_scene *scene = data->output->scene; - if (scene_buffer_should_blur(scene_buffer->backdrop_blur, &scene->blur_data)) { - pixman_region32_t opaque_region; - pixman_region32_init(&opaque_region); - - bool has_alpha = false; - if (scene_buffer->opacity < 1.0) { - has_alpha = true; - pixman_region32_union_rect(&opaque_region, &opaque_region, 0, 0, 0, 0); - } else { - struct wlr_scene_surface *scene_surface - = wlr_scene_surface_try_from_buffer(scene_buffer); - has_alpha = !scene_surface->surface->opaque; - pixman_region32_copy(&opaque_region, &scene_surface->surface->opaque_region); - } - - if (has_alpha) { - struct wlr_output *output = data->output->output; - int width, height; - wlr_output_transformed_resolution(output, &width, &height); - struct wlr_box monitor_box = { 0, 0, width, height }; - wlr_box_transform(&monitor_box, &monitor_box, - wlr_output_transform_invert(output->transform), - monitor_box.width, monitor_box.height); - struct fx_render_blur_pass_options blur_options = { - .tex_options = tex_options, - .scene_buffer = scene_buffer, - .output = output, - .monitor_box = monitor_box, - .blur_data = &scene->blur_data, - .ignore_transparent = scene_buffer->backdrop_blur_ignore_transparent, - }; - // Re-render the optimized blur buffer when needed - if (data->render_pass->buffer->renderer->blur_buffer_dirty - && scene_buffer->backdrop_blur_optimized) { - fx_render_pass_add_optimized_blur(data->render_pass, &blur_options); - } - // Render the actual blur behind the surface - fx_render_pass_add_blur(data->render_pass, &blur_options); - - } - pixman_region32_fini(&opaque_region); - } - // Shadow if (scene_buffer_has_shadow(&scene_buffer->shadow_data)) { struct fx_render_rect_options shadow_options = { @@ -1439,22 +1346,6 @@ void wlr_scene_set_presentation(struct wlr_scene *scene, wl_signal_add(&presentation->events.destroy, &scene->presentation_destroy); } -void wlr_scene_set_blur_data(struct wlr_scene *scene, struct blur_data blur_data) { - struct blur_data *buff_data = &scene->blur_data; - if (blur_data_cmp(buff_data, &blur_data)) { - return; - } - - memcpy(&scene->blur_data, &blur_data, - sizeof(struct blur_data)); - - wlr_scene_optimized_blur_mark_dirty(scene); -} - -static bool wlr_scene_should_blur(struct wlr_scene *scene) { - return scene->blur_data.radius > 0 && scene->blur_data.num_passes > 0; -} - static void scene_handle_linux_dmabuf_v1_destroy(struct wl_listener *listener, void *data) { struct wlr_scene *scene = @@ -1503,9 +1394,6 @@ static void scene_output_update_geometry(struct wlr_scene_output *scene_output, wlr_damage_ring_add_whole(&scene_output->damage_ring); wlr_output_schedule_frame(scene_output->output); - // Re-render the optimized blur when the output is changed - output_optimized_blur_mark_dirty(scene_output->output); - scene_node_output_update(&scene_output->scene->tree.node, &scene_output->scene->outputs, NULL, force_update ? scene_output : NULL); } @@ -1847,54 +1735,6 @@ static bool scene_entry_try_direct_scanout(struct render_list_entry *entry, return true; } -struct blur_info { - bool has_blur; - bool has_optimized; -}; - -static struct blur_info workspace_get_blur_info(int list_len, - struct render_list_entry *list_data, struct wlr_scene_output *scene_output, - pixman_region32_t *blur_region) { - if (!wlr_scene_should_blur(scene_output->scene)) { - return (struct blur_info) { - .has_blur = false, - .has_optimized = false, - }; - } - - bool has_optimized = false; - for (int i = list_len - 1; i >= 0; i--) { - struct wlr_scene_node *node = list_data[i].node; - switch (node->type) { - case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_try_from_buffer(scene_buffer); - assert(scene_buffer->buffer); - if (scene_buffer->backdrop_blur && scene_surface && - !scene_surface->surface->opaque) { - int x, y; - wlr_scene_node_coords(node, &x, &y); - pixman_region32_union_rect(blur_region, blur_region, - (x - scene_output->x) * scene_output->output->scale, - (y - scene_output->y) * scene_output->output->scale, - scene_buffer->dst_width * scene_output->output->scale, - scene_buffer->dst_height * scene_output->output->scale); - if (scene_buffer->backdrop_blur_optimized) { - has_optimized = true; - } - } - break; - default: - break; - } - } - return (struct blur_info) { - .has_blur = pixman_region32_not_empty(blur_region), - .has_optimized = has_optimized, - }; -} - bool wlr_scene_output_commit(struct wlr_scene_output *scene_output, const struct wlr_scene_output_state_options *options) { if (!scene_output->output->needs_frame && !pixman_region32_not_empty( @@ -2080,7 +1920,6 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, timer->pre_render_duration = timespec_to_nsec(&duration); } - struct fx_renderer *renderer = fx_get_renderer(output->renderer); struct fx_gles_render_pass *render_pass = fx_renderer_begin_buffer_pass(output->renderer, buffer, output, &(struct wlr_buffer_pass_options) { @@ -2097,61 +1936,6 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, wlr_damage_ring_get_buffer_damage(&scene_output->damage_ring, buffer_age, &render_data.damage); - // Blur artifact prevention - pixman_region32_t *damage = &render_data.damage; - pixman_region32_t blur_region; - pixman_region32_init(&blur_region); - struct blur_info blur_info = - workspace_get_blur_info(list_len, list_data, scene_output, &blur_region); - // Expand the damage to compensate for blur - if (blur_info.has_blur) { - // Skip the blur artifact prevention if damaging the whole viewport - if (renderer->blur_buffer_dirty) { - // Needs to be extended before clearing - pixman_region32_union_rect(&render_data.damage, &render_data.damage, - 0, 0, output->width, output->height); - } else { - // copy the surrounding content where the blur would display artifacts - // and draw it above the artifacts - struct blur_data *blur_data = &scene_output->scene->blur_data; - int output_width, output_height; - wlr_output_transformed_resolution(output, &output_width, &output_height); - - // ensure that the damage isn't expanding past the output's size - int32_t damage_width = damage->extents.x2 - damage->extents.x1; - int32_t damage_height = damage->extents.y2 - damage->extents.y1; - if (damage_width > output_width || damage_height > output_height) { - pixman_region32_intersect_rect(damage, damage, - 0, 0, output_width, output_height); - } else { - // Expand the original damage to compensate for surrounding - // blurred views to avoid sharp edges between damage regions - wlr_region_expand(damage, damage, blur_data_calc_size(blur_data)); - } - - pixman_region32_t extended_damage; - pixman_region32_init(&extended_damage); - pixman_region32_intersect(&extended_damage, damage, &blur_region); - // Expand the region to compensate for blur artifacts - wlr_region_expand(&extended_damage, &extended_damage, blur_data_calc_size(blur_data)); - // Limit to the monitors viewport - pixman_region32_intersect_rect(&extended_damage, &extended_damage, - 0, 0, output_width, output_height); - - // capture the padding pixels around the blur where artifacts will be drawn - pixman_region32_subtract(&renderer->blur_padding_region, - &extended_damage, damage); - // Combine into the surface damage (we need to redraw the padding area as well) - pixman_region32_union(damage, damage, &extended_damage); - pixman_region32_fini(&extended_damage); - - // Capture the padding pixels before blur for later use - fx_renderer_read_to_buffer(render_pass, &renderer->blur_padding_region, - renderer->blur_saved_pixels_buffer, render_pass->buffer); - } - } - pixman_region32_fini(&blur_region); - pixman_region32_t background; pixman_region32_init(&background); pixman_region32_copy(&background, &render_data.damage); @@ -2214,14 +1998,6 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, } } - // Not needed if we damaged the whole viewport - if (!renderer->blur_buffer_dirty) { - // TODO: Investigate blitting instead - // Render the saved pixels over the blur artifacts - fx_renderer_read_to_buffer(render_pass, &renderer->blur_padding_region, - render_pass->buffer, renderer->blur_saved_pixels_buffer); - } - if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { struct highlight_region *damage; wl_list_for_each(damage, &scene_output->damage_highlight_regions, link) {