[gtk/matthiasc/gltransition-demo: 2/3] Complete serialization for GskGLShaderNode
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/matthiasc/gltransition-demo: 2/3] Complete serialization for GskGLShaderNode
- Date: Wed, 23 Sep 2020 04:54:41 +0000 (UTC)
commit aeae3522b683fbc84641e5084d0935391c0f7026
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Sep 22 21:31:02 2020 -0400
Complete serialization for GskGLShaderNode
Make the node serialization and parsing handle
shader nodes.
gsk/gskrendernodeparser.c | 421 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 408 insertions(+), 13 deletions(-)
---
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index 747d5dc59a..db145aad4b 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -358,6 +358,13 @@ parse_double (GtkCssParser *parser,
return gtk_css_parser_consume_number (parser, out_double);
}
+static gboolean
+parse_int (GtkCssParser *parser,
+ gpointer out_int)
+{
+ return gtk_css_parser_consume_integer (parser, out_int);
+}
+
static gboolean
parse_point (GtkCssParser *parser,
gpointer out_point)
@@ -824,9 +831,9 @@ clear_node (gpointer inout_node)
static GskRenderNode *
parse_container_node (GtkCssParser *parser)
{
- GskRenderNode *node;
GPtrArray *nodes;
const GtkCssToken *token;
+ GskRenderNode *node;
nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
@@ -1089,13 +1096,249 @@ parse_inset_shadow_node (GtkCssParser *parser)
return gsk_inset_shadow_node_new (&outline, &color, dx, dy, spread, blur);
}
+typedef struct {
+ GskGLUniformType type;
+ char *name;
+ union {
+ int i;
+ double v[4];
+ } value;
+} Uniform;
+
+static gboolean
+parse_uniform_decl (GtkCssParser *parser, Uniform *decl)
+{
+ Uniform decls[] = {
+ { GSK_GLUNIFORM_TYPE_FLOAT, (char *) "float" },
+ { GSK_GLUNIFORM_TYPE_INT, (char *) "int" },
+ { GSK_GLUNIFORM_TYPE_UINT, (char*) "uint" },
+ { GSK_GLUNIFORM_TYPE_BOOL, (char *) "bool" },
+ { GSK_GLUNIFORM_TYPE_VEC2, (char *) "vec2" },
+ { GSK_GLUNIFORM_TYPE_VEC3, (char *) "vec3" },
+ { GSK_GLUNIFORM_TYPE_VEC4, (char *) "vec4" },
+ };
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (decls); i++)
+ {
+ if (gtk_css_parser_try_ident (parser, decls[i].name))
+ {
+ decl->type = decls[i].type;
+ decl->name = gtk_css_parser_consume_ident (parser);
+
+ gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+clear_uniform_decl (gpointer data)
+{
+ Uniform *decl = data;
+ g_free (decl->name);
+}
+
+static gboolean
+parse_uniforms (GtkCssParser *parser, gpointer data)
+{
+ GArray *uniforms = data;
+ Uniform decl;
+
+ while (parse_uniform_decl (parser, &decl))
+ g_array_append_val (uniforms, decl);
+
+ return TRUE;
+}
+
+static void
+clear_array (gpointer data)
+{
+ GArray *array = data;
+ g_array_set_size (array, 0);
+}
+
+static gboolean
+parse_uniform_value (GtkCssParser *parser, Uniform *uniform)
+{
+ switch (uniform->type)
+ {
+ case GSK_GLUNIFORM_TYPE_FLOAT:
+ if (!gtk_css_parser_consume_number (parser, &uniform->value.v[0]))
+ return FALSE;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_INT:
+ if (!gtk_css_parser_consume_integer (parser, &uniform->value.i))
+ return FALSE;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_UINT:
+ if (!gtk_css_parser_consume_integer (parser, &uniform->value.i) ||
+ uniform->value.i < 0)
+ return FALSE;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_BOOL:
+ if (!gtk_css_parser_consume_integer (parser, &uniform->value.i) ||
+ (uniform->value.i != 0 && uniform->value.i != 1))
+ return FALSE;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_VEC2:
+ if (!gtk_css_parser_consume_number (parser, &uniform->value.v[0]) ||
+ !gtk_css_parser_consume_number (parser, &uniform->value.v[1]))
+ return FALSE;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_VEC3:
+ if (!gtk_css_parser_consume_number (parser, &uniform->value.v[0]) ||
+ !gtk_css_parser_consume_number (parser, &uniform->value.v[1]) ||
+ !gtk_css_parser_consume_number (parser, &uniform->value.v[2]))
+ return FALSE;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_VEC4:
+ if (!gtk_css_parser_consume_number (parser, &uniform->value.v[0]) ||
+ !gtk_css_parser_consume_number (parser, &uniform->value.v[1]) ||
+ !gtk_css_parser_consume_number (parser, &uniform->value.v[2]) ||
+ !gtk_css_parser_consume_number (parser, &uniform->value.v[3]))
+ return FALSE;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_NONE:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA);
+
+ return TRUE;
+}
+
+static gboolean
+parse_uniform_data (GtkCssParser *parser, gpointer data)
+{
+ GArray *uniforms = data;
+ int i;
+
+ for (i = 0; i < uniforms->len; i++)
+ {
+ Uniform *uniform = &g_array_index (uniforms, Uniform, i);
+ if (!parse_uniform_value (parser, uniform))
+ return FALSE;
+ }
+
+ return TRUE;
+}
static GskRenderNode *
parse_glshader_node (GtkCssParser *parser)
{
- /* TODO */
- gtk_css_parser_error_syntax (parser, "glshader node parsing not implemented yet");
- return NULL;
+ graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
+ char *sourcecode = NULL;
+ int required_sources = 0;
+ GskRenderNode *fallback = NULL;
+ GskRenderNode *child[4] = { NULL, };
+ GArray *uniforms = g_array_new (FALSE, FALSE, sizeof (Uniform));
+ const Declaration declarations[] = {
+ { "bounds", parse_rect, NULL, &bounds },
+ { "sourcecode", parse_string, NULL, &sourcecode },
+ { "required-sources", parse_int, NULL, &required_sources },
+ { "uniforms", parse_uniforms, clear_array, uniforms },
+ { "uniform-data", parse_uniform_data, clear_array, uniforms },
+ { "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] },
+ { "child4", parse_node, clear_node, &child[3] },
+ };
+ GskGLShader *shader;
+ GskRenderNode *node;
+ guchar *uniform_data;
+ int len, i;
+
+ g_array_set_clear_func (uniforms, clear_uniform_decl);
+
+ parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
+
+ for (len = 0; len < 4; len++)
+ {
+ if (child[len] == NULL)
+ break;
+ }
+
+ shader = gsk_glshader_new (sourcecode);
+ gsk_glshader_set_n_required_sources (shader, required_sources);
+ for (i = 0; i < uniforms->len; i++)
+ {
+ Uniform *uniform = &g_array_index (uniforms, Uniform, i);
+ gsk_glshader_add_uniform (shader, uniform->name, uniform->type);
+ }
+
+ uniform_data = g_new (guchar, gsk_glshader_get_uniforms_size (shader));
+ for (i = 0; i < uniforms->len; i++)
+ {
+ Uniform *uniform = &g_array_index (uniforms, Uniform, i);
+ guchar *dest;
+
+ dest = uniform_data + gsk_glshader_get_uniform_offset (shader, i);
+
+ switch (uniform->type)
+ {
+ case GSK_GLUNIFORM_TYPE_FLOAT:
+ *(float *)dest = uniform->value.v[0];
+ break;
+
+ case GSK_GLUNIFORM_TYPE_INT:
+ *(gint32 *)dest = uniform->value.i;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_UINT:
+ *(guint32 *)dest = uniform->value.i;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_BOOL:
+ *(guint32 *)dest = uniform->value.i;
+ break;
+
+ case GSK_GLUNIFORM_TYPE_VEC4:
+ ((float *)dest)[3] = uniform->value.v[3];
+ G_GNUC_FALLTHROUGH;
+
+ case GSK_GLUNIFORM_TYPE_VEC3:
+ ((float *)dest)[2] = uniform->value.v[2];
+ G_GNUC_FALLTHROUGH;
+
+ case GSK_GLUNIFORM_TYPE_VEC2:
+ ((float *)dest)[1] = uniform->value.v[1];
+ ((float *)dest)[0] = uniform->value.v[0];
+ break;
+
+ case GSK_GLUNIFORM_TYPE_NONE:
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ node = gsk_glshader_node_new (shader, &bounds, uniform_data,
+ fallback, child, len);
+
+ g_array_unref (uniforms);
+ g_free (uniform_data);
+ g_object_unref (shader);
+
+ for (i = 0; i < 4; i++)
+ {
+ if (child[i])
+ gsk_render_node_unref (child[i]);
+ }
+
+ return node;
}
static GskRenderNode *
@@ -1849,15 +2092,47 @@ append_point (GString *str,
static void
append_string (GString *str,
- const char *value)
+ const char *string)
{
- char *escaped = g_strescape (value, NULL);
+ gsize len;
+
+ g_return_if_fail (str != NULL);
+ g_return_if_fail (string != NULL);
g_string_append_c (str, '"');
- g_string_append (str, escaped);
- g_string_append_c (str, '"');
- g_free (escaped);
+ do {
+ len = strcspn (string, "\\\"\n\r\f");
+ g_string_append_len (str, string, len);
+ string += len;
+ switch (*string)
+ {
+ case '\0':
+ goto out;
+ case '\n':
+ g_string_append (str, "\\A ");
+ break;
+ case '\r':
+ g_string_append (str, "\\D ");
+ break;
+ case '\f':
+ g_string_append (str, "\\C ");
+ break;
+ case '\"':
+ g_string_append (str, "\\\"");
+ break;
+ case '\\':
+ g_string_append (str, "\\\\");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ string++;
+ } while (*string);
+
+out:
+ g_string_append_c (str, '"');
}
static void
@@ -1889,6 +2164,19 @@ append_float_param (Printer *p,
g_string_append (p->str, ";\n");
}
+static void
+append_int_param (Printer *p,
+ const char *param_name,
+ int value,
+ int default_value)
+{
+ if (value == default_value)
+ return;
+
+ _indent (p);
+ g_string_append_printf (p->str, "%s: %d;\n", param_name, value);
+}
+
static void
append_rgba_param (Printer *p,
const char *param_name,
@@ -2478,16 +2766,123 @@ render_node_print (Printer *p,
case GSK_GLSHADER_NODE:
{
+ GskGLShader *shader = gsk_glshader_node_get_shader (node);
+ const guchar *uniform_data = gsk_glshader_node_get_uniform_data (node);
+
start_node (p, "glshader");
- GskGLShader *shader = gsk_glshader_node_get_shader (node);
- append_string_param (p, "shader", gsk_glshader_get_sourcecode (shader));
+ append_rect_param (p, "bounds", &node->bounds);
+
+ append_string_param (p, "sourcecode", gsk_glshader_get_sourcecode (shader));
+ append_int_param (p, "required-sources", gsk_glshader_get_n_required_sources (shader), 0);
+
+ if (gsk_glshader_get_n_uniforms (shader) > 0)
+ {
+ GString *decl = g_string_new ("");
+ GString *data = g_string_new ("");
+
+ for (guint i = 0; i < gsk_glshader_get_n_uniforms (shader); i++)
+ {
+ const char *name = gsk_glshader_get_uniform_name (shader, i);
+ int offset = gsk_glshader_get_uniform_offset (shader, i);
+
+ if (i > 0)
+ {
+ g_string_append (decl, ", ");
+ g_string_append (data, ", ");
+ }
+
+ switch (gsk_glshader_get_uniform_type (shader, i))
+ {
+ case GSK_GLUNIFORM_TYPE_NONE:
+ default:
+ g_assert_not_reached ();
+ break;
+
+ case GSK_GLUNIFORM_TYPE_FLOAT:
+ {
+ float value = *(float *)(uniform_data + offset);
+ g_string_append_printf (decl, "float %s", name);
+ g_string_append_printf (data, "%f", value);
+ }
+ break;
+
+ case GSK_GLUNIFORM_TYPE_INT:
+ {
+ gint32 value = *(gint32 *)(uniform_data + offset);
+ g_string_append_printf (decl, "int %s", name);
+ g_string_append_printf (data, "%d", value);
+ }
+ break;
+
+ case GSK_GLUNIFORM_TYPE_UINT:
+ {
+ guint32 value = *(guint32 *)(uniform_data + offset);
+ g_string_append_printf (decl, "uint %s", name);
+ g_string_append_printf (data, "%u", value);
+ }
+ break;
+
+ case GSK_GLUNIFORM_TYPE_BOOL:
+ {
+ gboolean value = *(gboolean *)(uniform_data + offset);
+ g_string_append_printf (decl, "bool %s", name);
+ g_string_append_printf (data, "%d", value);
+ }
+ break;
+
+ case GSK_GLUNIFORM_TYPE_VEC2:
+ {
+ graphene_vec2_t *v = (graphene_vec2_t *)(uniform_data + offset);
+ g_string_append_printf (decl, "vec2 %s", name);
+ g_string_append_printf (data, "%f %f",
+ graphene_vec2_get_x (v),
+ graphene_vec2_get_y (v));
+ }
+ break;
+
+ case GSK_GLUNIFORM_TYPE_VEC3:
+ {
+ graphene_vec3_t *v = (graphene_vec3_t *)(uniform_data + offset);
+ g_string_append_printf (decl, "vec3 %s", name);
+ g_string_append_printf (data, "%f %f %f",
+ graphene_vec3_get_x (v),
+ graphene_vec3_get_y (v),
+ graphene_vec3_get_z (v));
+ }
+ break;
+
+ case GSK_GLUNIFORM_TYPE_VEC4:
+ {
+ graphene_vec4_t *v = (graphene_vec4_t *)(uniform_data + offset);
+ g_string_append_printf (decl, "vec4 %s", name);
+ g_string_append_printf (data, "%f %f %f %f",
+ graphene_vec4_get_x (v),
+ graphene_vec4_get_y (v),
+ graphene_vec4_get_z (v),
+ graphene_vec4_get_w (v));
+ }
+ break;
+ }
+ }
+ _indent (p);
+ g_string_append_printf (p->str, "uniforms: %s;\n", decl->str);
+ _indent (p);
+ g_string_append_printf (p->str, "uniform-data: %s;\n", data->str);
+
+ g_string_free (decl, TRUE);
+ g_string_free (data, TRUE);
+ }
+
append_node_param (p, "fallback", gsk_glshader_node_get_fallback_child (node));
for (guint i = 0; i < gsk_glshader_node_get_n_children (node); i ++)
{
GskRenderNode *child = gsk_glshader_node_get_child (node, i);
- _indent (p);
- render_node_print (p, child);
+ char *name;
+
+ name = g_strdup_printf ("child%d", i + 1);
+ append_node_param (p, name, child);
+ g_free (name);
}
end_node (p);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]