mesa: print the Git SHA1 in GL_VERSION for ES1 and ES2.
[mesa.git] / src / mesa / main / shaderapi.c
index 2977a29ab7417365959baf921fd21898755e4b89..fd793a7abd2e05008655e20b0a908c4286dd5405 100644 (file)
 #include "main/dispatch.h"
 #include "main/enums.h"
 #include "main/hash.h"
+#include "main/mfeatures.h"
+#include "main/mtypes.h"
 #include "main/shaderapi.h"
 #include "main/shaderobj.h"
+#include "main/uniforms.h"
 #include "program/program.h"
 #include "program/prog_parameter.h"
-#include "program/prog_uniform.h"
-#include "talloc.h"
-
+#include "ralloc.h"
+#include <stdbool.h>
+#include "../glsl/glsl_parser_extras.h"
+#include "../glsl/ir_uniform.h"
 
 /** Define this to enable shader substitution (see below) */
 #define SHADER_SUBST 0
@@ -89,27 +93,22 @@ get_shader_flags(void)
  * Initialize context's shader state.
  */
 void
-_mesa_init_shader_state(GLcontext *ctx)
+_mesa_init_shader_state(struct gl_context *ctx)
 {
    /* Device drivers may override these to control what kind of instructions
     * are generated by the GLSL compiler.
     */
    struct gl_shader_compiler_options options;
-   GLuint i;
-   options.EmitHighLevelInstructions = GL_TRUE;
-   options.EmitContReturn = GL_TRUE;
-   options.EmitCondCodes = GL_FALSE;
-   options.EmitComments = GL_FALSE;
-   options.EmitNoIfs = GL_FALSE;
+   gl_shader_type sh;
+
+   memset(&options, 0, sizeof(options));
+   options.MaxUnrollIterations = 32;
 
    /* Default pragma settings */
-   options.DefaultPragmas.IgnoreOptimize = GL_FALSE;
-   options.DefaultPragmas.IgnoreDebug = GL_FALSE;
    options.DefaultPragmas.Optimize = GL_TRUE;
-   options.DefaultPragmas.Debug = GL_FALSE;
 
-   for(i = 0; i < MESA_SHADER_TYPES; ++i)
-      memcpy(&ctx->ShaderCompilerOptions[i], &options, sizeof(options));
+   for (sh = 0; sh < MESA_SHADER_TYPES; ++sh)
+      memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options));
 
    ctx->Shader.Flags = get_shader_flags();
 }
@@ -119,67 +118,16 @@ _mesa_init_shader_state(GLcontext *ctx)
  * Free the per-context shader-related state.
  */
 void
-_mesa_free_shader_state(GLcontext *ctx)
+_mesa_free_shader_state(struct gl_context *ctx)
 {
-   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
-}
-
-
-/**
- * Return the size of the given GLSL datatype, in floats (components).
- */
-GLint
-_mesa_sizeof_glsl_type(GLenum type)
-{
-   switch (type) {
-   case GL_FLOAT:
-   case GL_INT:
-   case GL_BOOL:
-   case GL_SAMPLER_1D:
-   case GL_SAMPLER_2D:
-   case GL_SAMPLER_3D:
-   case GL_SAMPLER_CUBE:
-   case GL_SAMPLER_1D_SHADOW:
-   case GL_SAMPLER_2D_SHADOW:
-   case GL_SAMPLER_2D_RECT_ARB:
-   case GL_SAMPLER_2D_RECT_SHADOW_ARB:
-   case GL_SAMPLER_1D_ARRAY_EXT:
-   case GL_SAMPLER_2D_ARRAY_EXT:
-   case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
-   case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
-   case GL_SAMPLER_CUBE_SHADOW_EXT:
-      return 1;
-   case GL_FLOAT_VEC2:
-   case GL_INT_VEC2:
-   case GL_UNSIGNED_INT_VEC2:
-   case GL_BOOL_VEC2:
-      return 2;
-   case GL_FLOAT_VEC3:
-   case GL_INT_VEC3:
-   case GL_UNSIGNED_INT_VEC3:
-   case GL_BOOL_VEC3:
-      return 3;
-   case GL_FLOAT_VEC4:
-   case GL_INT_VEC4:
-   case GL_UNSIGNED_INT_VEC4:
-   case GL_BOOL_VEC4:
-      return 4;
-   case GL_FLOAT_MAT2:
-   case GL_FLOAT_MAT2x3:
-   case GL_FLOAT_MAT2x4:
-      return 8; /* two float[4] vectors */
-   case GL_FLOAT_MAT3:
-   case GL_FLOAT_MAT3x2:
-   case GL_FLOAT_MAT3x4:
-      return 12; /* three float[4] vectors */
-   case GL_FLOAT_MAT4:
-   case GL_FLOAT_MAT4x2:
-   case GL_FLOAT_MAT4x3:
-      return 16;  /* four float[4] vectors */
-   default:
-      _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()");
-      return 1;
-   }
+   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram,
+                                 NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram,
+                                 NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram,
+                                 NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
 }
 
 
