gl renderer: Rewrite shader builder
authorTimm Bäder <mail@baedert.org>
Sat, 14 Dec 2019 21:06:12 +0000 (22:06 +0100)
committerTimm Bäder <mail@baedert.org>
Tue, 7 Jan 2020 16:27:15 +0000 (17:27 +0100)
Use a unified approach to write both vertex and fragment shader in the
same file.

41 files changed:
gsk/gl/gskglrenderer.c
gsk/gl/gskglshaderbuilder.c [new file with mode: 0644]
gsk/gl/gskglshaderbuilderprivate.h [new file with mode: 0644]
gsk/gl/gskshaderbuilder.c [deleted file]
gsk/gl/gskshaderbuilderprivate.h [deleted file]
gsk/meson.build
gsk/resources/glsl/blend.fs.glsl [deleted file]
gsk/resources/glsl/blend.glsl [new file with mode: 0644]
gsk/resources/glsl/blit.fs.glsl [deleted file]
gsk/resources/glsl/blit.glsl [new file with mode: 0644]
gsk/resources/glsl/blit.vs.glsl [deleted file]
gsk/resources/glsl/blur.fs.glsl [deleted file]
gsk/resources/glsl/blur.glsl [new file with mode: 0644]
gsk/resources/glsl/border.fs.glsl [deleted file]
gsk/resources/glsl/border.glsl [new file with mode: 0644]
gsk/resources/glsl/color.fs.glsl [deleted file]
gsk/resources/glsl/color.glsl [new file with mode: 0644]
gsk/resources/glsl/color_matrix.fs.glsl [deleted file]
gsk/resources/glsl/color_matrix.glsl [new file with mode: 0644]
gsk/resources/glsl/coloring.fs.glsl [deleted file]
gsk/resources/glsl/coloring.glsl [new file with mode: 0644]
gsk/resources/glsl/cross_fade.fs.glsl [deleted file]
gsk/resources/glsl/cross_fade.glsl [new file with mode: 0644]
gsk/resources/glsl/es2_common.fs.glsl [deleted file]
gsk/resources/glsl/es2_common.vs.glsl [deleted file]
gsk/resources/glsl/gl3_common.fs.glsl [deleted file]
gsk/resources/glsl/gl3_common.vs.glsl [deleted file]
gsk/resources/glsl/gl_common.fs.glsl [deleted file]
gsk/resources/glsl/gl_common.vs.glsl [deleted file]
gsk/resources/glsl/inset_shadow.fs.glsl [deleted file]
gsk/resources/glsl/inset_shadow.glsl [new file with mode: 0644]
gsk/resources/glsl/linear_gradient.fs.glsl [deleted file]
gsk/resources/glsl/linear_gradient.glsl [new file with mode: 0644]
gsk/resources/glsl/outset_shadow.fs.glsl [deleted file]
gsk/resources/glsl/outset_shadow.glsl [new file with mode: 0644]
gsk/resources/glsl/preamble.fs.glsl [new file with mode: 0644]
gsk/resources/glsl/preamble.vs.glsl [new file with mode: 0644]
gsk/resources/glsl/repeat.fs.glsl [deleted file]
gsk/resources/glsl/repeat.glsl [new file with mode: 0644]
gsk/resources/glsl/unblurred_outset_shadow.fs.glsl [deleted file]
gsk/resources/glsl/unblurred_outset_shadow.glsl [new file with mode: 0644]

index 7f7767097723be9c54e9702d740282a66a68179f..999120cb01c543e3168fe480d79cabdde5661b08 100644 (file)
@@ -10,7 +10,7 @@
 #include "gskrendererprivate.h"
 #include "gskrendernodeprivate.h"
 #include "gsktransformprivate.h"
-#include "gskshaderbuilderprivate.h"
+#include "gskglshaderbuilderprivate.h"
 #include "gskglglyphcacheprivate.h"
 #include "gskgliconcacheprivate.h"
 #include "gskglrenderopsprivate.h"
@@ -411,19 +411,19 @@ struct _GskGLRenderer
   union {
     Program programs[GL_N_PROGRAMS];
     struct {
+      Program blend_program;
       Program blit_program;
+      Program blur_program;
+      Program border_program;
+      Program color_matrix_program;
       Program color_program;
       Program coloring_program;
-      Program color_matrix_program;
-      Program linear_gradient_program;
-      Program blur_program;
+      Program cross_fade_program;
       Program inset_shadow_program;
+      Program linear_gradient_program;
       Program outset_shadow_program;
-      Program unblurred_outset_shadow_program;
-      Program border_program;
-      Program cross_fade_program;
-      Program blend_program;
       Program repeat_program;
+      Program unblurred_outset_shadow_program;
     };
   };
 
@@ -2677,92 +2677,76 @@ static gboolean
 gsk_gl_renderer_create_programs (GskGLRenderer  *self,
                                  GError        **error)
 {
-  GskShaderBuilder *builder;
-  GError *shader_error = NULL;
+  GskGLShaderBuilder shader_builder;
   int i;
   static const struct {
+    const char *resource_path;
     const char *name;
-    const char *fs;
-    const char *vs;
   } program_definitions[] = {
-    { "blit",                      "blit.fs.glsl" },
-    { "color",                     "color.fs.glsl" },
-    { "coloring",                  "coloring.fs.glsl" },
-    { "color matrix",              "color_matrix.fs.glsl" },
-    { "linear gradient",           "linear_gradient.fs.glsl" },
-    { "blur",                      "blur.fs.glsl" },
-    { "inset shadow",              "inset_shadow.fs.glsl" },
-    { "outset shadow",             "outset_shadow.fs.glsl" },
-    { "unblurred outset shadow",   "unblurred_outset_shadow.fs.glsl" },
-    { "border",                    "border.fs.glsl" },
-    { "cross fade",                "cross_fade.fs.glsl" },
-    { "blend",                     "blend.fs.glsl" },
-    { "repeat",                    "repeat.fs.glsl" },
+    { "/org/gtk/libgsk/glsl/blend.glsl",                     "blend" },
+    { "/org/gtk/libgsk/glsl/blit.glsl",                      "blit" },
+    { "/org/gtk/libgsk/glsl/blur.glsl",                      "blur" },
+    { "/org/gtk/libgsk/glsl/border.glsl",                    "border" },
+    { "/org/gtk/libgsk/glsl/color_matrix.glsl",              "color matrix" },
+    { "/org/gtk/libgsk/glsl/color.glsl",                     "color" },
+    { "/org/gtk/libgsk/glsl/coloring.glsl",                  "coloring" },
+    { "/org/gtk/libgsk/glsl/cross_fade.glsl",                "cross fade" },
+    { "/org/gtk/libgsk/glsl/inset_shadow.glsl",              "inset shadow" },
+    { "/org/gtk/libgsk/glsl/linear_gradient.glsl",           "linear gradient" },
+    { "/org/gtk/libgsk/glsl/outset_shadow.glsl",             "outset shadow" },
+    { "/org/gtk/libgsk/glsl/repeat.glsl",                    "repeat" },
+    { "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl",   "unblurred_outset shadow" },
   };
+  gboolean success = TRUE;
+
+  gsk_gl_shader_builder_init (&shader_builder,
+                              "/org/gtk/libgsk/glsl/preamble.vs.glsl",
+                              "/org/gtk/libgsk/glsl/preamble.fs.glsl");
 
-  builder = gsk_shader_builder_new ();
+  g_assert (G_N_ELEMENTS (program_definitions) == GL_N_PROGRAMS);
 
-  gsk_shader_builder_set_resource_base_path (builder, "/org/gtk/libgsk/glsl");
+#ifdef G_ENABLE_DEBUG
+  if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), SHADERS))
+    shader_builder.debugging = TRUE;
+#endif
 
   if (gdk_gl_context_get_use_es (self->gl_context))
     {
-      gsk_shader_builder_set_version (builder, SHADER_VERSION_GLES);
-      gsk_shader_builder_set_vertex_preamble (builder, "es2_common.vs.glsl");
-      gsk_shader_builder_set_fragment_preamble (builder, "es2_common.fs.glsl");
-      gsk_shader_builder_add_define (builder, "GSK_GLES", "1");
+
+      gsk_gl_shader_builder_set_glsl_version (&shader_builder, SHADER_VERSION_GLES);
+      shader_builder.gles = TRUE;
     }
   else if (gdk_gl_context_is_legacy (self->gl_context))
     {
       int maj, min;
+
       gdk_gl_context_get_version (self->gl_context, &maj, &min);
 
       if (maj == 3)
-        gsk_shader_builder_set_version (builder, SHADER_VERSION_GL3_LEGACY);
+        gsk_gl_shader_builder_set_glsl_version (&shader_builder, SHADER_VERSION_GL3_LEGACY);
       else
-        gsk_shader_builder_set_version (builder, SHADER_VERSION_GL2_LEGACY);
+        gsk_gl_shader_builder_set_glsl_version (&shader_builder, SHADER_VERSION_GL2_LEGACY);
 
-      gsk_shader_builder_set_vertex_preamble (builder, "gl_common.vs.glsl");
-      gsk_shader_builder_set_fragment_preamble (builder, "gl_common.fs.glsl");
-      gsk_shader_builder_add_define (builder, "GSK_LEGACY", "1");
+      shader_builder.legacy = TRUE;
     }
   else
     {
-      gsk_shader_builder_set_version (builder, SHADER_VERSION_GL3);
-      gsk_shader_builder_set_vertex_preamble (builder, "gl3_common.vs.glsl");
-      gsk_shader_builder_set_fragment_preamble (builder, "gl3_common.fs.glsl");
-      gsk_shader_builder_add_define (builder, "GSK_GL3", "1");
+      gsk_gl_shader_builder_set_glsl_version (&shader_builder, SHADER_VERSION_GL3);
+      shader_builder.gl3 = TRUE;
     }
 
-#ifdef G_ENABLE_DEBUG
-  if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), SHADERS))
-    gsk_shader_builder_add_define (builder, "GSK_DEBUG", "1");
-#endif
-
-  gsk_shader_builder_set_common_vertex_shader (builder, "blit.vs.glsl",
-                                               &shader_error);
-
-  g_assert_no_error (shader_error);
-
   for (i = 0; i < GL_N_PROGRAMS; i ++)
     {
       Program *prog = &self->programs[i];
 
       prog->index = i;
-      prog->id = gsk_shader_builder_create_program (builder,
-                                                    program_definitions[i].fs,
-                                                    program_definitions[i].vs,
-                                                    &shader_error);
-
-      if (shader_error != NULL)
+      prog->id = gsk_gl_shader_builder_create_program (&shader_builder,
+                                                       program_definitions[i].resource_path,
+                                                       error);
+      if (prog->id < 0)
         {
-          g_propagate_prefixed_error (error, shader_error,
-                                      "Unable to create '%s' program (from %s and %s):\n",
-                                      program_definitions[i].name,
-                                      program_definitions[i].fs,
-                                      program_definitions[i].vs);
-
-          g_object_unref (builder);
-          return FALSE;
+          success = FALSE;
+          goto out;
         }
 
       INIT_COMMON_UNIFORM_LOCATION (prog, alpha);
@@ -2772,7 +2756,6 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
       INIT_COMMON_UNIFORM_LOCATION (prog, projection);
       INIT_COMMON_UNIFORM_LOCATION (prog, modelview);
     }
-
   /* color */
   INIT_PROGRAM_UNIFORM_LOCATION (color, color);
 
