Skip to content

Commit

Permalink
Add wlr_scene blur impl
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikReider committed Feb 27, 2024
1 parent 7f0883b commit f86ae3e
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 65 deletions.
2 changes: 2 additions & 0 deletions include/scenefx/types/fx/blur_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ 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);
Expand Down
4 changes: 2 additions & 2 deletions include/scenefx/types/fx/shadow_data.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef TYPES_DECORATION_DATA
#define TYPES_DECORATION_DATA
#ifndef TYPES_SHADOW_DATA_H
#define TYPES_SHADOW_DATA_H

#include <stdbool.h>
#include <wlr/util/addon.h>
Expand Down
42 changes: 40 additions & 2 deletions include/scenefx/types/wlr_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
*/

#include <pixman.h>
#include "scenefx/types/fx/shadow_data.h"
#include <time.h>
#include <wayland-server-core.h>
#include <wlr/render/wlr_renderer.h>
Expand All @@ -29,6 +28,9 @@
#include <wlr/util/addon.h>
#include <wlr/util/box.h>

#include "scenefx/types/fx/shadow_data.h"
#include "scenefx/types/fx/blur_data.h"

struct wlr_output;
struct wlr_output_layout;
struct wlr_output_layout_output;
Expand Down Expand Up @@ -111,6 +113,8 @@ 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. */
Expand Down Expand Up @@ -176,10 +180,13 @@ 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;
Expand Down Expand Up @@ -314,6 +321,9 @@ 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.
*
Expand Down Expand Up @@ -462,6 +472,34 @@ 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.
*/
Expand Down
1 change: 1 addition & 0 deletions render/fx_renderer/fx_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ void fx_render_pass_add_blur(struct fx_gles_render_pass *pass,

struct fx_framebuffer *buffer = renderer->optimized_blur_buffer;
if (!buffer || !fx_options->use_optimized_blur) {
return;
pixman_region32_translate(&translucent_region, dst_box.x, dst_box.y);
pixman_region32_intersect(&translucent_region, &translucent_region, options->clip);

Expand Down
78 changes: 32 additions & 46 deletions tinywl/tinywl.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,50 +557,6 @@ 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). */
Expand All @@ -610,8 +566,6 @@ 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);

Expand Down Expand Up @@ -703,10 +657,42 @@ 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);
Expand Down
4 changes: 4 additions & 0 deletions types/fx/blur_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ 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
Expand Down
Loading

0 comments on commit f86ae3e

Please sign in to comment.