@@ -206,6 +154,35 @@ _mesa_copy_string(GLchar *dst, GLsizei maxLength,
 
 
 
+/**
+ * Confirm that the a shader type is valid and supported by the implementation
+ *
+ * \param ctx   Current GL context
+ * \param type  Shader target
+ *
+ */
+static bool
+validate_shader_target(const struct gl_context *ctx, GLenum type)
+{
+   switch (type) {
+#if FEATURE_ARB_fragment_shader
+   case GL_FRAGMENT_SHADER:
+      return ctx->Extensions.ARB_fragment_shader;
+#endif
+#if FEATURE_ARB_vertex_shader
+   case GL_VERTEX_SHADER:
+      return ctx->Extensions.ARB_vertex_shader;
+#endif
+#if FEATURE_ARB_geometry_shader4
+   case GL_GEOMETRY_SHADER_ARB:
+      return ctx->Extensions.ARB_geometry_shader4;
+#endif
+   default:
+      return false;
+   }
+}
+
+
 /**
  * Find the length of the longest transform feedback varying name
  * which was specified with glTransformFeedbackVaryings().
@@ -226,7 +203,7 @@ longest_feedback_varying_name(const struct gl_shader_program *shProg)
 
 
 static GLboolean
-is_program(GLcontext *ctx, GLuint name)
+is_program(struct gl_context *ctx, GLuint name)
 {
    struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
    return shProg ? GL_TRUE : GL_FALSE;
@@ -234,7 +211,7 @@ is_program(GLcontext *ctx, GLuint name)
 
 
 static GLboolean
-is_shader(GLcontext *ctx, GLuint name)
+is_shader(struct gl_context *ctx, GLuint name)
 {
    struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
    return shader ? GL_TRUE : GL_FALSE;
@@ -245,7 +222,7 @@ is_shader(GLcontext *ctx, GLuint name)
  * Attach shader to a shader program.
  */
 static void
-attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
+attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
 {
    struct gl_shader_program *shProg;
    struct gl_shader *sh;
@@ -291,109 +268,19 @@ attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
 }
 
 
-static GLint
-get_attrib_location(GLcontext *ctx, GLuint program, const GLchar *name)
-{
-   struct gl_shader_program *shProg
-      = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
-
-   if (!shProg) {
-      return -1;
-   }
-
-   if (!shProg->LinkStatus) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetAttribLocation(program not linked)");
-      return -1;
-   }
-
-   if (!name)
-      return -1;
-
-   if (shProg->VertexProgram) {
-      const struct gl_program_parameter_list *attribs =
-         shProg->VertexProgram->Base.Attributes;
-      if (attribs) {
-         GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
-         if (i >= 0) {
-            return attribs->Parameters[i].StateIndexes[0];
-         }
-      }
-   }
-   return -1;
-}
-
-
-static void
-bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
-                     const GLchar *name)
-{
-   struct gl_shader_program *shProg;
-   const GLint size = -1; /* unknown size */
-   GLint i, oldIndex;
-   GLenum datatype = GL_FLOAT_VEC4;
-
-   shProg = _mesa_lookup_shader_program_err(ctx, program,
-                                            "glBindAttribLocation");
-   if (!shProg) {
-      return;
-   }
-
-   if (!name)
-      return;
-
-   if (strncmp(name, "gl_", 3) == 0) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glBindAttribLocation(illegal name)");
-      return;
-   }
-
-   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
-      return;
-   }
-
-   if (shProg->LinkStatus) {
-      /* get current index/location for the attribute */
-      oldIndex = get_attrib_location(ctx, program, name);
-   }
-   else {
-      oldIndex = -1;
-   }
-
-   /* this will replace the current value if it's already in the list */
-   i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
-   if (i < 0) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
-      return;
-   }
-
-   /*
-    * Note that this attribute binding won't go into effect until
-    * glLinkProgram is called again.
-    */
-}
-
-
 static GLuint
