Updated GLSL uniform/sampler handling from gallium-0.1 branch
authorBrian Paul <brian.paul@tungstengraphics.com>
Wed, 14 May 2008 22:09:46 +0000 (16:09 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Wed, 14 May 2008 22:09:46 +0000 (16:09 -0600)
Previously, the shader linker combined the uniforms used by the vertex and
fragment shaders into a combined set of uniforms.  This made the implementation
of glUniform*() simple, but was rather inefficient otherwise.  Now each shader
gets its own set of uniforms (no more modelview matrix showing up in the
fragment shader uniforms, for example).

cherry-picked by hand from gallium-0.1 branch

17 files changed:
src/mesa/main/config.h
src/mesa/main/mtypes.h
src/mesa/shader/prog_execute.c
src/mesa/shader/prog_execute.h
src/mesa/shader/prog_instruction.h
src/mesa/shader/prog_parameter.c
src/mesa/shader/prog_parameter.h
src/mesa/shader/shader_api.c
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_compile.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_link.c
src/mesa/shader/slang/slang_link.h
src/mesa/shader/slang/slang_typeinfo.h
src/mesa/sources
src/mesa/swrast/s_fragprog.c
src/mesa/swrast/s_span.c

index ab0f035b45b442cf6775a4004883298e7025845c..58a39d11d4d0f9e2e8e45cfbbdaf0066b3f30d5a 100644 (file)
 #define MAX_PROGRAM_ADDRESS_REGS 2
 #define MAX_UNIFORMS 128
 #define MAX_VARYING 8
+#define MAX_SAMPLERS 8
 /*@}*/
 
 /** For GL_NV_vertex_program */
index 001240a14f59e94a8896c771b068df061d378876..04da767ec91d9cb086add059b01a15141524e367 100644 (file)
@@ -1863,6 +1863,7 @@ enum register_file
 /** Vertex and fragment instructions */
 struct prog_instruction;
 struct gl_program_parameter_list;
+struct gl_uniform_list;
 
 
 /**
@@ -1882,6 +1883,7 @@ struct gl_program
    GLbitfield InputsRead;     /**< Bitmask of which input regs are read */
    GLbitfield OutputsWritten; /**< Bitmask of which output regs are written to */
    GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];  /**< TEXTURE_x_BIT bitmask */
+   GLbitfield SamplersUsed;   /**< Bitfield of which samplers are used */
    GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
 
    /** Named parameters, constants, etc. from program text */
@@ -1894,6 +1896,11 @@ struct gl_program
    /** Vertex program user-defined attributes */
    struct gl_program_parameter_list *Attributes;
 
+   /** Map from sampler unit to texture unit (set by glUniform1i()) */
+   GLubyte SamplerUnits[MAX_SAMPLERS];
+   /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
+   GLubyte SamplerTargets[MAX_SAMPLERS];
+
    /** Logical counts */
    /*@{*/
    GLuint NumInstructions;
@@ -2086,7 +2093,7 @@ struct gl_query_state
 
 
 /**
- * A GLSL shader object.
+ * A GLSL vertex or fragment shader object.
  */
 struct gl_shader
 {
@@ -2104,7 +2111,8 @@ struct gl_shader
 
 
 /**
- * A GLSL program object.  Basically a linked collection of "shaders".
+ * A GLSL program object.
+ * Basically a linked collection of vertex and fragment shaders.
  */
 struct gl_shader_program
 {
@@ -2119,7 +2127,7 @@ struct gl_shader_program
    /* post-link info: */
    struct gl_vertex_program *VertexProgram;     /**< Linked vertex program */
    struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
-   struct gl_program_parameter_list *Uniforms; /**< Plus constants, etc */
+   struct gl_uniform_list *Uniforms;
    struct gl_program_parameter_list *Varying;
    struct gl_program_parameter_list *Attributes; /**< Vertex attributes */
    GLboolean LinkStatus;   /**< GL_LINK_STATUS */
index cb17aa501ce525a38cffc3fa71c6aa8613133463..d9bde3fc04f3ca3479d91dca4513d190b920b61c 100644 (file)
@@ -310,6 +310,8 @@ fetch_texel(GLcontext *ctx,
             const GLfloat texcoord[4], GLfloat lodBias,
             GLfloat color[4])
 {
+   const GLuint unit = machine->Samplers[inst->TexSrcUnit];
+
    /* Note: we only have the right derivatives for fragment input attribs.
     */
    if (machine->NumDeriv > 0 &&
@@ -320,12 +322,10 @@ fetch_texel(GLcontext *ctx,
       machine->FetchTexelDeriv(ctx, texcoord,
                                machine->DerivX[attr],
                                machine->DerivY[attr],
-                               lodBias,
-                               inst->TexSrcUnit, color);
+                               lodBias, unit, color);
    }
    else {
-      machine->FetchTexelLod(ctx, texcoord, lodBias,
-                             inst->TexSrcUnit, color);
+      machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color);
    }
 }
 
index 3ea0ba1565c645c399029b220e9cd620f4321ef5..18b13e11a41d02eb3e33b6347e929f8c770d9a3c 100644 (file)
@@ -63,6 +63,8 @@ struct gl_program_machine
    GLuint CondCodes[4];  /**< COND_* value for x/y/z/w */
    GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4];
 
+   const GLubyte *Samplers;  /** Array mapping sampler var to tex unit */
+
    GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */
    GLuint StackDepth; /**< Index/ptr to top of CallStack[] */
 
