mesa: rename unbind_texobj_from_imgunits()
[mesa.git] / src / mesa / main / uniform_query.cpp
index f0ab0f079966aecf60854198a70316179727e4ba..82d7628e8d8aa89abd3524b593a8ffc8a337ddb4 100644 (file)
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include <stdlib.h>
@@ -32,6 +33,7 @@
 #include "program/hash_table.h"
 #include "../glsl/program.h"
 #include "../glsl/ir_uniform.h"
+#include "../glsl/glsl_parser_extras.h"
 #include "main/shaderapi.h"
 #include "main/shaderobj.h"
 #include "uniforms.h"
@@ -46,8 +48,6 @@ _mesa_GetActiveUniform(GLhandleARB program, GLuint index,
    struct gl_shader_program *shProg =
       _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
 
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
    if (!shProg)
       return;
 
@@ -154,11 +154,21 @@ _mesa_GetActiveUniformsiv(GLuint program,
         params[i] = uni->row_major;
         break;
 
+      case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
+         if (!ctx->Extensions.ARB_shader_atomic_counters)
+            goto invalid_enum;
+         params[i] = uni->atomic_buffer_index;
+         break;
+
       default:
-        _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
-        return;
+         goto invalid_enum;
       }
    }
+
+   return;
+
+ invalid_enum:
+   _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
 }
 
 static bool
@@ -236,7 +246,7 @@ validate_uniform_parameters(struct gl_context *ctx,
       return false;
    }
 
-   _mesa_uniform_split_location_offset(location, loc, array_index);
+   _mesa_uniform_split_location_offset(shProg, location, loc, array_index);
 
    if (*loc >= shProg->NumUserUniformStorage) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