-create_shader(GLcontext *ctx, GLenum type)
+create_shader(struct gl_context *ctx, GLenum type)
 {
    struct gl_shader *sh;
    GLuint name;
 
-   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
-
-   switch (type) {
-   case GL_FRAGMENT_SHADER:
-   case GL_VERTEX_SHADER:
-   case GL_GEOMETRY_SHADER_ARB:
-      sh = ctx->Driver.NewShader(ctx, name, type);
-      break;
-   default:
+   if (!validate_shader_target(ctx, type)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
       return 0;
    }
 
+   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
+   sh = ctx->Driver.NewShader(ctx, name, type);
    _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
 
    return name;
@@ -401,7 +288,7 @@ create_shader(GLcontext *ctx, GLenum type)
 
 
 static GLuint 
-create_shader_program(GLcontext *ctx)
+create_shader_program(struct gl_context *ctx)
 {
    GLuint name;
    struct gl_shader_program *shProg;
@@ -423,7 +310,7 @@ create_shader_program(GLcontext *ctx)
  * DeleteProgramARB.
  */
 static void
-delete_shader_program(GLcontext *ctx, GLuint name)
+delete_shader_program(struct gl_context *ctx, GLuint name)
 {
    /*
     * NOTE: deleting shaders/programs works a bit differently than
@@ -439,15 +326,17 @@ delete_shader_program(GLcontext *ctx, GLuint name)
    if (!shProg)
       return;
 
-   shProg->DeletePending = GL_TRUE;
+   if (!shProg->DeletePending) {
+      shProg->DeletePending = GL_TRUE;
 
-   /* effectively, decr shProg's refcount */
-   _mesa_reference_shader_program(ctx, &shProg, NULL);
+      /* effectively, decr shProg's refcount */
+      _mesa_reference_shader_program(ctx, &shProg, NULL);
+   }
 }
 
 
 static void
-delete_shader(GLcontext *ctx, GLuint shader)
+delete_shader(struct gl_context *ctx, GLuint shader)
 {
    struct gl_shader *sh;
 
@@ -463,7 +352,7 @@ delete_shader(GLcontext *ctx, GLuint shader)
 
 
 static void
-detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
+detach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
 {
    struct gl_shader_program *shProg;
    GLuint n;
@@ -530,43 +419,11 @@ detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
 }
 
 
-static void
-get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
-                  GLsizei maxLength, GLsizei *length, GLint *size,
-                  GLenum *type, GLchar *nameOut)
-{
-   const struct gl_program_parameter_list *attribs = NULL;
-   struct gl_shader_program *shProg;
-
-   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
-   if (!shProg)
-      return;
-
-   if (shProg->VertexProgram)
-      attribs = shProg->VertexProgram->Base.Attributes;
-
-   if (!attribs || index >= attribs->NumParameters) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
-      return;
-   }
-
-   _mesa_copy_string(nameOut, maxLength, length,
-                     attribs->Parameters[index].Name);
-
-   if (size)
-      *size = attribs->Parameters[index].Size
-         / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType);
-
-   if (type)
-      *type = attribs->Parameters[index].DataType;
-}
-
-
 /**
  * Return list of shaders attached to shader program.
  */
 static void
-get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
+get_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount,
                      GLsizei *count, GLuint *obj)
 {
    struct gl_shader_program *shProg =
@@ -586,11 +443,11 @@ get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
  * glGetHandleARB() - return ID/name of currently bound shader program.
  */
 static GLuint
-get_handle(GLcontext *ctx, GLenum pname)
+get_handle(struct gl_context *ctx, GLenum pname)
 {
    if (pname == GL_PROGRAM_OBJECT_ARB) {
-      if (ctx->Shader.CurrentProgram)
-         return ctx->Shader.CurrentProgram->Name;
+      if (ctx->Shader.ActiveProgram)
+         return ctx->Shader.ActiveProgram->Name;
       else
          return 0;
    }
@@ -607,9 +464,8 @@ get_handle(GLcontext *ctx, GLenum pname)
  * programs (see glGetProgramivARB).
  */
 static void
-get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params)
+get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *params)
 {
-   const struct gl_program_parameter_list *attribs;
    struct gl_shader_program *shProg
       = _mesa_lookup_shader_program(ctx, program);
 
@@ -618,11 +474,6 @@ get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params)
       return;
    }
 
-   if (shProg->VertexProgram)
-      attribs = shProg->VertexProgram->Base.Attributes;
-   else
-      attribs = NULL;
-
    switch (pname) {
    case GL_DELETE_STATUS:
       *params = shProg->DeletePending;
@@ -640,19 +491,30 @@ get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params)
       *params = shProg->NumShaders;
       break;
    case GL_ACTIVE_ATTRIBUTES:
