summaryrefslogtreecommitdiff
path: root/sway/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop')
-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
4 files changed, 133 insertions, 0 deletions
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);