gsk: Add a skeleton for a GLSL parser

This commit is contained in:
Benjamin Otte
2017-09-14 04:16:40 +02:00
parent 916981f66e
commit 3a298f8f9c
19 changed files with 3553 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ private_headers = [
'gskgldriverprivate.h',
'gskglprofilerprivate.h',
'gskglrendererprivate.h',
'gskpixelshaderprivate.h',
'gskprivate.h',
'gskprofilerprivate.h',
'gskrendererprivate.h',

View File

@@ -21,6 +21,7 @@
#define __GSK_H_INSIDE__
#include <gsk/gskenums.h>
#include <gsk/gskpixelshader.h>
#include <gsk/gskrenderer.h>
#include <gsk/gskrendernode.h>
#include <gsk/gskroundedrect.h>

184
gsk/gskpixelshader.c Normal file
View File

@@ -0,0 +1,184 @@
/* GSK - The GTK Scene Kit
*
* Copyright 2017 © Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:GskPixelShader
* @Title: GskPixelShader
* @Short_description: A pixel shader
*
* #GskPixelShader is the object used to create pixel shaders. The language
* used is GLSL with a few extensions.
*
* #GskPixelShader is an immutable object: That means you cannot change
* anything about it other than increasing the reference count via
* g_object_ref().
*/
#include "config.h"
#include "gskpixelshaderprivate.h"
#include "gskdebugprivate.h"
#include "gdk/gdkinternals.h"
/**
* GskPixelShader:
*
* The `GskPixelShader` structure contains only private data.
*
* Since: 3.90
*/
enum {
PROP_0,
PROP_N_TEXTURES,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
G_DEFINE_TYPE (GskPixelShader, gsk_pixel_shader, G_TYPE_OBJECT)
static void
gsk_pixel_shader_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
/* GskPixelShader *self = GSK_PIXEL_SHADER (gobject); */
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gsk_pixel_shader_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GskPixelShader *self = GSK_PIXEL_SHADER (gobject);
switch (prop_id)
{
case PROP_N_TEXTURES:
g_value_set_uint (value, self->n_textures);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gsk_pixel_shader_dispose (GObject *object)
{
GskPixelShader *self = GSK_PIXEL_SHADER (object);
gsk_sl_node_unref (self->program);
G_OBJECT_CLASS (gsk_pixel_shader_parent_class)->dispose (object);
}
static void
gsk_pixel_shader_class_init (GskPixelShaderClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gsk_pixel_shader_set_property;
gobject_class->get_property = gsk_pixel_shader_get_property;
gobject_class->dispose = gsk_pixel_shader_dispose;
/**
* GskPixelShader:n-textures:
*
* The number of input textures to the shader.
*
* Since: 3.92
*/
properties[PROP_N_TEXTURES] =
g_param_spec_uint ("n-textures",
"n textures",
"The number of input textures",
0,
G_MAXUINT,
0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gsk_pixel_shader_init (GskPixelShader *self)
{
}
GskPixelShader *
gsk_pixel_shader_new_for_data (GBytes *source,
GskShaderErrorFunc error_func,
gpointer error_data)
{
GskPixelShader *shader;
GskSlNode *program;
g_return_val_if_fail (source != NULL, NULL);
program = gsk_sl_node_new_program (source, NULL);
if (program == NULL)
return NULL;
shader = g_object_new (GSK_TYPE_PIXEL_SHADER, NULL);
shader->program = program;
return shader;
}
void
gsk_pixel_shader_print (GskPixelShader *shader,
GString *string)
{
g_return_if_fail (GSK_IS_PIXEL_SHADER (shader));
g_return_if_fail (string != NULL);
gsk_sl_node_print (shader->program, string);
}
char *
gsk_pixel_shader_to_string (GskPixelShader *shader)
{
GString *string;
g_return_val_if_fail (GSK_IS_PIXEL_SHADER (shader), NULL);
string = g_string_new (NULL);
gsk_pixel_shader_print (shader, string);
return g_string_free (string, FALSE);
}

62
gsk/gskpixelshader.h Normal file
View File

@@ -0,0 +1,62 @@
/* GSK - The GTK Scene Kit
*
* Copyright 2017 © Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_PIXEL_SHADER_H__
#define __GSK_PIXEL_SHADER_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_PIXEL_SHADER (gsk_pixel_shader_get_type ())
#define GSK_PIXEL_SHADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_PIXEL_SHADER, GskPixelShader))
#define GSK_IS_PIXEL_SHADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_PIXEL_SHADER))
typedef struct _GskPixelShaderClass GskPixelShaderClass;
typedef void (* GskShaderErrorFunc) (GskPixelShader *shader,
gboolean fatal,
const GskCodeLocation *location,
const GError *error,
gpointer user_data);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPixelShader, g_object_unref)
GDK_AVAILABLE_IN_3_92
GType gsk_pixel_shader_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_92
GskPixelShader * gsk_pixel_shader_new_for_data (GBytes *source,
GskShaderErrorFunc error_func,
gpointer error_data);
GDK_AVAILABLE_IN_3_92
void gsk_pixel_shader_print (GskPixelShader *shader,
GString *string);
GDK_AVAILABLE_IN_3_92
char * gsk_pixel_shader_to_string (GskPixelShader *shader);
G_END_DECLS
#endif /* __GSK_PIXEL_SHADER_H__ */

View File

@@ -0,0 +1,29 @@
#ifndef __GSK_PIXEL_SHADER_PRIVATE_H__
#define __GSK_PIXEL_SHADER_PRIVATE_H__
#include "gskpixelshader.h"
#include "gskslnodeprivate.h"
G_BEGIN_DECLS
#define GSK_PIXEL_SHADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_TEXTURE, GskPixelShaderClass))
#define GSK_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_TEXTURE))
#define GSK_PIXEL_SHADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_TEXTURE, GskPixelShaderClass))
struct _GskPixelShader
{
GObject parent_instance;
GskSlNode *program;
guint n_textures;
};
struct _GskPixelShaderClass {
GObjectClass parent_class;
};
G_END_DECLS
#endif /* __GSK_PIXEL_SHADER_PRIVATE_H__ */

285
gsk/gskslnode.c Normal file
View File

@@ -0,0 +1,285 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslnodeprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gsksltypeprivate.h"
#include <string.h>
static GskSlNode *
gsk_sl_node_alloc (const GskSlNodeClass *klass,
gsize size)
{
GskSlNode *node;
node = g_slice_alloc0 (size);
node->class = klass;
node->ref_count = 1;
return node;
}
#define gsk_sl_node_new(_name, _klass) ((_name *) gsk_sl_node_alloc ((_klass), sizeof (_name)))
/* PROGRAM */
typedef struct _GskSlNodeProgram GskSlNodeProgram;
struct _GskSlNodeProgram {
GskSlNode parent;
GSList *declarations;
GSList *functions;
};
static void
gsk_sl_node_program_free (GskSlNode *node)
{
GskSlNodeProgram *program = (GskSlNodeProgram *) node;
g_slist_free (program->declarations);
g_slist_free (program->functions);
g_slice_free (GskSlNodeProgram, program);
}
static void
gsk_sl_node_program_print (GskSlNode *node,
GString *string)
{
GskSlNodeProgram *program = (GskSlNodeProgram *) node;
GSList *l;
for (l = program->declarations; l; l = l->next)
gsk_sl_node_print (l->data, string);
for (l = program->functions; l; l = l->next)
gsk_sl_node_print (l->data, string);
}
static const GskSlNodeClass GSK_SL_NODE_PROGRAM = {
gsk_sl_node_program_free,
gsk_sl_node_program_print
};
/* FUNCTION */
typedef struct _GskSlNodeFunction GskSlNodeFunction;
struct _GskSlNodeFunction {
GskSlNode parent;
GskSlType *return_type;
char *name;
};
static void
gsk_sl_node_function_free (GskSlNode *node)
{
GskSlNodeFunction *function = (GskSlNodeFunction *) node;
if (function->return_type)
gsk_sl_type_unref (function->return_type);
g_free (function->name);
g_slice_free (GskSlNodeFunction, function);
}
static void
gsk_sl_node_function_print (GskSlNode *node,
GString *string)
{
GskSlNodeFunction *function = (GskSlNodeFunction *) node;
gsk_sl_type_print (function->return_type, string);
g_string_append (string, "\n");
g_string_append (string, function->name);
g_string_append (string, " (");
g_string_append (string, ")\n");
g_string_append (string, "{\n");
g_string_append (string, "}\n");
}
static const GskSlNodeClass GSK_SL_NODE_FUNCTION = {
gsk_sl_node_function_free,
gsk_sl_node_function_print
};
/* API */
static GskSlNodeFunction *
gsk_sl_node_parse_function_prototype (GskSlNodeProgram *program,
GskSlPreprocessor *stream)
{
GskSlType *type;
GskSlNodeFunction *function;
const GskSlToken *token;
type = gsk_sl_type_new_parse (stream);
if (type == NULL)
return NULL;
token = gsk_sl_preprocessor_get (stream);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
gsk_sl_preprocessor_error (stream, "Expected a function name");
gsk_sl_type_unref (type);
return NULL;
}
function = gsk_sl_node_new (GskSlNodeFunction, &GSK_SL_NODE_FUNCTION);
function->return_type = type;
function->name = g_strdup (token->str);
gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
token = gsk_sl_preprocessor_get (stream);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
{
gsk_sl_preprocessor_error (stream, "Expected an openening \"(\"");
gsk_sl_node_unref ((GskSlNode *) function);
return NULL;
}
gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
token = gsk_sl_preprocessor_get (stream);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
gsk_sl_preprocessor_error (stream, "Expected a closing \")\"");
gsk_sl_node_unref ((GskSlNode *) function);
return NULL;
}
gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
return function;
}
static gboolean
gsk_sl_node_parse_function_definition (GskSlNodeProgram *program,
GskSlPreprocessor *stream)
{
GskSlNodeFunction *function;
const GskSlToken *token;
function = gsk_sl_node_parse_function_prototype (program, stream);
if (function == NULL)
return FALSE;
token = gsk_sl_preprocessor_get (stream);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
{
gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
program->functions = g_slist_prepend (program->functions, function);
return TRUE;
}
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
{
gsk_sl_preprocessor_error (stream, "Expected an opening \"{\"");
gsk_sl_node_unref ((GskSlNode *) function);
return FALSE;
}
gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
token = gsk_sl_preprocessor_get (stream);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE))
{
gsk_sl_preprocessor_error (stream, "Expected a closing \"}\"");
gsk_sl_node_unref ((GskSlNode *) function);
return FALSE;
}
gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
program->functions = g_slist_prepend (program->functions, function);
return TRUE;
}
static gboolean
gsk_sl_node_parse_program (GskSlNodeProgram *program,
GskSlPreprocessor *stream)
{
const GskSlToken *token;
gboolean result = TRUE;
for (token = gsk_sl_preprocessor_get (stream);
!gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
token = gsk_sl_preprocessor_get (stream))
{
if (!gsk_sl_node_parse_function_definition (program, stream))
{
gsk_sl_preprocessor_consume (stream, (GskSlNode *) program);
result = FALSE;
}
}
return result;
}
GskSlNode *
gsk_sl_node_new_program (GBytes *source,
GError **error)
{
GskSlPreprocessor *stream;
GskSlNodeProgram *program;
program = gsk_sl_node_new (GskSlNodeProgram, &GSK_SL_NODE_PROGRAM);
stream = gsk_sl_preprocessor_new (source);
gsk_sl_node_parse_program (program, stream);
gsk_sl_preprocessor_unref (stream);
return (GskSlNode *) program;
}
GskSlNode *
gsk_sl_node_ref (GskSlNode *node)
{
g_return_val_if_fail (node != NULL, NULL);
node->ref_count += 1;
return node;
}
void
gsk_sl_node_unref (GskSlNode *node)
{
if (node == NULL)
return;
node->ref_count -= 1;
if (node->ref_count > 0)
return;
node->class->free (node);
}
void
gsk_sl_node_print (GskSlNode *node,
GString *string)
{
node->class->print (node, string);
}

52
gsk/gskslnodeprivate.h Normal file
View File

@@ -0,0 +1,52 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_NODE_PRIVATE_H__
#define __GSK_SL_NODE_PRIVATE_H__
#include <glib.h>
G_BEGIN_DECLS
typedef struct _GskSlNode GskSlNode;
typedef struct _GskSlNodeClass GskSlNodeClass;
struct _GskSlNode {
const GskSlNodeClass *class;
guint ref_count;
};
struct _GskSlNodeClass {
void (* free) (GskSlNode *node);
void (* print) (GskSlNode *node,
GString *string);
};
GskSlNode * gsk_sl_node_new_program (GBytes *source,
GError **error);
GskSlNode * gsk_sl_node_ref (GskSlNode *node);
void gsk_sl_node_unref (GskSlNode *node);
void gsk_sl_node_print (GskSlNode *node,
GString *string);
G_END_DECLS
#endif /* __GSK_SL_NODE_PRIVATE_H__ */

162
gsk/gskslpreprocessor.c Normal file
View File

@@ -0,0 +1,162 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslpreprocessorprivate.h"
struct _GskSlPreprocessor
{
int ref_count;
GskSlTokenizer *tokenizer;
GskCodeLocation location;
GskSlToken token;
};
/* API */
static void
gsk_sl_preprocessor_error_func (GskSlTokenizer *parser,
gboolean fatal,
const GskCodeLocation *location,
const GskSlToken *token,
const GError *error,
gpointer user_data)
{
g_printerr ("%3zu:%2zu: error: %3u: %s: %s\n",
location->lines + 1, location->line_bytes,
token->type, gsk_sl_token_to_string (token),
error->message);
}
GskSlPreprocessor *
gsk_sl_preprocessor_new (GBytes *source)
{
GskSlPreprocessor *preproc;
preproc = g_slice_new0 (GskSlPreprocessor);
preproc->ref_count = 1;
preproc->tokenizer = gsk_sl_tokenizer_new (source,
gsk_sl_preprocessor_error_func,
preproc,
NULL);
return preproc;
}
GskSlPreprocessor *
gsk_sl_preprocessor_ref (GskSlPreprocessor *preproc)
{
g_return_val_if_fail (preproc != NULL, NULL);
preproc->ref_count += 1;
return preproc;
}
void
gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc)
{
if (preproc == NULL)
return;
preproc->ref_count -= 1;
if (preproc->ref_count > 0)
return;
gsk_sl_tokenizer_unref (preproc->tokenizer);
gsk_sl_token_clear (&preproc->token);
g_slice_free (GskSlPreprocessor, preproc);
}
static gboolean
gsk_sl_token_is_skipped (const GskSlToken *token)
{
return gsk_sl_token_is (token, GSK_SL_TOKEN_ERROR)
|| gsk_sl_token_is (token, GSK_SL_TOKEN_WHITESPACE)
|| gsk_sl_token_is (token, GSK_SL_TOKEN_COMMENT)
|| gsk_sl_token_is (token, GSK_SL_TOKEN_SINGLE_LINE_COMMENT);
}
static void
gsk_sl_token_ensure (GskSlPreprocessor *preproc)
{
if (!gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_EOF))
return;
do
{
preproc->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
gsk_sl_tokenizer_read_token (preproc->tokenizer, &preproc->token);
}
while (gsk_sl_token_is_skipped (&preproc->token));
}
const GskSlToken *
gsk_sl_preprocessor_get (GskSlPreprocessor *preproc)
{
gsk_sl_token_ensure (preproc);
return &preproc->token;
}
const GskCodeLocation *
gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc)
{
gsk_sl_token_ensure (preproc);
return &preproc->location;
}
void
gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
GskSlNode *consumer)
{
gsk_sl_token_ensure (preproc);
gsk_sl_token_clear (&preproc->token);
}
void
gsk_sl_preprocessor_error (GskSlPreprocessor *preproc,
const char *format,
...)
{
GError *error;
va_list args;
va_start (args, format);
error = g_error_new_valist (G_FILE_ERROR,
G_FILE_ERROR_FAILED,
format,
args);
va_end (args);
gsk_sl_token_ensure (preproc);
gsk_sl_preprocessor_error_func (preproc->tokenizer,
TRUE,
&preproc->location,
&preproc->token,
error,
NULL);
g_error_free (error);
}

