Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/render/fx_renderer/shaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ struct tex_shader {
GLint radius_bottom_right;

GLint discard_transparent;

GLint clip_size;
GLint clip_position;
GLint clip_radius_top_left;
GLint clip_radius_top_right;
GLint clip_radius_bottom_left;
GLint clip_radius_bottom_right;
};

bool link_tex_program(struct tex_shader *shader, GLint client_version, enum fx_tex_shader_source source);
Expand Down
4 changes: 4 additions & 0 deletions include/scenefx/render/pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct fx_render_texture_options {
enum corner_location corners;
int corner_radius;
bool discard_transparent;
struct clipped_region clipped_region;
};

struct fx_render_rect_options {
Expand Down Expand Up @@ -103,6 +104,9 @@ struct fx_render_blur_pass_options {
bool use_optimized_blur;
bool ignore_transparent;
float blur_strength;
int corner_radius;
enum corner_location corners;
struct clipped_region clipped_region;
};

/**
Expand Down
33 changes: 33 additions & 0 deletions include/scenefx/types/linked_node.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef TYPES_LINKED_NODES_H
#include <stdbool.h>
#define TYPES_LINKED_NODES_H

/**
* A node in a link between two objects. Can be used to safely couple two
* objects together.
*/
struct linked_node {
struct link *link;
};

#define linked_node_init() \
((struct linked_node) { \
.link = NULL \
})

bool linked_nodes_are_linked(struct linked_node *node_1,
struct linked_node *node_2);

void linked_node_init_link(struct linked_node *main_node,
struct linked_node *reference_node);

struct linked_node *linked_nodes_get_sibling(struct linked_node *node);

void linked_node_orphan(struct linked_node *node);

void linked_node_unlink(struct linked_node *main_node,
struct linked_node *reference_node);

void linked_node_destroy(struct linked_node *node);

#endif
172 changes: 89 additions & 83 deletions include/scenefx/types/wlr_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "scenefx/types/fx/blur_data.h"
#include "scenefx/types/fx/clipped_region.h"
#include "scenefx/types/fx/corner_location.h"
#include "scenefx/types/linked_node.h"

struct wlr_output;
struct wlr_output_layout;
Expand Down Expand Up @@ -60,6 +61,7 @@ enum wlr_scene_node_type {
WLR_SCENE_NODE_SHADOW,
WLR_SCENE_NODE_BUFFER,
WLR_SCENE_NODE_OPTIMIZED_BLUR,
WLR_SCENE_NODE_BLUR,
};

/** A node is an object in the scene. */
Expand Down Expand Up @@ -149,10 +151,6 @@ struct wlr_scene_rect {
float color[4];
int corner_radius;
enum corner_location corners;
bool backdrop_blur;
bool backdrop_blur_optimized;
float backdrop_blur_strength;
float backdrop_blur_alpha;

bool accepts_input;
struct clipped_region clipped_region;
Expand All @@ -169,6 +167,22 @@ struct wlr_scene_shadow {
struct clipped_region clipped_region;
};

struct wlr_scene_blur {
struct wlr_scene_node node;
int width, height;
int corner_radius;

enum corner_location corners;
struct clipped_region clipped_region;

float strength;
float alpha;

bool should_only_blur_bottom_layer;

struct linked_node transparency_mask_source;
};

/** A scene-graph node telling SceneFX to render the optimized blur */
struct wlr_scene_optimized_blur {
struct wlr_scene_node node;
Expand Down Expand Up @@ -214,11 +228,6 @@ struct wlr_scene_buffer {
struct wlr_scene_output *primary_output;

int corner_radius;
bool backdrop_blur;
bool backdrop_blur_optimized;
bool backdrop_blur_ignore_transparent;
float backdrop_blur_strength;
float backdrop_blur_alpha;
enum corner_location corners;

float opacity;
Expand All @@ -228,6 +237,8 @@ struct wlr_scene_buffer {
enum wl_output_transform transform;
pixman_region32_t opaque_region;

struct linked_node blur;

struct {
uint64_t active_outputs;
struct wlr_texture *texture;
Expand Down Expand Up @@ -482,6 +493,8 @@ struct wlr_scene_rect *wlr_scene_rect_from_node(struct wlr_scene_node *node);
*/
struct wlr_scene_shadow *wlr_scene_shadow_from_node(struct wlr_scene_node *node);

struct wlr_scene_blur *wlr_scene_blur_from_node(struct wlr_scene_node *node);

/**
* If this buffer is backed by a surface, then the struct wlr_scene_surface is
* returned. If not, NULL will be returned.
Expand Down Expand Up @@ -526,39 +539,6 @@ void wlr_scene_rect_set_clipped_region(struct wlr_scene_rect *rect,
*/
void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]);

/**
* Sets whether or not the buffer should render backdrop blur
*/
void wlr_scene_rect_set_backdrop_blur(struct wlr_scene_rect *rect,
bool enabled);

/**
* Sets whether the backdrop blur should use optimized blur or not
*/
void wlr_scene_rect_set_backdrop_blur_optimized(struct wlr_scene_rect *rect,
bool enabled);

/**
* Sets the blur strength from 1.0f -> 0.0f. This adjusts how strong the blur is
* relative to the base 1.0 value.
*
* Can be used combined with backdrop_blur_alpha to create a good looking
* fade-out effect.
*/
void wlr_scene_rect_set_backdrop_blur_strength(struct wlr_scene_rect *rect,
float strength);

/**
* Sets the blur alpha from 1.0f -> 0.0f. This adjusts the actual alpha of the blur.
* Default is 1.0f.
*
* Lower values without also adjusting the backdrop_blur_strength will look off.
*
* Can be used combined with backdrop_blur_strength to create a good looking
* fade-out effect.
*/
void wlr_scene_rect_set_backdrop_blur_alpha(struct wlr_scene_rect *rect,
float alpha);
/**
* Add a node displaying a shadow to the scene-graph.
*/
Expand Down Expand Up @@ -597,6 +577,73 @@ void wlr_scene_shadow_set_color(struct wlr_scene_shadow *shadow, const float col
void wlr_scene_shadow_set_clipped_region(struct wlr_scene_shadow *shadow,
struct clipped_region clipped_region);

/**
* Add a node displaying a blur to the scene-graph.
*/
struct wlr_scene_blur *wlr_scene_blur_create(struct wlr_scene_tree *parent,
int width, int height);

/**
* Change the width and height of an existing blur node.
*/
void wlr_scene_blur_set_size(struct wlr_scene_blur *blur, int width, int height);

/**
* Change the corner radius of an existing blur node.
*/
void wlr_scene_blur_set_corner_radius(struct wlr_scene_blur *blur, int corner_radius,
enum corner_location corners);

/**
* Make the blur node only blur the bottom layer of the scene
*/
void wlr_scene_blur_set_should_only_blur_bottom_layer(struct wlr_scene_blur *blur,
bool should_only_blur_bottom_layer);

/**
* Set the transparency mask source for the blur, only rendering blur where the
* Mask source is actually rendering (e.g. skip transparent spaces)
*/
void wlr_scene_blur_set_transparency_mask_source(struct wlr_scene_blur *blur,
struct wlr_scene_buffer *source);

/**
* get the transparency mask source for the blur
*/
struct wlr_scene_buffer *wlr_scene_blur_get_transparency_mask_source(
struct wlr_scene_blur *blur);

/**
* Sets the blur alpha from 1.0f -> 0.0f. This adjusts the actual alpha of the blur.
* Default is 1.0f.
*
* Lower values without also adjusting the strength will look off.
*
* Can be used combined with strength to create a good-looking
* fade-out effect.
*/
void wlr_scene_blur_set_alpha(struct wlr_scene_blur *blur, float alpha);

/**
* Sets the blur strength from 1.0f -> 0.0f. This adjusts how strong the blur is
* relative to the base 1.0 value.
*
* Can be used combined with alpha to create a good-looking
* fade-out effect.
*/
void wlr_scene_blur_set_strength(struct wlr_scene_blur *blur, float strength);

/**
* Sets the region where to clip the blur.
*
* For there to be corner rounding of the clipped region, the corner radius and
* corners must be non-zero.
*
* NOTE: The positioning is node-relative.
*/
void wlr_scene_blur_set_clipped_region(struct wlr_scene_blur *blur,
struct clipped_region clipped_region);

/**
* If this node represents a wlr_scene_optimized_blur node, that node will
* be returned. It is not legal to feed a node that does not represent
Expand Down Expand Up @@ -726,47 +773,6 @@ void wlr_scene_buffer_set_filter_mode(struct wlr_scene_buffer *scene_buffer,
void wlr_scene_buffer_set_corner_radius(struct wlr_scene_buffer *scene_buffer,
int radii, enum corner_location corners);

/**
* Sets 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 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 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);

/**
* Sets the blur strength from 1.0f -> 0.0f. This adjusts how strong the blur is
* relative to the base 1.0 value.
*
* Can be used combined with backdrop_blur_alpha to create a good looking
* fade-out effect.
*/
void wlr_scene_buffer_set_backdrop_blur_strength(struct wlr_scene_buffer *scene_buffer,
float strength);

/**
* Sets the blur alpha from 1.0f -> 0.0f. This adjusts the actual alpha of the blur.
* Default is 1.0f.
*
* Lower values without also adjusting the backdrop_blur_strength will look off.
*
* Can be used combined with backdrop_blur_strength to create a good looking
* fade-out effect.
*/
void wlr_scene_buffer_set_backdrop_blur_alpha(struct wlr_scene_buffer *scene_buffer,
float alpha);

/**
* Calls the buffer's frame_done signal.
*/
Expand Down
46 changes: 44 additions & 2 deletions render/fx_renderer/fx_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct fx_render_texture_options fx_render_texture_options_default(
.corners = CORNER_LOCATION_NONE,
.discard_transparent = false,
.clip_box = NULL,
.clipped_region = {0},
};
memcpy(&options.base, base, sizeof(*base));
return options;
Expand Down Expand Up @@ -346,6 +347,30 @@ void fx_render_pass_add_texture(struct fx_gles_render_pass *pass,
|| fx_options->discard_transparent;
setup_blending(!has_alpha ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode);

pixman_region32_t clip_region;
if (options->clip) {
pixman_region32_init(&clip_region);
pixman_region32_copy(&clip_region, options->clip);
} else {
pixman_region32_init_rect(&clip_region, dst_box.x, dst_box.y, dst_box.width, dst_box.height);
}
const struct wlr_box clipped_region_box = fx_options->clipped_region.area;
enum corner_location clipped_region_corners = fx_options->clipped_region.corners;
int clipped_region_corner_radius = clipped_region_corners != CORNER_LOCATION_NONE ?
fx_options->clipped_region.corner_radius : 0;
if (!wlr_box_empty(&clipped_region_box)) {
pixman_region32_t user_clip_region;
pixman_region32_init_rect(
&user_clip_region,
clipped_region_box.x + clipped_region_corner_radius * 0.3,
clipped_region_box.y + clipped_region_corner_radius * 0.3,
fmax(clipped_region_box.width - clipped_region_corner_radius * 0.6, 0),
fmax(clipped_region_box.height - clipped_region_corner_radius * 0.6, 0)
);
pixman_region32_subtract(&clip_region, &clip_region, &user_clip_region);
pixman_region32_fini(&user_clip_region);
}

glUseProgram(shader->program);

glActiveTexture(GL_TEXTURE0);
Expand Down Expand Up @@ -378,10 +403,22 @@ void fx_render_pass_add_texture(struct fx_gles_render_pass *pass,
glUniform1f(shader->radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & corners) == CORNER_LOCATION_BOTTOM_RIGHT ?
fx_options->corner_radius : 0);

glUniform2f(shader->clip_size, clipped_region_box.width, clipped_region_box.height);
glUniform2f(shader->clip_position, clipped_region_box.x, clipped_region_box.y);
glUniform1f(shader->clip_radius_top_left, (CORNER_LOCATION_TOP_LEFT & clipped_region_corners) == CORNER_LOCATION_TOP_LEFT ?
clipped_region_corner_radius : 0);
glUniform1f(shader->clip_radius_top_right, (CORNER_LOCATION_TOP_RIGHT & clipped_region_corners) == CORNER_LOCATION_TOP_RIGHT ?
clipped_region_corner_radius : 0);
glUniform1f(shader->clip_radius_bottom_left, (CORNER_LOCATION_BOTTOM_LEFT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_LEFT ?
clipped_region_corner_radius : 0);
glUniform1f(shader->clip_radius_bottom_right, (CORNER_LOCATION_BOTTOM_RIGHT & clipped_region_corners) == CORNER_LOCATION_BOTTOM_RIGHT ?
clipped_region_corner_radius : 0);

set_proj_matrix(shader->proj, pass->projection_matrix, &dst_box);
set_tex_matrix(shader->tex_proj, options->transform, &src_fbox);

render(&dst_box, options->clip, shader->pos_attrib);
render(&dst_box, &clip_region, shader->pos_attrib);
pixman_region32_fini(&clip_region);

glBindTexture(texture->target, 0);
pop_fx_debug(renderer);
Expand Down Expand Up @@ -928,7 +965,10 @@ void fx_render_pass_add_blur(struct fx_gles_render_pass *pass,

// Gets the translucent region
pixman_box32_t surface_box = { 0, 0, dst_box.width, dst_box.height };
pixman_region32_copy(&translucent_region, fx_options->opaque_region);
if (fx_options->opaque_region != NULL) {
pixman_region32_copy(&translucent_region, fx_options->opaque_region);
}

pixman_region32_inverse(&translucent_region, &translucent_region, &surface_box);
if (!pixman_region32_not_empty(&translucent_region)) {
goto damage_finish;
Expand Down Expand Up @@ -971,6 +1011,7 @@ void fx_render_pass_add_blur(struct fx_gles_render_pass *pass,

struct fx_render_texture_options tex_options = fx_options->tex_options;
tex_options.discard_transparent = true;
tex_options.clipped_region = fx_options->clipped_region;
fx_render_pass_add_texture(pass, &tex_options);

stencil_mask_close(true);
Expand All @@ -985,6 +1026,7 @@ void fx_render_pass_add_blur(struct fx_gles_render_pass *pass,
.height = buffer->buffer->height,
};
tex_options->base.texture = &blur_texture->wlr_texture;
tex_options->clipped_region = fx_options->clipped_region;
fx_render_pass_add_texture(pass, tex_options);

wlr_texture_destroy(&blur_texture->wlr_texture);
Expand Down
Loading