mesa: print the Git SHA1 in GL_VERSION for ES1 and ES2.
[mesa.git] / src / mesa / main / shaderapi.c
index 9e0ed9c69772e9d02bdd61ca94beadcc0a3b5577..fd793a7abd2e05008655e20b0a908c4286dd5405 100644 (file)
 #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 "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
@@ -124,69 +125,12 @@ _mesa_free_shader_state(struct gl_context *ctx)
                                  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);
 }
 
 
-/**
- * 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_UNSIGNED_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;
-   }
-}
-
-
 /**
  * Copy string from <src> to <dst>, up to maxLength characters, returning
  * length of <dst> in <length>.
@@ -324,14 +268,6 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
 }
 
 
-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(struct gl_context *ctx, GLenum type)
 {
@@ -390,10 +326,12 @@ delete_shader_program(struct gl_context *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);
+   }
 }
 
 
@@ -501,16 +439,6 @@ get_attached_shaders(struct gl_context *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.
  */
@@ -569,13 +497,24 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param
       *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;
@@ -755,7 +694,7 @@ link_program(struct gl_context *ctx, GLuint program)
           || shProg == ctx->Shader.CurrentGeometryProgram
           || shProg == ctx->Shader.CurrentFragmentProgram)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glLinkProgram(transform feedback active");
+                  "glLinkProgram(transform feedback active)");
       return;
    }
 
@@ -808,12 +747,15 @@ 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->GeometryProgram)
-      printf("  geom prog %u\n", shProg->GeometryProgram->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);
 }
 
 
@@ -877,6 +819,33 @@ use_shader_program(struct gl_context *ctx, GLenum type,
 
    if (*target != shProg) {
       FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+
+      /* 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;
    }
@@ -900,60 +869,6 @@ _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
 }
 
 
-/**
- * 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
- */
-static GLboolean
-validate_samplers(const struct gl_program *prog, char *errMsg)
-{
-   static const char *targetName[] = {
-      "TEXTURE_BUFFER",
-      "TEXTURE_2D_ARRAY",
-      "TEXTURE_1D_ARRAY",
-      "TEXTURE_CUBE",
-      "TEXTURE_3D",
-      "TEXTURE_RECT",
-      "TEXTURE_2D",
-      "TEXTURE_1D",
-   };
-   GLint targetUsed[MAX_COMBINED_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 < Elements(prog->SamplerUnits));
-      unit = prog->SamplerUnits[sampler];
-      target = prog->SamplerTargets[sampler];
-      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]);
-         return GL_FALSE;
-      }
-      targetUsed[unit] = target;
-      samplersUsed ^= (1 << sampler);
-   }
-
-   return GL_TRUE;
-}
-
-
 /**
  * Do validation of the given shader program.
  * \param errMsg  returns error message if validation fails.
@@ -963,10 +878,6 @@ static GLboolean
 validate_shader_program(const struct gl_shader_program *shProg,
                         char *errMsg)
 {
-   const struct gl_vertex_program *vp = shProg->VertexProgram;
-   const struct gl_geometry_program *gp = shProg->GeometryProgram;
-   const struct gl_fragment_program *fp = shProg->FragmentProgram;
-
    if (!shProg->LinkStatus) {
       return GL_FALSE;
    }
@@ -991,15 +902,8 @@ validate_shader_program(const struct gl_shader_program *shProg,
     * 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(&vp->Base, errMsg)) {
+   if (!_mesa_sampler_uniforms_are_valid(shProg, errMsg, 100))
       return GL_FALSE;
-   }
-   if (gp && !validate_samplers(&gp->Base, errMsg)) {
-      return GL_FALSE;
-   }
-   if (fp && !validate_samplers(&fp->Base, errMsg)) {
-      return GL_FALSE;
-   }
 
    return GL_TRUE;
 }
@@ -1047,16 +951,6 @@ _mesa_AttachShader(GLuint program, GLuint shader)
 }
 
 
-/* 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)
 {
@@ -1183,16 +1077,6 @@ _mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
 }
 
 
-/* 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)
@@ -1461,7 +1345,7 @@ _mesa_UseProgramObjectARB(GLhandleARB program)
 
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (obj->Active) {
+   if (obj->Active && !obj->Paused) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glUseProgram(transform feedback active)");
       return;
@@ -1663,7 +1547,8 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
       return;
    }
 
-   if (ctx->TransformFeedback.CurrentObject->Active) {
+   if (ctx->TransformFeedback.CurrentObject->Active &&
+       !ctx->TransformFeedback.CurrentObject->Paused) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glUseShaderProgramEXT(transform feedback is active)");
       return;
@@ -1803,6 +1688,9 @@ _mesa_init_shader_dispatch(struct _glapi_table *exec)
    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 */
 }