index aca768376a2b9e09c62cf9e6b9db010865b82635..f8ff33ed309d1e1ae0940151994f5db5a946b75e 100644 (file)
@@ -413,12 +413,13 @@ struct prog_instruction
     */
    GLint BranchTarget;
 
+#if 0
    /**
     * For TEX instructions in shaders, the sampler to use for the
     * texture lookup.
     */
    GLint Sampler;
-
+#endif
    const char *Comment;
 };
 
index 500cfbbd8732bbee2a0bca24225b1b82984a2e3f..0b61bac69615db1cc493d3426c88f4b72d4606cb 100644 (file)
@@ -282,22 +282,25 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList,
  * Add a sampler to the parameter list.
  * \param name  uniform's name
  * \param datatype  GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc.
+ * \param index  the sampler number (as seen in TEX instructions)
  */
 GLint
 _mesa_add_sampler(struct gl_program_parameter_list *paramList,
-                  const char *name, GLenum datatype)
+                  const char *name, GLenum datatype, GLuint index)
 {
    GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
    if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) {
       ASSERT(paramList->Parameters[i].Size == 1);
       ASSERT(paramList->Parameters[i].DataType == datatype);
+      ASSERT(paramList->ParameterValues[i][0] == index);
       /* already in list */
       return i;
    }
    else {
+      GLfloat indexf = index;
       const GLint size = 1; /* a sampler is basically a texture unit number */
       i = _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name,
-                              size, datatype, NULL, NULL);
+                              size, datatype, &indexf, NULL);
       return i;
    }
 }
index 105f6f24debe9909d599aef957fac2af55acd2b1..d6cc03448c87aaff932fa0e905fae4bdfb879256 100644 (file)
@@ -114,7 +114,7 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList,
 
 extern GLint
 _mesa_add_sampler(struct gl_program_parameter_list *paramList,
-                  const char *name, GLenum datatype);
+                  const char *name, GLenum datatype, GLuint index);
 
 extern GLint
 _mesa_add_varying(struct gl_program_parameter_list *paramList,
index 65a8c6cc54af53cf040900634f1f413857c044b2..11450db6448edcec9dfc3a4b6ebb1aa7c6a16eff 100644 (file)
@@ -43,6 +43,7 @@
 #include "prog_parameter.h"
 #include "prog_print.h"
 #include "prog_statevars.h"
+#include "prog_uniform.h"
 #include "shader/shader_api.h"
 #include "shader/slang/slang_compile.h"
 #include "shader/slang/slang_link.h"
@@ -75,23 +76,23 @@ _mesa_clear_shader_program_data(GLcontext *ctx,
                                 struct gl_shader_program *shProg)
 {
    if (shProg->VertexProgram) {
-      if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
-         /* to prevent a double-free in the next call */
-         shProg->VertexProgram->Base.Parameters = NULL;
-      }
+      /* Set ptr to NULL since the param list is shared with the
+       * original/unlinked program.
+       */
+      shProg->VertexProgram->Base.Parameters = NULL;
       _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
    }
 
    if (shProg->FragmentProgram) {
-      if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
-         /* to prevent a double-free in the next call */
-         shProg->FragmentProgram->Base.Parameters = NULL;
-      }
+      /* Set ptr to NULL since the param list is shared with the
+       * original/unlinked program.
+       */
+      shProg->FragmentProgram->Base.Parameters = NULL;
       _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
    }
 
    if (shProg->Uniforms) {
-      _mesa_free_parameter_list(shProg->Uniforms);
+      _mesa_free_uniform_list(shProg->Uniforms);
       shProg->Uniforms = NULL;
    }
 
@@ -680,9 +681,9 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
                shProg->Attributes->Parameters[index].Name);
    sz = shProg->Attributes->Parameters[index].Size;
    if (size)
-      *size = 1;   /* attributes may not be arrays */
-   if (type && sz > 0 && sz <= 4)  /* XXX this is a temporary hack */
-      *type = vec_types[sz - 1];
+      *size = sz;
+   if (type)
+      *type = vec_types[sz]; /* XXX this is a temporary hack */
 }
 
 
@@ -696,41 +697,41 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
 {
    struct gl_shader_program *shProg
       = _mesa_lookup_shader_program(ctx, program);
-   GLuint ind, j;
+   const struct gl_program *prog;
+   GLint progPos;
 
    if (!shProg) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
       return;
    }
 
-   if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
+   if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
       return;
    }
 
