mesa: call FLUSH_VERTICES() before deleting shaders, buffers, query objects
[mesa.git] / src / mesa / main / shaderapi.c
index 1335f0f4111f0858d627e1a0d56e766962c0c01e..6650613d28d76ea3cca3dec505b71568a807aa94 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 "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"
 
 /** Define this to enable shader substitution (see below) */
 #define SHADER_SUBST 0
@@ -89,23 +92,24 @@ 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.
     */
-   ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
-   ctx->Shader.EmitContReturn = GL_TRUE;
-   ctx->Shader.EmitCondCodes = GL_FALSE;
-   ctx->Shader.EmitComments = GL_FALSE;
-   ctx->Shader.EmitNoIfs = GL_FALSE;
-   ctx->Shader.Flags = get_shader_flags();
+   struct gl_shader_compiler_options options;
+   gl_shader_type sh;
+
+   memset(&options, 0, sizeof(options));
+   options.MaxUnrollIterations = 32;
 
    /* Default pragma settings */
-   ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
-   ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
-   ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
-   ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
+   options.DefaultPragmas.Optimize = GL_TRUE;
+
+   for (sh = 0; sh < MESA_SHADER_TYPES; ++sh)
+      memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options));
+
+   ctx->Shader.Flags = get_shader_flags();
 }
 
 
@@ -113,9 +117,14 @@ _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);
+   _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.ActiveProgram, NULL);
 }
 
 
@@ -200,6 +209,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().
@@ -220,7 +258,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;
@@ -228,7 +266,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;
@@ -239,7 +277,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;
@@ -286,7 +324,7 @@ attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
 
 
 static GLint
-get_attrib_location(GLcontext *ctx, GLuint program, const GLchar *name)
+get_attrib_location(struct gl_context *ctx, GLuint program, const GLchar *name)
 {
    struct gl_shader_program *shProg
       = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
@@ -319,7 +357,7 @@ get_attrib_location(GLcontext *ctx, GLuint program, const GLchar *name)
 
 
 static void
-bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
+bind_attrib_location(struct gl_context *ctx, GLuint program, GLuint index,
                      const GLchar *name)
 {
    struct gl_shader_program *shProg;
@@ -369,25 +407,27 @@ bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
 }
 
 
+static void
+bind_frag_data_location(struct gl_context *ctx, GLuint program,
+                        GLuint colorNumber, const GLchar *name)
+{
+   _mesa_problem(ctx, "bind_frag_data_location() not implemented yet");
+}
+
+
 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;
@@ -395,7 +435,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;
@@ -417,7 +457,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
@@ -441,7 +481,7 @@ delete_shader_program(GLcontext *ctx, GLuint name)
 
 
 static void
-delete_shader(GLcontext *ctx, GLuint shader)
+delete_shader(struct gl_context *ctx, GLuint shader)
 {
    struct gl_shader *sh;
 
@@ -457,7 +497,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;
@@ -525,7 +565,7 @@ detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
 
 
 static void
-get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
+get_active_attrib(struct gl_context *ctx, GLuint program, GLuint index,
                   GLsizei maxLength, GLsizei *length, GLint *size,
                   GLenum *type, GLchar *nameOut)
 {
@@ -560,7 +600,7 @@ get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
  * 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 =
@@ -576,15 +616,25 @@ get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
 }
 
 
+static GLint
+get_frag_data_location(struct gl_context *ctx, GLuint program,
+                       const GLchar *name)
+{
+   _mesa_problem(ctx, "get_frag_data_location() not implemented yet");
+   return -1;
+}
+
+
+
 /**
  * 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;
    }
@@ -601,7 +651,7 @@ 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
@@ -644,6 +694,8 @@ get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params)
       break;
    case GL_ACTIVE_UNIFORM_MAX_LENGTH:
       *params = _mesa_longest_uniform_name(shProg->Uniforms);
+      if (*params > 0)
+         (*params)++;  /* add one for terminating zero */
       break;
    case GL_PROGRAM_BINARY_LENGTH_OES:
       *params = 0;
@@ -681,7 +733,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");
@@ -714,7 +766,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
@@ -728,7 +780,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);
@@ -744,7 +796,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;
@@ -760,7 +812,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;
 
@@ -784,16 +836,19 @@ 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;
 
    sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
    if (!sh)
       return;
 
+   options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(sh->Type)];
+
    /* set default pragma state for shader */
