[gnome-shell/eos3.8: 133/255] code-view-effect: add shader effect for flipped window



commit c12e315312fe5ee78156529aab044bea328ee040
Author: Cosimo Cecchi <cosimo endlessm com>
Date:   Fri Nov 9 12:21:37 2018 -0800

    code-view-effect: add shader effect for flipped window
    
    We add a shader effect on the back of the window, as for the latest
    design. The shader is a gradient map with a 5-point color gradient.

 src/meson.build              |   2 +
 src/shell-code-view-effect.c | 299 +++++++++++++++++++++++++++++++++++++++++++
 src/shell-code-view-effect.h |  47 +++++++
 3 files changed, 348 insertions(+)
---
diff --git a/src/meson.build b/src/meson.build
index 2dc21a82b7..d40906e4a0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -93,6 +93,7 @@ libshell_public_headers = [
   'shell-app-system.h',
   'shell-app-usage.h',
   'shell-blur-effect.h',
+  'shell-code-view-effect.h',
   'shell-desktop-dir-info.h',
   'shell-dir-info.h',
   'shell-embedded-window.h',
@@ -132,6 +133,7 @@ libshell_sources = [
   'shell-app-system.c',
   'shell-app-usage.c',
   'shell-blur-effect.c',
+  'shell-code-view-effect.c',
   'shell-desktop-dir-info.c',
   'shell-dir-info.c',
   'shell-embedded-window.c',
diff --git a/src/shell-code-view-effect.c b/src/shell-code-view-effect.c
new file mode 100644
index 0000000000..1f1bfff981
--- /dev/null
+++ b/src/shell-code-view-effect.c
@@ -0,0 +1,299 @@
+/*
+ * shell-code-view-effect.c
+ *
+ * Based on clutter-desaturate-effect.c.
+ *
+ * Copyright (C) 2010  Intel Corporation.
+ * Copyright (C) 2018  Endless Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Emmanuele Bassi <ebassi linux intel com>
+ *   Cosimo Cecchi <cosimo endlessm com>
+ */
+
+#include <math.h>
+
+#include "shell-code-view-effect.h"
+
+#include <cogl/cogl.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct
+{
+  ClutterColor gradient_colors[5];
+  gfloat gradient_points[5];
+
+  gint gradient_colors_uniform;
+  gint gradient_points_uniform;
+
+  CoglPipeline *pipeline;
+} ShellCodeViewEffectPrivate;
+
+struct _ShellCodeViewEffectClass
+{
+  ClutterOffscreenEffectClass parent_class;
+
+  CoglPipeline *base_pipeline;
+};
+
+/* the magic gray vec3 has been taken from the NTSC conversion weights
+ * as defined by:
+ *
+ *   "OpenGL Superbible, 4th edition"
+ *   -- Richard S. Wright Jr, Benjamin Lipchak, Nicholas Haemel
+ *   Addison-Wesley
+ */
+static const gchar *glsl_declarations =
+  "uniform vec3 colors[5];\n"
+  "uniform float points[5];\n"
+  "\n"
+  "vec4 gradient_map (const vec4 color)\n"
+  "{\n"
+  "  if (color.a != 1.0)\n"
+  "  {\n"
+  "    return color;\n"
+  "  }\n"
+  "  const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n"
+  "  float desaturated = dot (color.rgb, gray_conv);\n"
+  "  vec4 color_out = color;\n"
+  "  if (desaturated <= points[1])\n"
+  "  {\n"
+  "    color_out.rgb = mix (colors[0], colors[1], (desaturated - points[0]) / (points[1] - points[0]));\n"
+  "  }\n"
+  "  else if (desaturated <= points[2])\n"
+  "  {\n"
+  "    color_out.rgb = mix (colors[1], colors[2], (desaturated - points[1]) / (points[2] - points[1]));\n"
+  "  }\n"
+  "  else if (desaturated <= points[3])\n"
+  "  {\n"
+  "    color_out.rgb = mix (colors[2], colors[3], (desaturated - points[2]) / (points[3] - points[2]));\n"
+  "  }\n"
+  "  else\n"
+  "  {\n"
+  "    color_out.rgb = mix (colors[3], colors[4], (desaturated - points[3]) / (points[4] - points[3]));\n"
+  "  }\n"
+  "  return color_out;\n"
+  "}\n";
+
+static const gchar *glsl_source =
+  "  cogl_color_out.rgba = gradient_map (cogl_color_out.rgba);";
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (ShellCodeViewEffect,
+                            shell_code_view_effect,
+                            CLUTTER_TYPE_OFFSCREEN_EFFECT)
+
+static gboolean
+shell_code_view_effect_pre_paint (ClutterEffect       *effect,
+                                  ClutterPaintContext *paint_context)
+{
+  ShellCodeViewEffect *self = SHELL_CODE_VIEW_EFFECT (effect);
+  ShellCodeViewEffectPrivate *priv = shell_code_view_effect_get_instance_private (self);
+  ClutterEffectClass *parent_class;
+
+  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_code_view_effect_parent_class);
+  if (parent_class->pre_paint (effect, paint_context))
+    {
+      ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect);
+      CoglHandle texture;
+
+      texture = clutter_offscreen_effect_get_texture (offscreen_effect);
+      cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
+
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static void
+shell_code_view_effect_paint_target (ClutterOffscreenEffect *effect,
+                                     ClutterPaintContext    *paint_context)
+{
+  ShellCodeViewEffect *self = SHELL_CODE_VIEW_EFFECT (effect);
+  ShellCodeViewEffectPrivate *priv = shell_code_view_effect_get_instance_private (self);
+  CoglFramebuffer *fb;
+  ClutterActor *actor;
+  CoglHandle texture;
+  guint8 paint_opacity;
+
+  texture = clutter_offscreen_effect_get_texture (effect);
+  cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
+
+  actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
+  paint_opacity = clutter_actor_get_paint_opacity (actor);
+
+  fb = clutter_paint_context_get_framebuffer (paint_context);
+  cogl_pipeline_set_color4ub (priv->pipeline,
+                              paint_opacity,
+                              paint_opacity,
+                              paint_opacity,
+                              paint_opacity);
+  cogl_framebuffer_draw_rectangle (fb, priv->pipeline,
+                                   0, 0,
+                                   cogl_texture_get_width (texture),
+                                   cogl_texture_get_height (texture));
+}
+
+static void
+shell_code_view_effect_dispose (GObject *gobject)
+{
+  ShellCodeViewEffect *self = SHELL_CODE_VIEW_EFFECT (gobject);
+  ShellCodeViewEffectPrivate *priv = shell_code_view_effect_get_instance_private (self);
+
+  g_clear_pointer (&priv->pipeline, cogl_object_unref);
+
+  G_OBJECT_CLASS (shell_code_view_effect_parent_class)->dispose (gobject);
+}
+
+static void
+update_gradient_uniforms (ShellCodeViewEffect *self)
+{
+  ShellCodeViewEffectPrivate *priv = shell_code_view_effect_get_instance_private (self);
+
+  if (!(priv->gradient_points_uniform > -1) || !(priv->gradient_colors_uniform > -1))
+    return;
+
+  cogl_pipeline_set_uniform_float (priv->pipeline,
+                                   priv->gradient_points_uniform,
+                                   1, /* n_components */
+                                   5, /* count */
+                                   priv->gradient_points);
+
+  float colors[15];
+
+  int i = 0;
+  for (int j = 0; j < 5; j++)
+    {
+      colors[i++] = priv->gradient_colors[j].red / 255.0;
+      colors[i++] = priv->gradient_colors[j].green / 255.0;
+      colors[i++] = priv->gradient_colors[j].blue / 255.0;
+    }
+
+  cogl_pipeline_set_uniform_float (priv->pipeline,
+                                   priv->gradient_colors_uniform,
+                                   3, /* n_components */
+                                   5, /* count */
+                                   colors);
+}
+
+static void
+shell_code_view_effect_class_init (ShellCodeViewEffectClass *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_code_view_effect_paint_target;
+
+  effect_class->pre_paint = shell_code_view_effect_pre_paint;
+
+  gobject_class->dispose = shell_code_view_effect_dispose;
+}
+
+static void
+shell_code_view_effect_init (ShellCodeViewEffect *self)
+{
+  ShellCodeViewEffectClass *klass = SHELL_CODE_VIEW_EFFECT_GET_CLASS (self);
+  ShellCodeViewEffectPrivate *priv = shell_code_view_effect_get_instance_private (self);
+
+  if (G_UNLIKELY (klass->base_pipeline == NULL))
+    {
+      CoglContext *ctx =
+        clutter_backend_get_cogl_context (clutter_get_default_backend ());
+      CoglSnippet *snippet;
+
+      klass->base_pipeline = cogl_pipeline_new (ctx);
+
+      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                                  glsl_declarations,
+                                  glsl_source);
+      cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
+      cogl_object_unref (snippet);
+
+      cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
+    }
+
+  priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
+
+  priv->gradient_colors_uniform =
+    cogl_pipeline_get_uniform_location (priv->pipeline, "colors");
+  priv->gradient_points_uniform =
+    cogl_pipeline_get_uniform_location (priv->pipeline, "points");
+
+  update_gradient_uniforms (self);
+}
+
+/**
+ * shell_code_view_effect_set_gradient_stops:
+ * @effect: a #ShellCodeViewEffect
+ * @gradient_colors: (array length=gradient_len) (element-type utf8): gradient colors
+ * @gradient_points: (array length=gradient_len) (element-type gfloat): gradient points
+ * @gradient_len: length of gradient stops
+ *
+ * Set the gradient colors and stop points for this effect.
+ */
+void
+shell_code_view_effect_set_gradient_stops (ShellCodeViewEffect *effect,
+                                           gchar **gradient_colors,
+                                           gfloat *gradient_points,
+                                           gsize gradient_len)
+{
+  ShellCodeViewEffectPrivate *priv = shell_code_view_effect_get_instance_private (effect);
+  gint i;
+
+  g_return_if_fail (gradient_colors != NULL);
+  g_return_if_fail (gradient_points != NULL);
+  g_return_if_fail (gradient_len == 5);
+
+  memcpy (priv->gradient_points, gradient_points, sizeof (gfloat) * gradient_len);
+  for (i = 0; i < gradient_len; i++)
+    clutter_color_from_string (&priv->gradient_colors[i], gradient_colors[i]);
+
+  update_gradient_uniforms (effect);
+}
+
+/**
+ * shell_code_view_effect_new:
+ *
+ * Creates a new #ShellCodeViewEffect to be used with
+ * clutter_actor_add_effect()
+ *
+ * Return value: the newly created #ShellCodeViewEffect or %NULL
+ */
+ClutterEffect *
+shell_code_view_effect_new (void)
+{
+  return g_object_new (SHELL_TYPE_CODE_VIEW_EFFECT, NULL);
+}
diff --git a/src/shell-code-view-effect.h b/src/shell-code-view-effect.h
new file mode 100644
index 0000000000..a33dc4e77a
--- /dev/null
+++ b/src/shell-code-view-effect.h
@@ -0,0 +1,47 @@
+/*
+ * shell-code-view-effect.h
+ *
+ * Based on clutter-desaturate-effect.h.
+ *
+ * Copyright (C) 2010  Intel Corporation.
+ * Copyright (C) 2018  Endless Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Emmanuele Bassi <ebassi linux intel com>
+ *   Cosimo Cecchi <cosimo endlessm com>
+ */
+
+#ifndef __SHELL_CODE_VIEW_EFFECT_H__
+#define __SHELL_CODE_VIEW_EFFECT_H__
+
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define SHELL_TYPE_CODE_VIEW_EFFECT (shell_code_view_effect_get_type ())
+G_DECLARE_DERIVABLE_TYPE (ShellCodeViewEffect, shell_code_view_effect,
+                          SHELL, CODE_VIEW_EFFECT, ClutterOffscreenEffect)
+
+ClutterEffect *shell_code_view_effect_new        (void);
+
+void shell_code_view_effect_set_gradient_stops (ShellCodeViewEffect *effect,
+                                                gchar **gradient_colors,
+                                                gfloat *gradient_points,
+                                                gsize gradient_len);
+
+G_END_DECLS
+
+#endif /* __SHELL_CODE_VIEW_EFFECT_H__ */


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