glsl/parser: Handle "#version 300 es" directive.
authorPaul Berry <stereotype441@gmail.com>
Thu, 2 Aug 2012 18:17:30 +0000 (11:17 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Thu, 6 Dec 2012 20:13:22 +0000 (12:13 -0800)
Note that GLSL 1.00 is selected using "#version 100", so "#version 100
es" is prohibited.

v2: Check for GLES3 before allowing '#version 300 es'

v3: Make sure a correct language_version is set in
_mesa_glsl_parse_state::process_version_directive.

Signed-off-by: Paul Berry <stereotype441@gmail.com>
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Acked-by: Carl Worth <cworth@cworth.org>
src/glsl/glsl_parser.yy
src/glsl/glsl_parser_extras.cpp
src/glsl/glsl_parser_extras.h

index b15e1d1f5482a1f6f20f8ccab7eaa666dba5f7c7..d938765d750d7860ccf357cfd0640bcd01a451f6 100644 (file)
@@ -261,8 +261,12 @@ version_statement:
        /* blank - no #version specified: defaults are already set */
        | VERSION_TOK INTCONSTANT EOL
        {
-           state->process_version_directive(&@2, $2);
+           state->process_version_directive(&@2, $2, NULL);
        }
+        | VERSION_TOK INTCONSTANT any_identifier EOL
+        {
+           state->process_version_directive(&@2, $2, $3);
+        }
        ;
 
 pragma_statement:
index cc33a0724e158c2619005dabdd31af40cd01ee29..19518f166d4b3be6450220ab7d1832a8ec2a874b 100644 (file)
@@ -178,38 +178,72 @@ _mesa_glsl_parse_state::check_version(unsigned required_glsl_version,
  * Process a GLSL #version directive.
  *
  * \param version is the integer that follows the #version token.
+ *
+ * \param ident is a string identifier that follows the integer, if any is
+ * present.  Otherwise NULL.
  */
 void
-_mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version)
+_mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version,
+                                                  const char *ident)
 {
+   bool es_token_present = false;
+   if (ident) {
+      if (strcmp(ident, "es") == 0) {
+         es_token_present = true;
+      } else {
+         _mesa_glsl_error(locp, this,
+                          "Illegal text following version number\n");
+      }
+   }
+
    bool supported = false;
 
-   switch (version) {
-   case 100:
+   if (es_token_present) {
       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;
+      switch (version) {
+      case 100:
+         _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:
+         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;
@@ -219,6 +253,25 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version)
                        "Supported versions are: %s\n",
                        this->get_version_string(),
                        this->supported_version_string);
+
+      /* On exit, the language_version must be set to a valid value.
+       * Later calls to _mesa_glsl_initialize_types will misbehave if
+       * the version is invalid.
+       */
+      switch (this->ctx->API) {
+      case API_OPENGL_COMPAT:
+      case API_OPENGL_CORE:
+        this->language_version = this->ctx->Const.GLSLVersion;
+        break;
+
+      case API_OPENGLES:
+        assert(!"Should not get here.");
+        /* FALLTHROUGH */
+
+      case API_OPENGLES2:
+        this->language_version = 100;
+        break;
+      }
    }
 
    if (this->language_version >= 140) {
index 59c4b24dcd3648972aadaa460149c12314c7b7f1..8cda92784153bb48d277d38706776e511a9f8eb0 100644 (file)
@@ -136,7 +136,8 @@ struct _mesa_glsl_parse_state {
       return check_version(130, 300, locp, "bit-wise operations are forbidden");
    }
 
-   void process_version_directive(YYLTYPE *locp, int version);
+   void process_version_directive(YYLTYPE *locp, int version,
+                                  const char *ident);
 
    struct gl_context *const ctx;
    void *scanner;