-   sh->Pragmas = ctx->Shader.DefaultPragmas;
+   sh->Pragmas = options->DefaultPragmas;
 
    /* this call will set the sh->CompileStatus field to indicate if
     * compilation was successful.
@@ -806,7 +861,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 =
@@ -816,7 +871,10 @@ 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");
       return;
@@ -879,52 +937,83 @@ print_shader_info(const struct gl_shader_program *shProg)
 
 
 /**
- * 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);
+      _mesa_reference_shader_program(ctx, target, shProg);
+      return true;
    }
 
+   return false;
+}
+
+/**
+ * Use the named shader program for subsequent rendering.
+ */
+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");
+
    if (ctx->Driver.UseProgram)
       ctx->Driver.UseProgram(ctx, shProg);
 }
@@ -937,7 +1026,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
  * \return GL_TRUE if valid, GL_FALSE if invalid
  */
 static GLboolean
-validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
+validate_samplers(const struct gl_program *prog, char *errMsg)
 {
    static const char *targetName[] = {
       "TEXTURE_2D_ARRAY",
@@ -969,7 +1058,7 @@ validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
       assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
       unit = prog->SamplerUnits[sampler];
       target = prog->SamplerTargets[sampler];
-      if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
+      if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) {
          _mesa_snprintf(errMsg, 100,
                  "Texture unit %d is accessed both as %s and %s",
                  unit, targetName[targetUsed[unit]], targetName[target]);
@@ -989,8 +1078,7 @@ 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;
@@ -1020,10 +1108,10 @@ 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)) {
+   if (vp && !validate_samplers(&vp->Base, errMsg)) {
       return GL_FALSE;
    }
-   if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
+   if (fp && !validate_samplers(&fp->Base, errMsg)) {
       return GL_FALSE;
    }
 
@@ -1035,7 +1123,7 @@ 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];
@@ -1045,13 +1133,13 @@ validate_program(GLcontext *ctx, GLuint program)
       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);
    }
 }
 
@@ -1082,10 +1170,22 @@ _mesa_BindAttribLocationARB(GLhandleARB program, GLuint index,
 }
 
 
+/* GL_EXT_gpu_shader4, GL3 */
+void GLAPIENTRY
+_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
+                           const GLchar *name)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   bind_frag_data_location(ctx, program, colorNumber, 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);
 }
 
@@ -1094,6 +1194,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);
 }
 
@@ -1110,6 +1212,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);
 }
 
@@ -1125,8 +1229,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);
       }
@@ -1145,6 +1255,7 @@ _mesa_DeleteProgram(GLuint name)
 {
    if (name) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       delete_shader_program(ctx, name);
    }
 }
@@ -1155,6 +1266,7 @@ _mesa_DeleteShader(GLuint name)
 {
    if (name) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       delete_shader(ctx, name);
    }
 }
@@ -1212,6 +1324,16 @@ _mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name)
 }
 
 
+/* GL_EXT_gpu_shader4, GL3 */
+GLint GLAPIENTRY
+_mesa_GetFragDataLocation(GLuint program, const GLchar *name)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   return get_frag_data_location(ctx, program, name);
+}
+
+
+
 void GLAPIENTRY
 _mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length,
                     GLcharARB * infoLog)
@@ -1473,8 +1595,37 @@ 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;
+
+   if (obj->Active) {
+      _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);
 }
 
 
@@ -1491,16 +1642,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();
 }
 
 
@@ -1509,6 +1702,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__);
 }
 
@@ -1534,7 +1732,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.GeometryProgram.MaxGeometryOutputVertices) {
          _mesa_error(ctx, GL_INVALID_VALUE,
                      "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d",
                      value);
@@ -1581,6 +1779,104 @@ _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;
+
+   if (!validate_shader_target(ctx, type)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
+      return;
+   }
+
+   if (ctx->TransformFeedback.CurrentObject->Active) {
+      _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.
@@ -1631,6 +1927,19 @@ _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);
+
 #endif /* FEATURE_GL */
 }