-   ind = 0;
-   for (j = 0; j < shProg->Uniforms->NumParameters; j++) {
-      if (shProg->Uniforms->Parameters[j].Type == PROGRAM_UNIFORM ||
-          shProg->Uniforms->Parameters[j].Type == PROGRAM_SAMPLER) {
-         if (ind == index) {
-            GLuint uSize = shProg->Uniforms->Parameters[j].Size;
-            GLenum uType = shProg->Uniforms->Parameters[j].DataType;
-            /* found it */
-            copy_string(nameOut, maxLength, length,
-                        shProg->Uniforms->Parameters[j].Name);
-            if (size) {
-               /* convert from floats to 'type' (eg: sizeof(mat4x4)=1) */
-               *size = uSize / sizeof_glsl_type(uType);
-            }
-            if (type)
-               *type = uType;
-            return;
-         }
-         ind++;
+   progPos = shProg->Uniforms->Uniforms[index].VertPos;
+   if (progPos >= 0) {
+      prog = &shProg->VertexProgram->Base;
+   }
+   else {
+      progPos = shProg->Uniforms->Uniforms[index].FragPos;
+      if (progPos >= 0) {
+         prog = &shProg->FragmentProgram->Base;
       }
    }
 
-   _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
+   if (!prog || progPos < 0)
+      return; /* should never happen */
+
+   if (nameOut)
+      copy_string(nameOut, maxLength, length,
+                  prog->Parameters->Parameters[progPos].Name);
+   if (size)
+      *size = prog->Parameters->Parameters[progPos].Size;
+
+   if (type)
+      *type = prog->Parameters->Parameters[progPos].DataType;
 }
 
 
@@ -848,14 +849,10 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program,
                                              PROGRAM_INPUT) + 1;
       break;
    case GL_ACTIVE_UNIFORMS:
-      *params
-         = _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_UNIFORM)
-         + _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_SAMPLER);
+      *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
       break;
    case GL_ACTIVE_UNIFORM_MAX_LENGTH:
-      *params = MAX2(
-             _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM),
-             _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_SAMPLER));
+      *params = _mesa_longest_uniform_name(shProg->Uniforms);
       if (*params > 0)
          (*params)++;  /* add one for terminating zero */
       break;
@@ -952,42 +949,24 @@ _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
    struct gl_shader_program *shProg
       = _mesa_lookup_shader_program(ctx, program);
    if (shProg) {
-      GLint i;
-      if (location >= 0 && location < shProg->Uniforms->NumParameters) {
-         GLuint uSize;
-         GLenum uType;
-         GLint rows = 0;
-         uType = shProg->Uniforms->Parameters[location].DataType;
-         uSize = sizeof_glsl_type(uType);
-         /* Matrix types need special handling, because they span several
-          * parameters, and may also not be fully packed.
-          */
-         switch (shProg->Uniforms->Parameters[location].DataType) {
-            case GL_FLOAT_MAT2:
-            case GL_FLOAT_MAT3x2:
-            case GL_FLOAT_MAT4x2:
-               rows = 2;
-               break;
-            case GL_FLOAT_MAT2x3:
-            case GL_FLOAT_MAT3:
-            case GL_FLOAT_MAT4x3:
-               rows = 3;
-               break;
-            case GL_FLOAT_MAT2x4:
-            case GL_FLOAT_MAT3x4:
-            case GL_FLOAT_MAT4:
-               rows = 4;
-         }
-         if (rows != 0) {
-            GLint r, c;
-            for (c = 0, i = 0; c * 4 < uSize; c++)
-               for (r = 0; r < rows; r++, i++)
-                  params[i] = shProg->Uniforms->ParameterValues[location + c][r];
+      if (location < shProg->Uniforms->NumUniforms) {
+         GLint progPos, i;
+         const struct gl_program *prog;
+
+         progPos = shProg->Uniforms->Uniforms[location].VertPos;
+         if (progPos >= 0) {
+            prog = &shProg->VertexProgram->Base;
          }
-         else
-            for (i = 0; i < uSize; i++) {
-               params[i] = shProg->Uniforms->ParameterValues[location][i];
+         else {
+            progPos = shProg->Uniforms->Uniforms[location].FragPos;
+            if (progPos >= 0) {
+               prog = &shProg->FragmentProgram->Base;
             }
+         }
+
+         for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
+            params[i] = prog->Parameters->ParameterValues[progPos][i];
+         }
       }
       else {
          _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
@@ -1007,23 +986,10 @@ _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
 {
    struct gl_shader_program *shProg
       = _mesa_lookup_shader_program(ctx, program);
-   if (shProg) {
-      GLuint loc;
-      for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
-         const struct gl_program_parameter *u
-            = shProg->Uniforms->Parameters + loc;
-         /* XXX this is a temporary simplification / short-cut.
-          * We need to handle things like "e.c[0].b" as seen in the
-          * GLSL orange book, page 189.
-          */
-         if ((u->Type == PROGRAM_UNIFORM ||
-              u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
-            return loc;
-         }
-      }
-   }
-   return -1;
+   if (!shProg)
+      return -1;
 
+   return _mesa_lookup_uniform(shProg->Uniforms, name);
 }
 
 
@@ -1134,55 +1100,121 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
 }
 
 
+
 /**
- * Called via ctx->Driver.Uniform().
+ * Update the vertex and fragment program's TexturesUsed arrays.
  */
-void
-_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
-              const GLvoid *values, GLenum type)
+static void
+update_textures_used(struct gl_program *prog)
 {
-   struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
-   GLint elems, i, k;
-   GLenum uType;
-   GLsizei maxCount;
+   GLuint s;
 
-   if (!shProg || !shProg->LinkStatus) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
-      return;
-   }
+   memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
 
-   if (location == -1)
-      return;   /* The standard specifies this as a no-op */
-
-   /* The spec says this is GL_INVALID_OPERATION, although it seems like it
-    * ought to be GL_INVALID_VALUE
-    */
-   if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
-      return;
+   for (s = 0; s < MAX_SAMPLERS; s++) {
+      if (prog->SamplersUsed & (1 << s)) {
+         GLuint u = prog->SamplerUnits[s];
+         GLuint t = prog->SamplerTargets[s];
+         assert(u < MAX_TEXTURE_IMAGE_UNITS);
+         prog->TexturesUsed[u] |= (1 << t);
+      }
    }
+}
 
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
-   uType = shProg->Uniforms->Parameters[location].DataType;
-   /*
-    * If we're setting a sampler, we must use glUniformi1()!
-    */
-   if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
-      GLint unit;
+/**
+ * Set the value of a program's uniform variable.
+ * \param program  the program whose uniform to update
+ * \param location  the location/index of the uniform
+ * \param type  the datatype of the uniform
+ * \param count  the number of uniforms to set
+ * \param elems  number of elements per uniform
+ * \param values  the new values
+ */
+static void
+set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
+                    GLenum type, GLint count, GLint elems, const void *values)
+{
+   if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
+      /* This controls which texture unit which is used by a sampler */
+      GLuint texUnit, sampler;
+
+      /* data type for setting samplers must be int */
       if (type != GL_INT || count != 1) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glUniform(only glUniform1i can be used "
                      "to set sampler uniforms)");
          return;
       }
