[Mesa-dev] [PATCH] glsl: Fix unsupported version error for GLSL ES 3.00, future proof for 3.30.

Paul Berry stereotype441 at gmail.com
Tue Feb 5 16:50:18 PST 2013


When the user specifies an unsupported GLSL version,
_mesa_glsl_parse_state::process_version_directive() nicely gives them
an error message telling them which GLSL versions are supported.
Previous to this patch, the logic for determining whether a given
language version was supported was independent from the logic to
generate this error message string; as a result, we had a bug where
GLSL 3.00 would never be listed in the error message as an available
language version, even if it was really available.

To make matters worse, the code for generating the error message
string assumed that desktop GL versions were always separated by 0.10,
an assumption that will be wrong as soon as we support GLSL 3.30.

This patch fixes both problems by adding a table of supported GLSL
versions to _mesa_glsl_parse_state; this table is used both to
generate the error message and to check whether a given version is
supported.
---
 src/glsl/glsl_parser_extras.cpp | 112 +++++++++++++++++++++-------------------
 src/glsl/glsl_parser_extras.h   |   8 +++
 2 files changed, 66 insertions(+), 54 deletions(-)

diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index c8dbc89..db35f44 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -47,6 +47,11 @@ glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version)
                           version / 100, version % 100);
 }
 
+
+static unsigned known_desktop_glsl_versions[] =
+   { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430 };
+
+
 _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
 					       GLenum target, void *mem_ctx)
  : ctx(_ctx)
@@ -97,22 +102,51 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
 
    this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
 
-   const unsigned lowest_version =
-      (ctx->API == API_OPENGLES2) || ctx->Extensions.ARB_ES2_compatibility
-      ? 100 : 110;
-   const unsigned highest_version =
-      _mesa_is_desktop_gl(ctx) ? ctx->Const.GLSLVersion : 100;
-   char *supported = ralloc_strdup(this, "");
+   /* Populate the list of supported GLSL versions */
+   /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or
+    * the OpenGL 3.2 Core context is supported, this logic will need
+    * change.  Older versions of GLSL are no longer supported
+    * outside the compatibility contexts of 3.x.
+    */
+   this->num_supported_versions = 0;
+   if (_mesa_is_desktop_gl(ctx)) {
+      for (unsigned i = 0; i < ARRAY_SIZE(known_desktop_glsl_versions); i++) {
+         if (known_desktop_glsl_versions[i] <= ctx->Const.GLSLVersion) {
+            this->supported_versions[this->num_supported_versions].ver
+               = known_desktop_glsl_versions[i];
+            this->supported_versions[this->num_supported_versions].es = false;
+            this->num_supported_versions++;
+         }
+      }
+   }
+   if (ctx->API == API_OPENGLES2 || ctx->Extensions.ARB_ES2_compatibility) {
+      this->supported_versions[this->num_supported_versions].ver = 100;
+      this->supported_versions[this->num_supported_versions].es = true;
+      this->num_supported_versions++;
+   }
+   if (_mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility) {
+      this->supported_versions[this->num_supported_versions].ver = 300;
+      this->supported_versions[this->num_supported_versions].es = true;
+      this->num_supported_versions++;
+   }
+   assert(this->num_supported_versions
+          <= ARRAY_SIZE(this->supported_versions));
 
-   for (unsigned ver = lowest_version; ver <= highest_version; ver += 10) {
-      const char *const prefix = (ver == lowest_version)
+   /* Create a string for use in error messages to tell the user which GLSL
+    * versions are supported.
+    */
+   char *supported = ralloc_strdup(this, "");
+   for (unsigned i = 0; i < this->num_supported_versions; i++) {
+      unsigned ver = this->supported_versions[i].ver;
+      const char *const prefix = (i == 0)
 	 ? ""
-	 : ((ver == highest_version) ? ", and " : ", ");
+	 : ((i == this->num_supported_versions - 1) ? ", and " : ", ");
+      const char *const suffix = (this->supported_versions[i].es) ? " ES" : "";
 
-      ralloc_asprintf_append(& supported, "%s%d.%02d%s",
+      ralloc_asprintf_append(& supported, "%s%u.%02u%s",
 			     prefix,
 			     ver / 100, ver % 100,
-			     (ver == 100) ? " ES" : "");
+			     suffix);
    }
 
    this->supported_version_string = supported;
@@ -198,58 +232,28 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version,
       }
    }
 
-   bool supported = false;
-
-   if (es_token_present) {
-      this->es_shader = true;
-      switch (version) {
-      case 100:
+   this->es_shader = es_token_present;
+   if (version == 100) {
+      if (es_token_present) {
          _mesa_glsl_error(locp, this,
                           "GLSL 1.00 ES should be selected using "
                           "`#version 100'\n");
-         supported = this->ctx->API == API_OPENGLES2 ||
-            this->ctx->Extensions.ARB_ES2_compatibility;
-         break;
-      case 300:
-         supported = _mesa_is_gles3(this->ctx) ||
-	    this->ctx->Extensions.ARB_ES3_compatibility;
-         break;
-      default:
-         supported = false;
-         break;
-      }
-   } else {
-      switch (version) {
-      case 100:
+      } else {
          this->es_shader = true;
-         supported = this->ctx->API == API_OPENGLES2 ||
-            this->ctx->Extensions.ARB_ES2_compatibility;
-         break;
-      case 110:
-      case 120:
-         /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or
-          * the OpenGL 3.2 Core context is supported, this logic will need
-          * change.  Older versions of GLSL are no longer supported
-          * outside the compatibility contexts of 3.x.
-          */
-      case 130:
-      case 140:
-      case 150:
-      case 330:
-      case 400:
-      case 410:
-      case 420:
-         supported = _mesa_is_desktop_gl(this->ctx) &&
-            ((unsigned) version) <= this->ctx->Const.GLSLVersion;
-         break;
-      default:
-         supported = false;
-         break;
       }
    }
 
    this->language_version = version;
 
+   bool supported = false;
+   for (unsigned i = 0; i < this->num_supported_versions; i++) {
+      if (this->supported_versions[i].ver == (unsigned) version
+          && this->supported_versions[i].es == this->es_shader) {
+         supported = true;
+         break;
+      }
+   }
+
    if (!supported) {
       _mesa_glsl_error(locp, this, "%s is not supported. "
                        "Supported versions are: %s\n",
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
index 53df149..ed123be 100644
--- a/src/glsl/glsl_parser_extras.h
+++ b/src/glsl/glsl_parser_extras.h
@@ -25,6 +25,8 @@
 #ifndef GLSL_PARSER_EXTRAS_H
 #define GLSL_PARSER_EXTRAS_H
 
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+
 /*
  * Most of the definitions here only apply to C++
  */
@@ -148,6 +150,12 @@ struct _mesa_glsl_parse_state {
    unsigned uniform_block_array_size;
    struct gl_uniform_block *uniform_blocks;
 
+   unsigned num_supported_versions;
+   struct {
+      unsigned ver;
+      bool es;
+   } supported_versions[12];
+
    bool es_shader;
    unsigned language_version;
    enum _mesa_glsl_parser_targets target;
-- 
1.8.1.2



More information about the mesa-dev mailing list