i965: Turn if (query->bo) into an assertion.
[mesa.git] / src / glsl / glsl_parser_extras.cpp
index 14589b020058a0995df2efe5aadab2a8df6e2c16..9d7de3381fd115a38a612ff42275bc561d31051f 100644 (file)
@@ -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)
@@ -92,25 +97,56 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
    this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits;
    this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
    this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
+   this->Const.MinProgramTexelOffset = ctx->Const.MinProgramTexelOffset;
+   this->Const.MaxProgramTexelOffset = ctx->Const.MaxProgramTexelOffset;
 
    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;
@@ -149,22 +185,22 @@ _mesa_glsl_parse_state::check_version(unsigned required_glsl_version,
 
    va_list args;
    va_start(args, fmt);
-   char *problem = ralloc_vasprintf(ctx, fmt, args);
+   char *problem = ralloc_vasprintf(this, fmt, args);
    va_end(args);
    const char *glsl_version_string
-      = glsl_compute_version_string(ctx, false, required_glsl_version);
+      = glsl_compute_version_string(this, false, required_glsl_version);
    const char *glsl_es_version_string
-      = glsl_compute_version_string(ctx, true, required_glsl_es_version);
+      = glsl_compute_version_string(this, true, required_glsl_es_version);
    const char *requirement_string = "";
    if (required_glsl_version && required_glsl_es_version) {
-      requirement_string = ralloc_asprintf(ctx, " (%s or %s required)",
+      requirement_string = ralloc_asprintf(this, " (%s or %s required)",
                                            glsl_version_string,
                                            glsl_es_version_string);
    } else if (required_glsl_version) {
-      requirement_string = ralloc_asprintf(ctx, " (%s required)",
+      requirement_string = ralloc_asprintf(this, " (%s required)",
                                            glsl_version_string);
    } else if (required_glsl_es_version) {
-      requirement_string = ralloc_asprintf(ctx, " (%s required)",
+      requirement_string = ralloc_asprintf(this, " (%s required)",
                                            glsl_es_version_string);
    }
    _mesa_glsl_error(locp, this, "%s in %s%s.",
@@ -174,6 +210,85 @@ _mesa_glsl_parse_state::check_version(unsigned required_glsl_version,
    return false;
 }
 
+/**
+ * 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,
+                                                  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");
+      }
+   }
+
+   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");
+      } else {
+         this->es_shader = true;
+      }
+   }
+
+   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",
+                       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) {
+      this->ARB_uniform_buffer_object_enable = true;
+   }
+
+   if (this->language_version == 300 && this->es_shader) {
+      this->ARB_explicit_attrib_location_enable = true;
+   }
+}
+
 const char *
 _mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
 {
@@ -351,6 +466,8 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
    EXT(ARB_uniform_buffer_object,      true,  false, true,  true,  false,     ARB_uniform_buffer_object),
    EXT(OES_standard_derivatives,       false, false, true,  false,  true,     OES_standard_derivatives),
    EXT(ARB_texture_cube_map_array,     true,  false, true,  true,  false,     ARB_texture_cube_map_array),
+   EXT(ARB_shading_language_packing,   true,  false, true,  true,  false,     ARB_shading_language_packing),
+   EXT(ARB_texture_multisample,        true,  false, true,  true,  false,     ARB_texture_multisample),
 };
 
 #undef EXT
@@ -1083,8 +1200,8 @@ ast_struct_specifier::ast_struct_specifier(const char *identifier,
  *                                    The setting of this flag only matters if
  *                                    \c linked is \c true.
  * \param max_unroll_iterations       Maximum number of loop iterations to be
- *                                    unrolled.  Setting to 0 forces all loops
- *                                    to be unrolled.
+ *                                    unrolled.  Setting to 0 disables loop
+ *                                    unrolling.
  */
 bool
 do_common_optimization(exec_list *ir, bool linked,