From 82eccb566c04261fedb690f64126514bcca15092 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 17 Sep 2011 03:06:00 -0400 Subject: [PATCH] windowManager: Use an off-screen buffer for window dimming The way the window dimmer shader is applied will cause rendering errors with the rounded corners, invisible borders or shaped textures since it doesn't deal well with the multitexturing used by the MetaShapedTexture. Use an off-screen buffer to flatten the texture before being applied. https://bugzilla.gnome.org/show_bug.cgi?id=659302 --- data/shaders/dim-window.glsl | 14 ++++++------ js/ui/windowManager.js | 42 ++++++++++++++++-------------------- src/shell-util.c | 28 ++++++++++++++++++++++++ src/shell-util.h | 4 ++++ 4 files changed, 58 insertions(+), 30 deletions(-) diff --git a/data/shaders/dim-window.glsl b/data/shaders/dim-window.glsl index 935c8e239..2c95022ef 100644 --- a/data/shaders/dim-window.glsl +++ b/data/shaders/dim-window.glsl @@ -1,5 +1,5 @@ #version 110 -uniform sampler2D sampler0; +uniform sampler2D tex; uniform float fraction; uniform float height; const float c = -0.2; @@ -12,15 +12,17 @@ mat4 contrast = mat4 (1.0 + c, 0.0, 0.0, 0.0, vec4 off = vec4(0.633, 0.633, 0.633, 0); void main() { - vec4 color = texture2D(sampler0, gl_TexCoord[0].st); - float y = height * gl_TexCoord[0][1]; + vec4 color = texture2D(tex, cogl_tex_coord_in[0].xy); + float y = height * cogl_tex_coord_in[0].y; // To reduce contrast, blend with a mid gray - gl_FragColor = color * contrast - off * c; + cogl_color_out = color * contrast - off * c; // We only fully dim at a distance of BORDER_MAX_HEIGHT from the edge and // when the fraction is 1.0. For other locations and fractions we linearly // interpolate back to the original undimmed color. - gl_FragColor = color + (gl_FragColor - color) * min(y / border_max_height, 1.0); - gl_FragColor = color + (gl_FragColor - color) * fraction; + cogl_color_out = color + (cogl_color_out - color) * min(y / border_max_height, 1.0); + cogl_color_out = color + (cogl_color_out - color) * fraction; + + cogl_color_out *= color.a; } diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js index 16756ad1f..48276fe08 100644 --- a/js/ui/windowManager.js +++ b/js/ui/windowManager.js @@ -19,22 +19,9 @@ const UNDIM_TIME = 0.250; var dimShader = undefined; -function getDimShader() { - if (dimShader === null) - return null; - if (!dimShader) { - let source = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl'); - try { - let shader = new Clutter.Shader(); - shader.set_fragment_source(source, -1); - shader.compile(); - - dimShader = shader; - } catch (e) { - log(e.message); - dimShader = null; - } - } +function getDimShaderSource() { + if (!dimShader) + dimShader = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl'); return dimShader; } @@ -44,22 +31,29 @@ function WindowDimmer(actor) { WindowDimmer.prototype = { _init: function(actor) { + this.effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER }); + this.effect.set_shader_source(getDimShaderSource()); + this.actor = actor; }, set dimFraction(fraction) { this._dimFraction = fraction; - let shader = getDimShader(); - if (!Meta.prefs_get_attach_modal_dialogs() || !shader) { - this.actor.set_shader(null); + if (!Meta.prefs_get_attach_modal_dialogs()) { + this.effect.enabled = false; return; } + if (fraction > 0.01) { - this.actor.set_shader(shader); - this.actor.set_shader_param_float('height', this.actor.get_height()); - this.actor.set_shader_param_float('fraction', fraction); - } else - this.actor.set_shader(null); + Shell.shader_effect_set_double_uniform(this.effect, 'height', this.actor.get_height()); + Shell.shader_effect_set_double_uniform(this.effect, 'fraction', fraction); + + if (!this.effect.actor) + this.actor.add_effect(this.effect); + } else { + if (this.effect.actor) + this.actor.remove_effect(this.effect); + } }, get dimFraction() { diff --git a/src/shell-util.c b/src/shell-util.c index d371861ab..a06f99a54 100644 --- a/src/shell-util.c +++ b/src/shell-util.c @@ -850,3 +850,31 @@ shell_parse_search_provider (const char *data, return FALSE; } + +/** + * shell_shader_effect_set_double_uniform: + * @effect: The #ClutterShaderEffect + * @name: The name of the uniform + * @value: The value to set it to. + * + * Set a double uniform on a ClutterShaderEffect. + * + * The problem here is that JavaScript doesn't have more than + * one number type, and gjs tries to automatically guess what + * type we want to set a GValue to. If the number is "1.0" or + * something, it will use an integer, which will cause errors + * in GLSL. + */ +void +shell_shader_effect_set_double_uniform (ClutterShaderEffect *effect, + const gchar *name, + gdouble value) +{ + GValue gvalue = G_VALUE_INIT; + g_value_init (&gvalue, G_TYPE_DOUBLE); + g_value_set_double (&gvalue, value); + + clutter_shader_effect_set_uniform_value (effect, + name, + &gvalue); +} diff --git a/src/shell-util.h b/src/shell-util.h index 7ff08917b..c0d45671e 100644 --- a/src/shell-util.h +++ b/src/shell-util.h @@ -50,6 +50,10 @@ gboolean shell_parse_search_provider (const char *data, char **icon_data_uri, GError **error); +void shell_shader_effect_set_double_uniform (ClutterShaderEffect *effect, + const gchar *name, + gdouble value); + G_END_DECLS #endif /* __SHELL_UTIL_H__ */