-      *params = attribs ? attribs->NumParameters : 0;
+      *params = _mesa_count_active_attribs(shProg);
       break;
    case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
-      *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
+      *params = _mesa_longest_attribute_name_length(shProg);
       break;
    case GL_ACTIVE_UNIFORMS:
-      *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
+      *params = shProg->NumUserUniformStorage;
       break;
-   case GL_ACTIVE_UNIFORM_MAX_LENGTH:
-      *params = _mesa_longest_uniform_name(shProg->Uniforms);
-      if (*params > 0)
-         (*params)++;  /* add one for terminating zero */
+   case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
+      unsigned i;
+      GLint max_len = 0;
+
+      for (i = 0; i < shProg->NumUserUniformStorage; i++) {
+        /* Add one for the terminating NUL character.
+         */
+        const GLint len = strlen(shProg->UniformStorage[i].name) + 1;
+
+        if (len > max_len)
+           max_len = len;
+      }
+
+      *params = max_len;
       break;
+   }
    case GL_PROGRAM_BINARY_LENGTH_OES:
       *params = 0;
       break;
@@ -689,7 +551,7 @@ get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params)
  * glGetShaderiv() - get GLSL shader state
  */
 static void
-get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
+get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
 {
    struct gl_shader *shader =
       _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
@@ -722,7 +584,7 @@ get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
 
 
 static void
-get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
+get_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize,
                      GLsizei *length, GLchar *infoLog)
 {
    struct gl_shader_program *shProg
@@ -736,7 +598,7 @@ get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
 
 
 static void
-get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
+get_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize,
                     GLsizei *length, GLchar *infoLog)
 {
    struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
@@ -752,7 +614,7 @@ get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
  * Return shader source code.
  */
 static void
-get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
+get_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength,
                   GLsizei *length, GLchar *sourceOut)
 {
    struct gl_shader *sh;
@@ -768,7 +630,7 @@ get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
  * Set/replace shader source code.
  */
 static void
-shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
+shader_source(struct gl_context *ctx, GLuint shader, const GLchar *source)
 {
    struct gl_shader *sh;
 
@@ -792,7 +654,7 @@ shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
  * Compile a shader.
  */
 static void
-compile_shader(GLcontext *ctx, GLuint shaderObj)
+compile_shader(struct gl_context *ctx, GLuint shaderObj)
 {
    struct gl_shader *sh;
    struct gl_shader_compiler_options *options;
@@ -817,7 +679,7 @@ compile_shader(GLcontext *ctx, GLuint shaderObj)
  * Link a program's shaders.
  */
 static void
-link_program(GLcontext *ctx, GLuint program)
+link_program(struct gl_context *ctx, GLuint program)
 {
    struct gl_shader_program *shProg;
    struct gl_transform_feedback_object *obj =
@@ -827,9 +689,12 @@ link_program(GLcontext *ctx, GLuint program)
    if (!shProg)
       return;
 
-   if (obj->Active && shProg == ctx->Shader.CurrentProgram) {
+   if (obj->Active
+       && (shProg == ctx->Shader.CurrentVertexProgram
+          || shProg == ctx->Shader.CurrentGeometryProgram
+          || shProg == ctx->Shader.CurrentFragmentProgram)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glLinkProgram(transform feedback active");
+                  "glLinkProgram(transform feedback active)");
       return;
    }
 
@@ -882,115 +747,125 @@ print_shader_info(const struct gl_shader_program *shProg)
             shProg->Shaders[i]->Name,
             shProg->Shaders[i]->SourceChecksum);
    }
-   if (shProg->VertexProgram)
-      printf("  vert prog %u\n", shProg->VertexProgram->Base.Id);
-   if (shProg->FragmentProgram)
-      printf("  frag prog %u\n", shProg->FragmentProgram->Base.Id);
+   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX])
+      printf("  vert prog %u\n",
+            shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program->Id);
+   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT])
+      printf("  frag prog %u\n",
+            shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->Id);
+   if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY])
+      printf("  geom prog %u\n",
+            shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program->Id);
 }
 
 
 /**
- * Use the named shader program for subsequent rendering.
+ * Use the named shader program for subsequent glUniform calls
  */
 void
