[gtk+/wip/otte/shader: 127/127] gsk: Add GskSlEnvironment



commit 6811f83b2caac1cc4dc54dd73835eccda6e72e1a
Author: Benjamin Otte <otte redhat com>
Date:   Fri Oct 13 00:48:46 2017 +0200

    gsk: Add GskSlEnvironment
    
    This is the object that is meant to hold information about different GL
    versions and take care of intializing native functions and variables at
    the start of parsing.

 gsk/gskslcompiler.c              |    2 +-
 gsk/gskslcompiler.h              |    3 +-
 gsk/gskslenvironment.c           |   98 ++++++++++++++++++++++++++++++++++++++
 gsk/gskslenvironmentprivate.h    |   41 ++++++++++++++++
 gsk/gskslnativefunction.c        |   47 +++++++++++++++---
 gsk/gskslnativefunctionprivate.h |    3 +-
 gsk/gskslpreprocessor.c          |   43 +++++++++++++++--
 gsk/gskslpreprocessorprivate.h   |    2 +
 gsk/gskslprogram.c               |    7 ++-
 gsk/gskslscope.c                 |   17 -------
 gsk/gsksltypesprivate.h          |    1 +
 gsk/meson.build                  |    1 +
 12 files changed, 231 insertions(+), 34 deletions(-)