View File

@@ -0,0 +1,47 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_PREPROCESSOR_PRIVATE_H__
#define __GSK_SL_PREPROCESSOR_PRIVATE_H__
#include <glib.h>
#include "gskslnodeprivate.h"
#include "gsksltokenizerprivate.h"
G_BEGIN_DECLS
typedef struct _GskSlPreprocessor GskSlPreprocessor;
GskSlPreprocessor * gsk_sl_preprocessor_new (GBytes *source);
GskSlPreprocessor * gsk_sl_preprocessor_ref (GskSlPreprocessor *preproc);
void gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc);
const GskSlToken * gsk_sl_preprocessor_get (GskSlPreprocessor *preproc);
const GskCodeLocation * gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc);
void gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
GskSlNode *consumer);
void gsk_sl_preprocessor_error (GskSlPreprocessor *preproc,
const char *format,
...) G_GNUC_PRINTF(2, 3);
G_END_DECLS
#endif /* __GSK_SL_PREPROCESSOR_PRIVATE_H__ */

1838
gsk/gsksltokenizer.c Normal file

File diff suppressed because it is too large Load Diff

293
gsk/gsksltokenizerprivate.h Normal file
View File

@@ -0,0 +1,293 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_TOKENIZER_PRIVATE_H__
#define __GSK_SL_TOKENIZER_PRIVATE_H__
#include <gsktypes.h>
G_BEGIN_DECLS
typedef enum {
GSK_SL_TOKEN_EOF = 0,
GSK_SL_TOKEN_ERROR,
GSK_SL_TOKEN_WHITESPACE,
GSK_SL_TOKEN_COMMENT,
GSK_SL_TOKEN_SINGLE_LINE_COMMENT,
/* real tokens */
GSK_SL_TOKEN_CONST,
GSK_SL_TOKEN_BOOL,
GSK_SL_TOKEN_FLOAT,
GSK_SL_TOKEN_DOUBLE,
GSK_SL_TOKEN_INT,
GSK_SL_TOKEN_UINT,
GSK_SL_TOKEN_BREAK,
GSK_SL_TOKEN_CONTINUE,
GSK_SL_TOKEN_DO,
GSK_SL_TOKEN_ELSE,
GSK_SL_TOKEN_FOR,
GSK_SL_TOKEN_IF,
GSK_SL_TOKEN_DISCARD,
GSK_SL_TOKEN_RETURN,
GSK_SL_TOKEN_SWITCH,
GSK_SL_TOKEN_CASE,
GSK_SL_TOKEN_DEFAULT,
GSK_SL_TOKEN_SUBROUTINE,
GSK_SL_TOKEN_BVEC2,
GSK_SL_TOKEN_BVEC3,
GSK_SL_TOKEN_BVEC4,
GSK_SL_TOKEN_IVEC2,
GSK_SL_TOKEN_IVEC3,
GSK_SL_TOKEN_IVEC4,
GSK_SL_TOKEN_UVEC2,
GSK_SL_TOKEN_UVEC3,
GSK_SL_TOKEN_UVEC4,
GSK_SL_TOKEN_VEC2,
GSK_SL_TOKEN_VEC3,
GSK_SL_TOKEN_VEC4,
GSK_SL_TOKEN_MAT2,
GSK_SL_TOKEN_MAT3,
GSK_SL_TOKEN_MAT4,
GSK_SL_TOKEN_CENTROID,
GSK_SL_TOKEN_IN,
GSK_SL_TOKEN_OUT,
GSK_SL_TOKEN_INOUT,
GSK_SL_TOKEN_UNIFORM,
GSK_SL_TOKEN_PATCH,
GSK_SL_TOKEN_SAMPLE,
GSK_SL_TOKEN_BUFFER,
GSK_SL_TOKEN_SHARED,
GSK_SL_TOKEN_COHERENT,
GSK_SL_TOKEN_VOLATILE,
GSK_SL_TOKEN_RESTRICT,
GSK_SL_TOKEN_READONLY,
GSK_SL_TOKEN_WRITEONLY,
GSK_SL_TOKEN_DVEC2,
GSK_SL_TOKEN_DVEC3,
GSK_SL_TOKEN_DVEC4,
GSK_SL_TOKEN_DMAT2,
GSK_SL_TOKEN_DMAT3,
GSK_SL_TOKEN_DMAT4,
GSK_SL_TOKEN_NOPERSPECTIVE,
GSK_SL_TOKEN_FLAT,
GSK_SL_TOKEN_SMOOTH,
GSK_SL_TOKEN_LAYOUT,
GSK_SL_TOKEN_MAT2X2,
GSK_SL_TOKEN_MAT2X3,
GSK_SL_TOKEN_MAT2X4,
GSK_SL_TOKEN_MAT3X2,
GSK_SL_TOKEN_MAT3X3,
GSK_SL_TOKEN_MAT3X4,
GSK_SL_TOKEN_MAT4X2,
GSK_SL_TOKEN_MAT4X3,
GSK_SL_TOKEN_MAT4X4,
GSK_SL_TOKEN_DMAT2X2,
GSK_SL_TOKEN_DMAT2X3,
GSK_SL_TOKEN_DMAT2X4,
GSK_SL_TOKEN_DMAT3X2,
GSK_SL_TOKEN_DMAT3X3,
GSK_SL_TOKEN_DMAT3X4,
GSK_SL_TOKEN_DMAT4X2,
GSK_SL_TOKEN_DMAT4X3,
GSK_SL_TOKEN_DMAT4X4,
GSK_SL_TOKEN_ATOMIC_UINT,
GSK_SL_TOKEN_SAMPLER1D,
GSK_SL_TOKEN_SAMPLER2D,
GSK_SL_TOKEN_SAMPLER3D,
GSK_SL_TOKEN_SAMPLERCUBE,
GSK_SL_TOKEN_SAMPLER1DSHADOW,
GSK_SL_TOKEN_SAMPLER2DSHADOW,
GSK_SL_TOKEN_SAMPLERCUBESHADOW,
GSK_SL_TOKEN_SAMPLER1DARRAY,
GSK_SL_TOKEN_SAMPLER2DARRAY,
GSK_SL_TOKEN_SAMPLER1DARRAYSHADOW,
GSK_SL_TOKEN_SAMPLER2DARRAYSHADOW,
GSK_SL_TOKEN_ISAMPLER1D,
GSK_SL_TOKEN_ISAMPLER2D,
GSK_SL_TOKEN_ISAMPLER3D,
GSK_SL_TOKEN_ISAMPLERCUBE,
GSK_SL_TOKEN_ISAMPLER1DARRAY,
GSK_SL_TOKEN_ISAMPLER2DARRAY,
GSK_SL_TOKEN_USAMPLER1D,
GSK_SL_TOKEN_USAMPLER2D,
GSK_SL_TOKEN_USAMPLER3D,
GSK_SL_TOKEN_USAMPLERCUBE,
GSK_SL_TOKEN_USAMPLER1DARRAY,
GSK_SL_TOKEN_USAMPLER2DARRAY,
GSK_SL_TOKEN_SAMPLER2DRECT,
GSK_SL_TOKEN_SAMPLER2DRECTSHADOW,
GSK_SL_TOKEN_ISAMPLER2DRECT,
GSK_SL_TOKEN_USAMPLER2DRECT,
GSK_SL_TOKEN_SAMPLERBUFFER,
GSK_SL_TOKEN_ISAMPLERBUFFER,
GSK_SL_TOKEN_USAMPLERBUFFER,
GSK_SL_TOKEN_SAMPLERCUBEARRAY,
GSK_SL_TOKEN_SAMPLERCUBEARRAYSHADOW,
GSK_SL_TOKEN_ISAMPLERCUBEARRAY,
GSK_SL_TOKEN_USAMPLERCUBEARRAY,
GSK_SL_TOKEN_SAMPLER2DMS,
GSK_SL_TOKEN_ISAMPLER2DMS,
GSK_SL_TOKEN_USAMPLER2DMS,
GSK_SL_TOKEN_SAMPLER2DMSARRAY,
GSK_SL_TOKEN_ISAMPLER2DMSARRAY,
GSK_SL_TOKEN_USAMPLER2DMSARRAY,
GSK_SL_TOKEN_IMAGE1D,
GSK_SL_TOKEN_IIMAGE1D,
GSK_SL_TOKEN_UIMAGE1D,
GSK_SL_TOKEN_IMAGE2D,
GSK_SL_TOKEN_IIMAGE2D,
GSK_SL_TOKEN_UIMAGE2D,
GSK_SL_TOKEN_IMAGE3D,
GSK_SL_TOKEN_IIMAGE3D,
GSK_SL_TOKEN_UIMAGE3D,
GSK_SL_TOKEN_IMAGE2DRECT,
GSK_SL_TOKEN_IIMAGE2DRECT,
GSK_SL_TOKEN_UIMAGE2DRECT,
GSK_SL_TOKEN_IMAGECUBE,
GSK_SL_TOKEN_IIMAGECUBE,
GSK_SL_TOKEN_UIMAGECUBE,
GSK_SL_TOKEN_IMAGEBUFFER,
GSK_SL_TOKEN_IIMAGEBUFFER,
GSK_SL_TOKEN_UIMAGEBUFFER,
GSK_SL_TOKEN_IMAGE1DARRAY,
GSK_SL_TOKEN_IIMAGE1DARRAY,
GSK_SL_TOKEN_UIMAGE1DARRAY,
GSK_SL_TOKEN_IMAGE2DARRAY,
GSK_SL_TOKEN_IIMAGE2DARRAY,
GSK_SL_TOKEN_UIMAGE2DARRAY,
GSK_SL_TOKEN_IMAGECUBEARRAY,
GSK_SL_TOKEN_IIMAGECUBEARRAY,
GSK_SL_TOKEN_UIMAGECUBEARRAY,
GSK_SL_TOKEN_IMAGE2DMS,
GSK_SL_TOKEN_IIMAGE2DMS,
GSK_SL_TOKEN_UIMAGE2DMS,
GSK_SL_TOKEN_IMAGE2DMSARRAY,
GSK_SL_TOKEN_IIMAGE2DMSARRAY,
GSK_SL_TOKEN_UIMAGE2DMSARRAY,
GSK_SL_TOKEN_STRUCT,
GSK_SL_TOKEN_VOID,
GSK_SL_TOKEN_WHILE,
GSK_SL_TOKEN_IDENTIFIER,
GSK_SL_TOKEN_FLOATCONSTANT,
GSK_SL_TOKEN_DOUBLECONSTANT,
GSK_SL_TOKEN_INTCONSTANT,
GSK_SL_TOKEN_UINTCONSTANT,
GSK_SL_TOKEN_BOOLCONSTANT,
GSK_SL_TOKEN_LEFT_OP,
GSK_SL_TOKEN_RIGHT_OP,
GSK_SL_TOKEN_INC_OP,
GSK_SL_TOKEN_DEC_OP,
GSK_SL_TOKEN_LE_OP,
GSK_SL_TOKEN_GE_OP,
GSK_SL_TOKEN_EQ_OP,
GSK_SL_TOKEN_NE_OP,
GSK_SL_TOKEN_AND_OP,
GSK_SL_TOKEN_OR_OP,
GSK_SL_TOKEN_XOR_OP,
GSK_SL_TOKEN_MUL_ASSIGN,
GSK_SL_TOKEN_DIV_ASSIGN,
GSK_SL_TOKEN_ADD_ASSIGN,
GSK_SL_TOKEN_MOD_ASSIGN,
GSK_SL_TOKEN_LEFT_ASSIGN,
GSK_SL_TOKEN_RIGHT_ASSIGN,
GSK_SL_TOKEN_AND_ASSIGN,
GSK_SL_TOKEN_XOR_ASSIGN,
GSK_SL_TOKEN_OR_ASSIGN,
GSK_SL_TOKEN_SUB_ASSIGN,
GSK_SL_TOKEN_LEFT_PAREN,
GSK_SL_TOKEN_RIGHT_PAREN,
GSK_SL_TOKEN_LEFT_BRACKET,
GSK_SL_TOKEN_RIGHT_BRACKET,
GSK_SL_TOKEN_LEFT_BRACE,
GSK_SL_TOKEN_RIGHT_BRACE,
GSK_SL_TOKEN_DOT,
GSK_SL_TOKEN_COMMA,
GSK_SL_TOKEN_COLON,
GSK_SL_TOKEN_EQUAL,
GSK_SL_TOKEN_SEMICOLON,
GSK_SL_TOKEN_BANG,
GSK_SL_TOKEN_DASH,
GSK_SL_TOKEN_TILDE,
GSK_SL_TOKEN_PLUS,
GSK_SL_TOKEN_STAR,
GSK_SL_TOKEN_SLASH,
GSK_SL_TOKEN_PERCENT,
GSK_SL_TOKEN_LEFT_ANGLE,
GSK_SL_TOKEN_RIGHT_ANGLE,
GSK_SL_TOKEN_VERTICAL_BAR,
GSK_SL_TOKEN_CARET,
GSK_SL_TOKEN_AMPERSAND,
GSK_SL_TOKEN_QUESTION,
GSK_SL_TOKEN_INVARIANT,
GSK_SL_TOKEN_PRECISE,
GSK_SL_TOKEN_HIGH_PRECISION,
GSK_SL_TOKEN_MEDIUM_PRECISION,
GSK_SL_TOKEN_LOW_PRECISION,
GSK_SL_TOKEN_PRECISION
} GskSlTokenType;
typedef struct _GskSlToken GskSlToken;
typedef struct _GskSlTokenizer GskSlTokenizer;
typedef void (* GskSlTokenizerErrorFunc) (GskSlTokenizer *parser,
gboolean fatal,
const GskCodeLocation *location,
const GskSlToken *token,
const GError *error,
gpointer user_data);
struct _GskSlToken {
GskSlTokenType type;
union {
gint32 i32;
guint32 u32;
float f;
double d;
gboolean b;
char *str;
};
};
void gsk_sl_token_clear (GskSlToken *token);
gboolean gsk_sl_token_is_finite (const GskSlToken *token);
#define gsk_sl_token_is(token, _type) ((token)->type == (_type))
gboolean gsk_sl_token_is_ident (const GskSlToken *token,
const char *ident);
gboolean gsk_sl_token_is_function (const GskSlToken *token,
const char *ident);
void gsk_sl_token_print (const GskSlToken *token,
GString *string);
char * gsk_sl_token_to_string (const GskSlToken *token);
GskSlTokenizer * gsk_sl_tokenizer_new (GBytes *bytes,
GskSlTokenizerErrorFunc func,
gpointer user_data,
GDestroyNotify user_destroy);
GskSlTokenizer * gsk_sl_tokenizer_ref (GskSlTokenizer *tokenizer);
void gsk_sl_tokenizer_unref (GskSlTokenizer *tokenizer);
const GskCodeLocation * gsk_sl_tokenizer_get_location (GskSlTokenizer *tokenizer);
void gsk_sl_tokenizer_read_token (GskSlTokenizer *tokenizer,
GskSlToken *token);
G_END_DECLS
#endif /* __GSK_SL_TOKENIZER_PRIVATE_H__ */