-_mesa_use_program(GLcontext *ctx, GLuint program)
+_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
+                    const char *caller)
 {
-   struct gl_shader_program *shProg;
-   struct gl_transform_feedback_object *obj =
-      ctx->TransformFeedback.CurrentObject;
-
-   if (obj->Active) {
+   if ((shProg != NULL) && !shProg->LinkStatus) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glUseProgram(transform feedback active)");
+                 "%s(program %u not linked)", caller, shProg->Name);
       return;
    }
 
-   if (ctx->Shader.CurrentProgram &&
-       ctx->Shader.CurrentProgram->Name == program) {
-      /* no-op */
-      return;
+   if (ctx->Shader.ActiveProgram != shProg) {
+      _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg);
    }
+}
 
-   if (program) {
-      shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
-      if (!shProg) {
-         return;
+/**
+ */
+static bool
+use_shader_program(struct gl_context *ctx, GLenum type,
+                  struct gl_shader_program *shProg)
+{
+   struct gl_shader_program **target;
+
+   switch (type) {
+#if FEATURE_ARB_vertex_shader
+   case GL_VERTEX_SHADER:
+      target = &ctx->Shader.CurrentVertexProgram;
+      if ((shProg == NULL)
+         || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) {
+        shProg = NULL;
       }
-      if (!shProg->LinkStatus) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glUseProgram(program %u not linked)", program);
-         return;
+      break;
+#endif
+#if FEATURE_ARB_geometry_shader4
+   case GL_GEOMETRY_SHADER_ARB:
+      target = &ctx->Shader.CurrentGeometryProgram;
+      if ((shProg == NULL)
+         || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) {
+        shProg = NULL;
       }
-
-      /* debug code */
-      if (ctx->Shader.Flags & GLSL_USE_PROG) {
-         print_shader_info(shProg);
+      break;
+#endif
+#if FEATURE_ARB_fragment_shader
+   case GL_FRAGMENT_SHADER:
+      target = &ctx->Shader.CurrentFragmentProgram;
+      if ((shProg == NULL)
+         || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) {
+        shProg = NULL;
       }
-   }
-   else {
-      shProg = NULL;
+      break;
+#endif
+   default:
+      return false;
    }
 
-   if (ctx->Shader.CurrentProgram != shProg) {
+   if (*target != shProg) {
       FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
-      _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
+
+      /* If the shader is also bound as the current rendering shader, unbind
+       * it from that binding point as well.  This ensures that the correct
+       * semantics of glDeleteProgram are maintained.
+       */
+      switch (type) {
+#if FEATURE_ARB_vertex_shader
+      case GL_VERTEX_SHADER:
+        /* Empty for now. */
+        break;
+#endif
+#if FEATURE_ARB_geometry_shader4
+      case GL_GEOMETRY_SHADER_ARB:
+        /* Empty for now. */
+        break;
+#endif
+#if FEATURE_ARB_fragment_shader
+      case GL_FRAGMENT_SHADER:
+        if (*target == ctx->Shader._CurrentFragmentProgram) {
+           _mesa_reference_shader_program(ctx,
+                                          &ctx->Shader._CurrentFragmentProgram,
+                                          NULL);
+        }
+        break;
+#endif
+      }
+
+      _mesa_reference_shader_program(ctx, target, shProg);
+      return true;
    }
 
-   if (ctx->Driver.UseProgram)
-      ctx->Driver.UseProgram(ctx, shProg);
+   return false;
 }
 
-
 /**
- * Validate a program's samplers.
- * Specifically, check that there aren't two samplers of different types
- * pointing to the same texture unit.
- * \return GL_TRUE if valid, GL_FALSE if invalid
+ * Use the named shader program for subsequent rendering.
  */
-static GLboolean
-validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
-{
-   static const char *targetName[] = {
-      "TEXTURE_2D_ARRAY",
-      "TEXTURE_1D_ARRAY",
-      "TEXTURE_CUBE",
-      "TEXTURE_3D",
-      "TEXTURE_RECT",
-      "TEXTURE_2D",
-      "TEXTURE_1D",
-   };
-   GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
-   GLbitfield samplersUsed = prog->SamplersUsed;
-   GLuint i;
-
-   assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
-
-   if (samplersUsed == 0x0)
-      return GL_TRUE;
-
-   for (i = 0; i < Elements(targetUsed); i++)
-      targetUsed[i] = -1;
-
-   /* walk over bits which are set in 'samplers' */
-   while (samplersUsed) {
-      GLuint unit;
-      gl_texture_index target;
-      GLint sampler = _mesa_ffs(samplersUsed) - 1;
-      assert(sampler >= 0);
-      assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
-      unit = prog->SamplerUnits[sampler];
-      target = prog->SamplerTargets[sampler];
-      if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
-         _mesa_snprintf(errMsg, 100,
-                 "Texture unit %d is accessed both as %s and %s",
-                 unit, targetName[targetUsed[unit]], targetName[target]);
-         return GL_FALSE;
-      }
-      targetUsed[unit] = target;
-      samplersUsed ^= (1 << sampler);
-   }
+void
+_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+   use_shader_program(ctx, GL_VERTEX_SHADER, shProg);
+   use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg);
+   use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg);
+   _mesa_active_program(ctx, shProg, "glUseProgram");
 
-   return GL_TRUE;
+   if (ctx->Driver.UseProgram)
+      ctx->Driver.UseProgram(ctx, shProg);
 }
 
 
@@ -1000,13 +875,9 @@ validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
  * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
  */
 static GLboolean
-validate_shader_program(GLcontext *ctx,
-                        const struct gl_shader_program *shProg,
+validate_shader_program(const struct gl_shader_program *shProg,
                         char *errMsg)
 {
-   const struct gl_vertex_program *vp = shProg->VertexProgram;
-   const struct gl_fragment_program *fp = shProg->FragmentProgram;
-
    if (!shProg->LinkStatus) {
       return GL_FALSE;
    }
@@ -1031,12 +902,8 @@ validate_shader_program(GLcontext *ctx,
     * Check: any two active samplers in the current program object are of
     * different types, but refer to the same texture image unit,
     */
-   if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
-      return GL_FALSE;
-   }
-   if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
+   if (!_mesa_sampler_uniforms_are_valid(shProg, errMsg, 100))
       return GL_FALSE;
-   }
 
    return GL_TRUE;
 }
@@ -1046,23 +913,23 @@ validate_shader_program(GLcontext *ctx,
  * Called via glValidateProgram()
  */
 static void
-validate_program(GLcontext *ctx, GLuint program)
+validate_program(struct gl_context *ctx, GLuint program)
 {
    struct gl_shader_program *shProg;
-   char errMsg[100];
+   char errMsg[100] = "";
 
    shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
    if (!shProg) {
       return;
    }
 
-   shProg->Validated = validate_shader_program(ctx, shProg, errMsg);
+   shProg->Validated = validate_shader_program(shProg, errMsg);
    if (!shProg->Validated) {
       /* update info log */
       if (shProg->InfoLog) {
-         talloc_free(shProg->InfoLog);
+         ralloc_free(shProg->InfoLog);
       }
-      shProg->InfoLog = talloc_strdup(shProg, errMsg);
+      shProg->InfoLog = ralloc_strdup(shProg, errMsg);
    }
 }
 
@@ -1084,19 +951,12 @@ _mesa_AttachShader(GLuint program, GLuint shader)
 }
 
 
-void GLAPIENTRY
-_mesa_BindAttribLocationARB(GLhandleARB program, GLuint index,
-                            const GLcharARB *name)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   bind_attrib_location(ctx, program, index, name);
-}
-
-
 void GLAPIENTRY
 _mesa_CompileShaderARB(GLhandleARB shaderObj)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCompileShader %u\n", shaderObj);
    compile_shader(ctx, shaderObj);
 }
 
