summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorozwaldorf <[email protected]>2024-01-03 12:38:44 -0500
committerGitHub <[email protected]>2024-01-03 12:38:44 -0500
commit04b657b58cf54ac611f73723ec44f51feba16b15 (patch)
treee8c310f8957ded3304503dc1d908b8a233bbae20
parent1c5c60d9280eb0b13d9884366bdeaf3748b04308 (diff)
feat: blur tweaks (#258)
-rw-r--r--README.md4
-rw-r--r--include/sway/commands.h4
-rw-r--r--include/sway/config.h4
-rw-r--r--include/sway/desktop/fx_renderer/fx_renderer.h21
-rw-r--r--sway/commands.c4
-rw-r--r--sway/commands/blur_brightness.c28
-rw-r--r--sway/commands/blur_contrast.c28
-rw-r--r--sway/commands/blur_noise.c28
-rw-r--r--sway/commands/blur_saturation.c29
-rw-r--r--sway/config.c4
-rw-r--r--sway/desktop/fx_renderer/fx_renderer.c61
-rw-r--r--sway/desktop/fx_renderer/shaders/blur_effects.frag54
-rw-r--r--sway/desktop/fx_renderer/shaders/meson.build1
-rw-r--r--sway/desktop/render.c17
-rw-r--r--sway/meson.build4
-rw-r--r--sway/sway.5.scd16
16 files changed, 305 insertions, 2 deletions
diff --git a/README.md b/README.md
index 0941944e..01a777da 100644
--- a/README.md
+++ b/README.md
@@ -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`
diff --git a/include/sway/commands.h b/include/sway/commands.h
index c29d4ff4..b8f5660a 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -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;
diff --git a/include/sway/config.h b/include/sway/config.h
index 81213dbc..2bb33352 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -473,6 +473,10 @@ enum xwayland_mode {
struct blur_parameters {
int num_passes;
int radius;
+ float noise;
+ float brightness;
+ float contrast;
+ float saturation;
};
/**
diff --git a/include/sway/desktop/fx_renderer/fx_renderer.h b/include/sway/desktop/fx_renderer/fx_renderer.h
index bfae7b72..924d9951 100644
--- a/include/sway/desktop/fx_renderer/fx_renderer.h
+++ b/include/sway/desktop/fx_renderer/fx_renderer.h
@@ -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
diff --git a/sway/commands.c b/sway/commands.c
index 75c6c1e5..5ce714e6 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -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 },
diff --git a/sway/commands/blur_brightness.c b/sway/commands/blur_brightness.c
new file mode 100644
index 00000000..79a40266
--- /dev/null
+++ b/sway/commands/blur_brightness.c
@@ -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);
+}
diff --git a/sway/commands/blur_contrast.c b/sway/commands/blur_contrast.c
new file mode 100644
index 00000000..61e3aec4
--- /dev/null
+++ b/sway/commands/blur_contrast.c
@@ -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);
+}
diff --git a/sway/commands/blur_noise.c b/sway/commands/blur_noise.c
new file mode 100644
index 00000000..bd737911
--- /dev/null
+++ b/sway/commands/blur_noise.c
@@ -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);
+}
diff --git a/sway/commands/blur_saturation.c b/sway/commands/blur_saturation.c
new file mode 100644
index 00000000..35627363
--- /dev/null
+++ b/sway/commands/blur_saturation.c
@@ -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);
+}
+
diff --git a/sway/config.c b/sway/config.c
index db395475..58d243e2 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -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;
diff --git a/sway/desktop/fx_renderer/fx_renderer.c b/sway/desktop/fx_renderer/fx_renderer.c
index 7196bb0e..089e1693 100644
--- a/sway/desktop/fx_renderer/fx_renderer.c
+++ b/sway/desktop/fx_renderer/fx_renderer.c
@@ -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);
+}
diff --git a/sway/desktop/fx_renderer/shaders/blur_effects.frag b/sway/desktop/fx_renderer/shaders/blur_effects.frag
new file mode 100644
index 00000000..2fc16c15
--- /dev/null
+++ b/sway/desktop/fx_renderer/shaders/blur_effects.frag
@@ -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;
+}
diff --git a/sway/desktop/fx_renderer/shaders/meson.build b/sway/desktop/fx_renderer/shaders/meson.build
index 7a27de80..19f76dc2 100644
--- a/sway/desktop/fx_renderer/shaders/meson.build
+++ b/sway/desktop/fx_renderer/shaders/meson.build
@@ -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',
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index c054b3a5..391533c5 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -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, &current_buffer, blur_noise,
+ blur_brightness, blur_contrast, blur_saturation);
+ }
+ }
+
pixman_region32_fini(&tempDamage);
pixman_region32_fini(&damage);
diff --git a/sway/meson.build b/sway/meson.build
index 099f2b52..f0f26346 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -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',
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 08c1a7cb..b0f583f2 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -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.