161
gsk/gsksltype.c Normal file
View File

@@ -0,0 +1,161 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gsksltypeprivate.h"
#include <string.h>
struct _GskSlType
{
int ref_count;
GskSlBuiltinType builtin;
};
static GskSlType
builtin_types[GSK_SL_N_BUILTIN_TYPES] = {
[GSK_SL_VOID] = { 1, GSK_SL_VOID },
[GSK_SL_FLOAT] = { 1, GSK_SL_FLOAT },
[GSK_SL_DOUBLE] = { 1, GSK_SL_DOUBLE },
[GSK_SL_INT] = { 1, GSK_SL_INT },
[GSK_SL_UINT] = { 1, GSK_SL_UINT },
[GSK_SL_BOOL] = { 1, GSK_SL_BOOL },
[GSK_SL_VEC2] = { 1, GSK_SL_VEC2 },
[GSK_SL_VEC3] = { 1, GSK_SL_VEC3 },
[GSK_SL_VEC4] = { 1, GSK_SL_VEC4 }
};
GskSlType *
gsk_sl_type_new_parse (GskSlPreprocessor *stream)
{
GskSlBuiltinType builtin;
const GskSlToken *token;
token = gsk_sl_preprocessor_get (stream);
switch ((guint) token->type)
{
case GSK_SL_TOKEN_VOID:
builtin = GSK_SL_VOID;
break;
case GSK_SL_TOKEN_FLOAT:
builtin = GSK_SL_FLOAT;
break;
case GSK_SL_TOKEN_DOUBLE:
builtin = GSK_SL_DOUBLE;
break;
case GSK_SL_TOKEN_INT:
builtin = GSK_SL_INT;
break;
case GSK_SL_TOKEN_UINT:
builtin = GSK_SL_UINT;
break;
case GSK_SL_TOKEN_BOOL:
builtin = GSK_SL_BOOL;
break;
case GSK_SL_TOKEN_VEC2:
builtin = GSK_SL_VEC2;
break;
case GSK_SL_TOKEN_VEC3:
builtin = GSK_SL_VEC3;
break;
case GSK_SL_TOKEN_VEC4:
builtin = GSK_SL_VEC4;
break;
default:
gsk_sl_preprocessor_error (stream, "Expected type specifier");
return NULL;
}
gsk_sl_preprocessor_consume (stream, NULL);
return gsk_sl_type_ref (gsk_sl_type_get_builtin (builtin));
}
GskSlType *
gsk_sl_type_get_builtin (GskSlBuiltinType builtin)
{
g_assert (builtin < GSK_SL_N_BUILTIN_TYPES);
return &builtin_types[builtin];
}
GskSlType *
gsk_sl_type_ref (GskSlType *type)
{
g_return_val_if_fail (type != NULL, NULL);
type->ref_count += 1;
return type;
}
void
gsk_sl_type_unref (GskSlType *type)
{
if (type == NULL)
return;
type->ref_count -= 1;
if (type->ref_count > 0)
return;
g_assert_not_reached ();
}
void
gsk_sl_type_print (const GskSlType *type,
GString *string)
{
switch (type->builtin)
{
case GSK_SL_VOID:
g_string_append (string, "void");
break;
case GSK_SL_FLOAT:
g_string_append (string, "float");
break;
case GSK_SL_DOUBLE:
g_string_append (string, "double");
break;
case GSK_SL_INT:
g_string_append (string, "int");
break;
case GSK_SL_UINT:
g_string_append (string, "uint");
break;
case GSK_SL_BOOL:
g_string_append (string, "bool");
break;
case GSK_SL_VEC2:
g_string_append (string, "vec2");
break;
case GSK_SL_VEC3:
g_string_append (string, "vec3");
break;
case GSK_SL_VEC4:
g_string_append (string, "vec4");
break;
/* add more above */
case GSK_SL_N_BUILTIN_TYPES:
default:
g_assert_not_reached ();
break;
}
}