@@ -1105,6 +965,8 @@ GLuint GLAPIENTRY
 _mesa_CreateShader(GLenum type)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type));
    return create_shader(ctx, type);
 }
 
@@ -1121,6 +983,8 @@ GLuint GLAPIENTRY
 _mesa_CreateProgram(void)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateProgram\n");
    return create_shader_program(ctx);
 }
 
@@ -1136,8 +1000,14 @@ _mesa_CreateProgramObjectARB(void)
 void GLAPIENTRY
 _mesa_DeleteObjectARB(GLhandleARB obj)
 {
+   if (MESA_VERBOSE & VERBOSE_API) {
+      GET_CURRENT_CONTEXT(ctx);
+      _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj);
+   }
+
    if (obj) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       if (is_program(ctx, obj)) {
          delete_shader_program(ctx, obj);
       }
@@ -1156,6 +1026,7 @@ _mesa_DeleteProgram(GLuint name)
 {
    if (name) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       delete_shader_program(ctx, name);
    }
 }
@@ -1166,6 +1037,7 @@ _mesa_DeleteShader(GLuint name)
 {
    if (name) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       delete_shader(ctx, name);
    }
 }
@@ -1187,16 +1059,6 @@ _mesa_DetachShader(GLuint program, GLuint shader)
 }
 
 