@@ -2827,8 +2810,10 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   INIT_PROGRAM_UNIFORM_LOCATION (repeat, child_bounds);
   INIT_PROGRAM_UNIFORM_LOCATION (repeat, texture_rect);
 
-  g_object_unref (builder);
-  return TRUE;
+out:
+  gsk_gl_shader_builder_finish (&shader_builder);
+
+  return success;
 }
 
 static GskGLTextureAtlases *
diff --git a/gsk/gl/gskglshaderbuilder.c b/gsk/gl/gskglshaderbuilder.c
new file mode 100644 (file)
index 0000000..f28bf12
--- /dev/null
@@ -0,0 +1,198 @@
+#include "config.h"
+
+#include "gskglshaderbuilderprivate.h"
+
+#include "gskdebugprivate.h"
+
+#include <gdk/gdk.h>
+#include <epoxy/gl.h>
+
+void
+gsk_gl_shader_builder_init (GskGLShaderBuilder *self,
+                            const char         *vs_preamble_resource_path,
+                            const char         *fs_preamble_resource_path)
+{
+  memset (self, 0, sizeof (*self));
+
+  self->vs_preamble = g_resources_lookup_data (vs_preamble_resource_path, 0, NULL);
+  self->fs_preamble = g_resources_lookup_data (fs_preamble_resource_path, 0, NULL);
+
+  g_assert (self->vs_preamble);
+  g_assert (self->fs_preamble);
+}
+
+void
+gsk_gl_shader_builder_finish (GskGLShaderBuilder *self)
+{
+  g_bytes_unref (self->vs_preamble);
+  g_bytes_unref (self->fs_preamble);
+}
+
+void
+gsk_gl_shader_builder_set_glsl_version (GskGLShaderBuilder *self,
+                                        int                 version)
+{
+  self->version = version;
+}
+
+static gboolean
+check_shader_error (int     shader_id,
+                    GError **error)
+{
+  int status;
+  int log_len;
+  char *buffer;
+  int code_len;
+  char *code;
+
+  glGetShaderiv (shader_id, GL_COMPILE_STATUS, &status);
+
+  if (G_LIKELY (status == GL_TRUE))
+    return TRUE;
+
+  glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &log_len);
+  buffer = g_malloc0 (log_len + 1);
+  glGetShaderInfoLog (shader_id, log_len, NULL, buffer);
+
+  glGetShaderiv (shader_id, GL_SHADER_SOURCE_LENGTH, &code_len);
+  code = g_malloc0 (code_len + 1);
+  glGetShaderSource (shader_id, code_len, NULL, code);
+
+  g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
+               "Compilation failure in shader.\nError message: %s\n\nSource code:\n%s\n\n",
+               buffer,
+               code);
+
+  g_free (buffer);
+  g_free (code);
+
+  return FALSE;
+}
+
+int
+gsk_gl_shader_builder_create_program (GskGLShaderBuilder  *self,
+                                      const char          *resource_path,
+                                      GError             **error)
+{
+
+  GBytes *source_bytes = g_resources_lookup_data (resource_path, 0, NULL);
+  char version_buffer[64];
+  const char *source;
+  const char *vertex_shader_start;
+  const char *fragment_shader_start;
+  int vertex_id;
+  int fragment_id;
+  int program_id = -1;
+  int status;
+
+  g_assert (source_bytes);
+
+  source = g_bytes_get_data (source_bytes, NULL);
+  vertex_shader_start = strstr (source, "VERTEX_SHADER");
+  fragment_shader_start = strstr (source, "FRAGMENT_SHADER");
+
+  g_assert (vertex_shader_start);
+  g_assert (fragment_shader_start);
+
+  /* They both start at the next newline */
+  vertex_shader_start = strstr (vertex_shader_start, "\n");
+  fragment_shader_start = strstr (fragment_shader_start, "\n");
+
+  g_snprintf (version_buffer, sizeof (version_buffer),
+              "#version %d\n", self->version);
+
+  vertex_id = glCreateShader (GL_VERTEX_SHADER);
+  glShaderSource (vertex_id, 7,
+                  (const char *[]) {
+                    version_buffer,
+                    self->debugging ? "#define GSK_DEBUG 1\n" : "",
+                    self->legacy ? "#define GSK_LEGACY 1\n" : "",
+                    self->gl3 ? "#define GSK_GL3 1\n" : "",
+                    self->gles ? "#define GSK_GLES 1\n" : "",
+                    g_bytes_get_data (self->vs_preamble, NULL),
+                    vertex_shader_start
+                  },
+                  (int[]) {
+                    -1,
+                    -1,
+                    -1,
+                    -1,
+                    -1,
+                    -1,
+                    fragment_shader_start - vertex_shader_start
+                  });
+  glCompileShader (vertex_id);
+
+  if (!check_shader_error (vertex_id, error))
+    {
+      glDeleteShader (vertex_id);
+      goto out;
+    }
+
+  fragment_id = glCreateShader (GL_FRAGMENT_SHADER);
+  glShaderSource (fragment_id, 7,
+                  (const char *[]) {
+                    version_buffer,
+                    self->debugging ? "#define GSK_DEBUG 1\n" : "",
+                    self->legacy ? "#define GSK_LEGACY 1\n" : "",
+                    self->gl3 ? "#define GSK_GL3 1\n" : "",
+                    self->gles ? "#define GSK_GLES 1\n" : "",
+                    g_bytes_get_data (self->fs_preamble, NULL),
+                    fragment_shader_start
+                  },
+                  (int[]) {
+                    -1,
+                    -1,
+                    -1,
+                    -1,
+                    -1,
+                    -1,
+                    -1,
+                  });
+  glCompileShader (fragment_id);
+
+  if (!check_shader_error (fragment_id, error))
+    {
+      glDeleteShader (fragment_id);
+      goto out;
+    }
+
+  program_id = glCreateProgram ();
+  glAttachShader (program_id, vertex_id);
+  glAttachShader (program_id, fragment_id);
+  glLinkProgram (program_id);
+
+  glGetProgramiv (program_id, GL_LINK_STATUS, &status);
+  if (status == GL_FALSE)
+    {
+      char *buffer = NULL;
+      int log_len = 0;
+
+      glGetProgramiv (program_id, GL_INFO_LOG_LENGTH, &log_len);
+
+      buffer = g_malloc0 (log_len + 1);
+      glGetProgramInfoLog (program_id, log_len, NULL, buffer);
+
+      g_warning ("Linking failure in shader:\n%s", buffer);
+      g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED,
+                   "Linking failure in shader: %s", buffer);
+
+      g_free (buffer);
+
+      glDeleteProgram (program_id);
+
+      goto out;
+    }
+
+  glDetachShader (program_id, vertex_id);
+  glDeleteShader (vertex_id);
+
+  glDetachShader (program_id, fragment_id);
+  glDeleteShader (fragment_id);
+
+out:
+  g_bytes_unref (source_bytes);
+
+  return program_id;
+}
+
diff --git a/gsk/gl/gskglshaderbuilderprivate.h b/gsk/gl/gskglshaderbuilderprivate.h
new file mode 100644 (file)
index 0000000..209fa5f
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __GSK_SHADER_BUILDER_PRIVATE_H__
+#define __GSK_SHADER_BUILDER_PRIVATE_H__
+
+#include <gdk/gdk.h>
+#include <graphene.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+  GBytes *vs_preamble;
+  GBytes *fs_preamble;
+
+  int version;
+
+  guint debugging: 1;
+  guint gles: 1;
+  guint gl3: 1;
+  guint legacy: 1;
+
+} GskGLShaderBuilder;
+
+
+void   gsk_gl_shader_builder_init             (GskGLShaderBuilder  *self,
+                                               const char          *vs_preamble_resource_path,
+                                               const char          *fs_preamble_resource_path);
+void   gsk_gl_shader_builder_finish           (GskGLShaderBuilder  *self);
+
+void   gsk_gl_shader_builder_set_glsl_version (GskGLShaderBuilder  *self,
+                                               int                  version);
+
+int    gsk_gl_shader_builder_create_program   (GskGLShaderBuilder  *self,
+                                               const char          *resource_path,
+                                               GError             **error);
+
+G_END_DECLS
+
+#endif /* __GSK_SHADER_BUILDER_PRIVATE_H__ */
diff --git a/gsk/gl/gskshaderbuilder.c b/gsk/gl/gskshaderbuilder.c
deleted file mode 100644 (file)
index 97cfbb8..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-#include "config.h"
-
-#include "gskshaderbuilderprivate.h"
-
-#include "gskdebugprivate.h"
-
-#include <gdk/gdk.h>
-#include <epoxy/gl.h>
-
-struct _GskShaderBuilder
-{
-  GObject parent_instance;
-
-  char *resource_base_path;
-  char *vertex_preamble;
-  char *fragment_preamble;
-
-
-  int common_vertex_shader_id;
-
-  int version;
-
-  GPtrArray *defines;
-
-  /* We reuse this one for all the shaders */
-  GString *shader_code;
-};
-
-G_DEFINE_TYPE (GskShaderBuilder, gsk_shader_builder, G_TYPE_OBJECT)
-
-static void
-gsk_shader_builder_finalize (GObject *gobject)
-{
-  GskShaderBuilder *self = GSK_SHADER_BUILDER (gobject);
-
-  g_free (self->resource_base_path);
-  g_free (self->vertex_preamble);
-  g_free (self->fragment_preamble);
-  g_string_free (self->shader_code, TRUE);
-
-  g_clear_pointer (&self->defines, g_ptr_array_unref);
-
-  if (self->common_vertex_shader_id > 0)
-    glDeleteShader (self->common_vertex_shader_id);
-
-  G_OBJECT_CLASS (gsk_shader_builder_parent_class)->finalize (gobject);
-}
-
-static void
-gsk_shader_builder_class_init (GskShaderBuilderClass *klass)
-{
-  G_OBJECT_CLASS (klass)->finalize = gsk_shader_builder_finalize;
-}
-
-static void
-gsk_shader_builder_init (GskShaderBuilder *self)
-{
-  self->defines = g_ptr_array_new_with_free_func (g_free);
-  self->shader_code = g_string_new (NULL);
-}
-
-GskShaderBuilder *
-gsk_shader_builder_new (void)
-{
-  return g_object_new (GSK_TYPE_SHADER_BUILDER, NULL);
-}
-
-void
-gsk_shader_builder_set_resource_base_path (GskShaderBuilder *builder,
-                                           const char       *base_path)
-{
-  g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
-
-  g_free (builder->resource_base_path);
-  builder->resource_base_path = g_strdup (base_path);
-}
-
-void
-gsk_shader_builder_set_vertex_preamble (GskShaderBuilder *builder,
-                                        const char       *vertex_preamble)
-{
-  g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
-
-  g_free (builder->vertex_preamble);
-  builder->vertex_preamble = g_strdup (vertex_preamble);
-}
-
-void
-gsk_shader_builder_set_fragment_preamble (GskShaderBuilder *builder,
-                                          const char       *fragment_preamble)
-{
-  g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
-
-  g_free (builder->fragment_preamble);
-  builder->fragment_preamble = g_strdup (fragment_preamble);
-}
-
-void
-gsk_shader_builder_set_version (GskShaderBuilder *builder,
-                                int               version)
-{
-  g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
-
-  builder->version = version;
-}
-
-void
-gsk_shader_builder_add_define (GskShaderBuilder *builder,
-                               const char       *define_name,
-                               const char       *define_value)
-{
-  g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
-  g_return_if_fail (define_name != NULL && *define_name != '\0');
-  g_return_if_fail (define_value != NULL && *define_value != '\0');
-
-  g_ptr_array_add (builder->defines, g_strdup (define_name));
-  g_ptr_array_add (builder->defines, g_strdup (define_value));
-}
-
-static gboolean
-lookup_shader_code (GString *code,
-                    const char *base_path,
-                    const char *shader_file,
-                    GError **error)
-{
-  GBytes *source;
-  char *path;
-
-  if (base_path != NULL)
-    path = g_build_filename (base_path, shader_file, NULL);
-  else
-    path = g_strdup (shader_file);
-
-  source = g_resources_lookup_data (path, 0, error);
-  g_free (path);
-
-  if (source == NULL)
-    return FALSE;
-
-  g_string_append (code, g_bytes_get_data (source, NULL));
-
-  g_bytes_unref (source);
-
-  return TRUE;
-}
-
-static int
-gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
-                                   int               shader_type,
-                                   const char       *shader_preamble,
-                                   const char       *shader_source,
-                                   GError          **error)
-{
-  GString *code;
-  const char *source;
-  int shader_id;
-  int status;
-  int i;
-
-  /* Clear possibly previously set shader code */
-  g_string_erase (builder->shader_code, 0, -1);
-  code = builder->shader_code;
-
-  if (builder->version > 0)
-    {
-      g_string_append_printf (code, "#version %d\n", builder->version);
-      g_string_append_c (code, '\n');
-    }
-
-  for (i = 0; i < builder->defines->len; i += 2)
-    {
-      const char *name = g_ptr_array_index (builder->defines, i);
-      const char *value = g_ptr_array_index (builder->defines, i + 1);
-
-      g_string_append (code, "#define");
-      g_string_append_c (code, ' ');
-      g_string_append (code, name);
-      g_string_append_c (code, ' ');
-      g_string_append (code, value);
-      g_string_append_c (code, '\n');
-    }
-
-  g_string_append_c (code, '\n');
-
-  if (!lookup_shader_code (code, builder->resource_base_path, shader_preamble, error))
-    {
-      return -1;
-    }
-
-  g_string_append_c (code, '\n');
-
-  if (!lookup_shader_code (code, builder->resource_base_path, shader_source, error))
-    {
-      return -1;
-    }
-
-  source = code->str;
-
-  shader_id = glCreateShader (shader_type);
-  glShaderSource (shader_id, 1, (const GLchar **) &source, NULL);
-  glCompileShader (shader_id);
-
-#ifdef G_ENABLE_DEBUG
-  if (GSK_DEBUG_CHECK (SHADERS))
-    {
-      g_print ("*** Compiling %s shader from '%s' + '%s' ***\n"
-               "%s\n",
-               shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
-               shader_preamble, shader_source,
-               source);
-    }
-#endif
-
-  glGetShaderiv (shader_id, GL_COMPILE_STATUS, &status);
-  if (status == GL_FALSE)
-    {
-      int log_len;
-      char *buffer;
-
-      glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &log_len);
-
-      buffer = g_malloc0 (log_len + 1);
-      glGetShaderInfoLog (shader_id, log_len, NULL, buffer);
-
-      g_message ("\n%s\n", source);
-
-      g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
-                   "Compilation failure in %s shader:\n%s",
-                   shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
-                   buffer);
-      g_free (buffer);
-
-      glDeleteShader (shader_id);
-
-      return -1;
-    }
-
-  return shader_id;
-}
-
-void
-gsk_shader_builder_set_common_vertex_shader (GskShaderBuilder  *self,
-                                             const char        *vertex_shader,
-                                             GError           **error)
-{
-  int shader_id;
-
-
-  shader_id = gsk_shader_builder_compile_shader (self,
-                                                 GL_VERTEX_SHADER,
-                                                 self->vertex_preamble,
-                                                 vertex_shader,
-                                                 error);
-
-  g_assert (shader_id > 0);
-  self->common_vertex_shader_id = shader_id;
-}
-
-int
-gsk_shader_builder_create_program (GskShaderBuilder *builder,
-                                   const char       *fragment_shader,
-                                   const char       *vertex_shader,
-                                   GError          **error)
-{
-  int vertex_id;
-  int fragment_id;
-  int program_id;
-  int status;
-
-  g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
-  g_return_val_if_fail (fragment_shader != NULL, -1);
-  g_return_val_if_fail (builder->common_vertex_shader_id != 0, -1);
-
-  if (vertex_shader == NULL)
-    vertex_id = builder->common_vertex_shader_id;
-  else
-    vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
-                                                   builder->vertex_preamble,
-                                                   vertex_shader,
-                                                   error);
-  if (vertex_id < 0)
-      return -1;
-
-  fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
-                                                   builder->fragment_preamble,
-                                                   fragment_shader,
-                                                   error);
-  if (fragment_id < 0)
-    {
-      glDeleteShader (vertex_id);
-      return -1;
-    }
-
-  program_id = glCreateProgram ();
-  glAttachShader (program_id, vertex_id);
-  glAttachShader (program_id, fragment_id);
-  glLinkProgram (program_id);
-
-  glGetProgramiv (program_id, GL_LINK_STATUS, &status);
-  if (status == GL_FALSE)
-    {
-      char *buffer = NULL;
-      int log_len = 0;
-
-      glGetProgramiv (program_id, GL_INFO_LOG_LENGTH, &log_len);
-
-      buffer = g_malloc0 (log_len + 1);
-      glGetProgramInfoLog (program_id, log_len, NULL, buffer);
-
-      g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED,
-                   "Linking failure in shader:\n%s", buffer);
-      g_free (buffer);
-
-      glDeleteProgram (program_id);
-      program_id = -1;
-
-      goto out;
-    }
-
-out:
-  if (vertex_id > 0)
-    {
-      /* We delete the common vertex shader when destroying the shader builder */
-      glDetachShader (program_id, vertex_id);
-    }
-
-  if (fragment_id > 0)
-    {
-      glDetachShader (program_id, fragment_id);
-      glDeleteShader (fragment_id);
-    }
-
-  return program_id;
-}
diff --git a/gsk/gl/gskshaderbuilderprivate.h b/gsk/gl/gskshaderbuilderprivate.h
deleted file mode 100644 (file)
index b91af84..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef __GSK_SHADER_BUILDER_PRIVATE_H__
-#define __GSK_SHADER_BUILDER_PRIVATE_H__
-
-#include <gdk/gdk.h>
-#include <graphene.h>
-
-G_BEGIN_DECLS
-
-#define GSK_TYPE_SHADER_BUILDER (gsk_shader_builder_get_type ())
-
-G_DECLARE_FINAL_TYPE (GskShaderBuilder, gsk_shader_builder, GSK, SHADER_BUILDER, GObject)
-
-GskShaderBuilder *      gsk_shader_builder_new                          (void);
-
-void                    gsk_shader_builder_set_version                  (GskShaderBuilder *builder,
-                                                                         int               version);
-void                    gsk_shader_builder_set_resource_base_path       (GskShaderBuilder *builder,
-                                                                         const char       *base_path);
-void                    gsk_shader_builder_set_vertex_preamble          (GskShaderBuilder *builder,
-                                                                         const char       *shader_preamble);
-void                    gsk_shader_builder_set_fragment_preamble        (GskShaderBuilder *builder,
-                                                                         const char       *shader_preamble);
-
-void                    gsk_shader_builder_add_define                   (GskShaderBuilder *builder,
-                                                                         const char       *define_name,
-                                                                         const char       *define_value);
-
-void                    gsk_shader_builder_set_common_vertex_shader     (GskShaderBuilder  *self,
-                                                                         const char        *vertex_shader,
-                                                                         GError           **error);
-
-int                     gsk_shader_builder_create_program               (GskShaderBuilder *builder,
-                                                                         const char       *fragment_shader,
-                                                                         const char       *vertex_shader,
-                                                                         GError          **error);
-
-G_END_DECLS
-
-#endif /* __GSK_SHADER_BUILDER_PRIVATE_H__ */
index c897cabdf6eb0faaa8c79df2a8d0354ec8e5c03f..6dd4925155897c1a5c31495f3afbb2f92aa0e300 100644 (file)
@@ -1,24 +1,19 @@
 gsk_private_gl_shaders = [
-  'resources/glsl/blit.fs.glsl',
-  'resources/glsl/blit.vs.glsl',
-  'resources/glsl/color.fs.glsl',
-  'resources/glsl/coloring.fs.glsl',
-  'resources/glsl/color_matrix.fs.glsl',
-  'resources/glsl/linear_gradient.fs.glsl',
-  'resources/glsl/blur.fs.glsl',
-  'resources/glsl/inset_shadow.fs.glsl',
-  'resources/glsl/outset_shadow.fs.glsl',
-  'resources/glsl/unblurred_outset_shadow.fs.glsl',
-  'resources/glsl/border.fs.glsl',
-  'resources/glsl/cross_fade.fs.glsl',
-  'resources/glsl/blend.fs.glsl',
-  'resources/glsl/repeat.fs.glsl',
-  'resources/glsl/es2_common.fs.glsl',
-  'resources/glsl/es2_common.vs.glsl',
-  'resources/glsl/gl3_common.fs.glsl',
-  'resources/glsl/gl3_common.vs.glsl',
-  'resources/glsl/gl_common.fs.glsl',
-  'resources/glsl/gl_common.vs.glsl',
+  'resources/glsl/preamble.fs.glsl',
+  'resources/glsl/preamble.vs.glsl',
+  'resources/glsl/border.glsl',
+  'resources/glsl/blit.glsl',
+  'resources/glsl/coloring.glsl',
+  'resources/glsl/color.glsl',
+  'resources/glsl/linear_gradient.glsl',
+  'resources/glsl/color_matrix.glsl',
+  'resources/glsl/blur.glsl',
+  'resources/glsl/inset_shadow.glsl',
+  'resources/glsl/outset_shadow.glsl',
+  'resources/glsl/unblurred_outset_shadow.glsl',
+  'resources/glsl/cross_fade.glsl',
+  'resources/glsl/blend.glsl',
+  'resources/glsl/repeat.glsl',
 ]
 
 gsk_public_sources = files([
@@ -38,7 +33,7 @@ gsk_private_sources = files([
   'gskdebug.c',
   'gskprivate.c',
   'gskprofiler.c',
-  'gl/gskshaderbuilder.c',
+  'gl/gskglshaderbuilder.c',
   'gl/gskglprofiler.c',
   'gl/gskglglyphcache.c',
   'gl/gskglimage.c',
diff --git a/gsk/resources/glsl/blend.fs.glsl b/gsk/resources/glsl/blend.fs.glsl
deleted file mode 100644 (file)
index 249b8fe..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-uniform int u_mode;
-uniform sampler2D u_source2;
-
-float
-combine (float source, float backdrop)
-{
-  return source + backdrop * (1.0 - source);
-}
-
-vec4
-composite (vec4 Cs, vec4 Cb, vec3 B)
-{
-  float ao = Cs.a + Cb.a * (1.0 - Cs.a);
-  vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
-  return vec4(Co, ao);
-}
-
-vec4
-normal (vec4 Cs, vec4 Cb)
-{
-  return composite (Cs, Cb, Cs.rgb);
-}
-
-vec4
-multiply (vec4 Cs, vec4 Cb)
-{
-  return composite (Cs, Cb, Cs.rgb * Cb.rgb);
-}
-
-vec4
-difference (vec4 Cs, vec4 Cb)
-{
-  return composite (Cs, Cb, abs(Cs.rgb - Cb.rgb));
-}
-
-vec4
-screen (vec4 Cs, vec4 Cb)
-{
-  return composite (Cs, Cb, Cs.rgb + Cb.rgb - Cs.rgb * Cb.rgb);
-}
-
-float
-hard_light (float source, float backdrop)
-{
-  if (source <= 0.5)
-    return 2.0 * backdrop * source;
-  else
-    return 2.0 * (backdrop + source - backdrop * source) - 1.0;
-}
-
-vec4
-hard_light (vec4 Cs, vec4 Cb)
-{
-  vec3 B = vec3 (hard_light (Cs.r, Cb.r),
-                 hard_light (Cs.g, Cb.g),
-                 hard_light (Cs.b, Cb.b));
-  return composite (Cs, Cb, B);
-}
-
-float
-soft_light (float source, float backdrop)
-{
-  float db;
-
-  if (backdrop <= 0.25)
-    db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
-  else
-    db = sqrt (backdrop);
-
-  if (source <= 0.5)
-    return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
-  else
-    return backdrop + (2.0 * source - 1.0) * (db - backdrop);
-}
-
-vec4
-soft_light (vec4 Cs, vec4 Cb)
-{
-  vec3 B = vec3 (soft_light (Cs.r, Cb.r),
-                 soft_light (Cs.g, Cb.g),
-                 soft_light (Cs.b, Cb.b));
-  return composite (Cs, Cb, B);
-}
-
-vec4
-overlay (vec4 Cs, vec4 Cb)
-{
-  vec3 B = vec3 (hard_light (Cb.r, Cs.r),
-                 hard_light (Cb.g, Cs.g),
-                 hard_light (Cb.b, Cs.b));
-  return composite (Cs, Cb, B);
-}
-
-vec4
-darken (vec4 Cs, vec4 Cb)
-{
-  vec3 B = min (Cs.rgb, Cb.rgb);
-  return composite (Cs, Cb, B);
-}
-
-vec4
-lighten (vec4 Cs, vec4 Cb)
-{
-  vec3 B = max (Cs.rgb, Cb.rgb);
-  return composite (Cs, Cb, B);
-}
-
-float
-color_dodge (float source, float backdrop)
-{
-  return (source == 1.0) ? source : min (backdrop / (1.0 - source), 1.0);
-}
-
-vec4
-color_dodge (vec4 Cs, vec4 Cb)
-{
-  vec3 B = vec3 (color_dodge (Cs.r, Cb.r),
-                 color_dodge (Cs.g, Cb.g),
-                 color_dodge (Cs.b, Cb.b));
-  return composite (Cs, Cb, B);
-}
-
-
-float
-color_burn (float source, float backdrop)
-{
-  return (source == 0.0) ? source : max ((1.0 - ((1.0 - backdrop) / source)), 0.0);
-}
-
-vec4
-color_burn (vec4 Cs, vec4 Cb)
-{
-  vec3 B = vec3 (color_burn (Cs.r, Cb.r),
-                 color_burn (Cs.g, Cb.g),
-                 color_burn (Cs.b, Cb.b));
-  return composite (Cs, Cb, B);
-}
-
-vec4
-exclusion (vec4 Cs, vec4 Cb)
-{
-  vec3 B = Cb.rgb + Cs.rgb - 2.0 * Cb.rgb * Cs.rgb;
-  return composite (Cs, Cb, B);
-}
-
-float
-lum (vec3 c)
-{
-  return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
-}
-
-vec3
-clip_color (vec3 c)
-{
-  float l = lum (c);
-  float n = min (c.r, min (c.g, c.b));
-  float x = max (c.r, max (c.g, c.b));
-  if (n < 0.0) c = l + (((c - l) * l) / (l - n));
-  if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
-  return c;
-}
-
-vec3
-set_lum (vec3 c, float l)
-{
-  float d = l - lum (c);
-  return clip_color (vec3 (c.r + d, c.g + d, c.b + d));
-}
-
-float
-sat (vec3 c)
-{
-  return max (c.r, max (c.g, c.b)) - min (c.r, min (c.g, c.b));
-}
-
-vec3
-set_sat (vec3 c, float s)
-{
-  float cmin = min (c.r, min (c.g, c.b));
-  float cmax = max (c.r, max (c.g, c.b));
-  vec3 res;
-
-  if (cmax == cmin)
-    res = vec3 (0, 0, 0);
-  else
-    {
-      if (c.r == cmax)
-        {
-          if (c.g == cmin)
-            {
-              res.b = ((c.b - cmin) * s) / (cmax - cmin);
-              res.g = 0.0;
-            }
-          else
-            {
-              res.g = ((c.g - cmin) * s) / (cmax - cmin);
-              res.b = 0.0;
-            }
-          res.r = s;
-        }
-      else if (c.g == cmax)
-        {
-          if (c.r == cmin)
-            {
-              res.b = ((c.b - cmin) * s) / (cmax - cmin);
-              res.r = 0.0;
-            }
-          else
-            {
-              res.r = ((c.r - cmin) * s) / (cmax - cmin);
-              res.b = 0.0;
-            }
-          res.g = s;
-        }
-      else
-        {
-          if (c.r == cmin)
-            {
-              res.g = ((c.g - cmin) * s) / (cmax - cmin);
-              res.r = 0.0;
-            }
-          else
-            {
-              res.r = ((c.r - cmin) * s) / (cmax - cmin);
-              res.g = 0.0;
-            }
-          res.b = s;
-        }
-    }
-  return res;
-}
-
-vec4
-color (vec4 Cs, vec4 Cb)
-{
-  vec3 B = set_lum (Cs.rgb, lum (Cb.rgb));
-  return composite (Cs, Cb, B);
-}
-
-vec4
-hue (vec4 Cs, vec4 Cb)
-{
-  vec3 B = set_lum (set_sat (Cs.rgb, sat (Cb.rgb)), lum (Cb.rgb));
-  return composite (Cs, Cb, B);
-}
-
-vec4
-saturation (vec4 Cs, vec4 Cb)
-{
-  vec3 B = set_lum (set_sat (Cb.rgb, sat (Cs.rgb)), lum (Cb.rgb));
-  return composite (Cs, Cb, B);
-}
-
-vec4
-luminosity (vec4 Cs, vec4 Cb)
-{
-  vec3 B = set_lum (Cb.rgb, lum (Cs.rgb));
-  return composite (Cs, Cb, B);
-}
-
-void main() {
-  vec4 bottom_color = Texture(u_source, vUv);
-  vec4 top_color = Texture(u_source2, vUv);
-
-  vec4 result;
-  if (u_mode == 0)
-    {
-      result = normal(top_color, bottom_color);
-    }
-  else if (u_mode == 1)
-    {
-      result = multiply(top_color, bottom_color);
-    }
-  else if (u_mode == 2)
-    {
-      result = screen(top_color, bottom_color);
-    }
-  else if (u_mode == 3)
-    {
-      result = overlay(top_color, bottom_color);
-    }
-  else if (u_mode == 4)
-    {
-      result = darken(top_color, bottom_color);
-    }
-  else if (u_mode == 5)
-    {
-      result = lighten(top_color, bottom_color);
-    }
-  else if (u_mode == 6)
-    {
-      result = color_dodge(top_color, bottom_color);
-    }
-  else if (u_mode == 7)
-    {
-      result = color_burn(top_color, bottom_color);
-    }
-  else if (u_mode == 8)
-    {
-      result = hard_light(top_color, bottom_color);
-    }
-  else if (u_mode == 9)
-    {
-      result = soft_light(top_color, bottom_color);
-    }
-  else if (u_mode == 10)
-    {
-      result = difference(top_color, bottom_color);
-    }
-  else if (u_mode == 11)
-    {
-      result = exclusion(top_color, bottom_color);
-    }
-  else if (u_mode == 12)
-    {
-      result = color(top_color, bottom_color);
-    }
-  else if (u_mode == 13)
-    {
-      result = hue(top_color, bottom_color);
-    }
-  else if (u_mode == 14)
-    {
-      result = saturation(top_color, bottom_color);
-    }
-  else if (u_mode == 15)
-    {
-      result = luminosity(top_color, bottom_color);
-    }
-  else
-    {
-      discard;
-    }
-
-  setOutputColor(result * u_alpha);
-}
diff --git a/gsk/resources/glsl/blend.glsl b/gsk/resources/glsl/blend.glsl
new file mode 100644 (file)
index 0000000..f1e0c49
--- /dev/null
@@ -0,0 +1,310 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform int u_mode;
+uniform sampler2D u_source2;
+
+float
+combine (float source, float backdrop)
+{
+  return source + backdrop * (1.0 - source);
+}
+
+vec4
+composite (vec4 Cs, vec4 Cb, vec3 B)
+{
+  float ao = Cs.a + Cb.a * (1.0 - Cs.a);
+  vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
+  return vec4(Co, ao);
+}
+
+vec4
+normal (vec4 Cs, vec4 Cb)
+{
+  return composite (Cs, Cb, Cs.rgb);
+}
+
+vec4
+multiply (vec4 Cs, vec4 Cb)
+{
+  return composite (Cs, Cb, Cs.rgb * Cb.rgb);
+}
+
+vec4
+difference (vec4 Cs, vec4 Cb)
+{
+  return composite (Cs, Cb, abs(Cs.rgb - Cb.rgb));
+}
+
+vec4
+screen (vec4 Cs, vec4 Cb)
+{
+  return composite (Cs, Cb, Cs.rgb + Cb.rgb - Cs.rgb * Cb.rgb);
+}
+
+float
+hard_light (float source, float backdrop)
+{
+  if (source <= 0.5)
+    return 2.0 * backdrop * source;
+  else
+    return 2.0 * (backdrop + source - backdrop * source) - 1.0;
+}
+
+vec4
+hard_light (vec4 Cs, vec4 Cb)
+{
+  vec3 B = vec3 (hard_light (Cs.r, Cb.r),
+                 hard_light (Cs.g, Cb.g),
+                 hard_light (Cs.b, Cb.b));
+  return composite (Cs, Cb, B);
+}
+
+float
+soft_light (float source, float backdrop)
+{
+  float db;
+
+  if (backdrop <= 0.25)
+    db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
+  else
+    db = sqrt (backdrop);
+
+  if (source <= 0.5)
+    return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
+  else
+    return backdrop + (2.0 * source - 1.0) * (db - backdrop);
+}
+
+vec4
+soft_light (vec4 Cs, vec4 Cb)
+{
+  vec3 B = vec3 (soft_light (Cs.r, Cb.r),
+                 soft_light (Cs.g, Cb.g),
+                 soft_light (Cs.b, Cb.b));
+  return composite (Cs, Cb, B);
+}
+
+vec4
+overlay (vec4 Cs, vec4 Cb)
+{
+  vec3 B = vec3 (hard_light (Cb.r, Cs.r),
+                 hard_light (Cb.g, Cs.g),
+                 hard_light (Cb.b, Cs.b));
+  return composite (Cs, Cb, B);
+}
+
+vec4
+darken (vec4 Cs, vec4 Cb)
+{
+  vec3 B = min (Cs.rgb, Cb.rgb);
+  return composite (Cs, Cb, B);
+}
+
+vec4
+lighten (vec4 Cs, vec4 Cb)
+{
+  vec3 B = max (Cs.rgb, Cb.rgb);
+  return composite (Cs, Cb, B);
+}
+
+float
+color_dodge (float source, float backdrop)
+{
+  return (source == 1.0) ? source : min (backdrop / (1.0 - source), 1.0);
+}
+
+vec4
+color_dodge (vec4 Cs, vec4 Cb)
+{
+  vec3 B = vec3 (color_dodge (Cs.r, Cb.r),
+                 color_dodge (Cs.g, Cb.g),
+                 color_dodge (Cs.b, Cb.b));
+  return composite (Cs, Cb, B);
+}
+
+
+float
+color_burn (float source, float backdrop)
+{
+  return (source == 0.0) ? source : max ((1.0 - ((1.0 - backdrop) / source)), 0.0);
+}
+
+vec4
+color_burn (vec4 Cs, vec4 Cb)
+{
+  vec3 B = vec3 (color_burn (Cs.r, Cb.r),
+                 color_burn (Cs.g, Cb.g),
+                 color_burn (Cs.b, Cb.b));
+  return composite (Cs, Cb, B);
+}
+
+vec4
+exclusion (vec4 Cs, vec4 Cb)
+{
+  vec3 B = Cb.rgb + Cs.rgb - 2.0 * Cb.rgb * Cs.rgb;
+  return composite (Cs, Cb, B);
+}
+
+float
+lum (vec3 c)
+{
+  return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
+}
+
+vec3
+clip_color (vec3 c)
+{
+  float l = lum (c);
+  float n = min (c.r, min (c.g, c.b));
+  float x = max (c.r, max (c.g, c.b));
+  if (n < 0.0) c = l + (((c - l) * l) / (l - n));
+  if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
+  return c;
+}
+
+vec3
+set_lum (vec3 c, float l)
+{
+  float d = l - lum (c);
+  return clip_color (vec3 (c.r + d, c.g + d, c.b + d));
+}
+
+float
+sat (vec3 c)
+{
+  return max (c.r, max (c.g, c.b)) - min (c.r, min (c.g, c.b));
+}
+
+vec3
+set_sat (vec3 c, float s)
+{
+  float cmin = min (c.r, min (c.g, c.b));
+  float cmax = max (c.r, max (c.g, c.b));
+  vec3 res;
+
+  if (cmax == cmin)
+    res = vec3 (0, 0, 0);
+  else
+    {
+      if (c.r == cmax)
+        {
+          if (c.g == cmin)
+            {
+              res.b = ((c.b - cmin) * s) / (cmax - cmin);
+              res.g = 0.0;
+            }
+          else
+            {
+              res.g = ((c.g - cmin) * s) / (cmax - cmin);
+              res.b = 0.0;
+            }
+          res.r = s;
+        }
+      else if (c.g == cmax)
+        {
+          if (c.r == cmin)
+            {
+              res.b = ((c.b - cmin) * s) / (cmax - cmin);
+              res.r = 0.0;
+            }
+          else
+            {
+              res.r = ((c.r - cmin) * s) / (cmax - cmin);
+              res.b = 0.0;
+            }
+          res.g = s;
+        }
+      else
+        {
+          if (c.r == cmin)
+            {
+              res.g = ((c.g - cmin) * s) / (cmax - cmin);
+              res.r = 0.0;
+            }
+          else
+            {
+              res.r = ((c.r - cmin) * s) / (cmax - cmin);
+              res.g = 0.0;
+            }
+          res.b = s;
+        }
+    }
+  return res;
+}
+
+vec4
+color (vec4 Cs, vec4 Cb)
+{
+  vec3 B = set_lum (Cs.rgb, lum (Cb.rgb));
+  return composite (Cs, Cb, B);
+}
+
+vec4
+hue (vec4 Cs, vec4 Cb)
+{
+  vec3 B = set_lum (set_sat (Cs.rgb, sat (Cb.rgb)), lum (Cb.rgb));
+  return composite (Cs, Cb, B);
+}
+
+vec4
+saturation (vec4 Cs, vec4 Cb)
+{
+  vec3 B = set_lum (set_sat (Cb.rgb, sat (Cs.rgb)), lum (Cb.rgb));
+  return composite (Cs, Cb, B);
+}
+
+vec4
+luminosity (vec4 Cs, vec4 Cb)
+{
+  vec3 B = set_lum (Cb.rgb, lum (Cs.rgb));
+  return composite (Cs, Cb, B);
+}
+
+void main() {
+  vec4 bottom_color = Texture(u_source, vUv);
+  vec4 top_color = Texture(u_source2, vUv);
+
+  vec4 result;
+  if (u_mode == 0)
+    result = normal(top_color, bottom_color);
+  else if (u_mode == 1)
+    result = multiply(top_color, bottom_color);
+  else if (u_mode == 2)
+    result = screen(top_color, bottom_color);
+  else if (u_mode == 3)
+    result = overlay(top_color, bottom_color);
+  else if (u_mode == 4)
+    result = darken(top_color, bottom_color);
+  else if (u_mode == 5)
+    result = lighten(top_color, bottom_color);
+  else if (u_mode == 6)
+    result = color_dodge(top_color, bottom_color);
+  else if (u_mode == 7)
+    result = color_burn(top_color, bottom_color);
+  else if (u_mode == 8)
+    result = hard_light(top_color, bottom_color);
+  else if (u_mode == 9)
+    result = soft_light(top_color, bottom_color);
+  else if (u_mode == 10)
+    result = difference(top_color, bottom_color);
+  else if (u_mode == 11)
+    result = exclusion(top_color, bottom_color);
+  else if (u_mode == 12)
+    result = color(top_color, bottom_color);
+  else if (u_mode == 13)
+    result = hue(top_color, bottom_color);
+  else if (u_mode == 14)
+    result = saturation(top_color, bottom_color);
+  else if (u_mode == 15)
+    result = luminosity(top_color, bottom_color);
+  else
+    discard;
+
+  setOutputColor(result * u_alpha);
+}
diff --git a/gsk/resources/glsl/blit.fs.glsl b/gsk/resources/glsl/blit.fs.glsl
deleted file mode 100644 (file)
index 594739d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-void main() {
-  vec4 diffuse = Texture(u_source, vUv);
-
-  setOutputColor(diffuse * u_alpha);
-}
diff --git a/gsk/resources/glsl/blit.glsl b/gsk/resources/glsl/blit.glsl
new file mode 100644 (file)
index 0000000..0f9fe10
--- /dev/null
@@ -0,0 +1,13 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+void main() {
+  vec4 diffuse = Texture(u_source, vUv);
+
+  setOutputColor(diffuse * u_alpha);
+}
diff --git a/gsk/resources/glsl/blit.vs.glsl b/gsk/resources/glsl/blit.vs.glsl
deleted file mode 100644 (file)
index 02b3285..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-void main() {
-  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
-
-  vUv = vec2(aUv.x, aUv.y);
-}
diff --git a/gsk/resources/glsl/blur.fs.glsl b/gsk/resources/glsl/blur.fs.glsl
deleted file mode 100644 (file)
index e4df8fd..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-uniform float u_blur_radius;
-uniform vec2 u_blur_size;
-uniform vec2 u_blur_dir;
-
-const float PI = 3.14159265;
-const float RADIUS_MULTIPLIER = 3.0;
-
-// blur_radius 0 is NOT supported and MUST be caught before.
-
-// Partially from http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
-void main() {
-  float sigma = u_blur_radius; // *shrug*
-  float blur_radius = u_blur_radius * RADIUS_MULTIPLIER;
-  vec3 incrementalGaussian;
-  incrementalGaussian.x = 1.0 / (sqrt(2.0 * PI) * sigma);
-  incrementalGaussian.y = exp(-0.5 / (sigma * sigma));
-  incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
-
-  vec2 pixel_step = vec2(1.0) / u_blur_size;
-
-  float coefficientSum = 0;
-  vec4 sum = Texture(u_source, vUv) * incrementalGaussian.x;
-  coefficientSum += incrementalGaussian.x;
-  incrementalGaussian.xy *= incrementalGaussian.yz;
-
-  int pixels_per_side = int(floor(blur_radius / 2.0));
-  for (int i = 1; i <= pixels_per_side; i++) {
-    vec2 p = i * pixel_step * u_blur_dir;
-
-    sum += Texture(u_source, vUv - p) * incrementalGaussian.x;
-    sum += Texture(u_source, vUv + p) * incrementalGaussian.x;
-
-    coefficientSum += 2.0 * incrementalGaussian.x;
-    incrementalGaussian.xy *= incrementalGaussian.yz;
-  }
-
-  setOutputColor(sum / coefficientSum);
-}
diff --git a/gsk/resources/glsl/blur.glsl b/gsk/resources/glsl/blur.glsl
new file mode 100644 (file)
index 0000000..4b0109b
--- /dev/null
@@ -0,0 +1,46 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform float u_blur_radius;
+uniform vec2 u_blur_size;
+uniform vec2 u_blur_dir;
+
+const float PI = 3.14159265;
+const float RADIUS_MULTIPLIER = 3.0;
+
+// blur_radius 0 is NOT supported and MUST be caught before.
+
+// Partially from http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
+void main() {
+  float sigma = u_blur_radius; // *shrug*
+  float blur_radius = u_blur_radius * RADIUS_MULTIPLIER;
+  vec3 incrementalGaussian;
+  incrementalGaussian.x = 1.0 / (sqrt(2.0 * PI) * sigma);
+  incrementalGaussian.y = exp(-0.5 / (sigma * sigma));
+  incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
+
+  vec2 pixel_step = vec2(1.0) / u_blur_size;
+
+  float coefficientSum = 0;
+  vec4 sum = Texture(u_source, vUv) * incrementalGaussian.x;
+  coefficientSum += incrementalGaussian.x;
+  incrementalGaussian.xy *= incrementalGaussian.yz;
+
+  int pixels_per_side = int(floor(blur_radius / 2.0));
+  for (int i = 1; i <= pixels_per_side; i++) {
+    vec2 p = i * pixel_step * u_blur_dir;
+
+    sum += Texture(u_source, vUv - p) * incrementalGaussian.x;
+    sum += Texture(u_source, vUv + p) * incrementalGaussian.x;
+
+    coefficientSum += 2.0 * incrementalGaussian.x;
+    incrementalGaussian.xy *= incrementalGaussian.yz;
+  }
+
+  setOutputColor(sum / coefficientSum);
+}
diff --git a/gsk/resources/glsl/border.fs.glsl b/gsk/resources/glsl/border.fs.glsl
deleted file mode 100644 (file)
index d83fb23..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-uniform vec4 u_color;
-uniform vec4 u_widths;
-uniform RoundedRect u_outline_rect;
-
-void main() {
-  vec4 f = gl_FragCoord;
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-
-  RoundedRect rinside = rounded_rect_shrink (u_outline_rect, u_widths);
-
-  float alpha = clamp (rounded_rect_coverage (u_outline_rect, f.xy) -
-                       rounded_rect_coverage (rinside, f.xy),
-                       0.0, 1.0);
-
-  /* Pre-multiply */
-  vec4 color = u_color;
-  color.rgb *= color.a;
-
-  setOutputColor (color * alpha * u_alpha);
-}
diff --git a/gsk/resources/glsl/border.glsl b/gsk/resources/glsl/border.glsl
new file mode 100644 (file)
index 0000000..e919461
--- /dev/null
@@ -0,0 +1,30 @@
+// VERTEX_SHADER:
+
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform vec4 u_color;
+uniform vec4 u_widths;
+uniform RoundedRect u_outline_rect;
+
+void main() {
+  vec4 f = gl_FragCoord;
+  f.x += u_viewport.x;
+  f.y = (u_viewport.y + u_viewport.w) - f.y;
+
+  RoundedRect rinside = rounded_rect_shrink (u_outline_rect, u_widths);
+
+  float alpha = clamp (rounded_rect_coverage (u_outline_rect, f.xy) -
+                       rounded_rect_coverage (rinside, f.xy),
+                       0.0, 1.0);
+
+  /* Pre-multiply */
+  vec4 color = u_color;
+  color.rgb *= color.a;
+
+  setOutputColor (color * alpha * u_alpha);
+}
diff --git a/gsk/resources/glsl/color.fs.glsl b/gsk/resources/glsl/color.fs.glsl
deleted file mode 100644 (file)
index b98bc21..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-uniform vec4 u_color;
-
-void main() {
-  vec4 color = u_color;
-
-  // Pre-multiply alpha
-  color.rgb *= color.a;
-  setOutputColor(color * u_alpha);
-}
diff --git a/gsk/resources/glsl/color.glsl b/gsk/resources/glsl/color.glsl
new file mode 100644 (file)
index 0000000..8163ddd
--- /dev/null
@@ -0,0 +1,18 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform vec4 u_color;
+
+void main() {
+  vec4 color = u_color;
+
+  // Pre-multiply alpha
+  color.rgb *= color.a;
+  setOutputColor(color * u_alpha);
+}
+
diff --git a/gsk/resources/glsl/color_matrix.fs.glsl b/gsk/resources/glsl/color_matrix.fs.glsl
deleted file mode 100644 (file)
index 284e0a9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-uniform mat4 u_color_matrix;
-uniform vec4 u_color_offset;
-
-void main() {
-  vec4 diffuse = Texture(u_source, vUv);
-  vec4 color;
-
-  color = diffuse;
-
-  // Un-premultilpy
-  if (color.a != 0.0)
-    color.rgb /= color.a;
-
-  color = u_color_matrix * color + u_color_offset;
-  color = clamp(color, 0.0f, 1.0f);
-
-  color.rgb *= color.a;
-
-  setOutputColor(color * u_alpha);
-}
diff --git a/gsk/resources/glsl/color_matrix.glsl b/gsk/resources/glsl/color_matrix.glsl
new file mode 100644 (file)
index 0000000..7904eae
--- /dev/null
@@ -0,0 +1,28 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform mat4 u_color_matrix;
+uniform vec4 u_color_offset;
+
+void main() {
+  vec4 diffuse = Texture(u_source, vUv);
+  vec4 color;
+
+  color = diffuse;
+
+  // Un-premultilpy
+  if (color.a != 0.0)
+    color.rgb /= color.a;
+
+  color = u_color_matrix * color + u_color_offset;
+  color = clamp(color, 0.0f, 1.0f);
+
+  color.rgb *= color.a;
+
+  setOutputColor(color * u_alpha);
+}
diff --git a/gsk/resources/glsl/coloring.fs.glsl b/gsk/resources/glsl/coloring.fs.glsl
deleted file mode 100644 (file)
index 9de8a13..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-uniform vec4 u_color;
-
-void main() {
-  vec4 diffuse = Texture(u_source, vUv);
-  vec4 color = u_color;
-
-  // pre-multiply
-  color.rgb *= color.a;
-
-  // u_source is drawn using cairo, so already pre-multiplied.
-  color = vec4(color.rgb * diffuse.a * u_alpha,
-               color.a * diffuse.a * u_alpha);
-
-  setOutputColor(color);
-}
diff --git a/gsk/resources/glsl/coloring.glsl b/gsk/resources/glsl/coloring.glsl
new file mode 100644 (file)
index 0000000..a61d922
--- /dev/null
@@ -0,0 +1,23 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform vec4 u_color;
+
+void main() {
+  vec4 diffuse = Texture(u_source, vUv);
+  vec4 color = u_color;
+
+  // pre-multiply
+  color.rgb *= color.a;
+
+  // u_source is drawn using cairo, so already pre-multiplied.
+  color = vec4(color.rgb * diffuse.a * u_alpha,
+               color.a * diffuse.a * u_alpha);
+
+  setOutputColor(color);
+}
diff --git a/gsk/resources/glsl/cross_fade.fs.glsl b/gsk/resources/glsl/cross_fade.fs.glsl
deleted file mode 100644 (file)
index 612673b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-
-uniform float u_progress;
-uniform sampler2D u_source2;
-
-void main() {
-  vec4 source1 = Texture(u_source, vUv);  // start child
-  vec4 source2 = Texture(u_source2, vUv); // end child
-
-  float p_start = (1.0 - u_progress) * u_alpha;
-  float p_end = u_progress * u_alpha;
-  vec4 color = (p_start * source1) + (p_end * source2);
-  setOutputColor(color);
-}
diff --git a/gsk/resources/glsl/cross_fade.glsl b/gsk/resources/glsl/cross_fade.glsl
new file mode 100644 (file)
index 0000000..d384042
--- /dev/null
@@ -0,0 +1,20 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform float u_progress;
+uniform sampler2D u_source2;
+
+void main() {
+  vec4 source1 = Texture(u_source, vUv);  // start child
+  vec4 source2 = Texture(u_source2, vUv); // end child
+
+  float p_start = (1.0 - u_progress) * u_alpha;
+  float p_end = u_progress * u_alpha;
+  vec4 color = (p_start * source1) + (p_end * source2);
+  setOutputColor(color);
+}
diff --git a/gsk/resources/glsl/es2_common.fs.glsl b/gsk/resources/glsl/es2_common.fs.glsl
deleted file mode 100644 (file)
index 9ee61eb..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-precision mediump float;
-
-uniform sampler2D u_source;
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-uniform float u_alpha;
-uniform vec4 u_viewport;
-
-// In GtkSnapshot coordinates
-uniform vec4 u_clip;
-uniform vec4 u_clip_corner_widths;
-uniform vec4 u_clip_corner_heights;
-
-varying vec2 vUv;
-
-
-struct RoundedRect
-{
-  vec4 bounds;
-  vec4 corner_widths;
-  vec4 corner_heights;
-};
-
-float
-ellipsis_dist (vec2 p, vec2 radius)
-{
-  if (radius == vec2(0, 0))
-    return 0.0;
-
-  vec2 p0 = p / radius;
-  vec2 p1 = 2.0 * p0 / radius;
-
-  return (dot(p0, p0) - 1.0) / length (p1);
-}
-
-float
-ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
-{
-  float d = ellipsis_dist (point - center, radius);
-  return clamp (0.5 - d, 0.0, 1.0);
-}
-
-float
-rounded_rect_coverage (RoundedRect r, vec2 p)
-{
-  if (p.x < r.bounds.x || p.y < r.bounds.y ||
-      p.x >= r.bounds.z || p.y >= r.bounds.w)
-    return 0.0;
-
-  vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
-  vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
-  vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
-  vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
-
-  vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x,  r.corner_heights.x);
-  vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y,  r.corner_heights.y);
-  vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
-  vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
-
-  float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
-  float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
-  float d_br = ellipsis_coverage(p, ref_br, rad_br);
-  float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
-
-  vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
-
-  bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
-                       p.x > ref_tr.x && p.y < ref_tr.y,
-                       p.x > ref_br.x && p.y > ref_br.y,
-                       p.x < ref_bl.x && p.y > ref_bl.y);
-
-  return 1.0 - dot(vec4(is_out), corner_coverages);
-}
-
-RoundedRect
-rounded_rect_shrink (RoundedRect r, vec4 amount)
-{
-  vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
-  vec4 new_widths = max (r.corner_widths - amount.wyyw, 0.0);
-  vec4 new_heights = max (r.corner_heights - amount.xxzz, 0.0);
-
-  return RoundedRect (new_bounds, new_widths, new_heights);
-}
-
-vec4 Texture(sampler2D sampler, vec2 texCoords) {
-  return texture2D(sampler, texCoords);
-}
-
-void setOutputColor(vec4 color) {
-  vec4 clipBounds = u_clip;
-  vec4 f = gl_FragCoord;
-
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-
-  clipBounds.z = clipBounds.x + clipBounds.z;
-  clipBounds.w = clipBounds.y + clipBounds.w;
-
-  RoundedRect r = RoundedRect(clipBounds, u_clip_corner_widths, u_clip_corner_heights);
-
-  gl_FragColor = color * rounded_rect_coverage(r, f.xy);
-  /*gl_FragColor = color;*/
-}
diff --git a/gsk/resources/glsl/es2_common.vs.glsl b/gsk/resources/glsl/es2_common.vs.glsl
deleted file mode 100644 (file)
index c39fc44..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-precision mediump float;
-
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-
-attribute vec2 aPosition;
-attribute vec2 aUv;
-
-varying vec2 vUv;
diff --git a/gsk/resources/glsl/gl3_common.fs.glsl b/gsk/resources/glsl/gl3_common.fs.glsl
deleted file mode 100644 (file)
index bdc2fc9..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-precision highp float;
-
-uniform sampler2D u_source;
-uniform mat4 u_projection = mat4(1.0);
-uniform mat4 u_modelview = mat4(1.0);
-uniform float u_alpha = 1.0;
-uniform vec4 u_viewport;
-
-struct RoundedRect
-{
-  vec4 bounds;
-  vec2 corners[4];
-};
-
-uniform RoundedRect u_clip_rect;
-
-in vec2 vUv;
-out vec4 outputColor;
-
-float
-ellipsis_dist (vec2 p, vec2 radius)
-{
-  if (radius == vec2(0, 0))
-    return 0.0;
-
-  vec2 p0 = p / radius;
-  vec2 p1 = 2.0 * p0 / radius;
-
-  return (dot(p0, p0) - 1.0) / length (p1);
-}
-
-float
-ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
-{
-  float d = ellipsis_dist (point - center, radius);
-  return clamp (0.5 - d, 0.0, 1.0);
-}
-
-float
-rounded_rect_coverage (RoundedRect r, vec2 p)
-{
-  if (p.x < r.bounds.x || p.y < r.bounds.y ||
-      p.x >= (r.bounds.x + r.bounds.z) || p.y >= (r.bounds.y + r.bounds.w))
-    return 0.0;
-
-  vec2 rad_tl = r.corners[0];
-  vec2 rad_tr = r.corners[1];
-  vec2 rad_br = r.corners[2];
-  vec2 rad_bl = r.corners[3];
-
-  vec2 ref_tl = r.bounds.xy + r.corners[0];
-  vec2 ref_tr = vec2(r.bounds.x + r.bounds.z, r.bounds.y) + (r.corners[1] * vec2(-1, 1));
-  vec2 ref_br = vec2(r.bounds.x + r.bounds.z, r.bounds.y + r.bounds.w) - r.corners[2];
-  vec2 ref_bl = vec2(r.bounds.x, r.bounds.y + r.bounds.w) + (r.corners[3] * vec2(1, -1));
-
-  float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
-  float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
-  float d_br = ellipsis_coverage(p, ref_br, rad_br);
-  float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
-
-  vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
-
-  bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
-                       p.x > ref_tr.x && p.y < ref_tr.y,
-                       p.x > ref_br.x && p.y > ref_br.y,
-                       p.x < ref_bl.x && p.y > ref_bl.y);
-
-  return 1.0 - dot(vec4(is_out), corner_coverages);
-}
-
-// amount is: top, right, bottom, left
-RoundedRect
-rounded_rect_shrink (RoundedRect r, vec4 amount)
-{
-  vec4 new_bounds = r.bounds;
-  vec2 new_corners[4];
-
-  new_bounds.xy += amount.wx;
-  new_bounds.zw -= amount.wx + amount.yz;
-
-  new_corners[0] = vec2(0);
-  new_corners[1] = vec2(0);
-  new_corners[2] = vec2(0);
-  new_corners[3] = vec2(0);
-
-  // Left top
-  if (r.corners[0].x > 0 || r.corners[0].y > 0)
-    new_corners[0] = r.corners[0] - amount.wx;
-
-  // top right
-  if (r.corners[1].x > 0 || r.corners[1].y > 0)
-    new_corners[1] = r.corners[1] - amount.yx;
-
-  // Bottom right
-  if (r.corners[2].x > 0 || r.corners[2].y > 0)
-    new_corners[2] = r.corners[2] - amount.yz;
-
-  // Bottom left
-  if (r.corners[3].x > 0 || r.corners[3].y > 0)
-    new_corners[3] = r.corners[3] - amount.wz;
-
-  return RoundedRect (new_bounds, new_corners);
-}
-
-vec4 Texture(sampler2D sampler, vec2 texCoords) {
-  return texture(sampler, texCoords);
-}
-
-void setOutputColor(vec4 color) {
-  vec4 f = gl_FragCoord;
-
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-
-  outputColor = color * rounded_rect_coverage(u_clip_rect, f.xy);
-  /*outputColor = color;*/
-}
diff --git a/gsk/resources/glsl/gl3_common.vs.glsl b/gsk/resources/glsl/gl3_common.vs.glsl
deleted file mode 100644 (file)
index 6630efe..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-
-in vec2 aPosition;
-in vec2 aUv;
-
-out vec2 vUv;
diff --git a/gsk/resources/glsl/gl_common.fs.glsl b/gsk/resources/glsl/gl_common.fs.glsl
deleted file mode 100644 (file)
index 4df992c..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-uniform sampler2D u_source;
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-uniform float u_alpha;
-uniform vec4 u_viewport;
-
-// In GtkSnapshot coordinates
-uniform vec4 u_clip;
-uniform vec4 u_clip_corner_widths;
-uniform vec4 u_clip_corner_heights;
-
-varying vec2 vUv;
-
-
-struct RoundedRect
-{
-  vec4 bounds;
-  vec4 corner_widths;
-  vec4 corner_heights;
-};
-
-float
-ellipsis_dist (vec2 p, vec2 radius)
-{
-  if (radius == vec2(0, 0))
-    return 0.0;
-
-  vec2 p0 = p / radius;
-  vec2 p1 = 2.0 * p0 / radius;
-
-  return (dot(p0, p0) - 1.0) / length (p1);
-}
-
-float
-ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
-{
-  float d = ellipsis_dist (point - center, radius);
-  return clamp (0.5 - d, 0.0, 1.0);
-}
-
-float
-rounded_rect_coverage (RoundedRect r, vec2 p)
-{
-  if (p.x < r.bounds.x || p.y < r.bounds.y ||
-      p.x >= r.bounds.z || p.y >= r.bounds.w)
-    return 0.0;
-
-  vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
-  vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
-  vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
-  vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
-
-  vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x,  r.corner_heights.x);
-  vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y,  r.corner_heights.y);
-  vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
-  vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
-
-  float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
-  float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
-  float d_br = ellipsis_coverage(p, ref_br, rad_br);
-  float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
-
-  vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
-
-  bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
-                       p.x > ref_tr.x && p.y < ref_tr.y,
-                       p.x > ref_br.x && p.y > ref_br.y,
-                       p.x < ref_bl.x && p.y > ref_bl.y);
-
-  return 1.0 - dot(vec4(is_out), corner_coverages);
-}
-
-RoundedRect
-rounded_rect_shrink (RoundedRect r, vec4 amount)
-{
-  vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
-  vec4 new_widths = max (r.corner_widths - amount.wyyw, 0.0);
-  vec4 new_heights = max (r.corner_heights - amount.xxzz, 0.0);
-
-  return RoundedRect (new_bounds, new_widths, new_heights);
-}
-
-vec4 Texture(sampler2D sampler, vec2 texCoords) {
-  return texture2D(sampler, texCoords);
-}
-
-void setOutputColor(vec4 color) {
-  vec4 clipBounds = u_clip;
-  vec4 f = gl_FragCoord;
-
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-
-  clipBounds.z = clipBounds.x + clipBounds.z;
-  clipBounds.w = clipBounds.y + clipBounds.w;
-
-  RoundedRect r = RoundedRect(clipBounds, u_clip_corner_widths, u_clip_corner_heights);
-
-  gl_FragColor = color * rounded_rect_coverage(r, f.xy);
-}
diff --git a/gsk/resources/glsl/gl_common.vs.glsl b/gsk/resources/glsl/gl_common.vs.glsl
deleted file mode 100644 (file)
index 8d52641..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-
-attribute vec2 aPosition;
-attribute vec2 aUv;
-
-varying vec2 vUv;
diff --git a/gsk/resources/glsl/inset_shadow.fs.glsl b/gsk/resources/glsl/inset_shadow.fs.glsl
deleted file mode 100644 (file)
index 44bd4d7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-uniform float u_spread;
-uniform vec4 u_color;
-uniform vec2 u_offset;
-uniform RoundedRect u_outline_rect;
-
-
-void main() {
-  vec4 f = gl_FragCoord;
-
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-
-  RoundedRect inside = rounded_rect_shrink(u_outline_rect, vec4(u_spread));
-  vec2 offset = vec2(u_offset.x, - u_offset.y);
-  vec4 color = vec4(u_color.rgb * u_color.a, u_color.a);
-  color = color * clamp (rounded_rect_coverage (u_outline_rect, f.xy) -
-                         rounded_rect_coverage (inside, f.xy - offset),
-                         0.0, 1.0);
-  setOutputColor(color * u_alpha);
-}
diff --git a/gsk/resources/glsl/inset_shadow.glsl b/gsk/resources/glsl/inset_shadow.glsl
new file mode 100644 (file)
index 0000000..fa0e467
--- /dev/null
@@ -0,0 +1,27 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform float u_spread;
+uniform vec4 u_color;
+uniform vec2 u_offset;
+uniform RoundedRect u_outline_rect;
+
+void main() {
+  vec4 f = gl_FragCoord;
+
+  f.x += u_viewport.x;
+  f.y = (u_viewport.y + u_viewport.w) - f.y;
+
+  RoundedRect inside = rounded_rect_shrink(u_outline_rect, vec4(u_spread));
+  vec2 offset = vec2(u_offset.x, - u_offset.y);
+  vec4 color = vec4(u_color.rgb * u_color.a, u_color.a);
+  color = color * clamp (rounded_rect_coverage (u_outline_rect, f.xy) -
+                         rounded_rect_coverage (inside, f.xy - offset),
+                         0.0, 1.0);
+  setOutputColor(color * u_alpha);
+}
diff --git a/gsk/resources/glsl/linear_gradient.fs.glsl b/gsk/resources/glsl/linear_gradient.fs.glsl
deleted file mode 100644 (file)
index 0b1f1cc..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-uniform vec4 u_color_stops[8];
-uniform float u_color_offsets[8];
-uniform int u_num_color_stops;
-uniform vec2 u_start_point;
-uniform vec2 u_end_point;
-
-vec4 fragCoord() {
-  vec4 f = gl_FragCoord;
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-  return f;
-}
-
-void main() {
-  vec2 startPoint = (u_modelview * vec4(u_start_point, 0, 1)).xy;
-  vec2 endPoint   = (u_modelview * vec4(u_end_point,   0, 1)).xy;
-  float maxDist   = length(endPoint - startPoint);
-
-  // Position relative to startPoint
-  vec2 pos = fragCoord().xy - startPoint;
-
-  // Gradient direction
-  vec2 gradient = endPoint - startPoint;
-  float gradientLength = length(gradient);
-
-  // Current pixel, projected onto the line between the start point and the end point
-  // The projection will be relative to the start point!
-  vec2 proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient;
-
-  // Offset of the current pixel
-  float offset = length(proj) / maxDist;
-
-  vec4 color = u_color_stops[0];
-  for (int i = 1; i < u_num_color_stops; i ++) {
-    if (offset >= u_color_offsets[i - 1])  {
-      float o = (offset - u_color_offsets[i - 1]) / (u_color_offsets[i] - u_color_offsets[i - 1]);
-      color = mix(u_color_stops[i - 1], u_color_stops[i], clamp(o, 0.0, 1.0));
-    }
-  }
-
-  /* Pre-multiply */
-  color.rgb *= color.a;
-
-  setOutputColor(color * u_alpha);
-}
diff --git a/gsk/resources/glsl/linear_gradient.glsl b/gsk/resources/glsl/linear_gradient.glsl
new file mode 100644 (file)
index 0000000..f0ba465
--- /dev/null
@@ -0,0 +1,53 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform vec4 u_color_stops[8];
+uniform float u_color_offsets[8];
+uniform int u_num_color_stops;
+uniform vec2 u_start_point;
+uniform vec2 u_end_point;
+
+vec4 fragCoord() {
+  vec4 f = gl_FragCoord;
+  f.x += u_viewport.x;
+  f.y = (u_viewport.y + u_viewport.w) - f.y;
+  return f;
+}
+
+void main() {
+  vec2 startPoint = (u_modelview * vec4(u_start_point, 0, 1)).xy;
+  vec2 endPoint   = (u_modelview * vec4(u_end_point,   0, 1)).xy;
+  float maxDist   = length(endPoint - startPoint);
+
+  // Position relative to startPoint
+  vec2 pos = fragCoord().xy - startPoint;
+
+  // Gradient direction
+  vec2 gradient = endPoint - startPoint;
+  float gradientLength = length(gradient);
+
+  // Current pixel, projected onto the line between the start point and the end point
+  // The projection will be relative to the start point!
+  vec2 proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient;
+
+  // Offset of the current pixel
+  float offset = length(proj) / maxDist;
+
+  vec4 color = u_color_stops[0];
+  for (int i = 1; i < u_num_color_stops; i ++) {
+    if (offset >= u_color_offsets[i - 1])  {
+      float o = (offset - u_color_offsets[i - 1]) / (u_color_offsets[i] - u_color_offsets[i - 1]);
+      color = mix(u_color_stops[i - 1], u_color_stops[i], clamp(o, 0.0, 1.0));
+    }
+  }
+
+  /* Pre-multiply */
+  color.rgb *= color.a;
+
+  setOutputColor(color * u_alpha);
+}
diff --git a/gsk/resources/glsl/outset_shadow.fs.glsl b/gsk/resources/glsl/outset_shadow.fs.glsl
deleted file mode 100644 (file)
index be8f78c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-uniform RoundedRect u_outline_rect;
-
-void main() {
-  vec4 f = gl_FragCoord;
-
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-
-  vec4 color = Texture(u_source, vUv);
-  color = color * (1.0 -  clamp(rounded_rect_coverage (u_outline_rect, f.xy), 0.0, 1.0));
-  setOutputColor(color * u_alpha);
-}
diff --git a/gsk/resources/glsl/outset_shadow.glsl b/gsk/resources/glsl/outset_shadow.glsl
new file mode 100644 (file)
index 0000000..150b5aa
--- /dev/null
@@ -0,0 +1,20 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform RoundedRect u_outline_rect;
+
+void main() {
+  vec4 f = gl_FragCoord;
+
+  f.x += u_viewport.x;
+  f.y = (u_viewport.y + u_viewport.w) - f.y;
+
+  vec4 color = Texture(u_source, vUv);
+  color = color * (1.0 -  clamp(rounded_rect_coverage (u_outline_rect, f.xy), 0.0, 1.0));
+  setOutputColor(color * u_alpha);
+}
diff --git a/gsk/resources/glsl/preamble.fs.glsl b/gsk/resources/glsl/preamble.fs.glsl
new file mode 100644 (file)
index 0000000..81ee188
--- /dev/null
@@ -0,0 +1,135 @@
+
+#if GDK_GL3
+precision highp float;
+#endif
+
+uniform sampler2D u_source;
+uniform mat4 u_projection;
+uniform mat4 u_modelview;
+uniform float u_alpha = 1.0;
+uniform vec4 u_viewport;
+
+struct RoundedRect
+{
+  vec4 bounds;
+  vec2 corners[4];
+};
+
+uniform RoundedRect u_clip_rect;
+
+#if GSK_GLES
+varying vec2 vUv;
+#elif GSK_LEGACY
+varying vec2 vUv;
+varying vec4 outputColor;
+#else
+in vec2 vUv;
+out vec4 outputColor;
+#endif
+
+float
+ellipsis_dist (vec2 p, vec2 radius)
+{
+  if (radius == vec2(0, 0))
+    return 0.0;
+
+  vec2 p0 = p / radius;
+  vec2 p1 = 2.0 * p0 / radius;
+
+  return (dot(p0, p0) - 1.0) / length (p1);
+}
+
+float
+ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
+{
+  float d = ellipsis_dist (point - center, radius);
+  return clamp (0.5 - d, 0.0, 1.0);
+}
+
+float
+rounded_rect_coverage (RoundedRect r, vec2 p)
+{
+  if (p.x < r.bounds.x || p.y < r.bounds.y ||
+      p.x >= (r.bounds.x + r.bounds.z) || p.y >= (r.bounds.y + r.bounds.w))
+    return 0.0;
+
+  vec2 rad_tl = r.corners[0];
+  vec2 rad_tr = r.corners[1];
+  vec2 rad_br = r.corners[2];
+  vec2 rad_bl = r.corners[3];
+
+  vec2 ref_tl = r.bounds.xy + r.corners[0];
+  vec2 ref_tr = vec2(r.bounds.x + r.bounds.z, r.bounds.y) + (r.corners[1] * vec2(-1, 1));
+  vec2 ref_br = vec2(r.bounds.x + r.bounds.z, r.bounds.y + r.bounds.w) - r.corners[2];
+  vec2 ref_bl = vec2(r.bounds.x, r.bounds.y + r.bounds.w) + (r.corners[3] * vec2(1, -1));
+
+  float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
+  float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
+  float d_br = ellipsis_coverage(p, ref_br, rad_br);
+  float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
+
+  vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
+
+  bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
+                       p.x > ref_tr.x && p.y < ref_tr.y,
+                       p.x > ref_br.x && p.y > ref_br.y,
+                       p.x < ref_bl.x && p.y > ref_bl.y);
+
+  return 1.0 - dot(vec4(is_out), corner_coverages);
+}
+
+// amount is: top, right, bottom, left
+RoundedRect
+rounded_rect_shrink (RoundedRect r, vec4 amount)
+{
+  vec4 new_bounds = r.bounds;
+  vec2 new_corners[4];
+
+  new_bounds.xy += amount.wx;
+  new_bounds.zw -= amount.wx + amount.yz;
+
+  new_corners[0] = vec2(0);
+  new_corners[1] = vec2(0);
+  new_corners[2] = vec2(0);
+  new_corners[3] = vec2(0);
+
+  // Left top
+  if (r.corners[0].x > 0 || r.corners[0].y > 0)
+    new_corners[0] = r.corners[0] - amount.wx;
+
+  // top right
+  if (r.corners[1].x > 0 || r.corners[1].y > 0)
+    new_corners[1] = r.corners[1] - amount.yx;
+
+  // Bottom right
+  if (r.corners[2].x > 0 || r.corners[2].y > 0)
+    new_corners[2] = r.corners[2] - amount.yz;
+
+  // Bottom left
+  if (r.corners[3].x > 0 || r.corners[3].y > 0)
+    new_corners[3] = r.corners[3] - amount.wz;
+
+  return RoundedRect (new_bounds, new_corners);
+}
+
+vec4 Texture(sampler2D sampler, vec2 texCoords) {
+#if GSK_GLES
+  return texture2D(sampler, texCoords);
+#else
+  return texture(sampler, texCoords);
+#endif
+}
+
+void setOutputColor(vec4 color) {
+  vec4 f = gl_FragCoord;
+
+  f.x += u_viewport.x;
+  f.y = (u_viewport.y + u_viewport.w) - f.y;
+
+#if GSK_GLES
+  gl_FragColor = color * rounded_rect_coverage(u_clip_rect, f.xy);
+#else
+  outputColor = color * rounded_rect_coverage(u_clip_rect, f.xy);
+#endif
+  /*outputColor = color;*/
+}
diff --git a/gsk/resources/glsl/preamble.vs.glsl b/gsk/resources/glsl/preamble.vs.glsl
new file mode 100644 (file)
index 0000000..2af42e5
--- /dev/null
@@ -0,0 +1,17 @@
+uniform mat4 u_projection;
+uniform mat4 u_modelview;
+
+
+#if GSK_GLES
+attribute vec2 aPosition;
+attribute vec2 aUv;
+varying vec2 vUv;
+#elif GSK_LEGACY
+attribute vec2 aPosition;
+attribute vec2 aUv;
+varying vec2 vUv;
+#else
+in vec2 aPosition;
+in vec2 aUv;
+out vec2 vUv;
+#endif
diff --git a/gsk/resources/glsl/repeat.fs.glsl b/gsk/resources/glsl/repeat.fs.glsl
deleted file mode 100644 (file)
index 0bd973e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-uniform vec4 u_child_bounds;
-uniform vec4 u_texture_rect;
-
-
-float wrap(float f, float wrap_for) {
-  return mod(f, wrap_for);
-}
-
-/* We get the texture coordinates via vUv,
- * but that might be on a texture atlas, so we need to do the
- * wrapping ourselves.
- */
-void main() {
-
-  /* We map the texture coordinate to [1;0], then wrap it and scale the result again */
-
-  float tw = u_texture_rect.z - u_texture_rect.x;
-  float th = u_texture_rect.w - u_texture_rect.y;
-
-  float mapped_x = (vUv.x - u_texture_rect.x) / tw;
-  float mapped_y = (vUv.y - u_texture_rect.y) / th;
-
-  float wrapped_x = wrap(u_child_bounds.x + mapped_x * u_child_bounds.z, 1.0);
-  float wrapped_y = wrap(u_child_bounds.y + mapped_y * u_child_bounds.w, 1.0);
-
-  vec2 tp;
-  tp.x = u_texture_rect.x + (wrapped_x * tw);
-  tp.y = u_texture_rect.y + (wrapped_y * th);
-
-  vec4 diffuse = Texture(u_source, tp);
-
-  setOutputColor(diffuse * u_alpha);
-}
diff --git a/gsk/resources/glsl/repeat.glsl b/gsk/resources/glsl/repeat.glsl
new file mode 100644 (file)
index 0000000..4f94ee3
--- /dev/null
@@ -0,0 +1,41 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform vec4 u_child_bounds;
+uniform vec4 u_texture_rect;
+
+
+float wrap(float f, float wrap_for) {
+  return mod(f, wrap_for);
+}
+
+/* We get the texture coordinates via vUv,
+ * but that might be on a texture atlas, so we need to do the
+ * wrapping ourselves.
+ */
+void main() {
+
+  /* We map the texture coordinate to [1;0], then wrap it and scale the result again */
+
+  float tw = u_texture_rect.z - u_texture_rect.x;
+  float th = u_texture_rect.w - u_texture_rect.y;
+
+  float mapped_x = (vUv.x - u_texture_rect.x) / tw;
+  float mapped_y = (vUv.y - u_texture_rect.y) / th;
+
+  float wrapped_x = wrap(u_child_bounds.x + mapped_x * u_child_bounds.z, 1.0);
+  float wrapped_y = wrap(u_child_bounds.y + mapped_y * u_child_bounds.w, 1.0);
+
+  vec2 tp;
+  tp.x = u_texture_rect.x + (wrapped_x * tw);
+  tp.y = u_texture_rect.y + (wrapped_y * th);
+
+  vec4 diffuse = Texture(u_source, tp);
+
+  setOutputColor(diffuse * u_alpha);
+}
diff --git a/gsk/resources/glsl/unblurred_outset_shadow.fs.glsl b/gsk/resources/glsl/unblurred_outset_shadow.fs.glsl
deleted file mode 100644 (file)
index ac37d0e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-uniform float u_spread;
-uniform vec4 u_color;
-uniform vec2 u_offset;
-uniform RoundedRect u_outline_rect;
-
-void main() {
-  vec4 f = gl_FragCoord;
-
-  f.x += u_viewport.x;
-  f.y = (u_viewport.y + u_viewport.w) - f.y;
-
-  RoundedRect outline = rounded_rect_shrink(u_outline_rect, vec4(- u_spread));
-
-  vec2 offset = vec2(u_offset.x, - u_offset.y);
-  vec4 color = vec4(u_color.rgb * u_color.a, u_color.a);
-  color = color * clamp (rounded_rect_coverage (outline, f.xy - offset) -
-                         rounded_rect_coverage (u_outline_rect, f.xy),
-                         0.0, 1.0);
-  setOutputColor(color * u_alpha);
-}
diff --git a/gsk/resources/glsl/unblurred_outset_shadow.glsl b/gsk/resources/glsl/unblurred_outset_shadow.glsl
new file mode 100644 (file)
index 0000000..fa14f11
--- /dev/null
@@ -0,0 +1,28 @@
+// VERTEX_SHADER:
+void main() {
+  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
+
+  vUv = vec2(aUv.x, aUv.y);
+}
+
+// FRAGMENT_SHADER:
+uniform float u_spread;
+uniform vec4 u_color;
+uniform vec2 u_offset;
+uniform RoundedRect u_outline_rect;
+
+void main() {
+  vec4 f = gl_FragCoord;
+
+  f.x += u_viewport.x;
+  f.y = (u_viewport.y + u_viewport.w) - f.y;
+
+  RoundedRect outline = rounded_rect_shrink(u_outline_rect, vec4(- u_spread));
+
+  vec2 offset = vec2(u_offset.x, - u_offset.y);
+  vec4 color = vec4(u_color.rgb * u_color.a, u_color.a);
+  color = color * clamp (rounded_rect_coverage (outline, f.xy - offset) -
+                         rounded_rect_coverage (u_outline_rect, f.xy),
+                         0.0, 1.0);
+  setOutputColor(color * u_alpha);
+}