Merge commit 'origin/gallium-master-merge'
[mesa.git] / src / mesa / shader / shader_api.c
index 504d7693234a5794c255f4de50a874a1b28e2923..a5cf1ca1d440a7830a93e067c19ca8c0d7f30f84 100644 (file)
@@ -370,6 +370,31 @@ _mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
 }
 
 
+/**
+ * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
+ */
+static GLbitfield
+get_shader_flags(void)
+{
+   GLbitfield flags = 0x0;
+   const char *env = _mesa_getenv("MESA_GLSL");
+
+   if (env) {
+      if (_mesa_strstr(env, "dump"))
+         flags |= GLSL_DUMP;
+      if (_mesa_strstr(env, "log"))
+         flags |= GLSL_LOG;
+      if (_mesa_strstr(env, "nopt"))
+         flags |= GLSL_NO_OPT;
+      else if (_mesa_strstr(env, "opt"))
+         flags |= GLSL_OPT;
+      if (_mesa_strstr(env, "uniform"))
+         flags |= GLSL_UNIFORMS;
+   }
+
+   return flags;
+}
+
 
 /**
  * Initialize context's shader state.
@@ -381,8 +406,9 @@ _mesa_init_shader_state(GLcontext * ctx)
     * are generated by the GLSL compiler.
     */
    ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
-   ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
+   ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */
    ctx->Shader.EmitComments = GL_FALSE;
+   ctx->Shader.Flags = get_shader_flags();
 }
 
 
@@ -1117,7 +1143,8 @@ get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
 
 /**
  * Determine the number of rows and columns occupied by a uniform
- * according to its datatype.
+ * according to its datatype.  For non-matrix types (such as GL_FLOAT_VEC4),
+ * the number of rows = 1 and cols = number of elements in the vector.
  */
 static void
 get_uniform_rows_cols(const struct gl_program_parameter *p,
@@ -1126,11 +1153,17 @@ get_uniform_rows_cols(const struct gl_program_parameter *p,
    get_matrix_dims(p->DataType, rows, cols);
    if (*rows == 0 && *cols == 0) {
       /* not a matrix type, probably a float or vector */
-      *rows = p->Size / 4 + 1;
-      if (p->Size % 4 == 0)
-         *cols = 4;
-      else
-         *cols = p->Size % 4;
+      if (p->Size <= 4) {
+         *rows = 1;
+         *cols = p->Size;
+      }
+      else {
+         *rows = p->Size / 4 + 1;
+         if (p->Size % 4 == 0)
+            *cols = 4;
+         else
+            *cols = p->Size % 4;
+      }
    }
 }
 
@@ -1357,7 +1390,10 @@ _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
    if (!sh)
       return;
 
-   sh->CompileStatus = _slang_compile(ctx, sh);
+   /* this call will set the sh->CompileStatus field to indicate if
+    * compilation was successful.
+    */
+   (void) _slang_compile(ctx, sh);
 }
 
 
@@ -1415,10 +1451,22 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
 
 
 /**
- * Update the vertex and fragment program's TexturesUsed arrays.
+ * Update the vertex/fragment program's TexturesUsed array.
+ *
+ * This needs to be called after glUniform(set sampler var) is called.
+ * A call to glUniform(samplerVar, value) causes a sampler to point to a
+ * particular texture unit.  We know the sampler's texture target
+ * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
+ * set by glUniform() calls.
+ *
+ * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
+ * information to update the prog->TexturesUsed[] values.
+ * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
+ * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
+ * We'll use that info for state validation before rendering.
  */
