#include "gskrendererprivate.h"
#include "gskrendernodeprivate.h"
#include "gsktransformprivate.h"
-#include "gskshaderbuilderprivate.h"
+#include "gskglshaderbuilderprivate.h"
#include "gskglglyphcacheprivate.h"
#include "gskgliconcacheprivate.h"
#include "gskglrenderopsprivate.h"
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;
};
};
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);
INIT_COMMON_UNIFORM_LOCATION (prog, projection);
INIT_COMMON_UNIFORM_LOCATION (prog, modelview);
}
-
/* color */
INIT_PROGRAM_UNIFORM_LOCATION (color, color);
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 *
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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__ */
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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__ */
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([
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
- 'gl/gskshaderbuilder.c',
+ 'gl/gskglshaderbuilder.c',
'gl/gskglprofiler.c',
'gl/gskglglyphcache.c',
'gl/gskglimage.c',
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-void main() {
- vec4 diffuse = Texture(u_source, vUv);
-
- setOutputColor(diffuse * u_alpha);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-void main() {
- gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
-
- vUv = vec2(aUv.x, aUv.y);
-}
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-uniform vec4 u_color;
-
-void main() {
- vec4 color = u_color;
-
- // Pre-multiply alpha
- color.rgb *= color.a;
- setOutputColor(color * u_alpha);
-}
--- /dev/null
+// 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);
+}
+
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-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;*/
-}
+++ /dev/null
-precision mediump float;
-
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-
-attribute vec2 aPosition;
-attribute vec2 aUv;
-
-varying vec2 vUv;
+++ /dev/null
-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;*/
-}
+++ /dev/null
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-
-in vec2 aPosition;
-in vec2 aUv;
-
-out vec2 vUv;
+++ /dev/null
-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);
-}
+++ /dev/null
-uniform mat4 u_projection;
-uniform mat4 u_modelview;
-
-attribute vec2 aPosition;
-attribute vec2 aUv;
-
-varying vec2 vUv;
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
--- /dev/null
+
+#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;*/
+}
--- /dev/null
+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
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}
+++ /dev/null
-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);
-}
--- /dev/null
+// 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);
+}