mesa: Implement glGetFragDataLocation
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 4 Nov 2011 23:32:02 +0000 (16:32 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 8 Nov 2011 19:10:11 +0000 (11:10 -0800)
Fixes piglit's getfragdatalocation test.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/main/shader_query.cpp
src/mesa/main/shaderapi.c

index 23667a13328206dd6fce023ca718eafa780304b5..38bacdb747bbe1515a3fe5042861eb5098c533b5 100644 (file)
@@ -274,3 +274,59 @@ _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
     * glLinkProgram is called again.
     */
 }
+
+GLint GLAPIENTRY
+_mesa_GetFragDataLocation(GLuint program, const GLchar *name)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *const shProg =
+      _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
+
+   if (!shProg) {
+      return -1;
+   }
+
+   if (!shProg->LinkStatus) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetFragDataLocation(program not linked)");
+      return -1;
+   }
+
+   if (!name)
+      return -1;
+
+   if (strncmp(name, "gl_", 3) == 0) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetFragDataLocation(illegal name)");
+      return -1;
+   }
+
+   /* Not having a fragment shader is not an error.
+    */
+   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
+      return -1;
+
+   exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
+   foreach_list(node, ir) {
+      const ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+      /* The extra check against FRAG_RESULT_DATA0 is because
+       * glGetFragDataLocation cannot be used on "conventional" attributes.
+       *
+       * From page 95 of the OpenGL 3.0 spec:
+       *
+       *     "If name is not an active attribute, if name is a conventional
+       *     attribute, or if an error occurs, -1 will be returned."
+       */
+      if (var == NULL
+         || var->mode != ir_var_out
+         || var->location == -1
+         || var->location < FRAG_RESULT_DATA0)
+        continue;
+
+      if (strcmp(var->name, name) == 0)
+        return var->location - FRAG_RESULT_DATA0;
+   }
+
+   return -1;
+}
index 1d8af3ea06bc9722008156a36de580f8d087f18f..c4d01abc7056b067e418b289510da4df08dba380 100644 (file)
@@ -496,16 +496,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.
  */
@@ -1178,16 +1168,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)