+
+      sampler = (GLuint) program->Parameters->ParameterValues[location][0];
+      texUnit = ((GLuint *) values)[0];
+
       /* check that the sampler (tex unit index) is legal */
-      unit = ((GLint *) values)[0];
-      if (unit >= ctx->Const.MaxTextureImageUnits) {
+      if (texUnit >= ctx->Const.MaxTextureImageUnits) {
          _mesa_error(ctx, GL_INVALID_VALUE,
                      "glUniform1(invalid sampler/tex unit index)");
          return;
       }
+
+      /* This maps a sampler to a texture unit: */
+      program->SamplerUnits[sampler] = texUnit;
+      update_textures_used(program);
+
+      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+   }
+   else {
+      /* ordinary uniform variable */
+      GLint k, i;
+
+      if (count * elems > program->Parameters->Parameters[location].Size) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
+         return;
+      }
+
+      for (k = 0; k < count; k++) {
+         GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
+         if (type == GL_INT ||
+             type == GL_INT_VEC2 ||
+             type == GL_INT_VEC3 ||
+             type == GL_INT_VEC4) {
+            const GLint *iValues = ((const GLint *) values) + k * elems;
+            for (i = 0; i < elems; i++) {
+               uniformVal[i] = (GLfloat) iValues[i];
+            }
+         }
+         else {
+            const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
+            for (i = 0; i < elems; i++) {
+               uniformVal[i] = fValues[i];
+            }
+         }
+      }
+   }
+}
+
+
+/**
+ * Called via ctx->Driver.Uniform().
+ */
+void
+_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
+              const GLvoid *values, GLenum type)
+{
+   struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+   GLint elems;
+
+   if (!shProg || !shProg->LinkStatus) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
+      return;
+   }
+
+   if (location == -1)
+      return;   /* The standard specifies this as a no-op */
+
+   if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
+      return;
    }
 
    if (count < 0) {
@@ -1212,69 +1244,56 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
       return;
    }
 
-   /* OpenGL requires types to match exactly, except that one can convert
-    * float or int array to boolean array.
+   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+   /* 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:
     */
-   switch (uType)
-   {
-      case GL_BOOL:
-      case GL_BOOL_VEC2:
-      case GL_BOOL_VEC3:
-      case GL_BOOL_VEC4:
-         if (elems != sizeof_glsl_type(uType)) {
-            _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count mismatch)");
-         }
-         break;
-      case PROGRAM_SAMPLER:
-         break;
-      default:
-         if (shProg->Uniforms->Parameters[location].Type != PROGRAM_SAMPLER 
-             && uType != type) {
-            _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
-         }
-         break;
+   if (shProg->VertexProgram) {
+      GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
+      if (loc >= 0) {
+         set_program_uniform(ctx, &shProg->VertexProgram->Base,
+                             loc, type, count, elems, values);
+      }
+   }
+
+   if (shProg->FragmentProgram) {
+      GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
+      if (loc >= 0) {
+         set_program_uniform(ctx, &shProg->FragmentProgram->Base,
+                             loc, type, count, elems, values);
+      }
    }
+}
 
-   /* XXX if this is a base type, then count must equal 1. However, we
-    * don't have enough information from the compiler to distinguish a
-    * base type from a 1-element array of that type. The standard allows
-    * count to overrun an array, in which case the overflow is ignored.
+
+static void
+set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
+                           GLuint location, GLuint rows, GLuint cols,
+                           GLboolean transpose, const GLfloat *values)
+{
+   /*
+    * Note: the _columns_ of a matrix are stored in program registers, not
+    * the rows.
     */
