feat: blur tweaks (#258)
This commit is contained in:
parent
1c5c60d928
commit
04b657b58c
|
@ -30,6 +30,10 @@ Sway is an incredible window manager, and certainly one of the most well establi
|
|||
- `blur_xray enable|disable`: this will set floating windows to blur based on the background, not the windows below. You probably want to set this to `disable` :)
|
||||
- `blur_passes <integer value 0 - 10>`
|
||||
- `blur_radius <integer value 0 - 10>`
|
||||
- `blur_noise <float value 0 - 1>` (**Note**: git only, percentage of noise to add)
|
||||
- `blur_brightness <float value 0 - 2>` (**Note**: git only, percentage of original brightness to adjust)
|
||||
- `blur_contrast <float value 0 - 2>` (**Note**: git only, percentage of original contrast to adjust)
|
||||
- `blur_saturation <float value 0 - 2>` (**Note**: git only, percentage of original saturation to adjust)
|
||||
+ Corner radius: `corner_radius <val>`
|
||||
+ Window shadows:
|
||||
- `shadows enable|disable`
|
||||
|
|
|
@ -115,8 +115,12 @@ sway_cmd cmd_bindgesture;
|
|||
sway_cmd cmd_bindswitch;
|
||||
sway_cmd cmd_bindsym;
|
||||
sway_cmd cmd_blur;
|
||||
sway_cmd cmd_blur_brightness;
|
||||
sway_cmd cmd_blur_contrast;
|
||||
sway_cmd cmd_blur_noise;
|
||||
sway_cmd cmd_blur_passes;
|
||||
sway_cmd cmd_blur_radius;
|
||||
sway_cmd cmd_blur_saturation;
|
||||
sway_cmd cmd_blur_xray;
|
||||
sway_cmd cmd_border;
|
||||
sway_cmd cmd_client_noop;
|
||||
|
|
|
@ -473,6 +473,10 @@ enum xwayland_mode {
|
|||
struct blur_parameters {
|
||||
int num_passes;
|
||||
int radius;
|
||||
float noise;
|
||||
float brightness;
|
||||
float contrast;
|
||||
float saturation;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,6 +47,18 @@ struct blur_shader {
|
|||
GLint halfpixel;
|
||||
};
|
||||
|
||||
struct effects_shader {
|
||||
GLuint program;
|
||||
GLint proj;
|
||||
GLint tex;
|
||||
GLint pos_attrib;
|
||||
GLint tex_attrib;
|
||||
GLfloat noise;
|
||||
GLfloat brightness;
|
||||
GLfloat contrast;
|
||||
GLfloat saturation;
|
||||
};
|
||||
|
||||
struct box_shadow_shader {
|
||||
GLuint program;
|
||||
GLint proj;
|
||||
|
@ -153,6 +165,7 @@ struct fx_renderer {
|
|||
struct box_shadow_shader box_shadow;
|
||||
struct blur_shader blur1;
|
||||
struct blur_shader blur2;
|
||||
struct effects_shader blur_effects;
|
||||
struct corner_shader corner;
|
||||
struct quad_shader quad;
|
||||
struct rounded_quad_shader rounded_quad;
|
||||
|
@ -211,7 +224,11 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo
|
|||
const float matrix[static 9], int corner_radius, float blur_sigma);
|
||||
|
||||
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,
|
||||
int blur_radius);
|
||||
struct fx_framebuffer **buffer, struct blur_shader *shader,
|
||||
const struct wlr_box *box, int blur_radius);
|
||||
|
||||
void fx_render_blur_effects(struct fx_renderer *renderer, const float matrix[static 9],
|
||||
struct fx_framebuffer **buffer, float blur_noise, float blur_brightness,
|
||||
float blur_contrast, float blur_saturation);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,8 +50,12 @@ static const struct cmd_handler handlers[] = {
|
|||
{ "bindswitch", cmd_bindswitch },
|
||||
{ "bindsym", cmd_bindsym },
|
||||
{ "blur", cmd_blur },
|
||||
{ "blur_brightness", cmd_blur_brightness },
|
||||
{ "blur_contrast", cmd_blur_contrast },
|
||||
{ "blur_noise", cmd_blur_noise },
|
||||
{ "blur_passes", cmd_blur_passes },
|
||||
{ "blur_radius", cmd_blur_radius },
|
||||
{ "blur_saturation", cmd_blur_saturation },
|
||||
{ "blur_xray", cmd_blur_xray },
|
||||
{ "client.background", cmd_client_noop },
|
||||
{ "client.focused", cmd_client_focused },
|
||||
|
|
28
sway/commands/blur_brightness.c
Normal file
28
sway/commands/blur_brightness.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
|
||||
struct cmd_results *cmd_blur_brightness(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "blur_brightness", EXPECTED_EQUAL_TO, 1))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
char *inv;
|
||||
float value = strtof(argv[0], &inv);
|
||||
if (*inv != '\0' || value < 0 || value > 2) {
|
||||
return cmd_results_new(CMD_FAILURE, "Invalid brightness specified");
|
||||
}
|
||||
|
||||
config->blur_params.brightness = value;
|
||||
|
||||
struct sway_output *output;
|
||||
wl_list_for_each(output, &root->all_outputs, link) {
|
||||
if (output->renderer) {
|
||||
output->renderer->blur_buffer_dirty = true;
|
||||
output_damage_whole(output);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
28
sway/commands/blur_contrast.c
Normal file
28
sway/commands/blur_contrast.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
|
||||
struct cmd_results *cmd_blur_contrast(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "blur_contrast", EXPECTED_EQUAL_TO, 1))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
char *inv;
|
||||
float value = strtof(argv[0], &inv);
|
||||
if (*inv != '\0' || value < 0 || value > 2) {
|
||||
return cmd_results_new(CMD_FAILURE, "Invalid brightness specified");
|
||||
}
|
||||
|
||||
config->blur_params.contrast = value;
|
||||
|
||||
struct sway_output *output;
|
||||
wl_list_for_each(output, &root->all_outputs, link) {
|
||||
if (output->renderer) {
|
||||
output->renderer->blur_buffer_dirty = true;
|
||||
output_damage_whole(output);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
28
sway/commands/blur_noise.c
Normal file
28
sway/commands/blur_noise.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
|
||||
struct cmd_results *cmd_blur_noise(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "blur_noise", EXPECTED_EQUAL_TO, 1))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
char *inv;
|
||||
float value = strtof(argv[0], &inv);
|
||||
if (*inv != '\0' || value < 0 || value > 1) {
|
||||
return cmd_results_new(CMD_FAILURE, "Invalid noise specified");
|
||||
}
|
||||
|
||||
config->blur_params.noise = value;
|
||||
|
||||
struct sway_output *output;
|
||||
wl_list_for_each(output, &root->all_outputs, link) {
|
||||
if (output->renderer) {
|
||||
output->renderer->blur_buffer_dirty = true;
|
||||
output_damage_whole(output);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
29
sway/commands/blur_saturation.c
Normal file
29
sway/commands/blur_saturation.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
|
||||
struct cmd_results *cmd_blur_saturation(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "blur_saturation", EXPECTED_EQUAL_TO, 1))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
char *inv;
|
||||
float value = strtof(argv[0], &inv);
|
||||
if (*inv != '\0' || value < 0 || value > 2) {
|
||||
return cmd_results_new(CMD_FAILURE, "Invalid saturation specified");
|
||||
}
|
||||
|
||||
config->blur_params.saturation = value;
|
||||
|
||||
struct sway_output *output;
|
||||
wl_list_for_each(output, &root->all_outputs, link) {
|
||||
if (output->renderer) {
|
||||
output->renderer->blur_buffer_dirty = true;
|
||||
output_damage_whole(output);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
@ -360,6 +360,10 @@ static void config_defaults(struct sway_config *config) {
|
|||
config->blur_xray = false;
|
||||
config->blur_params.num_passes = 2;
|
||||
config->blur_params.radius = 5;
|
||||
config->blur_params.noise = 0.02;
|
||||
config->blur_params.brightness = 0.9;
|
||||
config->blur_params.contrast = 0.9;
|
||||
config->blur_params.saturation = 1.1;
|
||||
|
||||
config->titlebar_separator = true;
|
||||
config->scratchpad_minimize = false;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
// shaders
|
||||
#include "blur1_frag_src.h"
|
||||
#include "blur2_frag_src.h"
|
||||
#include "blur_effects_frag_src.h"
|
||||
#include "box_shadow_frag_src.h"
|
||||
#include "common_vert_src.h"
|
||||
#include "corner_frag_src.h"
|
||||
|
@ -107,6 +108,25 @@ static bool link_blur_program(struct blur_shader *shader, const char *shader_pro
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool link_blur_effects_program(struct effects_shader *shader, const char *shader_program) {
|
||||
GLuint prog;
|
||||
shader->program = prog = link_program(shader_program);
|
||||
if (!shader->program) {
|
||||
return false;
|
||||
}
|
||||
shader->proj = glGetUniformLocation(prog, "proj");
|
||||
shader->tex = glGetUniformLocation(prog, "tex");
|
||||
shader->pos_attrib = glGetAttribLocation(prog, "pos");
|
||||
shader->tex_attrib = glGetAttribLocation(prog, "texcoord");
|
||||
shader->noise = glGetUniformLocation(prog, "noise");
|
||||
shader->brightness = glGetUniformLocation(prog, "brightness");
|
||||
shader->contrast = glGetUniformLocation(prog, "contrast");
|
||||
shader->saturation = glGetUniformLocation(prog, "saturation");
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static bool link_box_shadow_program(struct box_shadow_shader *shader) {
|
||||
GLuint prog;
|
||||
shader->program = prog = link_program(box_shadow_frag_src);
|
||||
|
@ -305,6 +325,10 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl, struct wlr_output *w
|
|||
if (!link_blur_program(&renderer->shaders.blur2, blur2_frag_src)) {
|
||||
goto error;
|
||||
}
|
||||
// effects shader
|
||||
if (!link_blur_effects_program(&renderer->shaders.blur_effects, blur_effects_frag_src)) {
|
||||
goto error;
|
||||
}
|
||||
// box shadow shader
|
||||
if (!link_box_shadow_program(&renderer->shaders.box_shadow)) {
|
||||
goto error;
|
||||
|
@ -365,6 +389,7 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl, struct wlr_output *w
|
|||
error:
|
||||
glDeleteProgram(renderer->shaders.blur1.program);
|
||||
glDeleteProgram(renderer->shaders.blur2.program);
|
||||
glDeleteProgram(renderer->shaders.blur_effects.program);
|
||||
glDeleteProgram(renderer->shaders.box_shadow.program);
|
||||
glDeleteProgram(renderer->shaders.corner.program);
|
||||
glDeleteProgram(renderer->shaders.quad.program);
|
||||
|
@ -899,3 +924,39 @@ void fx_render_blur(struct fx_renderer *renderer, const float matrix[static 9],
|
|||
glDisableVertexAttribArray(shader->tex_attrib);
|
||||
|
||||
}
|
||||
|
||||
void fx_render_blur_effects(struct fx_renderer *renderer, const float matrix[static 9],
|
||||
struct fx_framebuffer **buffer, float blur_noise, float blur_brightness,
|
||||
float blur_contrast, float blur_saturation) {
|
||||
struct effects_shader shader = renderer->shaders.blur_effects;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture((*buffer)->texture.target, (*buffer)->texture.id);
|
||||
glTexParameteri((*buffer)->texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glUseProgram(shader.program);
|
||||
|
||||
// OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set
|
||||
// to GL_FALSE
|
||||
float gl_matrix[9];
|
||||
wlr_matrix_transpose(gl_matrix, matrix);
|
||||
glUniformMatrix3fv(shader.proj, 1, GL_FALSE, gl_matrix);
|
||||
|
||||
glUniform1i(shader.tex, 0);
|
||||
glUniform1f(shader.noise, blur_noise);
|
||||
glUniform1f(shader.brightness, blur_brightness);
|
||||
glUniform1f(shader.contrast, blur_contrast);
|
||||
glUniform1f(shader.saturation, blur_saturation);
|
||||
|
||||
glVertexAttribPointer(shader.pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(shader.tex_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
|
||||
glEnableVertexAttribArray(shader.pos_attrib);
|
||||
glEnableVertexAttribArray(shader.tex_attrib);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glDisableVertexAttribArray(shader.pos_attrib);
|
||||
glDisableVertexAttribArray(shader.tex_attrib);
|
||||
}
|
||||
|
|
54
sway/desktop/fx_renderer/shaders/blur_effects.frag
Normal file
54
sway/desktop/fx_renderer/shaders/blur_effects.frag
Normal file
|
@ -0,0 +1,54 @@
|
|||
precision mediump float;
|
||||
varying vec2 v_texcoord;
|
||||
uniform sampler2D tex;
|
||||
|
||||
uniform float noise;
|
||||
uniform float brightness;
|
||||
uniform float contrast;
|
||||
uniform float saturation;
|
||||
|
||||
mat4 brightnessMatrix() {
|
||||
float b = brightness - 1.0;
|
||||
return mat4(1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
b, b, b, 1);
|
||||
}
|
||||
|
||||
mat4 contrastMatrix() {
|
||||
float t = (1.0 - contrast) / 2.0;
|
||||
return mat4(contrast, 0, 0, 0,
|
||||
0, contrast, 0, 0,
|
||||
0, 0, contrast, 0,
|
||||
t, t, t, 1);
|
||||
}
|
||||
|
||||
mat4 saturationMatrix() {
|
||||
vec3 luminance = vec3(0.3086, 0.6094, 0.0820);
|
||||
float oneMinusSat = 1.0 - saturation;
|
||||
vec3 red = vec3(luminance.x * oneMinusSat);
|
||||
red+= vec3(saturation, 0, 0);
|
||||
vec3 green = vec3(luminance.y * oneMinusSat);
|
||||
green += vec3(0, saturation, 0);
|
||||
vec3 blue = vec3(luminance.z * oneMinusSat);
|
||||
blue += vec3(0, 0, saturation);
|
||||
return mat4(red, 0,
|
||||
green, 0,
|
||||
blue, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
// Fast generative noise function
|
||||
float hash(vec2 p) {
|
||||
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 color = texture2D(tex, v_texcoord);
|
||||
color *= brightnessMatrix() * contrastMatrix() * saturationMatrix();
|
||||
float noiseHash = hash(v_texcoord);
|
||||
float noiseAmount = (mod(noiseHash, 1.0) - 0.5);
|
||||
color.rgb += noiseAmount * noise;
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
|
@ -3,6 +3,7 @@ embed = find_program('./embed.sh', native: true)
|
|||
shaders = [
|
||||
'blur1.frag',
|
||||
'blur2.frag',
|
||||
'blur_effects.frag',
|
||||
'box_shadow.frag',
|
||||
'common.vert',
|
||||
'corner.frag',
|
||||
|
|
|
@ -258,6 +258,23 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct
|
|||
&renderer->shaders.blur2, box, blur_radius);
|
||||
}
|
||||
|
||||
float blur_noise = config->blur_params.noise;
|
||||
float blur_brightness = config->blur_params.brightness;
|
||||
float blur_contrast = config->blur_params.contrast;
|
||||
float blur_saturation = config->blur_params.saturation;
|
||||
|
||||
if (pixman_region32_not_empty(&damage)) {
|
||||
int nrects;
|
||||
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
|
||||
for (int i = 0; i < nrects; ++i) {
|
||||
const pixman_box32_t box = rects[i];
|
||||
struct wlr_box new_box = { box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1 };
|
||||
fx_renderer_scissor(&new_box);
|
||||
fx_render_blur_effects(renderer, gl_matrix, ¤t_buffer, blur_noise,
|
||||
blur_brightness, blur_contrast, blur_saturation);
|
||||
}
|
||||
}
|
||||
|
||||
pixman_region32_fini(&tempDamage);
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
|
|
|
@ -53,9 +53,13 @@ sway_sources = files(
|
|||
'commands/bar.c',
|
||||
'commands/bind.c',
|
||||
'commands/blur.c',
|
||||
'commands/blur_brightness.c',
|
||||
'commands/blur_contrast.c',
|
||||
'commands/blur_passes.c',
|
||||
'commands/blur_radius.c',
|
||||
'commands/blur_xray.c',
|
||||
'commands/blur_noise.c',
|
||||
'commands/blur_saturation.c',
|
||||
'commands/border.c',
|
||||
'commands/client.c',
|
||||
'commands/corner_radius.c',
|
||||
|
|
|
@ -707,6 +707,22 @@ The default colors are:
|
|||
Adjusts the blur radius of windows between 0 (disabled) and 10
|
||||
while 5 is the default value.
|
||||
|
||||
*blur_noise* <value>
|
||||
Adjusts the percentage of noise applied to the blur between 0 and 1
|
||||
while 0.02 (2%) is the default value.
|
||||
|
||||
*blur_brightness* <value>
|
||||
Adjusts the percentage of brightness for the blur between 0 and 2
|
||||
while 0.9 (90%) is the default value.
|
||||
|
||||
*blur_contrast* <value>
|
||||
Adjusts the percentage of contrast for the blur between 0 and 2
|
||||
while 0.9 (90%) is the default value.
|
||||
|
||||
*blur_saturation* <value>
|
||||
Adjusts the percentage of saturation for the blur between 0 and 2
|
||||
while 1.1 (110%) is the default value.
|
||||
|
||||
*default_border* normal|none|pixel [<n>]
|
||||
Set default border style for new tiled windows.
|
||||
|
||||
|
|
Loading…
Reference in a new issue