---
diff --git a/gsk/gskslcompiler.c b/gsk/gskslcompiler.c
index a789ba1..8af9579 100644
--- a/gsk/gskslcompiler.c
+++ b/gsk/gskslcompiler.c
@@ -239,7 +239,7 @@ gsk_sl_compiler_compile (GskSlCompiler *compiler,
 
   program = g_object_new (GSK_TYPE_SL_PROGRAM, NULL);
 
-  preproc = gsk_sl_preprocessor_new (compiler, source);
+  preproc = gsk_sl_preprocessor_new (compiler, NULL, source);
 
   gsk_sl_program_parse (program, preproc);
 
diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h
index 16c2f2e..6746e56 100644
--- a/gsk/gskslcompiler.h
+++ b/gsk/gskslcompiler.h
@@ -44,7 +44,8 @@ typedef enum {
   GSK_SL_COMPILER_WARNING_CONSTANT,
   GSK_SL_COMPILER_WARNING_DEAD_CODE,
   GSK_SL_COMPILER_WARNING_SHADOW,
-  GSK_SL_COMPILER_WARNING_UNIMPLEMENTED
+  GSK_SL_COMPILER_WARNING_UNIMPLEMENTED,
+  GSK_SL_COMPILER_WARNING_VERSION
 } GskSlCompilerWarning;
 
 #define GSK_SL_COMPILER_ERROR (gsk_sl_compiler_error_quark ())
diff --git a/gsk/gskslenvironment.c b/gsk/gskslenvironment.c
new file mode 100644
index 0000000..f9c5ef2
--- /dev/null
+++ b/gsk/gskslenvironment.c
@@ -0,0 +1,98 @@
+/* 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 "gskslenvironmentprivate.h"
+
+#include "gskslnativefunctionprivate.h"
+#include "gskslscopeprivate.h"
+
+#include <string.h>
+
+struct _GskSlEnvironment
+{
+  int ref_count;
+
+  GskSlProfile profile;
+  guint version;
+};
+
+GskSlEnvironment *
+gsk_sl_environment_new (GskSlProfile profile,
+                        guint        version)
+{
+  GskSlEnvironment *environment;
+  
+  environment = g_slice_new0 (GskSlEnvironment);
+  environment->ref_count = 1;
+
+  environment->profile = profile;
+  environment->version = version;
+
+  return environment;
+}
+
+GskSlEnvironment *
+gsk_sl_environment_ref (GskSlEnvironment *environment)
+{
+  g_return_val_if_fail (environment != NULL, NULL);
+
+  environment->ref_count += 1;
+
+  return environment;
+}
+
+void
+gsk_sl_environment_unref (GskSlEnvironment *environment)
+{
+  if (environment == NULL)
+    return;
+
+  environment->ref_count -= 1;
+  if (environment->ref_count > 0)
+    return;
+
+  g_slice_free (GskSlEnvironment, environment);
+}
+
+
+GskSlProfile
+gsk_sl_environment_get_profile (GskSlEnvironment *environment)
+{
+  return environment->profile;
+}
+
+guint
+gsk_sl_environment_get_version (GskSlEnvironment *environment)
+{
+  return environment->version;
+}
+
+GskSlScope *
+gsk_sl_environment_create_scope (GskSlEnvironment *environment)
+{
+  GskSlScope *scope;
+
+  scope = gsk_sl_scope_new (NULL, NULL);
+
+  gsk_sl_native_functions_add (scope, environment);
+
+  return scope;
+}
+
diff --git a/gsk/gskslenvironmentprivate.h b/gsk/gskslenvironmentprivate.h
new file mode 100644
index 0000000..5e73f1c
--- /dev/null
+++ b/gsk/gskslenvironmentprivate.h
@@ -0,0 +1,41 @@
+/* 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_ENVIRONMENT_PRIVATE_H__
+#define __GSK_SL_ENVIRONMENT_PRIVATE_H__
+
+#include <glib.h>
+
+#include "gsksltypesprivate.h"
+
+G_BEGIN_DECLS
+
+GskSlEnvironment *      gsk_sl_environment_new                  (GskSlProfile          profile,
+                                                                 guint                 version);
+
+GskSlEnvironment *      gsk_sl_environment_ref                  (GskSlEnvironment     *environment);
+void                    gsk_sl_environment_unref                (GskSlEnvironment     *environment);
+
+GskSlProfile            gsk_sl_environment_get_profile          (GskSlEnvironment     *environment);
+guint                   gsk_sl_environment_get_version          (GskSlEnvironment     *environment);
+
+GskSlScope *            gsk_sl_environment_create_scope         (GskSlEnvironment     *environment);
+
+G_END_DECLS
+
+#endif /* __GSK_SL_ENVIRONMENT_PRIVATE_H__ */
diff --git a/gsk/gskslnativefunction.c b/gsk/gskslnativefunction.c
index ca91ddb..3283a3e 100644
--- a/gsk/gskslnativefunction.c
+++ b/gsk/gskslnativefunction.c
@@ -20,13 +20,17 @@
 
 #include "gskslnativefunctionprivate.h"
 
+#include "gskslenvironmentprivate.h"
+#include "gskslfunctionprivate.h"
+#include "gskslscopeprivate.h"
+
 #define NATIVE1(type, name, arg1) \
   { name, GSK_SL_BUILTIN_ ## type, 1, (GskSlBuiltinType[1]) { GSK_SL_BUILTIN_ ## arg1 } }
 #define NATIVE2(type, name, arg1, arg2) \
   { name, GSK_SL_BUILTIN_ ## type, 2, (GskSlBuiltinType[2]) { GSK_SL_BUILTIN_ ## arg1, GSK_SL_BUILTIN_ ## 
arg2 } }
 #define NATIVE3(type, name, arg1, arg2, arg3) \
   { name, GSK_SL_BUILTIN_ ## type, 3, (GskSlBuiltinType[3]) { GSK_SL_BUILTIN_ ## arg1, GSK_SL_BUILTIN_ ## 
arg2, GSK_SL_BUILTIN_ ## arg3, } }
-const GskSlNativeFunction gsk_glsl_functions[] = {
+static const GskSlNativeFunction gsk_glsl_functions[] = {
   NATIVE1 (FLOAT, "radians", FLOAT),
   NATIVE1 (VEC2, "radians", VEC2),
   NATIVE1 (VEC3, "radians", VEC3),
@@ -248,12 +252,10 @@ const GskSlNativeFunction gsk_glsl_functions[] = {
   NATIVE1 (BVEC2, "not", BVEC2),
   NATIVE1 (BVEC3, "not", BVEC3),
   NATIVE1 (BVEC4, "not", BVEC4),
-#if 0
   { NULL }
 };
 
 static const GskSlNativeFunction gsk_glsl_functions_120[] = {
-#endif
   NATIVE2 (MAT2, "outerProduct", VEC2, VEC2),
   NATIVE2 (MAT3, "outerProduct", VEC3, VEC3),
   NATIVE2 (MAT4, "outerProduct", VEC4, VEC4),
@@ -278,12 +280,10 @@ static const GskSlNativeFunction gsk_glsl_functions_120[] = {
   NATIVE2 (MAT3X4, "matrixCompMult", MAT3X4, MAT3X4),
   NATIVE2 (MAT4X2, "matrixCompMult", MAT4X2, MAT4X2),
   NATIVE2 (MAT4X3, "matrixCompMult", MAT4X3, MAT4X3),
-#if 0
   { NULL }
 };
 
 static const GskSlNativeFunction gsk_glsl_functions_130[] = {
-#endif
   NATIVE1 (FLOAT, "sinh", FLOAT),
   NATIVE1 (VEC2, "sinh", VEC2),
   NATIVE1 (VEC3, "sinh", VEC3),
@@ -406,12 +406,10 @@ static const GskSlNativeFunction gsk_glsl_functions_130[] = {
   NATIVE2 (BVEC2, "notEqual", UVEC2, UVEC2),
   NATIVE2 (BVEC3, "notEqual", UVEC3, UVEC3),
   NATIVE2 (BVEC4, "notEqual", UVEC4, UVEC4),
-#if 0
   { NULL }
 };
 
 static const GskSlNativeFunction gsk_glsl_functions_150[] = {
-#endif
   NATIVE1 (FLOAT, "determinant", MAT2),
   NATIVE1 (FLOAT, "determinant", MAT3),
   NATIVE1 (FLOAT, "determinant", MAT4),
@@ -421,3 +419,38 @@ static const GskSlNativeFunction gsk_glsl_functions_150[] = {
   { NULL }
 };
 
+static void
+gsk_sl_native_functions_add_list (GskSlScope                *scope,
+                                  const GskSlNativeFunction *functions)
+{
+  guint i;
+
+  for (i = 0; functions[i].name; i++)
+    {
+      GskSlFunction *function = gsk_sl_function_new_native (&functions[i]);
+      gsk_sl_scope_add_function (scope, function);
+      gsk_sl_function_unref (function);
+    }
+}
+
+void
+gsk_sl_native_functions_add (GskSlScope       *scope,
+                             GskSlEnvironment *environment)
+{
+  guint version = gsk_sl_environment_get_version (environment);
+
+  gsk_sl_native_functions_add_list (scope, gsk_glsl_functions);
+
+  if (version < 120)
+    return;
+  gsk_sl_native_functions_add_list (scope, gsk_glsl_functions_120);
+
+  if (version < 130)
+    return;
+  gsk_sl_native_functions_add_list (scope, gsk_glsl_functions_130);
+
+  if (version < 150)
+    return;
+  gsk_sl_native_functions_add_list (scope, gsk_glsl_functions_150);
+}
+
diff --git a/gsk/gskslnativefunctionprivate.h b/gsk/gskslnativefunctionprivate.h
index 5d787f0..02a3ae3 100644
--- a/gsk/gskslnativefunctionprivate.h
+++ b/gsk/gskslnativefunctionprivate.h
@@ -33,7 +33,8 @@ struct _GskSlNativeFunction
   const GskSlBuiltinType *argument_types;
 };
  
-extern const GskSlNativeFunction gsk_glsl_functions[];
+void                    gsk_sl_native_functions_add             (GskSlScope           *scope,
+                                                                 GskSlEnvironment     *environment);
  
 G_END_DECLS
 
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index bf22097..e7e3de2 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -23,6 +23,7 @@
 #include "gskcodesource.h"
 #include "gskslcompilerprivate.h"
 #include "gsksldefineprivate.h"
+#include "gskslenvironmentprivate.h"
 #include "gsksltokenizerprivate.h"
 
 typedef struct _GskSlPpToken GskSlPpToken;
@@ -37,6 +38,7 @@ struct _GskSlPreprocessor
   int ref_count;
 
   GskSlCompiler *compiler;
+  GskSlEnvironment *environment;
   GskSlTokenizer *tokenizer;
   GSList *pending_tokenizers;
   GArray *tokens;
@@ -99,6 +101,7 @@ gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc)
   g_hash_table_destroy (preproc->defines);
   g_slist_free_full (preproc->pending_tokenizers, (GDestroyNotify) gsk_sl_tokenizer_unref);
   gsk_sl_tokenizer_unref (preproc->tokenizer);
+  gsk_sl_environment_unref (preproc->environment);
   g_object_unref (preproc->compiler);
   g_array_free (preproc->tokens, TRUE);
 
@@ -111,6 +114,12 @@ gsk_sl_preprocessor_has_fatal_error (GskSlPreprocessor *preproc)
   return preproc->fatal_error;
 }
 
+GskSlEnvironment *
+gsk_sl_preprocessor_get_environment (GskSlPreprocessor *preproc)
+{
+  return preproc->environment;
+}
+
 static void
 gsk_sl_preprocessor_push_conditional (GskSlPreprocessor *preproc,
                                       GskConditional     cond)
@@ -180,8 +189,29 @@ gsk_sl_preprocessor_handle_version (GskSlPreprocessor *preproc,
       gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "#version directive must be first in 
compilation.");
       return;
     }
-  
-  gsk_sl_preprocessor_warn_full (preproc, UNIMPLEMENTED, location, "#version directive not supported.");
+  if (preproc->environment)
+    {
+      if (gsk_sl_environment_get_profile (preproc->environment) == profile &&
+          gsk_sl_environment_get_version (preproc->environment) == version)
+        {
+          gsk_sl_preprocessor_warn_full (preproc, VERSION, location,
+                                         "#version directive should not be used, but it matches predefined 
version.");
+          return;
+        }
+      else
+        {
+          GskSlProfile env_profile = gsk_sl_environment_get_profile (preproc->environment);
+          gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location,
+                                          "#version directive not allowed. This compilation uses %u %s.",
+                                          gsk_sl_environment_get_version (preproc->environment),
+                                          env_profile == GSK_SL_PROFILE_ES ? "es" :
+                                          env_profile == GSK_SL_PROFILE_COMPATIBILITY ? "compatibility" :
+                                          "core");
+          return;
+        }
+    }
+
+  preproc->environment = gsk_sl_environment_new (profile, version);
 }
 
 static gboolean
@@ -675,8 +705,9 @@ gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
 }
 
 GskSlPreprocessor *
-gsk_sl_preprocessor_new (GskSlCompiler *compiler,
-                         GskCodeSource *source)
+gsk_sl_preprocessor_new (GskSlCompiler    *compiler,
+                         GskSlEnvironment *environment,
+                         GskCodeSource    *source)
 {
   GskSlPreprocessor *preproc;
   GskSlPpToken pp;
@@ -685,6 +716,8 @@ gsk_sl_preprocessor_new (GskSlCompiler *compiler,
 
   preproc->ref_count = 1;
   preproc->compiler = g_object_ref (compiler);
+  if (environment)
+    preproc->environment = gsk_sl_environment_ref (environment);
   preproc->tokenizer = gsk_sl_tokenizer_new (source, 
                                              gsk_sl_preprocessor_error_func,
                                              preproc,
@@ -704,6 +737,8 @@ gsk_sl_preprocessor_new (GskSlCompiler *compiler,
       gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
       gsk_sl_preprocessor_handle_token (preproc, &pp, TRUE, FALSE);
     }
+  if (preproc->environment == NULL)
+    preproc->environment = gsk_sl_environment_new (GSK_SL_PROFILE_CORE, 150);
 
   return preproc;
 }
diff --git a/gsk/gskslpreprocessorprivate.h b/gsk/gskslpreprocessorprivate.h
index 3ea5939..29def72 100644
--- a/gsk/gskslpreprocessorprivate.h
+++ b/gsk/gskslpreprocessorprivate.h
@@ -26,12 +26,14 @@
 G_BEGIN_DECLS
 
 GskSlPreprocessor *     gsk_sl_preprocessor_new                 (GskSlCompiler       *compiler,
+                                                                 GskSlEnvironment    *environment,
                                                                  GskCodeSource       *source);
 
 GskSlPreprocessor *     gsk_sl_preprocessor_ref                 (GskSlPreprocessor   *preproc);
 void                    gsk_sl_preprocessor_unref               (GskSlPreprocessor   *preproc);
 
 gboolean                gsk_sl_preprocessor_has_fatal_error     (GskSlPreprocessor   *preproc);
+GskSlEnvironment *      gsk_sl_preprocessor_get_environment     (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,
diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c
index bbea1ca..e5a1066 100644
--- a/gsk/gskslprogram.c
+++ b/gsk/gskslprogram.c
@@ -21,7 +21,7 @@
 #include "gskslprogramprivate.h"
 
 #include "gsksldeclarationprivate.h"
-#include "gskslexpressionprivate.h"
+#include "gskslenvironmentprivate.h"
 #include "gskslfunctionprivate.h"
 #include "gskslpreprocessorprivate.h"
 #include "gskslprinterprivate.h"
@@ -45,7 +45,7 @@ gsk_sl_program_dispose (GObject *object)
   GskSlProgram *program = GSK_SL_PROGRAM (object);
 
   g_slist_free_full (program->declarations, (GDestroyNotify) gsk_sl_declaration_unref);
-  gsk_sl_scope_unref (program->scope);
+  g_clear_pointer (&program->scope, gsk_sl_scope_unref);
 
   G_OBJECT_CLASS (gsk_sl_program_parent_class)->dispose (object);
 }
@@ -61,7 +61,6 @@ gsk_sl_program_class_init (GskSlProgramClass *klass)
 static void
 gsk_sl_program_init (GskSlProgram *program)
 {
-  program->scope = gsk_sl_scope_new (NULL, NULL);
 }
 
 void
@@ -71,6 +70,8 @@ gsk_sl_program_parse (GskSlProgram      *program,
   GskSlDeclaration *declaration;
   const GskSlToken *token;
 
+  program->scope = gsk_sl_environment_create_scope (gsk_sl_preprocessor_get_environment (preproc));
+
   for (token = gsk_sl_preprocessor_get (preproc);
        !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
        token = gsk_sl_preprocessor_get (preproc))
diff --git a/gsk/gskslscope.c b/gsk/gskslscope.c
index 97ff233..1d06b01 100644
--- a/gsk/gskslscope.c
+++ b/gsk/gskslscope.c
@@ -21,7 +21,6 @@
 #include "gskslscopeprivate.h"
 
 #include "gskslfunctionprivate.h"
-#include "gskslnativefunctionprivate.h"
 #include "gsksltypeprivate.h"
 #include "gskslvariableprivate.h"
 
@@ -45,19 +44,6 @@ free_function_list (gpointer data)
   g_list_free_full (data, (GDestroyNotify) gsk_sl_function_unref);
 }
 
-static void
-gsk_sl_scope_add_native_functions (GskSlScope *scope)
-{
-  guint i;
-
-  for (i = 0; gsk_glsl_functions[i].name; i++)
-    {
-      GskSlFunction *function = gsk_sl_function_new_native (&gsk_glsl_functions[i]);
-      gsk_sl_scope_add_function (scope, function);
-      gsk_sl_function_unref (function);
-    }
-}
-
 GskSlScope *
 gsk_sl_scope_new (GskSlScope *parent,
                   GskSlType  *return_type)
@@ -75,9 +61,6 @@ gsk_sl_scope_new (GskSlScope *parent,
   scope->functions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) 
free_function_list);
   scope->types = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsk_sl_type_unref);
 
-  if (!parent)
-    gsk_sl_scope_add_native_functions (scope);
-
   return scope;
 }
 
diff --git a/gsk/gsksltypesprivate.h b/gsk/gsksltypesprivate.h
index dc11f8d..baadc3b 100644
--- a/gsk/gsksltypesprivate.h
+++ b/gsk/gsksltypesprivate.h
@@ -22,6 +22,7 @@
 #include <gsk/gsktypes.h>
 
 typedef struct _GskSlDeclaration        GskSlDeclaration;
+typedef struct _GskSlEnvironment        GskSlEnvironment;
 typedef struct _GskSlExpression         GskSlExpression;
 typedef struct _GskSlFunction           GskSlFunction;
 typedef struct _GskSlFunctionMatcher    GskSlFunctionMatcher;
diff --git a/gsk/meson.build b/gsk/meson.build
index 7f279d1..5935a35 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -38,6 +38,7 @@ gsk_private_sources = files([
   'gskslbinary.c',
   'gsksldeclaration.c',
   'gsksldefine.c',
+  'gskslenvironment.c',
   'gskslexpression.c',
   'gskslfunction.c',
   'gskslfunctiontype.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]