-   maxCount = shProg->Uniforms->Parameters[location].Size / elems;
-   if (count > maxCount) count = maxCount;
-
-   for (k = 0; k < count; k++) {
-      GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
-      if (type == GL_INT ||
-          type == GL_INT_VEC2 ||
-          type == GL_INT_VEC3 ||
-          type == GL_INT_VEC4) {
-         const GLint *iValues = ((const GLint *) values) + k * elems;
-         for (i = 0; i < elems; i++) {
-            uniformVal[i] = (GLfloat) iValues[i];
+   /* XXXX need to test 3x3 and 2x2 matrices... */
+   if (transpose) {
+      GLuint row, col;
+      for (col = 0; col < cols; col++) {
+         GLfloat *v = program->Parameters->ParameterValues[location + col];
+         for (row = 0; row < rows; row++) {
+            v[row] = values[row * cols + col];
          }
       }
-      else {
-         const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
-         for (i = 0; i < elems; i++) {
-            uniformVal[i] = fValues[i];
+   }
+   else {
+      GLuint row, col;
+      for (col = 0; col < cols; col++) {
+         GLfloat *v = program->Parameters->ParameterValues[location + col];
+         for (row = 0; row < rows; row++) {
+            v[row] = values[col * rows + row];
          }
       }
-      if (uType == GL_BOOL ||
-          uType == GL_BOOL_VEC2 ||
-          uType == GL_BOOL_VEC3 ||
-          uType == GL_BOOL_VEC4) {
-          for (i = 0; i < elems; i++)
-              uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
-      }
-   }
-
-   if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
-      if (shProg->VertexProgram)
-         _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
-      if (shProg->FragmentProgram)
-         _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    }
 }
 
@@ -1287,62 +1306,42 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
                      GLenum matrixType, GLint location, GLsizei count,
                      GLboolean transpose, const GLfloat *values)
 {
-   GLsizei maxCount, i;
    struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+
    if (!shProg || !shProg->LinkStatus) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
          "glUniformMatrix(program not linked)");
       return;
    }
+
    if (location == -1)
       return;   /* The standard specifies this as a no-op */
-   /* The spec says this is GL_INVALID_OPERATION, although it seems like it
-    * ought to be GL_INVALID_VALUE
-    */
-   if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
+
+   if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
       return;
    }
    if (values == NULL) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
       return;
    }
-   if (count < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(count < 0)");
-      return;
-   }
 
    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
-   /*
-    * Note: the _columns_ of a matrix are stored in program registers, not
-    * the rows.
-    */
-   /* XXXX need to test 3x3 and 2x2 matrices... */
-   maxCount = shProg->Uniforms->Parameters[location].Size / (4 * cols);
-   if (count > maxCount)
-      count = maxCount;
-   for (i = 0; i < count; i++) {
-      if (transpose) {
-         GLuint row, col;
-         for (col = 0; col < cols; col++) {
-            GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
-            for (row = 0; row < rows; row++) {
-               v[row] = values[row * cols + col];
-            }
-         }
+   if (shProg->VertexProgram) {
+      GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
+      if (loc >= 0) {
+         set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
+                                    loc, rows, cols, transpose, values);
       }
-      else {
-         GLuint row, col;
-         for (col = 0; col < cols; col++) {
-            GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
-            for (row = 0; row < rows; row++) {
-               v[row] = values[col * rows + row];
-            }
-         }
+   }
+
+   if (shProg->FragmentProgram) {
+      GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
+      if (loc >= 0) {
+         set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
+                                    loc, rows, cols, transpose, values);
       }
-      location += cols;
-      values += rows * cols;
    }
 }
 
index ebead3274e1088f50bf49c8d294afe2c7f684d0d..88baf54d13fa2925b30057c121e11f949d38e229 100644 (file)
@@ -2836,14 +2836,14 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
    const GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
 
    if (texIndex != -1) {
-      /* Texture sampler:
+      /* This is a texture sampler variable...
        * store->File = PROGRAM_SAMPLER
-       * store->Index = sampler uniform location
+       * store->Index = sampler number (0..7, typically)
        * store->Size = texture type index (1D, 2D, 3D, cube, etc)
        */
-      GLint samplerUniform
-         = _mesa_add_sampler(prog->Parameters, varName, datatype);
-      store = _slang_new_ir_storage(PROGRAM_SAMPLER, samplerUniform, texIndex);
+      const GLint sampNum = A->numSamplers++;
+      _mesa_add_sampler(prog->Parameters, varName, datatype, sampNum);
+      store = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, texIndex);
       if (dbg) printf("SAMPLER ");
    }
    else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
index 2be89a5ce05235c0915d1870cb5637fc6960b88d..1449888f9f8f3fc6204725b851c0e798df974c0e 100644 (file)
@@ -31,6 +31,8 @@
 #include "main/imports.h"
 #include "main/context.h"
 #include "shader/program.h"
+#include "shader/programopt.h"
+#include "shader/prog_print.h"
 #include "shader/prog_parameter.h"
 #include "shader/grammar/grammar_mesa.h"
 #include "slang_codegen.h"
@@ -1618,6 +1620,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
       A.program = O->program;
       A.vartable = O->vartable;
       A.curFuncEndLabel = NULL;
+      A.numSamplers = 0;
       if (!_slang_codegen_global_variable(&A, var, C->type))
          return 0;
    }
@@ -1640,6 +1643,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
          A.space.funcs = O->funs;
          A.space.structs = O->structs;
          A.space.vars = O->vars;
+         A.numSamplers = 0;
          if (!initialize_global(&A, var))
             return 0;
       }
@@ -1773,6 +1777,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
       A.program = O->program;
       A.vartable = O->vartable;
       A.log = C->L;
+      A.numSamplers = 0;
 
       _slang_codegen_function(&A, *parsed_func_ret);
    }
@@ -2180,6 +2185,19 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader)
    _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
    ctx->Shader.MemPool = NULL;
 
