mesa: add KHR_no_error support for glAttachShader() and glAttachObjectARB()
[mesa.git] / src / mesa / main / shaderapi.c
index 68fb3faf0c629feab86b7172d84141f8f8429fbf..16d9f1e64867b528f2525ae037452d5e8d77ba2e 100644 (file)
@@ -77,6 +77,8 @@ _mesa_get_shader_flags(void)
          flags |= GLSL_DUMP;
       if (strstr(env, "log"))
          flags |= GLSL_LOG;
+      if (strstr(env, "cache_fb"))
+         flags |= GLSL_CACHE_FALLBACK;
       if (strstr(env, "cache_info"))
          flags |= GLSL_CACHE_INFO;
       if (strstr(env, "nopvert"))
@@ -242,7 +244,27 @@ is_shader(struct gl_context *ctx, GLuint name)
  * Attach shader to a shader program.
  */
 static void
-attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
+attach_shader(struct gl_context *ctx, struct gl_shader_program *shProg,
+              struct gl_shader *sh)
+{
+   GLuint n = shProg->NumShaders;
+
+   shProg->Shaders = realloc(shProg->Shaders,
+                             (n + 1) * sizeof(struct gl_shader *));
+   if (!shProg->Shaders) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
+      return;
+   }
+
+   /* append */
+   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
+   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
+   shProg->NumShaders++;
+}
+
+static void
+attach_shader_err(struct gl_context *ctx, GLuint program, GLuint shader,
+                  const char *caller)
 {
    struct gl_shader_program *shProg;
    struct gl_shader *sh;
@@ -250,11 +272,11 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
 
    const bool same_type_disallowed = _mesa_is_gles(ctx);
 
-   shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
+   shProg = _mesa_lookup_shader_program_err(ctx, program, caller);
    if (!shProg)
       return;
 
-   sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
+   sh = _mesa_lookup_shader_err(ctx, shader, caller);
    if (!sh) {
       return;
    }
@@ -268,7 +290,7 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
           *     "The error INVALID_OPERATION is generated by AttachObjectARB
           *     if <obj> is already attached to <containerObj>."
           */
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
+         _mesa_error(ctx, GL_INVALID_OPERATION, caller);
          return;
       } else if (same_type_disallowed &&
                  shProg->Shaders[i]->Stage == sh->Stage) {
@@ -280,25 +302,25 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
          *      is generated if [...] another shader object of the same type
          *      as shader is already attached to program."
          */
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
+         _mesa_error(ctx, GL_INVALID_OPERATION, caller);
          return;
       }
    }
 
-   /* grow list */
-   shProg->Shaders = realloc(shProg->Shaders,
-                             (n + 1) * sizeof(struct gl_shader *));
-   if (!shProg->Shaders) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
-      return;
-   }
-
-   /* append */
-   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
-   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
-   shProg->NumShaders++;
+   attach_shader(ctx, shProg, sh);
 }
 
+static void
+attach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
+{
+   struct gl_shader_program *shProg;
+   struct gl_shader *sh;
+
+   shProg = _mesa_lookup_shader_program(ctx, program);
+   sh = _mesa_lookup_shader(ctx, shader);
+
+   attach_shader(ctx, shProg, sh);
+}
 
 static GLuint
 create_shader(struct gl_context *ctx, GLenum type)
@@ -1323,12 +1345,27 @@ validate_program(struct gl_context *ctx, GLuint program)
 }
 
 
+void GLAPIENTRY
+_mesa_AttachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   attach_shader_no_error(ctx, program, shader);
+}
+
 
 void GLAPIENTRY
 _mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader)
 {
    GET_CURRENT_CONTEXT(ctx);
-   attach_shader(ctx, program, shader);
+   attach_shader_err(ctx, program, shader, "glAttachObjectARB");
+}
+
+
+void GLAPIENTRY
+_mesa_AttachShader_no_error(GLuint program, GLuint shader)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   attach_shader_no_error(ctx, program, shader);
 }
 
 
@@ -1336,7 +1373,7 @@ void GLAPIENTRY
 _mesa_AttachShader(GLuint program, GLuint shader)
 {
    GET_CURRENT_CONTEXT(ctx);
-   attach_shader(ctx, program, shader);
+   attach_shader_err(ctx, program, shader, "glAttachShader");
 }
 
 
@@ -2260,7 +2297,7 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count,
 
         get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
         if (compiled) {
-           attach_shader(ctx, program, shader);
+           attach_shader_err(ctx, program, shader, "glCreateShaderProgramv");
            _mesa_link_program(ctx, shProg);
            detach_shader(ctx, program, shader);
 
@@ -2352,11 +2389,6 @@ _mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return -1;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return -1;
@@ -2387,11 +2419,6 @@ _mesa_GetSubroutineIndex(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return -1;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return -1;
@@ -2431,11 +2458,6 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
    GLenum resource_type;
    int count, i, j;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2518,11 +2540,6 @@ _mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2557,11 +2574,6 @@ _mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2591,11 +2603,6 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
    gl_shader_stage stage;
    int i;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2614,6 +2621,7 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
    }
 
    i = 0;
+   bool flushed = false;
    do {
       struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
       if (uni == NULL) {
@@ -2621,6 +2629,11 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
          continue;
       }
 
+      if (!flushed) {
+         _mesa_flush_vertices_for_uniforms(ctx, uni);
+         flushed = true;
+      }
+
       int uni_count = uni->array_elements ? uni->array_elements : 1;
       int j, k, f;
 
@@ -2653,8 +2666,6 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
       }
       i += uni_count;
    } while(i < count);
-
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
 }
 
 
@@ -2666,11 +2677,6 @@ _mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location,
    const char *api_name = "glGetUniformSubroutineuiv";
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2702,11 +2708,6 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
    struct gl_linked_shader *sh;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;