From: Timm Bäder Date: Sat, 14 Dec 2019 21:06:12 +0000 (+0100) Subject: gl renderer: Rewrite shader builder X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~20^2~439 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=cc909b160f3ad3fd2eca78cbfff695ca54d8b7b4;p=gtk4.git gl renderer: Rewrite shader builder Use a unified approach to write both vertex and fragment shader in the same file. --- diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 7f77670977..999120cb01 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -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 index 0000000000..f28bf127f7 --- /dev/null +++ b/gsk/gl/gskglshaderbuilder.c @@ -0,0 +1,198 @@ +#include "config.h" + +#include "gskglshaderbuilderprivate.h" + +#include "gskdebugprivate.h" + +#include +#include + +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 index 0000000000..209fa5ff91 --- /dev/null +++ b/gsk/gl/gskglshaderbuilderprivate.h @@ -0,0 +1,38 @@ +#ifndef __GSK_SHADER_BUILDER_PRIVATE_H__ +#define __GSK_SHADER_BUILDER_PRIVATE_H__ + +#include +#include + +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 index 97cfbb8113..0000000000 --- a/gsk/gl/gskshaderbuilder.c +++ /dev/null @@ -1,334 +0,0 @@ -#include "config.h" - -#include "gskshaderbuilderprivate.h" - -#include "gskdebugprivate.h" - -#include -#include - -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 index b91af84ea6..0000000000 --- a/gsk/gl/gskshaderbuilderprivate.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __GSK_SHADER_BUILDER_PRIVATE_H__ -#define __GSK_SHADER_BUILDER_PRIVATE_H__ - -#include -#include - -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__ */ diff --git a/gsk/meson.build b/gsk/meson.build index c897cabdf6..6dd4925155 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -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 index 249b8fe6e4..0000000000 --- a/gsk/resources/glsl/blend.fs.glsl +++ /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 index 0000000000..f1e0c49b5e --- /dev/null +++ b/gsk/resources/glsl/blend.glsl @@ -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 index 594739d5ab..0000000000 --- a/gsk/resources/glsl/blit.fs.glsl +++ /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 index 0000000000..0f9fe10067 --- /dev/null +++ b/gsk/resources/glsl/blit.glsl @@ -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 index 02b3285a9a..0000000000 --- a/gsk/resources/glsl/blit.vs.glsl +++ /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 index e4df8fd704..0000000000 --- a/gsk/resources/glsl/blur.fs.glsl +++ /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 index 0000000000..4b0109bbfc --- /dev/null +++ b/gsk/resources/glsl/blur.glsl @@ -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 index d83fb23828..0000000000 --- a/gsk/resources/glsl/border.fs.glsl +++ /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 index 0000000000..e919461cce --- /dev/null +++ b/gsk/resources/glsl/border.glsl @@ -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 index b98bc21a9e..0000000000 --- a/gsk/resources/glsl/color.fs.glsl +++ /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 index 0000000000..8163dddfd0 --- /dev/null +++ b/gsk/resources/glsl/color.glsl @@ -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 index 284e0a9e65..0000000000 --- a/gsk/resources/glsl/color_matrix.fs.glsl +++ /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 index 0000000000..7904eae70c --- /dev/null +++ b/gsk/resources/glsl/color_matrix.glsl @@ -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 index 9de8a13ba7..0000000000 --- a/gsk/resources/glsl/coloring.fs.glsl +++ /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 index 0000000000..a61d9222b4 --- /dev/null +++ b/gsk/resources/glsl/coloring.glsl @@ -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 index 612673bf66..0000000000 --- a/gsk/resources/glsl/cross_fade.fs.glsl +++ /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 index 0000000000..d3840423fa --- /dev/null +++ b/gsk/resources/glsl/cross_fade.glsl @@ -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 index 9ee61eb15e..0000000000 --- a/gsk/resources/glsl/es2_common.fs.glsl +++ /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 index c39fc444d9..0000000000 --- a/gsk/resources/glsl/es2_common.vs.glsl +++ /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 index bdc2fc92aa..0000000000 --- a/gsk/resources/glsl/gl3_common.fs.glsl +++ /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 index 6630efe73f..0000000000 --- a/gsk/resources/glsl/gl3_common.vs.glsl +++ /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 index 4df992c2df..0000000000 --- a/gsk/resources/glsl/gl_common.fs.glsl +++ /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 index 8d52641d1f..0000000000 --- a/gsk/resources/glsl/gl_common.vs.glsl +++ /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 index 44bd4d733d..0000000000 --- a/gsk/resources/glsl/inset_shadow.fs.glsl +++ /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 index 0000000000..fa0e46769b --- /dev/null +++ b/gsk/resources/glsl/inset_shadow.glsl @@ -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 index 0b1f1cc0c1..0000000000 --- a/gsk/resources/glsl/linear_gradient.fs.glsl +++ /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 index 0000000000..f0ba46517f --- /dev/null +++ b/gsk/resources/glsl/linear_gradient.glsl @@ -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 index be8f78c297..0000000000 --- a/gsk/resources/glsl/outset_shadow.fs.glsl +++ /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 index 0000000000..150b5aafce --- /dev/null +++ b/gsk/resources/glsl/outset_shadow.glsl @@ -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 index 0000000000..81ee188ef5 --- /dev/null +++ b/gsk/resources/glsl/preamble.fs.glsl @@ -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 index 0000000000..2af42e58e1 --- /dev/null +++ b/gsk/resources/glsl/preamble.vs.glsl @@ -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 index 0bd973eea9..0000000000 --- a/gsk/resources/glsl/repeat.fs.glsl +++ /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 index 0000000000..4f94ee3506 --- /dev/null +++ b/gsk/resources/glsl/repeat.glsl @@ -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 index ac37d0eadb..0000000000 --- a/gsk/resources/glsl/unblurred_outset_shadow.fs.glsl +++ /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 index 0000000000..fa14f11629 --- /dev/null +++ b/gsk/resources/glsl/unblurred_outset_shadow.glsl @@ -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); +}