mesa: Handle binding of uniforms to image units with glUniform*().
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 23 Nov 2013 03:59:48 +0000 (19:59 -0800)
committerFrancisco Jerez <currojerez@riseup.net>
Wed, 12 Feb 2014 17:44:06 +0000 (18:44 +0100)
v2: Set driver-specified flag in NewDriverState when glUniform* is
    used to bind an image unit.
v3: Abbreviate argument type check.

Reviewed-by: Paul Berry <stereotype441@gmail.com>
src/mesa/main/uniform_query.cpp

index 82d7628e8d8aa89abd3524b593a8ffc8a337ddb4..8cc5da752ac7e43c088021ddea682f95fda60e37 100644 (file)
@@ -684,6 +684,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
       match = true;
       break;
    case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_IMAGE:
       match = (basicType == GLSL_TYPE_INT);
       break;
    default:
@@ -735,6 +736,22 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
       }
    }
 
+   if (uni->type->is_image()) {
+      int i;
+
+      for (i = 0; i < count; i++) {
+         const int unit = ((GLint *) values)[i];
+
+         /* check that the image unit is legal */
+         if (unit < 0 || unit >= (int)ctx->Const.MaxImageUnits) {
+            _mesa_error(ctx, GL_INVALID_VALUE,
+                        "glUniform1i(invalid image unit index for uniform %d)",
+                        location);
+            return;
+         }
+      }
+   }
+
    /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
     *
     *     "When loading N elements starting at an arbitrary position k in a
@@ -830,6 +847,25 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
         }
       }
    }
+
+   /* If the uniform is an image, update the mapping from image
+    * uniforms to image units present in the shader data structure.
+    */
+   if (uni->type->is_image()) {
+      int i, j;
+
+      for (i = 0; i < MESA_SHADER_STAGES; i++) {
+        if (uni->image[i].active) {
+            struct gl_shader *sh = shProg->_LinkedShaders[i];
+
+            for (j = 0; j < count; j++)
+               sh->ImageUnits[uni->image[i].index + offset + j] =
+                  ((GLint *) values)[j];
+         }
+      }
+
+      ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
+   }
 }
 
 /**