-void GLAPIENTRY
-_mesa_GetActiveAttribARB(GLhandleARB program, GLuint index,
-                         GLsizei maxLength, GLsizei * length, GLint * size,
-                         GLenum * type, GLcharARB * name)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   get_active_attrib(ctx, program, index, maxLength, length, size, type, name);
-}
-
-
 void GLAPIENTRY
 _mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount,
                             GLsizei * count, GLhandleARB * obj)
@@ -1215,14 +1077,6 @@ _mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
 }
 
 
-GLint GLAPIENTRY
-_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   return get_attrib_location(ctx, program, name);
-}
-
-
 void GLAPIENTRY
 _mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length,
                     GLcharARB * infoLog)
@@ -1415,7 +1269,8 @@ _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
    for (i = 0; i < count; i++) {
       if (string[i] == NULL) {
          free((GLvoid *) offsets);
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderSourceARB(null string)");
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glShaderSourceARB(null string)");
          return;
       }
       if (length == NULL || length[i] < 0)
@@ -1466,7 +1321,7 @@ _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
          free(source);
          source = newSource;
       }
-   }      
+   }
 
    shader_source(ctx, shaderObj, source);
 
@@ -1484,8 +1339,39 @@ void GLAPIENTRY
 _mesa_UseProgramObjectARB(GLhandleARB program)
 {
    GET_CURRENT_CONTEXT(ctx);
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-   _mesa_use_program(ctx, program);
+   struct gl_shader_program *shProg;
+   struct gl_transform_feedback_object *obj =
+      ctx->TransformFeedback.CurrentObject;
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (obj->Active && !obj->Paused) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glUseProgram(transform feedback active)");
+      return;
+   }
+
+   if (program) {
+      shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
+      if (!shProg) {
+         return;
+      }
+      if (!shProg->LinkStatus) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glUseProgram(program %u not linked)", program);
+         return;
+      }
+
+      /* debug code */
+      if (ctx->Shader.Flags & GLSL_USE_PROG) {
+         print_shader_info(shProg);
+      }
+   }
+   else {
+      shProg = NULL;
+   }
+
+   _mesa_use_program(ctx, shProg);
 }
 
 
@@ -1502,16 +1388,58 @@ void GLAPIENTRY
 _mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
                                GLint* range, GLint* precision)
 {
+   const struct gl_program_constants *limits;
+   const struct gl_precision *p;
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__);
+
+   switch (shadertype) {
+   case GL_VERTEX_SHADER:
+      limits = &ctx->Const.VertexProgram;
+      break;
+   case GL_FRAGMENT_SHADER:
+      limits = &ctx->Const.FragmentProgram;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetShaderPrecisionFormat(shadertype)");
+      return;
+   }
+
+   switch (precisiontype) {
+   case GL_LOW_FLOAT:
+      p = &limits->LowFloat;
+      break;
+   case GL_MEDIUM_FLOAT:
+      p = &limits->MediumFloat;
+      break;
+   case GL_HIGH_FLOAT:
+      p = &limits->HighFloat;
+      break;
+   case GL_LOW_INT:
+      p = &limits->LowInt;
+      break;
+   case GL_MEDIUM_INT:
+      p = &limits->MediumInt;
+      break;
+   case GL_HIGH_INT:
+      p = &limits->HighInt;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetShaderPrecisionFormat(precisiontype)");
+      return;
+   }
+
+   range[0] = p->RangeMin;
+   range[1] = p->RangeMax;
+   precision[0] = p->Precision;
 }
 
 
 void GLAPIENTRY
 _mesa_ReleaseShaderCompiler(void)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__);
+   _mesa_destroy_shader_compiler_caches();
 }
 
 
@@ -1520,6 +1448,11 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
                    const void* binary, GLint length)
 {
    GET_CURRENT_CONTEXT(ctx);
+   (void) n;
+   (void) shaders;
+   (void) binaryformat;
+   (void) binary;
+   (void) length;
    _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__);
 }
 
@@ -1529,8 +1462,7 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
 #if FEATURE_ARB_geometry_shader4
 
 void GLAPIENTRY