+   if (shader->Type == GL_VERTEX_SHADER) {
+      /* remove any reads of varying (output) registers */
+#if 0
+      printf("Pre-remove output reads:\n");
+      _mesa_print_program(shader->Programs[0]);
+#endif
+      _mesa_remove_varying_reads(shader->Programs[0]);
+#if 0
+      printf("Post-remove output reads:\n");
+      _mesa_print_program(shader->Programs[0]);
+#endif
+   }
+
    return success;
 }
 
index d6ec3c5761b388cf71c1697c05a938daffaf9099..ff63e05dd2001d8bb87f7bff071fdf8e304e63d6 100644 (file)
@@ -922,11 +922,15 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
    assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX);
    assert(n->Children[0]->Store->Size <= TEXTURE_RECT_INDEX);
 
-   inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
    inst->TexSrcTarget = n->Children[0]->Store->Size;
+#if 0
    inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at
                            * link time, using the sampler uniform's value.
                            */
+   inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
+#else
+   inst->TexSrcUnit = n->Children[0]->Store->Index; /* i.e. uniform's index */
+#endif
    return inst;
 }
 
index 72fe9997c5597215f0942c32248395914ff08a3c..8213b7772c2fa64baab20b724bc891e71b590346 100644 (file)
 #include "shader/prog_parameter.h"
 #include "shader/prog_print.h"
 #include "shader/prog_statevars.h"
+#include "shader/prog_uniform.h"
 #include "shader/shader_api.h"
 #include "slang_link.h"
 
 
 
