[gnome-shell] shell: Actually make GLSLEffect an effect



commit 007d3057364e2d50cba9ece6a6d9da7aeedf5d87
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Jul 26 22:08:52 2019 +0200

    shell: Actually make GLSLEffect an effect
    
    A generic, introspectable Shader effect is not only more flexible
    than a shader actor, it will also make it much easier to turn
    Lightbox into an actor subclass and replace Tweener with Clutter's
    own animation support.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/651

 js/ui/lightbox.js       | 17 ++++++-----
 src/shell-glsl-effect.c | 81 +++++++++++++++++++++++++++++++++++--------------
 src/shell-glsl-effect.h |  4 +--
 3 files changed, 70 insertions(+), 32 deletions(-)
---
diff --git a/js/ui/lightbox.js b/js/ui/lightbox.js
index 423564097..18a309997 100644
--- a/js/ui/lightbox.js
+++ b/js/ui/lightbox.js
@@ -24,8 +24,8 @@ t = clamp(t, 0.0, 1.0);\n\
 float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
 cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
 
-var RadialShaderQuad = GObject.registerClass(
-class RadialShaderQuad extends Shell.GLSLEffect {
+var RadialShaderEffect = GObject.registerClass(
+class RadialShaderEffect extends Shell.GLSLEffect {
     _init(params) {
         super._init(params);
 
@@ -99,12 +99,13 @@ var Lightbox = class Lightbox {
         this._children = container.get_children();
         this._fadeFactor = params.fadeFactor;
         this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && 
params.radialEffect;
+
+        this.actor = new St.Bin({ reactive: params.inhibitEvents });
+
         if (this._radialEffect)
-            this.actor = new RadialShaderQuad({ reactive: params.inhibitEvents });
+            this.actor.add_effect(new RadialShaderEffect({ name: 'radial' }));
         else
-            this.actor = new St.Bin({ opacity: 0,
-                                      style_class: 'lightbox',
-                                      reactive: params.inhibitEvents });
+            this.actor.set({ opacity: 0, style_class: 'lightbox' });
 
         container.add_actor(this.actor);
         this.actor.raise_top();
@@ -155,7 +156,7 @@ var Lightbox = class Lightbox {
 
         Tweener.removeTweens(this.actor);
         if (this._radialEffect) {
-            Tweener.addTween(this.actor,
+            Tweener.addTween(this.actor.get_effect('radial'),
                              { brightness: VIGNETTE_BRIGHTNESS,
                                vignetteSharpness: VIGNETTE_SHARPNESS,
                                time: fadeInTime,
@@ -186,7 +187,7 @@ var Lightbox = class Lightbox {
         this.shown = false;
         Tweener.removeTweens(this.actor);
         if (this._radialEffect) {
-            Tweener.addTween(this.actor,
+            Tweener.addTween(this.actor.get_effect('radial'),
                              { brightness: 1.0,
                                vignetteSharpness: 0.0,
                                opacity: 0,
diff --git a/src/shell-glsl-effect.c b/src/shell-glsl-effect.c
index 04d39ca51..1ffe9d0d9 100644
--- a/src/shell-glsl-effect.c
+++ b/src/shell-glsl-effect.c
@@ -2,13 +2,11 @@
 
 /**
  * SECTION:shell-glsl-effect
- * @short_description: Draw a rectangle using GLSL
+ * @short_description: An offscreen effect using GLSL
  *
- * A #ShellGLSLEffect draws one single rectangle, sized to the allocation
- * box, but allows running custom GLSL to the vertex and fragment
- * stages of the graphic pipeline.
- *
- * To ease writing the shader, a single texture layer is also used.
+ * A #ShellGLSLEffect is a #ClutterOffscreenEffect that allows
+ * running custom GLSL to the vertex and fragment stages of the
+ * graphic pipeline.
  */
 
 #include "config.h"
@@ -20,29 +18,65 @@ typedef struct _ShellGLSLEffectPrivate ShellGLSLEffectPrivate;
 struct _ShellGLSLEffectPrivate
 {
   CoglPipeline  *pipeline;
+
+  gint tex_width;
+  gint tex_height;
 };
 
-G_DEFINE_TYPE_WITH_PRIVATE (ShellGLSLEffect, shell_glsl_effect, CLUTTER_TYPE_ACTOR);
+G_DEFINE_TYPE_WITH_PRIVATE (ShellGLSLEffect, shell_glsl_effect, CLUTTER_TYPE_OFFSCREEN_EFFECT);
 
 static gboolean
-shell_glsl_effect_get_paint_volume (ClutterActor       *actor,
-                                    ClutterPaintVolume *volume)
+shell_glsl_effect_pre_paint (ClutterEffect *effect)
 {
-  return clutter_paint_volume_set_from_allocation (volume, actor);
+  ShellGLSLEffect *self = SHELL_GLSL_EFFECT (effect);
+  ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect);
+  ShellGLSLEffectPrivate *priv = shell_glsl_effect_get_instance_private (self);
+  ClutterEffectClass *parent_class;
+  CoglHandle texture;
+  gboolean success;
+
+  if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
+    return FALSE;
+
+  if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
+    {
+      /* if we don't have support for GLSL shaders then we
+       * forcibly disable the ActorMeta
+       */
+      g_warning ("Unable to use the ShaderEffect: the graphics hardware "
+                 "or the current GL driver does not implement support "
+                 "for the GLSL shading language.");
+      clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE);
+      return FALSE;
+    }
+
+  parent_class = CLUTTER_EFFECT_CLASS (shell_glsl_effect_parent_class);
+  success = parent_class->pre_paint (effect);
+
+  if (!success)
+    return FALSE;
+
+  texture = clutter_offscreen_effect_get_texture (offscreen_effect);
+  priv->tex_width = cogl_texture_get_width (texture);
+  priv->tex_height = cogl_texture_get_height (texture);
+
+  cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
+
+  return TRUE;
 }
 
 static void
-shell_glsl_effect_paint (ClutterActor *actor)
+shell_glsl_effect_paint_target (ClutterOffscreenEffect *effect)
 {
-  ShellGLSLEffect *self = SHELL_GLSL_EFFECT (actor);
+  ShellGLSLEffect *self = SHELL_GLSL_EFFECT (effect);
   ShellGLSLEffectPrivate *priv;
+  ClutterActor *actor;
   guint8 paint_opacity;
-  ClutterActorBox box;
 
   priv = shell_glsl_effect_get_instance_private (self);
 
+  actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
   paint_opacity = clutter_actor_get_paint_opacity (actor);
-  clutter_actor_get_allocation_box (actor, &box);
 
   cogl_pipeline_set_color4ub (priv->pipeline,
                               paint_opacity,
@@ -51,8 +85,8 @@ shell_glsl_effect_paint (ClutterActor *actor)
                               paint_opacity);
   cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
                                    priv->pipeline,
-                                   box.x1, box.y1,
-                                   box.x2, box.y2);
+                                   0, 0,
+                                   priv->tex_width, priv->tex_height);
 }
 
 
@@ -64,7 +98,7 @@ shell_glsl_effect_paint (ClutterActor *actor)
  * @code: GLSL code
  * @is_replace: wheter Cogl code should be replaced by the custom shader
  *
- * Adds a GLSL snippet to the pipeline used for drawing the actor texture.
+ * Adds a GLSL snippet to the pipeline used for drawing the effect texture.
  * See #CoglSnippet for details.
  *
  * This is only valid inside the a call to the build_pipeline() virtual
@@ -149,20 +183,23 @@ shell_glsl_effect_constructed (GObject *object)
 
   priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
 
-  cogl_pipeline_set_layer_null_texture (priv->pipeline, 0);
+  cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
 }
 
 static void
 shell_glsl_effect_class_init (ShellGLSLEffectClass *klass)
 {
-  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  ClutterOffscreenEffectClass *offscreen_class;
+
+  offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
+  offscreen_class->paint_target = shell_glsl_effect_paint_target;
+
+  effect_class->pre_paint = shell_glsl_effect_pre_paint;
 
   gobject_class->constructed = shell_glsl_effect_constructed;
   gobject_class->dispose = shell_glsl_effect_dispose;
-
-  actor_class->get_paint_volume = shell_glsl_effect_get_paint_volume;
-  actor_class->paint = shell_glsl_effect_paint;
 }
 
 /**
diff --git a/src/shell-glsl-effect.h b/src/shell-glsl-effect.h
index 4c1ad7bf2..d943cefb8 100644
--- a/src/shell-glsl-effect.h
+++ b/src/shell-glsl-effect.h
@@ -28,11 +28,11 @@ typedef enum {
 
 #define SHELL_TYPE_GLSL_EFFECT (shell_glsl_effect_get_type ())
 G_DECLARE_DERIVABLE_TYPE (ShellGLSLEffect, shell_glsl_effect,
-                          SHELL, GLSL_EFFECT, ClutterActor)
+                          SHELL, GLSL_EFFECT, ClutterOffscreenEffect)
 
 struct _ShellGLSLEffectClass
 {
-  ClutterActorClass parent_class;
+  ClutterOffscreenEffectClass parent_class;
 
   CoglPipeline *base_pipeline;
 


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