-_mesa_ProgramParameteriARB(GLuint program, GLenum pname,
-                           GLint value)
+_mesa_ProgramParameteriARB(GLuint program, GLenum pname, GLint value)
 {
    struct gl_shader_program *shProg;
    GET_CURRENT_CONTEXT(ctx);
@@ -1545,7 +1477,7 @@ _mesa_ProgramParameteriARB(GLuint program, GLenum pname,
    switch (pname) {
    case GL_GEOMETRY_VERTICES_OUT_ARB:
       if (value < 1 ||
-          value > ctx->Const.GeometryProgram.MaxGeometryOutputVertices) {
+          (unsigned) value > ctx->Const.MaxGeometryOutputVertices) {
          _mesa_error(ctx, GL_INVALID_VALUE,
                      "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d",
                      value);
@@ -1592,6 +1524,107 @@ _mesa_ProgramParameteriARB(GLuint program, GLenum pname,
 
 #endif
 
+void
+_mesa_use_shader_program(struct gl_context *ctx, GLenum type,
+                        struct gl_shader_program *shProg)
+{
+   use_shader_program(ctx, type, shProg);
+
+   if (ctx->Driver.UseProgram)
+      ctx->Driver.UseProgram(ctx, shProg);
+}
+
+void GLAPIENTRY
+_mesa_UseShaderProgramEXT(GLenum type, GLuint program)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = NULL;
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (!validate_shader_target(ctx, type)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
+      return;
+   }
+
+   if (ctx->TransformFeedback.CurrentObject->Active &&
+       !ctx->TransformFeedback.CurrentObject->Paused) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glUseShaderProgramEXT(transform feedback is active)");
+      return;
+   }
+
+   if (program) {
+      shProg = _mesa_lookup_shader_program_err(ctx, program,
+                                              "glUseShaderProgramEXT");
+      if (shProg == NULL)
+        return;
+
+      if (!shProg->LinkStatus) {
+        _mesa_error(ctx, GL_INVALID_OPERATION,
+                    "glUseShaderProgramEXT(program not linked)");
+        return;
+      }
+   }
+
+   _mesa_use_shader_program(ctx, type, shProg);
+}
+
+void GLAPIENTRY
+_mesa_ActiveProgramEXT(GLuint program)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = (program != 0)
+      ? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT")
+      : NULL;
+
+   _mesa_active_program(ctx, shProg, "glActiveProgramEXT");
+   return;
+}
+
+GLuint GLAPIENTRY
+_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLuint shader = create_shader(ctx, type);
+   GLuint program = 0;
+
+   if (shader) {
+      shader_source(ctx, shader, _mesa_strdup(string));
+      compile_shader(ctx, shader);
+
+      program = create_shader_program(ctx);
+      if (program) {
+        struct gl_shader_program *shProg;
+        struct gl_shader *sh;
+        GLint compiled = GL_FALSE;
+
+        shProg = _mesa_lookup_shader_program(ctx, program);
+        sh = _mesa_lookup_shader(ctx, shader);
+
+        get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
+        if (compiled) {
+           attach_shader(ctx, program, shader);
+           link_program(ctx, program);
+           detach_shader(ctx, program, shader);
+
+#if 0
+           /* Possibly... */
+           if (active-user-defined-varyings-in-linked-program) {
+              append-error-to-info-log;
+              shProg->LinkStatus = GL_FALSE;
+           }
+#endif
+        }
+
+        ralloc_strcat(&shProg->InfoLog, sh->InfoLog);
+      }
+
+      delete_shader(ctx, shader);
+   }
+
+   return program;
+}
 
 /**
  * Plug in shader-related functions into API dispatch table.
@@ -1642,6 +1675,22 @@ _mesa_init_shader_dispatch(struct _glapi_table *exec)
 #if FEATURE_ARB_geometry_shader4
    SET_ProgramParameteriARB(exec, _mesa_ProgramParameteriARB);
 #endif
+
+   SET_UseShaderProgramEXT(exec, _mesa_UseShaderProgramEXT);
+   SET_ActiveProgramEXT(exec, _mesa_ActiveProgramEXT);
+   SET_CreateShaderProgramEXT(exec, _mesa_CreateShaderProgramEXT);
+
+   /* GL_EXT_gpu_shader4 / GL 3.0 */
+   SET_BindFragDataLocationEXT(exec, _mesa_BindFragDataLocation);
+   SET_GetFragDataLocationEXT(exec, _mesa_GetFragDataLocation);
+
+   /* GL_ARB_ES2_compatibility */
+   SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler);
+   SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat);
+
+   /* GL_ARB_blend_func_extended */
+   SET_BindFragDataLocationIndexed(exec, _mesa_BindFragDataLocationIndexed);
+   SET_GetFragDataIndex(exec, _mesa_GetFragDataIndex);
 #endif /* FEATURE_GL */
 }