-
+/**
+ * Linking varying vars involves rearranging varying vars so that the
+ * vertex program's output varyings matches the order of the fragment
+ * program's input varyings.
+ */
 static GLboolean
 link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 {
@@ -132,145 +137,65 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 }
 
 
-static GLboolean
-is_uniform(GLuint file)
-{
-   return (file == PROGRAM_ENV_PARAM ||
-           file == PROGRAM_STATE_VAR ||
-           file == PROGRAM_NAMED_PARAM ||
-           file == PROGRAM_CONSTANT ||
-           file == PROGRAM_SAMPLER ||
-           file == PROGRAM_UNIFORM);
-}
-
-
-static GLboolean
-link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
+/**
+ * Build the shProg->Uniforms list.
+ * This is basically a list/index of all uniforms found in either/both of
+ * the vertex and fragment shaders.
+ */
+static void
+link_uniform_vars(struct gl_shader_program *shProg,
+                  struct gl_program *prog,
+                  GLuint *numSamplers)
 {
-   GLuint *map, i;
-
-#if 0
-   printf("================ pre link uniforms ===============\n");
-   _mesa_print_parameter_list(shProg->Uniforms);
-#endif
-
-   map = (GLuint *) malloc(prog->Parameters->NumParameters * sizeof(GLuint));
-   if (!map)
-      return GL_FALSE;
+   GLuint samplerMap[MAX_SAMPLERS];
+   GLuint i;
 
-   for (i = 0; i < prog->Parameters->NumParameters; /* incr below*/) {
-      /* see if this uniform is in the linked uniform list */
+   for (i = 0; i < prog->Parameters->NumParameters; i++) {
       const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
-      const GLfloat *pVals = prog->Parameters->ParameterValues[i];
-      GLint j;
-      GLint size;
 
-      /* sanity check */
-      assert(is_uniform(p->Type));
-
-      if (p->Name) {
-         j = _mesa_lookup_parameter_index(shProg->Uniforms, -1, p->Name);
-      }
-      else {
-         /*GLuint swizzle;*/
-         ASSERT(p->Type == PROGRAM_CONSTANT);
-         if (_mesa_lookup_parameter_constant(shProg->Uniforms, pVals,
-                                             p->Size, &j, NULL)) {
-            assert(j >= 0);
-         }
-         else {
-            j = -1;
-         }
-      }
-
-      if (j >= 0) {
-         /* already in list, check size XXX check this */
-#if 0
-         assert(p->Size == shProg->Uniforms->Parameters[j].Size);
-#endif
+      /*
+       * XXX FIX NEEDED HERE
+       * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
+       * For example, modelview matrix, light pos, etc.
+       * Also, we need to update the state-var name-generator code to
+       * generate GLSL-style names, like "gl_LightSource[0].position".
+       * Furthermore, we'll need to fix the state-var's size/datatype info.
+       */
+
+      if (p->Type == PROGRAM_UNIFORM ||
+          p->Type == PROGRAM_SAMPLER) {
+         _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
       }
-      else {
-         /* not already in linked list */
-         switch (p->Type) {
-         case PROGRAM_ENV_PARAM:
-            j = _mesa_add_named_parameter(shProg->Uniforms, p->Name, pVals);
-            break;
-         case PROGRAM_CONSTANT:
-            j = _mesa_add_named_constant(shProg->Uniforms, p->Name, pVals, p->Size);
-            break;
-         case PROGRAM_STATE_VAR:
-            j = _mesa_add_state_reference(shProg->Uniforms, p->StateIndexes);
-            break;
-         case PROGRAM_UNIFORM:
-            j = _mesa_add_uniform(shProg->Uniforms, p->Name, p->Size, p->DataType);
-            break;
-         case PROGRAM_SAMPLER:
-            j = _mesa_add_sampler(shProg->Uniforms, p->Name, p->DataType);
-            break;
-         default:
-            _mesa_problem(NULL, "bad parameter type in link_uniform_vars()");
-            return GL_FALSE;
-         }
-      }
-
-      ASSERT(j >= 0);
 
-      size = p->Size;
-      while (size > 0) {
-         map[i] = j;
-         i++;
-         j++;
-         size -= 4;
+      if (p->Type == PROGRAM_SAMPLER) {
+         /* Allocate a new sampler index */
+         GLuint sampNum = *numSamplers;
+         GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
+         assert(oldSampNum < MAX_SAMPLERS);
+         samplerMap[oldSampNum] = sampNum;
+         (*numSamplers)++;
       }
-
    }
 
-#if 0
-   printf("================ post link uniforms ===============\n");
-   _mesa_print_parameter_list(shProg->Uniforms);
-#endif
-
-#if 0
-   {
-      GLuint i;
-      for (i = 0; i < prog->Parameters->NumParameters; i++) {
-         printf("map[%d] = %d\n", i, map[i]);
-      }
-      _mesa_print_parameter_list(shProg->Uniforms);
-   }
-#endif
 
-   /* OK, now scan the program/shader instructions looking for uniform vars,
+   /* OK, now scan the program/shader instructions looking for sampler vars,
     * replacing the old index with the new index.
     */
+   prog->SamplersUsed = 0x0;
    for (i = 0; i < prog->NumInstructions; i++) {
       struct prog_instruction *inst = prog->Instructions + i;
-      GLuint j;
-
-      if (is_uniform(inst->DstReg.File)) {
-         inst->DstReg.Index = map[ inst->DstReg.Index ];
-      }
-
-      for (j = 0; j < 3; j++) {
-         if (is_uniform(inst->SrcReg[j].File)) {
-            inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ];
-         }
-      }
-
-      if (inst->Opcode == OPCODE_TEX ||
-          inst->Opcode == OPCODE_TXB ||
-          inst->Opcode == OPCODE_TXP) {
+      if (_mesa_is_tex_instruction(inst->Opcode)) {
          /*
          printf("====== remap sampler from %d to %d\n",
                 inst->Sampler, map[ inst->Sampler ]);
          */
-         inst->Sampler = map[ inst->Sampler ];
+         /* here, texUnit is really samplerUnit */
+         inst->TexSrcUnit = samplerMap[inst->TexSrcUnit];
+         prog->SamplerTargets[inst->TexSrcUnit] = inst->TexSrcTarget;
+         prog->SamplersUsed |= (1 << inst->TexSrcUnit);
       }
    }
 
-   free(map);
-
-   return GL_TRUE;
 }
 
 
@@ -329,10 +254,8 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
                 * glVertex/position.
                 */
                for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
-                  if (((1 << attr) & usedAttributes) == 0) {
-                     usedAttributes |= (1 << attr);
+                  if (((1 << attr) & usedAttributes) == 0)
                      break;
-                  }
                }
                if (attr == MAX_VERTEX_ATTRIBS) {
                   /* too many!  XXX record error log */
@@ -406,36 +329,6 @@ _slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, GLuint newAttr
 
 
 
-/**
- * Scan program for texture instructions, lookup sampler/uniform's value
- * to determine which texture unit to use.
- * Also, update the program's TexturesUsed[] array.
- */
-void
-_slang_resolve_samplers(struct gl_shader_program *shProg,
-                        struct gl_program *prog)
-{
-   GLuint i;
-
-   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
-      prog->TexturesUsed[i] = 0;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      if (inst->Opcode == OPCODE_TEX ||
-          inst->Opcode == OPCODE_TXB ||
-          inst->Opcode == OPCODE_TXP) {
-         GLint sampleUnit = (GLint) shProg->Uniforms->ParameterValues[inst->Sampler][0];
-         assert(sampleUnit < MAX_TEXTURE_IMAGE_UNITS);
-         inst->TexSrcUnit = sampleUnit;
-
-         prog->TexturesUsed[inst->TexSrcUnit] |= (1 << inst->TexSrcTarget);
-      }
-   }
-}
-
-
-
 /** cast wrapper */
 static struct gl_vertex_program *
 vertex_program(struct gl_program *prog)
@@ -476,12 +369,9 @@ link_error(struct gl_shader_program *shProg, const char *msg)
  * 2. Varying vars in the two shaders are combined so their locations
  *    agree between the vertex and fragment stages.  They're treated as
  *    vertex program output attribs and as fragment program input attribs.
- * 3. Uniform vars (including state references, constants, etc) from the
- *    vertex and fragment shaders are merged into one group.  Recall that
- *    GLSL uniforms are shared by all linked shaders.
- * 4. The vertex and fragment programs are cloned and modified to update
- *    src/dst register references so they use the new, linked uniform/
- *    varying storage locations.
+ * 3. The vertex and fragment programs are cloned and modified to update
+ *    src/dst register references so they use the new, linked varying
+ *    storage locations.
  */
 void
 _slang_link(GLcontext *ctx,
@@ -490,11 +380,12 @@ _slang_link(GLcontext *ctx,
 {
    const struct gl_vertex_program *vertProg;
    const struct gl_fragment_program *fragProg;
+   GLuint numSamplers = 0;
    GLuint i;
 
    _mesa_clear_shader_program_data(ctx, shProg);
 
-   shProg->Uniforms = _mesa_new_parameter_list();
+   shProg->Uniforms = _mesa_new_uniform_list();
    shProg->Varying = _mesa_new_parameter_list();
 
    /**
@@ -531,33 +422,30 @@ _slang_link(GLcontext *ctx,
       _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
    }
 
+   /* link varying vars */
    if (shProg->VertexProgram)
       link_varying_vars(shProg, &shProg->VertexProgram->Base);
    if (shProg->FragmentProgram)
       link_varying_vars(shProg, &shProg->FragmentProgram->Base);
 
+   /* link uniform vars */
    if (shProg->VertexProgram)
-      link_uniform_vars(shProg, &shProg->VertexProgram->Base);
+      link_uniform_vars(shProg, &shProg->VertexProgram->Base, &numSamplers);
    if (shProg->FragmentProgram)
-      link_uniform_vars(shProg, &shProg->FragmentProgram->Base);
+      link_uniform_vars(shProg, &shProg->FragmentProgram->Base, &numSamplers);
 
-   /* The vertex and fragment programs share a common set of uniforms now */
-   if (shProg->VertexProgram) {
-      _mesa_free_parameter_list(shProg->VertexProgram->Base.Parameters);
-      shProg->VertexProgram->Base.Parameters = shProg->Uniforms;
-      assert(shProg->Uniforms);
-   }
-   if (shProg->FragmentProgram) {
-      _mesa_free_parameter_list(shProg->FragmentProgram->Base.Parameters);
-      shProg->FragmentProgram->Base.Parameters = shProg->Uniforms;
-      assert(shProg->Uniforms);
-   }
+   /*_mesa_print_uniforms(shProg->Uniforms);*/
 
    if (shProg->VertexProgram) {
-      _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
+      /* Rather than cloning the parameter list here, just share it.
+       * We need to be careful _mesa_clear_shader_program_data() in
+       * to avoid double-freeing.
+       */
+      shProg->VertexProgram->Base.Parameters = vertProg->Base.Parameters;
    }
    if (shProg->FragmentProgram) {
-      _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
+      /* see comment just above */
+      shProg->FragmentProgram->Base.Parameters = fragProg->Base.Parameters;
    }
 
    if (shProg->VertexProgram) {
index 606b9e46b16df0fc9597e10a246b002638474b45..8ef8a6b4b3e8048aef4334c0b410685d6171f9ca 100644 (file)
@@ -32,10 +32,6 @@ extern void
 _slang_link(GLcontext *ctx, GLhandleARB h,
             struct gl_shader_program *shProg);
 
-extern void
-_slang_resolve_samplers(struct gl_shader_program *shProg,
-                        struct gl_program *prog);
-
 extern void
 _slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib,
                        GLuint newAttrib);
index 587331e8b1e0dd55244e047006a32330c2ab85fc..ad5aa3e195e7e6a2b878ad01c20dd75163e170b9 100644 (file)
@@ -65,6 +65,7 @@ typedef struct slang_assemble_ctx_
    struct slang_label_ *curFuncEndLabel;
    struct slang_ir_node_ *CurLoop;
    struct slang_function_ *CurFunction;
+   GLuint numSamplers;
 } slang_assemble_ctx;
 
 
index dbfc01d0edfb2270ee27b4e930a2ad2d2b4ef90c..054f667a254f9e68b4a8a24a4e8c1cd0c987774b 100644 (file)
@@ -165,6 +165,7 @@ SHADER_SOURCES = \
        shader/prog_parameter.c \
        shader/prog_print.c \
        shader/prog_statevars.c \
+       shader/prog_uniform.c \
        shader/programopt.c \
        shader/shader_api.c \
 
index 2dfc033d5012f0fbba9edf8fe66ab094dacef24b..ecace9c502514c23bf581c7c73bccf490e5cb2ee 100644 (file)
 
 
 /**
- * Fetch a texel.
+ * Fetch a texel with given lod.
+ * Called via machine->FetchTexelLod()
  */
 static void
-fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
-             GLuint unit, GLfloat color[4] )
+fetch_texel_lod( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
+                 GLuint unit, GLfloat color[4] )
 {
    GLchan rgba[4];
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
 
    lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
+
    /* XXX use a float-valued TextureSample routine here!!! */
    swrast->TextureSample[unit](ctx, texObj, 1, (const GLfloat (*)[4]) texcoord,
                                &lambda, &rgba);
@@ -58,6 +59,7 @@ fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
 /**
  * Fetch a texel with the given partial derivatives to compute a level
  * of detail in the mipmap.
+ * Called via machine->FetchTexelDeriv()
  */
 static void
 fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
@@ -117,6 +119,8 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine,
    machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
    machine->NumDeriv = FRAG_ATTRIB_MAX;
 
+   machine->Samplers = program->Base.SamplerUnits;
+
    /* if running a GLSL program (not ARB_fragment_program) */
    if (ctx->Shader.CurrentProgram) {
       /* Store front/back facing value in register FOGC.Y */
@@ -134,7 +138,7 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine,
    /* init call stack */
    machine->StackDepth = 0;
 
-   machine->FetchTexelLod = fetch_texel;
+   machine->FetchTexelLod = fetch_texel_lod;
    machine->FetchTexelDeriv = fetch_texel_deriv;
 }
 
index 656a90a99a9ace4a5cd935594aefec1ca8e90b1b..4c58f8de876be24efc89434d2a81fa32b4ee8e41 100644 (file)
@@ -1401,7 +1401,6 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
     * Write to renderbuffers
     */
    {
-      const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
       const GLuint numBuffers = fb->_NumColorDrawBuffers;
       const GLboolean multiFragOutputs = numBuffers > 1;
       GLuint buf;