@@ -435,20 +445,14 @@ log_uniform(const void *values, enum glsl_base_type basicType,
 static void
 log_program_parameters(const struct gl_shader_program *shProg)
 {
-   static const char *stages[] = {
-      "vertex", "fragment", "geometry"
-   };
-
-   assert(Elements(stages) == MESA_SHADER_TYPES);
-
-   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
       if (shProg->_LinkedShaders[i] == NULL)
         continue;
 
       const struct gl_program *const prog = shProg->_LinkedShaders[i]->Program;
 
       printf("Program %d %s shader parameters:\n",
-            shProg->Name, stages[i]);
+             shProg->Name, _mesa_shader_stage_to_string(i));
       for (unsigned j = 0; j < prog->Parameters->NumParameters; j++) {
         printf("%s: %p %f %f %f %f\n",
                prog->Parameters->Parameters[j].Name,
@@ -593,8 +597,6 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
    enum glsl_base_type basicType;
    struct gl_uniform_storage *uni;
 
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
    if (!validate_uniform_parameters(ctx, shProg, location, count,
                                    &loc, &offset, "glUniform", false))
       return;
@@ -781,24 +783,24 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
    if (uni->type->is_sampler()) {
       int i;
 
-      for (i = 0; i < count; i++) {
-        shProg->SamplerUnits[uni->sampler + offset + i] =
-           ((unsigned *) values)[i];
-      }
-
       bool flushed = false;
-      for (i = 0; i < MESA_SHADER_TYPES; i++) {
+      for (i = 0; i < MESA_SHADER_STAGES; i++) {
         struct gl_shader *const sh = shProg->_LinkedShaders[i];
+         int j;
 
-        /* If the shader stage doesn't use any samplers, don't bother
-         * checking if any samplers have changed.
+        /* If the shader stage doesn't use the sampler uniform, skip this.
          */
-        if (sh == NULL || sh->active_samplers == 0)
+        if (sh == NULL || !uni->sampler[i].active)
            continue;
 
+         for (j = 0; j < count; j++) {
+            sh->SamplerUnits[uni->sampler[i].index + offset + j] =
+               ((unsigned *) values)[j];
+         }
+
         struct gl_program *const prog = sh->Program;
 
-        assert(sizeof(prog->SamplerUnits) == sizeof(shProg->SamplerUnits));
+        assert(sizeof(prog->SamplerUnits) == sizeof(sh->SamplerUnits));
 
         /* Determine if any of the samplers used by this shader stage have
          * been modified.
@@ -806,7 +808,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
         bool changed = false;
         for (unsigned j = 0; j < Elements(prog->SamplerUnits); j++) {
            if ((sh->active_samplers & (1U << j)) != 0
-               && (prog->SamplerUnits[j] != shProg->SamplerUnits[j])) {
+               && (prog->SamplerUnits[j] != sh->SamplerUnits[j])) {
               changed = true;
               break;
            }
@@ -819,8 +821,8 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
            }
 
            memcpy(prog->SamplerUnits,
-                  shProg->SamplerUnits,
-                  sizeof(shProg->SamplerUnits));
+                  sh->SamplerUnits,
+                  sizeof(sh->SamplerUnits));
 
            _mesa_update_shader_textures_used(shProg, prog);
             if (ctx->Driver.SamplerUniformChange)
@@ -846,8 +848,6 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
    unsigned elements;
    struct gl_uniform_storage *uni;
 
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
    if (!validate_uniform_parameters(ctx, shProg, location, count,
                                    &loc, &offset, "glUniformMatrix", false))
       return;
@@ -935,6 +935,7 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
    _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
 }
 
+
 /**
  * Called via glGetUniformLocation().
  *
@@ -950,73 +951,35 @@ _mesa_get_uniform_location(struct gl_context *ctx,
                            const GLchar *name,
                            unsigned *out_offset)
 {
-   const size_t len = strlen(name);
-   long offset;
-   bool array_lookup;
-   char *name_copy;
-
-   /* If the name ends with a ']', assume that it refers to some element of an
-    * array.  Malformed array references will fail the hash table look up
-    * below, so it doesn't matter that they are not caught here.  This code
-    * only wants to catch the "leaf" array references so that arrays of
-    * structures containing arrays will be handled correctly.
+   /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
+    *
+    *     "The first element of a uniform array is identified using the
+    *     name of the uniform array appended with "[0]". Except if the last
+    *     part of the string name indicates a uniform array, then the
+    *     location of the first element of that array can be retrieved by
+    *     either using the name of the uniform array, or the name of the
+    *     uniform array appended with "[0]"."
+    *
+    * Note: since uniform names are not allowed to use whitespace, and array
+    * indices within uniform names are not allowed to use "+", "-", or leading
+    * zeros, it follows that each uniform has a unique name up to the possible
+    * ambiguity with "[0]" noted above.  Therefore we don't need to worry
+    * about mal-formed inputs--they will properly fail when we try to look up
+    * the uniform name in shProg->UniformHash.
     */
-   if (name[len-1] == ']') {
-      unsigned i;
 
-      /* Walk backwards over the string looking for a non-digit character.
-       * This had better be the opening bracket for an array index.
-       *
-       * Initially, i specifies the location of the ']'.  Since the string may
-       * contain only the ']' charcater, walk backwards very carefully.
-       */
-      for (i = len - 1; (i > 0) && isdigit(name[i-1]); --i)
-        /* empty */ ;
-
-      /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
-       *
-       *     "The first element of a uniform array is identified using the
-       *     name of the uniform array appended with "[0]". Except if the last
-       *     part of the string name indicates a uniform array, then the
-       *     location of the first element of that array can be retrieved by
-       *     either using the name of the uniform array, or the name of the
-       *     uniform array appended with "[0]"."
-       *
-       * Page 79 (page 93 of the PDF) of the OpenGL 2.1 spec says:
-       *
-       *     "name must be a null terminated string, without white space."
-       *
-       * Return an error if there is no opening '[' to match the closing ']'.
-       * An error will also be returned if there is intervening white space
-       * (or other non-digit characters) before the opening '['.
-       */
-      if ((i == 0) || name[i-1] != '[')
-        return GL_INVALID_INDEX;
-
-      /* Return an error if there are no digits between the opening '[' to
-       * match the closing ']'.
-       */
-      if (i == (len - 1))
-        return GL_INVALID_INDEX;
-
-      /* Make a new string that is a copy of the old string up to (but not
-       * including) the '[' character.
-       */
-      name_copy = (char *) malloc(i);
-      memcpy(name_copy, name, i - 1);
-      name_copy[i-1] = '\0';
-
-      offset = strtol(&name[i], NULL, 10);
-      if (offset < 0) {
-        free(name_copy);
-        return GL_INVALID_INDEX;
-      }
+   const GLchar *base_name_end;
+   long offset = parse_program_resource_name(name, &base_name_end);
+   bool array_lookup = offset >= 0;
+   char *name_copy;
 
-      array_lookup = true;
+   if (array_lookup) {
+      name_copy = (char *) malloc(base_name_end - name + 1);
+      memcpy(name_copy, name, base_name_end - name);
+      name_copy[base_name_end - name] = '\0';
    } else {
       name_copy = (char *) name;
       offset = 0;
-      array_lookup = false;
    }
 
    unsigned location = 0;