summaryrefslogtreecommitdiff
path: root/src/mesa/main/shaderapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/shaderapi.c')
-rw-r--r--src/mesa/main/shaderapi.c283
1 files changed, 248 insertions, 35 deletions
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 8ecda71928..030236e735 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -116,7 +116,12 @@ _mesa_init_shader_state(struct gl_context *ctx)
void
_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);
}
@@ -399,6 +404,14 @@ bind_attrib_location(struct gl_context *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(struct gl_context *ctx, GLenum type)
{
@@ -600,6 +613,16 @@ 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.
*/
@@ -607,8 +630,8 @@ static GLuint
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;
}
@@ -845,7 +868,10 @@ link_program(struct gl_context *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;
@@ -908,52 +934,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(struct gl_context *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);
}
@@ -1110,6 +1167,16 @@ _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)
{
@@ -1240,6 +1307,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)
@@ -1501,8 +1578,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);
}
@@ -1618,6 +1724,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
+ }
+
+ shProg->InfoLog = talloc_strdup_append(shProg->InfoLog, sh->InfoLog);
+ }
+
+ delete_shader(ctx, shader);
+ }
+
+ return program;
+}
/**
* Plug in shader-related functions into API dispatch table.
@@ -1668,6 +1872,15 @@ _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);
+
#endif /* FEATURE_GL */
}