55
gsk/gsksltypeprivate.h Normal file
View File

@@ -0,0 +1,55 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_TYPE_PRIVATE_H__
#define __GSK_SL_TYPE_PRIVATE_H__
#include <glib.h>
#include "gskslpreprocessorprivate.h"
G_BEGIN_DECLS
typedef enum {
GSK_SL_VOID,
GSK_SL_FLOAT,
GSK_SL_DOUBLE,
GSK_SL_INT,
GSK_SL_UINT,
GSK_SL_BOOL,
GSK_SL_VEC2,
GSK_SL_VEC3,
GSK_SL_VEC4,
/* add more above */
GSK_SL_N_BUILTIN_TYPES
} GskSlBuiltinType;
typedef struct _GskSlType GskSlType;
GskSlType * gsk_sl_type_new_parse (GskSlPreprocessor *stream);
GskSlType * gsk_sl_type_get_builtin (GskSlBuiltinType builtin);
GskSlType * gsk_sl_type_ref (GskSlType *type);
void gsk_sl_type_unref (GskSlType *type);
void gsk_sl_type_print (const GskSlType *type,
GString *string);
G_END_DECLS
#endif /* __GSK_SL_TYPE_PRIVATE_H__ */

View File

@@ -26,7 +26,18 @@
#include <gdk/gdk.h>
#include <gsk/gskenums.h>
typedef struct _GskCodeLocation GskCodeLocation;
typedef struct _GskPixelShader GskPixelShader;
typedef struct _GskRenderer GskRenderer;
typedef struct _GskTexture GskTexture;
struct _GskCodeLocation
{
gsize bytes;
gsize chars;
gsize lines;
gsize line_bytes;
gsize line_chars;
};
#endif /* __GSK_TYPES_H__ */