-static void
-update_textures_used(struct gl_program *prog)
+void
+_mesa_update_shader_textures_used(struct gl_program *prog)
 {
    GLuint s;
 
@@ -1505,20 +1553,22 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
                     GLenum type, GLsizei count, GLint elems,
                     const void *values)
 {
+   struct gl_program_parameter *param =
+      &program->Parameters->Parameters[index];
+
    assert(offset >= 0);
 
-   if (!compatible_types(type,
-                         program->Parameters->Parameters[index].DataType)) {
+   if (!compatible_types(type, param->DataType)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
       return;
    }
 
-   if (index + offset > program->Parameters->Size) {
+   if (index + offset > (GLint) program->Parameters->Size) {
       /* out of bounds! */
       return;
    }
 
-   if (program->Parameters->Parameters[index].Type == PROGRAM_SAMPLER) {
+   if (param->Type == PROGRAM_SAMPLER) {
       /* This controls which texture unit which is used by a sampler */
       GLuint texUnit, sampler;
 
@@ -1542,16 +1592,16 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
 
       /* This maps a sampler to a texture unit: */
       program->SamplerUnits[sampler] = texUnit;
-      update_textures_used(program);
+      _mesa_update_shader_textures_used(program);
 
       FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    }
    else {
       /* ordinary uniform variable */
       GLsizei k, i;
-      GLint slots = (program->Parameters->Parameters[index].Size + 3) / 4;
+      GLint slots = (param->Size + 3) / 4;
 
-      if (count * elems > (GLint) program->Parameters->Parameters[index].Size) {
+      if (count * elems > (GLint) param->Size) {
          _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
          return;
       }
@@ -1560,7 +1610,8 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
          count = slots;
 
       for (k = 0; k < count; k++) {
-         GLfloat *uniformVal = program->Parameters->ParameterValues[index + offset + k];
+         GLfloat *uniformVal =
+            program->Parameters->ParameterValues[index + offset + k];
          if (is_integer_type(type)) {
             const GLint *iValues = ((const GLint *) values) + k * elems;
             for (i = 0; i < elems; i++) {
@@ -1575,9 +1626,9 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
          }
 
          /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
-         if (is_boolean_type(program->Parameters->Parameters[index].DataType)) {
+         if (is_boolean_type(param->DataType)) {
             for (i = 0; i < elems; i++) {
-               uniformVal[i] = uniformVal[i] ? 1.0 : 0.0;
+               uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
             }
          }
       }
@@ -1593,7 +1644,9 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
               const GLvoid *values, GLenum type)
 {
    struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+   struct gl_uniform *uniform;
    GLint elems, offset;
+   GLenum basicType;
 
    if (!shProg || !shProg->LinkStatus) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
@@ -1617,19 +1670,35 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
 
    switch (type) {
    case GL_FLOAT:
+      basicType = GL_FLOAT;
+      elems = 1;
+      break;
    case GL_INT:
+      basicType = GL_INT;
       elems = 1;
       break;
    case GL_FLOAT_VEC2:
+      basicType = GL_FLOAT;
+      elems = 2;
+      break;
    case GL_INT_VEC2:
+      basicType = GL_INT;
       elems = 2;
       break;
    case GL_FLOAT_VEC3:
+      basicType = GL_FLOAT;
+      elems = 3;
+      break;
    case GL_INT_VEC3:
+      basicType = GL_INT;
       elems = 3;
       break;
    case GL_FLOAT_VEC4:
+      basicType = GL_FLOAT;
+      elems = 4;
+      break;
    case GL_INT_VEC4:
+      basicType = GL_INT;
       elems = 4;
       break;
    default:
@@ -1639,12 +1708,33 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
 
    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
+   uniform = &shProg->Uniforms->Uniforms[location];
+
+   if (ctx->Shader.Flags & GLSL_UNIFORMS) {
+      GLint i;
+      _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
+                   shProg->Name, uniform->Name, location);
+      if (basicType == GL_INT) {
+         const GLint *v = (const GLint *) values;
+         for (i = 0; i < count * elems; i++) {
+            _mesa_printf("%d ", v[i]);
+         }
+      }
+      else {
+         const GLfloat *v = (const GLfloat *) values;
+         for (i = 0; i < count * elems; i++) {
+            _mesa_printf("%g ", v[i]);
+         }
+      }
+      _mesa_printf("\n");
+   }
+
    /* A uniform var may be used by both a vertex shader and a fragment
     * shader.  We may need to update one or both shader's uniform here:
     */
    if (shProg->VertexProgram) {
       /* convert uniform location to program parameter index */
-      GLint index = shProg->Uniforms->Uniforms[location].VertPos;
+      GLint index = uniform->VertPos;
       if (index >= 0) {
          set_program_uniform(ctx, &shProg->VertexProgram->Base,
                              index, offset, type, count, elems, values);
@@ -1653,12 +1743,14 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
 
    if (shProg->FragmentProgram) {
       /* convert uniform location to program parameter index */
-      GLint index = shProg->Uniforms->Uniforms[location].FragPos;
+      GLint index = uniform->FragPos;
       if (index >= 0) {
          set_program_uniform(ctx, &shProg->FragmentProgram->Base,
                              index, offset, type, count, elems, values);
       }
    }
+
+   uniform->Initialized = GL_TRUE;
 }
 
 
@@ -1725,8 +1817,9 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
                      GLenum matrixType, GLint location, GLsizei count,
                      GLboolean transpose, const GLfloat *values)
 {
-   GLint offset;
    struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+   struct gl_uniform *uniform;
+   GLint offset;
 
    if (!shProg || !shProg->LinkStatus) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -1750,9 +1843,11 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
 
    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
+   uniform = &shProg->Uniforms->Uniforms[location];
+
    if (shProg->VertexProgram) {
       /* convert uniform location to program parameter index */
-      GLint index = shProg->Uniforms->Uniforms[location].VertPos;
+      GLint index = uniform->VertPos;
       if (index >= 0) {
          set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
                                     index, offset,
@@ -1762,13 +1857,15 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
 
    if (shProg->FragmentProgram) {
       /* convert uniform location to program parameter index */
-      GLint index = shProg->Uniforms->Uniforms[location].FragPos;
+      GLint index = uniform->FragPos;
       if (index >= 0) {
          set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
                                     index, offset,
                                     count, rows, cols, transpose, values);
       }
    }
+
+   uniform->Initialized = GL_TRUE;
 }