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
This commit is contained in:
Jasper St. Pierre 2011-09-17 03:06:00 -04:00
parent 543b29efe7
commit 82eccb566c
4 changed files with 58 additions and 30 deletions

View File

@ -1,5 +1,5 @@
#version 110 #version 110
uniform sampler2D sampler0; uniform sampler2D tex;
uniform float fraction; uniform float fraction;
uniform float height; uniform float height;
const float c = -0.2; 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); vec4 off = vec4(0.633, 0.633, 0.633, 0);
void main() void main()
{ {
vec4 color = texture2D(sampler0, gl_TexCoord[0].st); vec4 color = texture2D(tex, cogl_tex_coord_in[0].xy);
float y = height * gl_TexCoord[0][1]; float y = height * cogl_tex_coord_in[0].y;
// To reduce contrast, blend with a mid gray // 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 // 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 // when the fraction is 1.0. For other locations and fractions we linearly
// interpolate back to the original undimmed color. // interpolate back to the original undimmed color.
gl_FragColor = color + (gl_FragColor - color) * min(y / border_max_height, 1.0); cogl_color_out = color + (cogl_color_out - color) * min(y / border_max_height, 1.0);
gl_FragColor = color + (gl_FragColor - color) * fraction; cogl_color_out = color + (cogl_color_out - color) * fraction;
cogl_color_out *= color.a;
} }

View File

@ -19,22 +19,9 @@ const UNDIM_TIME = 0.250;
var dimShader = undefined; var dimShader = undefined;
function getDimShader() { function getDimShaderSource() {
if (dimShader === null) if (!dimShader)
return null; dimShader = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
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;
}
}
return dimShader; return dimShader;
} }
@ -44,22 +31,29 @@ function WindowDimmer(actor) {
WindowDimmer.prototype = { WindowDimmer.prototype = {
_init: function(actor) { _init: function(actor) {
this.effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
this.effect.set_shader_source(getDimShaderSource());
this.actor = actor; this.actor = actor;
}, },
set dimFraction(fraction) { set dimFraction(fraction) {
this._dimFraction = fraction; this._dimFraction = fraction;
let shader = getDimShader(); if (!Meta.prefs_get_attach_modal_dialogs()) {
if (!Meta.prefs_get_attach_modal_dialogs() || !shader) { this.effect.enabled = false;
this.actor.set_shader(null);
return; return;
} }
if (fraction > 0.01) { if (fraction > 0.01) {
this.actor.set_shader(shader); Shell.shader_effect_set_double_uniform(this.effect, 'height', this.actor.get_height());
this.actor.set_shader_param_float('height', this.actor.get_height()); Shell.shader_effect_set_double_uniform(this.effect, 'fraction', fraction);
this.actor.set_shader_param_float('fraction', fraction);
} else if (!this.effect.actor)
this.actor.set_shader(null); this.actor.add_effect(this.effect);
} else {
if (this.effect.actor)
this.actor.remove_effect(this.effect);
}
}, },
get dimFraction() { get dimFraction() {

View File

@ -850,3 +850,31 @@ shell_parse_search_provider (const char *data,
return FALSE; 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);
}

View File

@ -50,6 +50,10 @@ gboolean shell_parse_search_provider (const char *data,
char **icon_data_uri, char **icon_data_uri,
GError **error); GError **error);
void shell_shader_effect_set_double_uniform (ClutterShaderEffect *effect,
const gchar *name,
gdouble value);
G_END_DECLS G_END_DECLS
#endif /* __SHELL_UTIL_H__ */ #endif /* __SHELL_UTIL_H__ */