View File

@@ -14,6 +14,7 @@ gsk_private_source_shaders = [
]
gsk_public_sources = files([
'gskpixelshader.c',
'gskrenderer.c',
'gskrendernode.c',
'gskrendernodeimpl.c',
@@ -31,10 +32,15 @@ gsk_private_sources = files([
'gskprivate.c',
'gskprofiler.c',
'gskshaderbuilder.c',
'gskslnode.c',
'gskslpreprocessor.c',
'gsksltokenizer.c',
'gsksltype.c'
])
gsk_public_headers = files([
'gskenums.h',
'gskpixelshader.h',
'gskrenderer.h',
'gskrendernode.h',
'gskroundedrect.h',

View File

@@ -60,6 +60,8 @@ gtk_inspector_init (void)
g_type_ensure (G_TYPE_LIST_STORE);
g_type_ensure (GSK_TYPE_PIXEL_SHADER);
g_type_ensure (GTK_TYPE_CELL_RENDERER_GRAPH);
g_type_ensure (GTK_TYPE_GRAPH_DATA);
g_type_ensure (GTK_TYPE_INSPECTOR_ACTIONS);

View File

@@ -0,0 +1,3 @@
test_parser = executable('test-parser', 'test-parser.c', dependencies: libgtk_dep)
test('gsksl/parser', test_parser)

View File

@@ -0,0 +1,360 @@
/*
* Copyright (C) 2017 Red Hat Inc.
*
* Author:
* Benjamin Otte <otte@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#include <glib/gstdio.h>
#include <gsk/gsk.h>
#include <gtk/gtk.h>
#ifdef G_OS_WIN32
# include <io.h>
#endif
static char *
test_get_reference_file (const char *glsl_file)
{
GString *file = g_string_new (NULL);
if (g_str_has_suffix (glsl_file, ".glsl"))
g_string_append_len (file, glsl_file, strlen (glsl_file) - 4);
else
g_string_append (file, glsl_file);
g_string_append (file, ".ref.glsl");
if (!g_file_test (file->str, G_FILE_TEST_EXISTS))
{
g_string_free (file, TRUE);
return g_strdup (glsl_file);
}
return g_string_free (file, FALSE);
}
static char *
test_get_errors_file (const char *glsl_file)
{
GString *file = g_string_new (NULL);
if (g_str_has_suffix (glsl_file, ".glsl"))
g_string_append_len (file, glsl_file, strlen (glsl_file) - 4);
else
g_string_append (file, glsl_file);
g_string_append (file, ".errors");
if (!g_file_test (file->str, G_FILE_TEST_EXISTS))
{
g_string_free (file, TRUE);
return NULL;
}
return g_string_free (file, FALSE);
}
static char *
diff_with_file (const char *file1,
char *text,
gssize len,
GError **error)
{
const char *command[] = { "diff", "-u", file1, NULL, NULL };
char *diff, *tmpfile;
int fd;
diff = NULL;
if (len < 0)
len = strlen (text);
/* write the text buffer to a temporary file */
fd = g_file_open_tmp (NULL, &tmpfile, error);
if (fd < 0)
return NULL;
if (write (fd, text, len) != (int) len)
{
close (fd);
g_set_error (error,
G_FILE_ERROR, G_FILE_ERROR_FAILED,
"Could not write data to temporary file '%s'", tmpfile);
goto done;
}
close (fd);
command[3] = tmpfile;
/* run diff command */
g_spawn_sync (NULL,
(char **) command,
NULL,
G_SPAWN_SEARCH_PATH,
NULL, NULL,
&diff,
NULL, NULL,
error);
done:
g_unlink (tmpfile);
g_free (tmpfile);
return diff;
}
#if 0
static void
append_error_value (GString *string,
GType enum_type,
guint value)
{
GEnumClass *enum_class;
GEnumValue *enum_value;
enum_class = g_type_class_ref (enum_type);
enum_value = g_enum_get_value (enum_class, value);
g_string_append (string, enum_value->value_name);
g_type_class_unref (enum_class);
}
#endif
static void
parsing_error_cb (GskPixelShader *shader,
gboolean fatal,
const GskCodeLocation *location,
const GError *error,
gpointer user_data)
{
GString *errors = user_data;
if (fatal)
g_test_fail ();
g_string_append_printf (errors,
"%zu:%zu: %s: ",
location->lines, location->line_chars,
fatal ? "ERROR" : "warning");
g_string_append_printf (errors,
"%s\n",
error->message);
}
static void
parse_glsl_file (GFile *file, gboolean generate)
{
GskPixelShader *shader;
GBytes *bytes;
char *glsl, *diff;
char *glsl_file, *reference_file, *errors_file;
gsize length;
GString *errors;
GError *error = NULL;
glsl_file = g_file_get_path (file);
errors = g_string_new ("");
g_file_load_contents (file, NULL,
&glsl, &length,
NULL, &error);
g_assert_no_error (error);
bytes = g_bytes_new_take (glsl, length);
shader = gsk_pixel_shader_new_for_data (bytes,
parsing_error_cb,
errors);
glsl = gsk_pixel_shader_to_string (shader);
if (generate)
{
g_print ("%s", glsl);
goto out;
}
reference_file = test_get_reference_file (glsl_file);
diff = diff_with_file (reference_file, glsl, -1, &error);
g_assert_no_error (error);
if (diff && diff[0])
{
g_test_message ("Resulting CSS doesn't match reference:\n%s", diff);
g_test_fail ();
}
g_free (reference_file);
errors_file = test_get_errors_file (glsl_file);
if (errors_file)
{
diff = diff_with_file (errors_file, errors->str, errors->len, &error);
g_assert_no_error (error);
if (diff && diff[0])
{
g_test_message ("Errors don't match expected errors:\n%s", diff);
g_test_fail ();
}
}
else if (errors->str[0])
{
g_test_message ("Unexpected errors:\n%s", errors->str);
g_test_fail ();
}
g_object_unref (shader);
g_free (errors_file);
g_string_free (errors, TRUE);
g_free (diff);
out:
g_free (glsl_file);
g_free (glsl);
}
static void
test_glsl_file (GFile *file)
{
parse_glsl_file (file, FALSE);
}
static void
add_test_for_file (GFile *file)
{
char *path;
path = g_file_get_path (file);
g_test_add_vtable (path,
0,
g_object_ref (file),
NULL,
(GTestFixtureFunc) test_glsl_file,
(GTestFixtureFunc) g_object_unref);
g_free (path);
}
static int
compare_files (gconstpointer a, gconstpointer b)
{
GFile *file1 = G_FILE (a);
GFile *file2 = G_FILE (b);
char *path1, *path2;
int result;
path1 = g_file_get_path (file1);
path2 = g_file_get_path (file2);
result = strcmp (path1, path2);
g_free (path1);
g_free (path2);
return result;
}
static void
add_tests_for_files_in_directory (GFile *dir)
{
GFileEnumerator *enumerator;
GFileInfo *info;
GList *files;
GError *error = NULL;
enumerator = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
g_assert_no_error (error);
files = NULL;
while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)))
{
const char *filename;
filename = g_file_info_get_name (info);
if (!g_str_has_suffix (filename, ".glsl") ||
g_str_has_suffix (filename, ".out.glsl") ||
g_str_has_suffix (filename, ".ref.glsl"))
{
g_object_unref (info);
continue;
}
files = g_list_prepend (files, g_file_get_child (dir, filename));
g_object_unref (info);
}
g_assert_no_error (error);
g_object_unref (enumerator);
files = g_list_sort (files, compare_files);
g_list_foreach (files, (GFunc) add_test_for_file, NULL);
g_list_free_full (files, g_object_unref);
}
int
main (int argc, char **argv)
{
gtk_test_init (&argc, &argv);
if (argc < 2)
{
const char *basedir;
GFile *dir;
basedir = g_test_get_dir (G_TEST_DIST);
dir = g_file_new_for_path (basedir);
add_tests_for_files_in_directory (dir);
g_object_unref (dir);
}
else if (strcmp (argv[1], "--generate") == 0)
{
if (argc >= 3)
{
GFile *file = g_file_new_for_commandline_arg (argv[2]);
parse_glsl_file (file, TRUE);
g_object_unref (file);
}
}
else
{
guint i;
for (i = 1; i < argc; i++)
{
GFile *file = g_file_new_for_commandline_arg (argv[i]);
add_test_for_file (file);
g_object_unref (file);
}
}
return g_test_run ();
}

View File

@@ -4,6 +4,7 @@ installed_test_datadir = join_paths(gtk_datadir, 'installed-tests', 'gtk-4.0')
subdir('gdk')
subdir('gsk')
subdir('gsksl')
subdir('gtk')
subdir('css')
subdir('a11y')