summaryrefslogtreecommitdiff
path: root/src/compositor/meta-background-actor.c
diff options
context:
space:
mode:
authorAlessandro Bono <abono@gnome.org>2017-08-20 13:34:54 +0200
committerAlessandro Bono <abono@gnome.org>2017-09-07 16:59:56 +0200
commit068791f6c111baf8539a19030a4845e8e96a14af (patch)
tree41cd12951b55a55afbf6263b91c062bffe526d81 /src/compositor/meta-background-actor.c
parentcbc4563b30d081a4c77445baf60dc15cd076031d (diff)
downloadmutter-068791f6c111baf8539a19030a4845e8e96a14af.tar.gz
meta-background-actor: Add gradient effect
Add a gradient effect that goes from the top to the bottom. The height and the initial dark tone of the gradient are customizable. https://bugzilla.gnome.org/show_bug.cgi?id=786618
Diffstat (limited to 'src/compositor/meta-background-actor.c')
-rw-r--r--src/compositor/meta-background-actor.c188
1 files changed, 186 insertions, 2 deletions
diff --git a/src/compositor/meta-background-actor.c b/src/compositor/meta-background-actor.c
index 1de2dd133..197a62c0f 100644
--- a/src/compositor/meta-background-actor.c
+++ b/src/compositor/meta-background-actor.c
@@ -88,6 +88,9 @@ enum
PROP_META_SCREEN = 1,
PROP_MONITOR,
PROP_BACKGROUND,
+ PROP_GRADIENT,
+ PROP_GRADIENT_HEIGHT,
+ PROP_GRADIENT_MAX_DARKNESS,
PROP_VIGNETTE,
PROP_VIGNETTE_SHARPNESS,
PROP_VIGNETTE_BRIGHTNESS
@@ -97,9 +100,28 @@ typedef enum {
CHANGED_BACKGROUND = 1 << 0,
CHANGED_EFFECTS = 1 << 2,
CHANGED_VIGNETTE_PARAMETERS = 1 << 3,
+ CHANGED_GRADIENT_PARAMETERS = 1 << 4,
CHANGED_ALL = 0xFFFF
} ChangedFlags;
+#define GRADIENT_VERTEX_SHADER_DECLARATIONS \
+"uniform vec2 scale;\n" \
+"varying vec2 position;\n" \
+
+#define GRADIENT_VERTEX_SHADER_CODE \
+"position = cogl_tex_coord0_in.xy * scale;\n" \
+
+#define GRADIENT_FRAGMENT_SHADER_DECLARATIONS \
+"uniform float gradient_height_perc;\n" \
+"uniform float gradient_max_darkness;\n" \
+"varying vec2 position;\n" \
+
+#define GRADIENT_FRAGMENT_SHADER_CODE \
+"float min_brightness = 1.0 - gradient_max_darkness;\n" \
+"float gradient_y_pos = min(position.y, gradient_height_perc) / gradient_height_perc;\n" \
+"float pixel_brightness = (1.0 - min_brightness) * gradient_y_pos + min_brightness;\n" \
+"cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n" \
+
#define VIGNETTE_VERTEX_SHADER_DECLARATIONS \
"uniform vec2 scale;\n" \
"uniform vec2 offset;\n" \
@@ -123,6 +145,7 @@ typedef struct _MetaBackgroundLayer MetaBackgroundLayer;
typedef enum {
PIPELINE_VIGNETTE = (1 << 0),
PIPELINE_BLEND = (1 << 1),
+ PIPELINE_GRADIENT = (1 << 2),
} PipelineFlags;
struct _MetaBackgroundActorPrivate
@@ -132,6 +155,10 @@ struct _MetaBackgroundActorPrivate
MetaBackground *background;
+ gboolean gradient;
+ double gradient_max_darkness;
+ int gradient_height;
+
gboolean vignette;
double vignette_brightness;
double vignette_sharpness;
@@ -231,7 +258,7 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
static CoglPipeline *
make_pipeline (PipelineFlags pipeline_flags)
{
- static CoglPipeline *templates[4];
+ static CoglPipeline *templates[8];
CoglPipeline **templatep;
templatep = &templates[pipeline_flags];
@@ -263,6 +290,26 @@ make_pipeline (PipelineFlags pipeline_flags)
cogl_pipeline_add_snippet (*templatep, vignette_fragment_snippet);
}
+ if ((pipeline_flags & PIPELINE_GRADIENT) != 0)
+ {
+ static CoglSnippet *gradient_vertex_snippet;
+ static CoglSnippet *gradient_fragment_snippet;
+
+ if (!gradient_vertex_snippet)
+ gradient_vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
+ GRADIENT_VERTEX_SHADER_DECLARATIONS,
+ GRADIENT_VERTEX_SHADER_CODE);
+
+ cogl_pipeline_add_snippet (*templatep, gradient_vertex_snippet);
+
+ if (!gradient_fragment_snippet)
+ gradient_fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+ GRADIENT_FRAGMENT_SHADER_DECLARATIONS,
+ GRADIENT_FRAGMENT_SHADER_CODE);
+
+ cogl_pipeline_add_snippet (*templatep, gradient_fragment_snippet);
+ }
+
if ((pipeline_flags & PIPELINE_BLEND) == 0)
cogl_pipeline_set_blend (*templatep, "RGBA = ADD (SRC_COLOR, 0)", NULL);
}
@@ -285,6 +332,8 @@ setup_pipeline (MetaBackgroundActor *self,
pipeline_flags |= PIPELINE_BLEND;
if (priv->vignette && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
pipeline_flags |= PIPELINE_VIGNETTE;
+ if (priv->gradient && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
+ pipeline_flags |= PIPELINE_GRADIENT;
if (priv->pipeline &&
pipeline_flags != priv->pipeline_flags)
@@ -327,6 +376,25 @@ setup_pipeline (MetaBackgroundActor *self,
priv->changed &= ~CHANGED_VIGNETTE_PARAMETERS;
}
+ if ((priv->changed & CHANGED_GRADIENT_PARAMETERS) != 0)
+ {
+ MetaRectangle monitor_geometry;
+ float gradient_height_perc;
+
+ meta_screen_get_monitor_geometry (priv->screen, priv->monitor, &monitor_geometry);
+ gradient_height_perc = MAX (0.0001, priv->gradient_height / (float)monitor_geometry.height);
+ cogl_pipeline_set_uniform_1f (priv->pipeline,
+ cogl_pipeline_get_uniform_location (priv->pipeline,
+ "gradient_height_perc"),
+ gradient_height_perc);
+ cogl_pipeline_set_uniform_1f (priv->pipeline,
+ cogl_pipeline_get_uniform_location (priv->pipeline,
+ "gradient_max_darkness"),
+ priv->gradient_max_darkness);
+
+ priv->changed &= ~CHANGED_GRADIENT_PARAMETERS;
+ }
+
if (priv->vignette)
{
color_component = priv->vignette_brightness * opacity / 255.;
@@ -484,11 +552,29 @@ meta_background_actor_set_property (GObject *object,
priv->screen = g_value_get_object (value);
break;
case PROP_MONITOR:
- priv->monitor = g_value_get_int (value);
+ meta_background_actor_set_monitor (self, g_value_get_int (value));
break;
case PROP_BACKGROUND:
meta_background_actor_set_background (self, g_value_get_object (value));
break;
+ case PROP_GRADIENT:
+ meta_background_actor_set_gradient (self,
+ g_value_get_boolean (value),
+ priv->gradient_height,
+ priv->gradient_max_darkness);
+ break;
+ case PROP_GRADIENT_HEIGHT:
+ meta_background_actor_set_gradient (self,
+ priv->gradient,
+ g_value_get_int (value),
+ priv->gradient_max_darkness);
+ break;
+ case PROP_GRADIENT_MAX_DARKNESS:
+ meta_background_actor_set_gradient (self,
+ priv->gradient,
+ priv->gradient_height,
+ g_value_get_double (value));
+ break;
case PROP_VIGNETTE:
meta_background_actor_set_vignette (self,
g_value_get_boolean (value),
@@ -532,6 +618,15 @@ meta_background_actor_get_property (GObject *object,
case PROP_BACKGROUND:
g_value_set_object (value, priv->background);
break;
+ case PROP_GRADIENT:
+ g_value_set_boolean (value, priv->gradient);
+ break;
+ case PROP_GRADIENT_HEIGHT:
+ g_value_set_int (value, priv->gradient_height);
+ break;
+ case PROP_GRADIENT_MAX_DARKNESS:
+ g_value_set_double (value, priv->gradient_max_darkness);
+ break;
case PROP_VIGNETTE:
g_value_set_boolean (value, priv->vignette);
break;
@@ -595,6 +690,36 @@ meta_background_actor_class_init (MetaBackgroundActorClass *klass)
PROP_BACKGROUND,
param_spec);
+ param_spec = g_param_spec_boolean ("gradient",
+ "Gradient",
+ "Whether gradient effect is enabled",
+ FALSE,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_property (object_class,
+ PROP_GRADIENT,
+ param_spec);
+
+ param_spec = g_param_spec_int ("gradient-height",
+ "Gradient Height",
+ "Height of gradient effect",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_property (object_class,
+ PROP_GRADIENT_HEIGHT,
+ param_spec);
+
+ param_spec = g_param_spec_double ("gradient-max-darkness",
+ "Gradient Max Darkness",
+ "How dark is the gradient initially",
+ 0.0, 1.0, 0.0,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_property (object_class,
+ PROP_GRADIENT_MAX_DARKNESS,
+ param_spec);
+
param_spec = g_param_spec_boolean ("vignette",
"Vignette",
"Whether vignette effect is enabled",
@@ -635,6 +760,10 @@ meta_background_actor_init (MetaBackgroundActor *self)
META_TYPE_BACKGROUND_ACTOR,
MetaBackgroundActorPrivate);
+ priv->gradient = FALSE;
+ priv->gradient_height = 0;
+ priv->gradient_max_darkness = 0.0;
+
priv->vignette = FALSE;
priv->vignette_brightness = 1.0;
priv->vignette_sharpness = 0.0;
@@ -752,6 +881,61 @@ meta_background_actor_set_background (MetaBackgroundActor *self,
}
void
+meta_background_actor_set_gradient (MetaBackgroundActor *self,
+ gboolean enabled,
+ int height,
+ double max_darkness)
+{
+ MetaBackgroundActorPrivate *priv;
+ gboolean changed = FALSE;
+
+ g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
+ g_return_if_fail (height >= 0);
+ g_return_if_fail (max_darkness >= 0. && max_darkness <= 1.);
+
+ priv = self->priv;
+
+ enabled = enabled != FALSE && height != 0;
+
+ if (enabled != priv->gradient)
+ {
+ priv->gradient = enabled;
+ invalidate_pipeline (self, CHANGED_EFFECTS);
+ changed = TRUE;
+ }
+
+ if (height != priv->gradient_height || max_darkness != priv->gradient_max_darkness)
+ {
+ priv->gradient_height = height;
+ priv->gradient_max_darkness = max_darkness;
+ invalidate_pipeline (self, CHANGED_GRADIENT_PARAMETERS);
+ changed = TRUE;
+ }
+
+ if (changed)
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
+}
+
+void
+meta_background_actor_set_monitor (MetaBackgroundActor *self,
+ int monitor)
+{
+ MetaBackgroundActorPrivate *priv = self->priv;
+ MetaRectangle old_monitor_geometry;
+ MetaRectangle new_monitor_geometry;
+
+ if(priv->monitor == monitor)
+ return;
+
+ meta_screen_get_monitor_geometry (priv->screen, priv->monitor, &old_monitor_geometry);
+ meta_screen_get_monitor_geometry (priv->screen, monitor, &new_monitor_geometry);
+ if(old_monitor_geometry.height != new_monitor_geometry.height)
+ invalidate_pipeline (self, CHANGED_GRADIENT_PARAMETERS);
+
+ priv->monitor = monitor;
+}
+
+void
meta_background_actor_set_vignette (MetaBackgroundActor *self,
gboolean enabled,
double brightness,