[gtk/glshader-paintable: 1/8] GskGLShader: Drop fallback node and add try_compile function to replace it
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/glshader-paintable: 1/8] GskGLShader: Drop fallback node and add try_compile function to replace it
- Date: Fri, 25 Sep 2020 21:22:39 +0000 (UTC)
commit e93a51b1cc585762043e2b945898d457b655beb9
Author: Alexander Larsson <alexl redhat com>
Date: Fri Sep 25 14:05:21 2020 +0200
GskGLShader: Drop fallback node and add try_compile function to replace it
This removes the fallback node from GskGLShaderNode and adds
a new function gsk_gl_shader_try_compile_for() which tries to compile a
shader against a renderer. Then you can use the return value of this
both as a way to implement the fallback, and as a way to get at
the error report in a saner way.
demos/gtk-demo/gtkshaderbin.c | 53 +++++++---
demos/gtk-demo/gtkshaderstack.c | 33 +++---
gsk/broadway/gskbroadwayrenderer.c | 12 +--
gsk/gl/gskglrenderer.c | 207 ++++++++++++++++++++++---------------
gsk/gl/gskglrendererprivate.h | 14 +++
gsk/gl/gskglrenderopsprivate.h | 3 +-
gsk/gskglshader.c | 35 +++++++
gsk/gskglshader.h | 4 +
gsk/gskrendernode.h | 3 -
gsk/gskrendernodeimpl.c | 37 ++-----
gsk/gskrendernodeparser.c | 5 +-
gsk/vulkan/gskvulkanrenderpass.c | 5 +-
gtk/gtksnapshot.c | 41 +++-----
gtk/inspector/recorder.c | 2 +-
14 files changed, 262 insertions(+), 192 deletions(-)
---
diff --git a/demos/gtk-demo/gtkshaderbin.c b/demos/gtk-demo/gtkshaderbin.c
index bf18b735f9..c617984b7e 100644
--- a/demos/gtk-demo/gtkshaderbin.c
+++ b/demos/gtk-demo/gtkshaderbin.c
@@ -4,13 +4,15 @@ typedef struct {
GskGLShader *shader;
GtkStateFlags state;
GtkStateFlags state_mask;
+ gboolean compiled;
+ gboolean compiled_ok;
} ShaderInfo;
struct _GtkShaderBin
{
GtkWidget parent_instance;
GtkWidget *child;
- GskGLShader *active_shader;
+ ShaderInfo *active_shader;
GPtrArray *shaders;
guint tick_id;
float time;
@@ -79,7 +81,7 @@ void
gtk_shader_bin_update_active_shader (GtkShaderBin *self)
{
GtkStateFlags new_state = gtk_widget_get_state_flags (GTK_WIDGET (self));
- GskGLShader *new_shader = NULL;
+ ShaderInfo *new_shader = NULL;
for (int i = 0; i < self->shaders->len; i++)
{
@@ -87,7 +89,7 @@ gtk_shader_bin_update_active_shader (GtkShaderBin *self)
if ((info->state_mask & new_state) == info->state)
{
- new_shader = info->shader;
+ new_shader = info;
break;
}
}
@@ -177,20 +179,39 @@ gtk_shader_bin_snapshot (GtkWidget *widget,
if (self->active_shader)
{
- gtk_snapshot_push_gl_shader_v (snapshot, self->active_shader,
- &GRAPHENE_RECT_INIT(0, 0, width, height),
- 1,
- "u_time", &self->time,
- NULL);
- gtk_widget_snapshot_child (widget, self->child, snapshot);
- gtk_snapshot_pop (snapshot); /* Fallback */
- gtk_widget_snapshot_child (widget, self->child, snapshot);
- gtk_snapshot_pop (snapshot); /* Shader node child 1 */
- }
- else
- {
- gtk_widget_snapshot_child (widget, self->child, snapshot);
+ if (!self->active_shader->compiled)
+ {
+ GtkNative *native = gtk_widget_get_native (widget);
+ GskRenderer *renderer = gtk_native_get_renderer (native);
+ GError *error = NULL;
+
+ self->active_shader->compiled = TRUE;
+ self->active_shader->compiled_ok =
+ gsk_gl_shader_try_compile_for (self->active_shader->shader,
+ renderer, &error);
+ if (!self->active_shader->compiled_ok)
+ {
+ g_warning ("GtkShaderBin failed to compile shader: %s", error->message);
+ g_error_free (error);
+ }
+ }
+
+ if (self->active_shader->compiled_ok)
+ {
+ gtk_snapshot_push_gl_shader_v (snapshot, self->active_shader->shader,
+ &GRAPHENE_RECT_INIT(0, 0, width, height),
+ 1,
+ "u_time", &self->time,
+ NULL);
+ gtk_widget_snapshot_child (widget, self->child, snapshot);
+ gtk_snapshot_pop (snapshot);
+
+ return;
+ }
}
+
+ /* Non-shader fallback */
+ gtk_widget_snapshot_child (widget, self->child, snapshot);
}
static void
diff --git a/demos/gtk-demo/gtkshaderstack.c b/demos/gtk-demo/gtkshaderstack.c
index 8b3b336cf6..d83e115764 100644
--- a/demos/gtk-demo/gtkshaderstack.c
+++ b/demos/gtk-demo/gtkshaderstack.c
@@ -222,6 +222,8 @@ gtk_shader_stack_snapshot (GtkWidget *widget,
}
else
{
+ GtkNative *native = gtk_widget_get_native (widget);
+ GskRenderer *renderer = gtk_native_get_renderer (native);
float progress;
next = g_ptr_array_index (self->children, self->next);
@@ -236,18 +238,25 @@ gtk_shader_stack_snapshot (GtkWidget *widget,
progress = 1. - progress;
}
- gtk_snapshot_push_gl_shader_v (snapshot,
- self->shader,
- &GRAPHENE_RECT_INIT(0, 0, width, height),
- 2,
- "progress", &progress,
- NULL);
- gtk_widget_snapshot_child (widget, next, snapshot);
- gtk_snapshot_pop (snapshot); /* Fallback */
- gtk_widget_snapshot_child (widget, current, snapshot);
- gtk_snapshot_pop (snapshot); /* current child */
- gtk_widget_snapshot_child (widget, next, snapshot);
- gtk_snapshot_pop (snapshot); /* next child */
+ if (gsk_gl_shader_try_compile_for (self->shader,
+ renderer, NULL))
+ {
+ gtk_snapshot_push_gl_shader_v (snapshot,
+ self->shader,
+ &GRAPHENE_RECT_INIT(0, 0, width, height),
+ 2,
+ "progress", &progress,
+ NULL);
+ gtk_widget_snapshot_child (widget, current, snapshot);
+ gtk_snapshot_pop (snapshot); /* current child */
+ gtk_widget_snapshot_child (widget, next, snapshot);
+ gtk_snapshot_pop (snapshot); /* next child */
+ }
+ else
+ {
+ /* Non-shader fallback */
+ gtk_widget_snapshot_child (widget, current, snapshot);
+ }
}
}
diff --git a/gsk/broadway/gskbroadwayrenderer.c b/gsk/broadway/gskbroadwayrenderer.c
index 1dd8e8164d..bb6de84846 100644
--- a/gsk/broadway/gskbroadwayrenderer.c
+++ b/gsk/broadway/gskbroadwayrenderer.c
@@ -258,6 +258,7 @@ collect_reused_child_nodes (GskRenderer *renderer,
case GSK_LINEAR_GRADIENT_NODE:
/* Fallbacks (=> leaf for now */
+ case GSK_GL_SHADER_NODE:
case GSK_COLOR_MATRIX_NODE:
case GSK_TEXT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
@@ -272,11 +273,6 @@ collect_reused_child_nodes (GskRenderer *renderer,
/* Bin nodes */
- case GSK_GL_SHADER_NODE:
- collect_reused_node (renderer,
- gsk_gl_shader_node_get_fallback_child (node));
- break;
-
case GSK_SHADOW_NODE:
collect_reused_node (renderer,
gsk_shadow_node_get_child (node));
@@ -797,11 +793,6 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
}
return;
- case GSK_GL_SHADER_NODE:
- gsk_broadway_renderer_add_node (renderer,
- gsk_gl_shader_node_get_fallback_child (node), offset_x, offset_y,
clip_bounds);
- return;
-
/* Generic nodes */
case GSK_CONTAINER_NODE:
@@ -857,6 +848,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
case GSK_BLEND_NODE:
case GSK_CROSS_FADE_NODE:
case GSK_BLUR_NODE:
+ case GSK_GL_SHADER_NODE:
default:
break; /* Fallback */
}
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index b31d7c3cea..cb7fe8aaeb 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -1,6 +1,6 @@
#include "config.h"
-#include "gskglrenderer.h"
+#include "gskglrendererprivate.h"
#include "gskdebugprivate.h"
#include "gskenums.h"
@@ -138,7 +138,6 @@ print_render_node_tree (GskRenderNode *root, int level)
case GSK_GL_SHADER_NODE:
g_print ("%*s GL Shader\n", level * INDENT, " ");
- print_render_node_tree (gsk_gl_shader_node_get_fallback_child (root), level + 1);
for (i = 0; i < gsk_gl_shader_node_get_n_children (root); i++)
print_render_node_tree (gsk_gl_shader_node_get_child (root, i), level + 1);
break;
@@ -1053,93 +1052,136 @@ render_texture_node (GskGLRenderer *self,
}
}
-static inline void
-render_gl_shader_node (GskGLRenderer *self,
- GskRenderNode *node,
- RenderOpBuilder *builder)
+static Program *
+compile_glshader (GskGLRenderer *self,
+ GskGLShader *shader,
+ GError **error)
{
- GskGLShader *shader = gsk_gl_shader_node_get_shader (node);
- Program *program = gsk_gl_renderer_lookup_custom_program (self, shader);
- GskRenderNode *fallback = gsk_gl_shader_node_get_fallback_child (node);
- int n_children = gsk_gl_shader_node_get_n_children (node);
+ GskGLShaderBuilder shader_builder;
+ const char *shader_source;
+ gsize shader_source_len;
+ int n_uniforms;
+ const GskGLUniform *uniforms;
+ GBytes *bytes;
+ int n_required_textures = gsk_gl_shader_get_n_required_textures (shader);
+ int program_id;
+ Program *program;
- if (program == NULL)
+ bytes = gsk_gl_shader_get_bytes (shader);
+ shader_source = g_bytes_get_data (bytes, &shader_source_len);
+ uniforms = gsk_gl_shader_get_uniforms (shader, &n_uniforms);
+
+ if (n_uniforms > G_N_ELEMENTS (program->glshader.args_locations))
{
- GskGLShaderBuilder shader_builder;
- const char *shader_source;
- gsize shader_source_len;
- GError *error = NULL;
- int n_uniforms;
- const GskGLUniform *uniforms;
- GBytes *bytes;
- int n_required_textures = gsk_gl_shader_get_n_required_textures (shader);
+ g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_FORMAT,
+ "GLShaderNode supports max %d custom uniforms", (int)G_N_ELEMENTS
(program->glshader.args_locations));
+ return NULL;
+ }
- /* We always create the program, so that any compiler warnings or other is only reported once */
- program = gsk_gl_renderer_create_custom_program (self, shader);
+ if (n_required_textures > G_N_ELEMENTS (program->glshader.texture_locations))
+ {
+ g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_FORMAT,
+ "GLShaderNode supports max %d texture sources", (int)(G_N_ELEMENTS
(program->glshader.texture_locations)));
+ return NULL;
+ }
- bytes = gsk_gl_shader_get_bytes (shader);
- shader_source = g_bytes_get_data (bytes, &shader_source_len);
- uniforms = gsk_gl_shader_get_uniforms (shader, &n_uniforms);
+ gsk_gl_shader_builder_init (&shader_builder,
+ "/org/gtk/libgsk/glsl/preamble.glsl",
+ "/org/gtk/libgsk/glsl/preamble.vs.glsl",
+ "/org/gtk/libgsk/glsl/preamble.fs.glsl");
- if (n_uniforms > G_N_ELEMENTS (program->glshader.args_locations))
- {
- g_set_error (&error, GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_FORMAT,
- "GLShaderNode supports max %d custom uniforms", (int)G_N_ELEMENTS
(program->glshader.args_locations));
- }
- else if (n_required_textures > G_N_ELEMENTS (program->glshader.texture_locations))
+ init_shader_builder (self, &shader_builder);
+ program_id = gsk_gl_shader_builder_create_program (&shader_builder,
+ "/org/gtk/libgsk/glsl/custom.glsl",
+ shader_source, shader_source_len,
+ error);
+ gsk_gl_shader_builder_finish (&shader_builder);
+
+ if (program_id < 0)
+ return NULL;
+
+ program = gsk_gl_renderer_create_custom_program (self, shader);
+
+ program->id = program_id;
+ INIT_COMMON_UNIFORM_LOCATION (program, alpha);
+ INIT_COMMON_UNIFORM_LOCATION (program, clip_rect);
+ INIT_COMMON_UNIFORM_LOCATION (program, viewport);
+ INIT_COMMON_UNIFORM_LOCATION (program, projection);
+ INIT_COMMON_UNIFORM_LOCATION (program, modelview);
+ program->glshader.size_location = glGetUniformLocation(program->id, "u_size");
+ program->glshader.texture_locations[0] = glGetUniformLocation(program->id, "u_texture1");
+ program->glshader.texture_locations[1] = glGetUniformLocation(program->id, "u_texture2");
+ program->glshader.texture_locations[2] = glGetUniformLocation(program->id, "u_texture3");
+ program->glshader.texture_locations[3] = glGetUniformLocation(program->id, "u_texture4");
+
+ /* We use u_textue1 for the texture 0 in the glshaders, so alias it here so we can use the regular setters
*/
+ program->source_location = program->glshader.texture_locations[0];
+
+ for (int i = 0; i < G_N_ELEMENTS (program->glshader.args_locations); i++)
+ {
+ if (i < n_uniforms)
{
- g_set_error (&error, GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_FORMAT,
- "GLShaderNode supports max %d texture sources", (int)(G_N_ELEMENTS
(program->glshader.texture_locations)));
+ program->glshader.args_locations[i] = glGetUniformLocation(program->id, uniforms[i].name);
+ /* This isn't necessary a hard error, you might declare uniforms that are not actually
+ always used, for instance if you have an "API" in uniforms for multiple shaders. */
+ if (program->glshader.args_locations[i] == -1)
+ g_debug ("Declared uniform `%s` not found in GskGLShader", uniforms[i].name);
}
else
- {
- gsk_gl_shader_builder_init (&shader_builder,
- "/org/gtk/libgsk/glsl/preamble.glsl",
- "/org/gtk/libgsk/glsl/preamble.vs.glsl",
- "/org/gtk/libgsk/glsl/preamble.fs.glsl");
+ program->glshader.args_locations[i] = -1;
+ }
+
+ return program;
+}
- init_shader_builder (self, &shader_builder);
+gboolean
+gsk_gl_render_try_compile_gl_shader (GskGLRenderer *self,
+ GskGLShader *shader,
+ GError **error)
+{
+ Program *program;
- program->id = gsk_gl_shader_builder_create_program (&shader_builder,
- "/org/gtk/libgsk/glsl/custom.glsl",
- shader_source, shader_source_len,
- &error);
- gsk_gl_shader_builder_finish (&shader_builder);
+ gdk_gl_context_make_current (self->gl_context);
- if (program->id >= 0)
- {
- INIT_COMMON_UNIFORM_LOCATION (program, alpha);
- INIT_COMMON_UNIFORM_LOCATION (program, clip_rect);
- INIT_COMMON_UNIFORM_LOCATION (program, viewport);
- INIT_COMMON_UNIFORM_LOCATION (program, projection);
- INIT_COMMON_UNIFORM_LOCATION (program, modelview);
- program->glshader.size_location = glGetUniformLocation(program->id, "u_size");
- program->glshader.texture_locations[0] = glGetUniformLocation(program->id, "u_texture1");
- program->glshader.texture_locations[1] = glGetUniformLocation(program->id, "u_texture2");
- program->glshader.texture_locations[2] = glGetUniformLocation(program->id, "u_texture3");
- program->glshader.texture_locations[3] = glGetUniformLocation(program->id, "u_texture4");
-
- /* We use u_textue1 for the texture 0 in the glshaders, so alias it here so we can use the
regular setters */
- program->source_location = program->glshader.texture_locations[0];
-
- for (int i = 0; i < G_N_ELEMENTS (program->glshader.args_locations); i++)
- {
- if (i < n_uniforms)
- {
- program->glshader.args_locations[i] = glGetUniformLocation(program->id,
uniforms[i].name);
- if (program->glshader.args_locations[i] == -1)
- g_warning ("Expected uniform `%s` not found in shader", uniforms[i].name);
- }
- else
- program->glshader.args_locations[i] = -1;
- }
- }
+ /* Maybe we tried to compile it already? */
+ program = gsk_gl_renderer_lookup_custom_program (self, shader);
+ if (program != NULL)
+ {
+ if (program->id > 0)
+ return TRUE;
+ else
+ {
+ g_propagate_error (error, g_error_copy (program->glshader.compile_error));
+ return FALSE;
}
+ }
+
+ program = compile_glshader (self, shader, error);
+ return program != NULL;
+}
- if (program->id <= 0)
+static inline void
+render_gl_shader_node (GskGLRenderer *self,
+ GskRenderNode *node,
+ RenderOpBuilder *builder)
+{
+ GskGLShader *shader = gsk_gl_shader_node_get_shader (node);
+ Program *program = gsk_gl_renderer_lookup_custom_program (self, shader);
+ int n_children = gsk_gl_shader_node_get_n_children (node);
+
+ if (program == NULL)
+ {
+ GError *error = NULL;
+
+ program = compile_glshader (self, shader, &error);
+ if (program == NULL)
{
- g_warning ("Failed to compile gl shader: %s\n", error->message);
- g_error_free (error);
+ /* We create the program anyway (in a failed state), so that any compiler warnings or other are
only reported once */
+ program = gsk_gl_renderer_create_custom_program (self, shader);
+ program->id = -1;
+ program->glshader.compile_error = error;
+
+ g_warning ("Failed to compile gl shader: %s", error->message);
}
}
@@ -1148,7 +1190,6 @@ render_gl_shader_node (GskGLRenderer *self,
GBytes *uniform_data;
TextureRegion regions[4];
gboolean is_offscreen[4];
-
for (guint i = 0; i < n_children; i++)
{
GskRenderNode *child = gsk_gl_shader_node_get_child (node, i);
@@ -1157,11 +1198,7 @@ render_gl_shader_node (GskGLRenderer *self,
child,
®ions[i], &is_offscreen[i],
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY))
- {
- if (fallback)
- gsk_gl_renderer_add_render_ops (self, fallback, builder);
- return;
- }
+ return;
}
uniform_data = gsk_gl_shader_node_get_uniform_data (node);
@@ -1180,8 +1217,10 @@ render_gl_shader_node (GskGLRenderer *self,
}
else
{
- if (fallback)
- gsk_gl_renderer_add_render_ops (self, fallback, builder);
+ static GdkRGBA pink = { 255 / 255., 105 / 255., 180 / 255., 1.0 };
+ ops_set_program (builder, &self->programs->color_program);
+ ops_set_color (builder, &pink);
+ load_vertex_data (ops_draw (builder, NULL), node, builder);
}
}
@@ -3133,6 +3172,10 @@ program_finalize (Program *program)
{
if (program->id > 0)
glDeleteProgram (program->id);
+ if (program->index == -1 &&
+ program->glshader.compile_error != NULL)
+ g_error_free (program->glshader.compile_error);
+
gsk_transform_unref (program->state.modelview);
}
diff --git a/gsk/gl/gskglrendererprivate.h b/gsk/gl/gskglrendererprivate.h
new file mode 100644
index 0000000000..917aecb2e8
--- /dev/null
+++ b/gsk/gl/gskglrendererprivate.h
@@ -0,0 +1,14 @@
+#ifndef __GSK_GL_RENDERER_PRIVATE_H__
+#define __GSK_GL_RENDERER_PRIVATE_H__
+
+#include "gskglrenderer.h"
+
+G_BEGIN_DECLS
+
+gboolean gsk_gl_render_try_compile_gl_shader (GskGLRenderer *self,
+ GskGLShader *shader,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GSK_GL_RENDERER_PRIVATE_H__ */
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index 2f87117110..1d642bc3ac 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -84,7 +84,7 @@ typedef struct
struct _Program
{
- int index; /* Into the renderer's program array */
+ int index; /* Into the renderer's program array -1 for custom */
int id;
/* Common locations (gl_common)*/
@@ -163,6 +163,7 @@ struct _Program
int size_location;
int args_locations[8];
int texture_locations[4];
+ GError *compile_error;
} glshader;
};
diff --git a/gsk/gskglshader.c b/gsk/gskglshader.c
index 281e3b67b8..c1a336c214 100644
--- a/gsk/gskglshader.c
+++ b/gsk/gskglshader.c
@@ -112,6 +112,7 @@
#include "gskglshader.h"
#include "gskglshaderprivate.h"
#include "gskdebugprivate.h"
+#include "gl/gskglrendererprivate.h"
static GskGLUniformType
uniform_type_from_glsl (const char *str)
@@ -483,6 +484,40 @@ gsk_gl_shader_new_from_resource (const char *resource_path)
NULL);
}
+/**
+ * gsk_gl_shader_try_compile_for:
+ * @shader: A #GskGLShader
+ * @renderer: A #GskRenderer
+ * @error: Location to store error int
+ *
+ * Tries to compile the @shader for the given @renderer, and reports
+ * %FALSE with an error if there is a problem. You should use this
+ * before relying on the shader for rendering and use a fallback with
+ * a simpler shader or without shaders if it fails.
+ *
+ * Note that this will modify the rendering state (for example
+ * change the current GL context) and requires the renderer to be
+ * set up. This means that the widget has to be realized. Commonly you
+ * want to call this from the realize signal of a widget, or during
+ * widget snapshot.
+ *
+ * Returns: %TRUE on success, %FALSE if an error occurred
+ */
+gboolean
+gsk_gl_shader_try_compile_for (GskGLShader *shader,
+ GskRenderer *renderer,
+ GError **error)
+{
+ if (GSK_IS_GL_RENDERER (renderer))
+ return gsk_gl_render_try_compile_gl_shader (GSK_GL_RENDERER (renderer),
+ shader, error);
+
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "The renderer does not support gl shaders");
+ return FALSE;
+}
+
+
/**
* gsk_gl_shader_get_sourcecode:
* @shader: A #GskGLShader
diff --git a/gsk/gskglshader.h b/gsk/gskglshader.h
index 26f21ee694..b27544780c 100644
--- a/gsk/gskglshader.h
+++ b/gsk/gskglshader.h
@@ -40,6 +40,10 @@ GskGLShader * gsk_gl_shader_new_from_bytes (GBytes *source
GDK_AVAILABLE_IN_ALL
GskGLShader * gsk_gl_shader_new_from_resource (const char *resource_path);
GDK_AVAILABLE_IN_ALL
+gboolean gsk_gl_shader_try_compile_for (GskGLShader *shader,
+ GskRenderer *renderer,
+ GError **error);
+GDK_AVAILABLE_IN_ALL
GBytes * gsk_gl_shader_get_bytes (GskGLShader *shader);
GDK_AVAILABLE_IN_ALL
int gsk_gl_shader_get_n_required_textures (GskGLShader *shader);
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index f554ef56a5..9585449f82 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -460,12 +460,9 @@ GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_gl_shader_node_new (GskGLShader *shader,
const graphene_rect_t *bounds,
GBytes *uniform_data,
- GskRenderNode *fallback,
GskRenderNode **children,
int n_children);
GDK_AVAILABLE_IN_ALL
-GskRenderNode * gsk_gl_shader_node_get_fallback_child (GskRenderNode *node);
-GDK_AVAILABLE_IN_ALL
guint gsk_gl_shader_node_get_n_children (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_gl_shader_node_get_child (GskRenderNode *node,
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index f59c93cbc5..8f47e0234d 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -4478,7 +4478,6 @@ struct _GskGLShaderNode
GskGLShader *shader;
GBytes *uniform_data;
- GskRenderNode *fallback;
GskRenderNode **children;
guint n_children;
};
@@ -4493,7 +4492,6 @@ gsk_gl_shader_node_finalize (GskRenderNode *node)
gsk_render_node_unref (self->children[i]);
g_free (self->children);
- gsk_render_node_unref (self->fallback);
g_bytes_unref (self->uniform_data);
g_object_unref (self->shader);
@@ -4505,9 +4503,9 @@ static void
gsk_gl_shader_node_draw (GskRenderNode *node,
cairo_t *cr)
{
- GskGLShaderNode *self = (GskGLShaderNode *) node;
-
- gsk_render_node_draw (self->fallback, cr);
+ cairo_set_source_rgb (cr, 255 / 255., 105 / 255., 180 / 255.);
+ gsk_cairo_rectangle (cr, &node->bounds);
+ cairo_fill (cr);
}
static void
@@ -4523,8 +4521,6 @@ gsk_gl_shader_node_diff (GskRenderNode *node1,
g_bytes_compare (self1->uniform_data, self2->uniform_data) == 0 &&
self1->n_children == self2->n_children)
{
- gsk_render_node_diff (self1->fallback, self2->fallback, region);
-
for (guint i = 0; i < self1->n_children; i++)
{
if (self1->children[i] != self2->children[i])
@@ -4545,7 +4541,6 @@ gsk_gl_shader_node_diff (GskRenderNode *node1,
* @shader: the #GskGLShader
* @bounds: the rectangle to render the shader into
* @uniform_data: Data for the uniforms
- * @fallback: Render node to use if OpenGL is not supported
* @children: List of child nodes, these will be rendered to textures and used as input.
* @n_children: Length of @children (currenly the GL backend only supports max 4 children)
*
@@ -4560,8 +4555,10 @@ gsk_gl_shader_node_diff (GskRenderNode *node1,
* #GskTextureNodes, which will be used directly). These textures will be
* sent as input to the shader.
*
- * If the backend doesn't support GL shaders, or if there is any problem when
- * compiling the shader, then the fallback shader node will be used instead.
+ * If the renderer doesn't support GL shaders, or if there is any problem when
+ * compiling the shader, then the node will draw pink. You should use
+ * gsk_gl_shader_try_compile_for() to ensure the @shader will work for the renderer
+ * before using it.
*
* Returns: (transfer full) (type GskGLShaderNode): A new #GskRenderNode
*/
@@ -4569,7 +4566,6 @@ GskRenderNode *
gsk_gl_shader_node_new (GskGLShader *shader,
const graphene_rect_t *bounds,
GBytes *uniform_data,
- GskRenderNode *fallback,
GskRenderNode **children,
int n_children)
{
@@ -4589,7 +4585,6 @@ gsk_gl_shader_node_new (GskGLShader *shader,
g_assert (g_bytes_get_size (uniform_data) == uniforms_size);
self->uniform_data = g_bytes_ref (uniform_data);
- self->fallback = gsk_render_node_ref (fallback);
self->n_children = n_children;
if (n_children > 0)
@@ -4602,24 +4597,6 @@ gsk_gl_shader_node_new (GskGLShader *shader,
return node;
}
-/**
- * gsk_gl_shader_node_get_fallback_child:
- * @node: (type GskGLShaderNode): a #GskRenderNode for a gl shader
- *
- * Gets the fallback child node
- *
- * Returns: (transfer none): The fallback node
- */
-GskRenderNode *
-gsk_gl_shader_node_get_fallback_child (GskRenderNode *node)
-{
- GskGLShaderNode *self = (GskGLShaderNode *) node;
-
- g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_GL_SHADER_NODE), NULL);
-
- return self->fallback;
-}
-
/**
* gsk_gl_shader_node_get_n_children:
* @node: (type GskGLShaderNode): a #GskRenderNode for a gl shader
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index ca447e4a8d..28ecebbdea 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -1213,7 +1213,6 @@ static GskRenderNode *
parse_glshader_node (GtkCssParser *parser)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
- GskRenderNode *fallback = NULL;
GskRenderNode *child[4] = { NULL, };
ShaderInfo shader_info = {
NULL,
@@ -1223,7 +1222,6 @@ parse_glshader_node (GtkCssParser *parser)
{ "bounds", parse_rect, NULL, &bounds },
{ "sourcecode", parse_shader, NULL, &shader_info },
{ "uniform-data", parse_uniform_data, clear_shader_info, &shader_info },
- { "fallback", parse_node, clear_node, &fallback },
{ "child1", parse_node, clear_node, &child[0] },
{ "child2", parse_node, clear_node, &child[1] },
{ "child3", parse_node, clear_node, &child[2] },
@@ -1303,7 +1301,7 @@ parse_glshader_node (GtkCssParser *parser)
gsk_uniform_data_builder_free (builder);
node = gsk_gl_shader_node_new (shader, &bounds, uniform_data,
- fallback, child, len);
+ child, len);
g_array_unref (shader_info.uniform_values);
g_bytes_unref (uniform_data);
@@ -2832,7 +2830,6 @@ render_node_print (Printer *p,
g_string_free (data, TRUE);
}
- append_node_param (p, "fallback", gsk_gl_shader_node_get_fallback_child (node));
for (guint i = 0; i < gsk_gl_shader_node_get_n_children (node); i ++)
{
GskRenderNode *child = gsk_gl_shader_node_get_child (node, i);
diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c
index ad729958ca..be8dd2795a 100644
--- a/gsk/vulkan/gskvulkanrenderpass.c
+++ b/gsk/vulkan/gskvulkanrenderpass.c
@@ -256,6 +256,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_NOT_A_RENDER_NODE:
g_assert_not_reached ();
return;
+ case GSK_GL_SHADER_NODE:
case GSK_SHADOW_NODE:
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
@@ -539,10 +540,6 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
}
return;
- case GSK_GL_SHADER_NODE:
- gsk_vulkan_render_pass_add_node (self, render, constants, gsk_gl_shader_node_get_fallback_child (node));
- return;
-
case GSK_DEBUG_NODE:
gsk_vulkan_render_pass_add_node (self, render, constants, gsk_debug_node_get_child (node));
return;
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 310a271feb..74cf37d960 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -820,19 +820,6 @@ gtk_snapshot_push_clip (GtkSnapshot *snapshot,
gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &state->data.clip.bounds);
}
-static GskRenderNode *
-maybe_clip (GskRenderNode *node,
- const graphene_rect_t *bounds)
-{
- if (node &&
- !graphene_rect_contains_rect (bounds, &node->bounds))
- {
- return gsk_clip_node_new (node, bounds);
- }
-
- return gsk_render_node_ref (node);
-}
-
static GskRenderNode *
gtk_snapshot_collect_gl_shader (GtkSnapshot *snapshot,
GtkSnapshotState *state,
@@ -849,7 +836,7 @@ gtk_snapshot_collect_gl_shader (GtkSnapshot *snapshot,
state->data.glshader.nodes[state->data.glshader.node_idx] = child_node;
- if (state->data.glshader.node_idx != state->data.glshader.n_children)
+ if (state->data.glshader.node_idx != state->data.glshader.n_children - 1)
return NULL; /* Not last */
/* This is the last pop */
@@ -859,20 +846,16 @@ gtk_snapshot_collect_gl_shader (GtkSnapshot *snapshot,
if (state->data.glshader.bounds.size.width != 0 &&
state->data.glshader.bounds.size.height != 0)
{
- GskRenderNode *fallback_node = maybe_clip (state->data.glshader.nodes[0],
- &state->data.glshader.bounds);
shader_node = gsk_gl_shader_node_new (state->data.glshader.shader,
&state->data.glshader.bounds,
state->data.glshader.uniform_data,
- fallback_node,
- &state->data.glshader.nodes[1],
+ &state->data.glshader.nodes[0],
state->data.glshader.n_children);
- gsk_render_node_unref (fallback_node);
}
g_object_unref (state->data.glshader.shader);
g_bytes_unref (state->data.glshader.uniform_data);
- for (guint i = 0; i < state->data.glshader.n_children + 1; i++)
+ for (guint i = 0; i < state->data.glshader.n_children; i++)
gsk_render_node_unref (state->data.glshader.nodes[i]);
g_free (state->data.glshader.nodes);
@@ -888,13 +871,13 @@ gtk_snapshot_collect_gl_shader (GtkSnapshot *snapshot,
* @n_children: The number of extra nodes given as argument to the shader as textures.
*
* Push a #GskGLShaderNode with a specific #GskGLShader and a set of uniform values
- * to use while rendering. Additionally this takes a fallback node and a list of
- * @n_children other nodes which will be passed to the #GskGLShaderNode.
+ * to use while rendering. Additionally this takes a list of @n_children other nodes
+ * which will be passed to the #GskGLShaderNode.
*
- * The fallback node is used if GLSL shaders are not supported by the backend, or if
- * there is any problem compiling the shader. The fallback node needs to be pushed
- * directly after the gtk_snapshot_push_gl_shader() call up until the first call
- * to gtk_snapshot_pop().
+ * If the renderer doesn't support GL shaders, or if there is any problem when
+ * compiling the shader, then the node will draw pink. You should use
+ * gsk_gl_shader_try_compile_for() to ensure the @shader will work for the renderer
+ * before using it.
*
* If @n_children > 0, then it is expected that you (after the fallback call
* gtk_snapshot_pop() @n_children times. Each of these will generate a node that
@@ -926,13 +909,13 @@ gtk_snapshot_push_gl_shader (GtkSnapshot *snapshot,
state->data.glshader.shader = g_object_ref (shader);
state->data.glshader.uniform_data = g_bytes_ref (uniform_data);
state->data.glshader.n_children = n_children;
- nodes = g_new0 (GskRenderNode *, n_children + 1);
- node_idx = n_children; /* We pop in reverse order */
+ nodes = g_new0 (GskRenderNode *, n_children);
+ node_idx = n_children-1; /* We pop in reverse order */
state->data.glshader.node_idx = node_idx--;
state->data.glshader.nodes = nodes;
- for (int i = 0; i < n_children; i++)
+ for (int i = 0; i < n_children-1; i++)
{
state = gtk_snapshot_push_state (snapshot,
gtk_snapshot_get_current_state (snapshot)->transform,
diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c
index 59747d625a..c14d4412a4 100644
--- a/gtk/inspector/recorder.c
+++ b/gtk/inspector/recorder.c
@@ -173,7 +173,7 @@ create_list_model_for_render_node (GskRenderNode *node)
case GSK_GL_SHADER_NODE:
{
- GListStore *store = G_LIST_STORE (create_render_node_list_model ((GskRenderNode *[1]) {
gsk_gl_shader_node_get_fallback_child (node) }, 1));
+ GListStore *store = g_list_store_new (GDK_TYPE_PAINTABLE);
for (guint i = 0; i < gsk_gl_shader_node_get_n_children (node); i++)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]