[gnome-shell] windowManager: Use an off-screen buffer for window dimming



commit 82eccb566c04261fedb690f64126514bcca15092
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sat Sep 17 03:06:00 2011 -0400

    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 935c8e2..2c95022 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 16756ad..48276fe 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 d371861..a06f99a 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 7ff0891..c0d4567 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__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]