diff options
author | Gregory Hainaut <[email protected]> | 2013-06-28 14:33:54 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2014-03-25 10:25:25 -0700 |
commit | b2bddaf7a000bf9830a7947b18d8e31fb25353ae (patch) | |
tree | 1c7d2871fa96db31f7d35963024ea6dc39c82999 /src/mesa/main/shaderapi.c | |
parent | b995a010e688bc4d4557e973e5e28091c378e881 (diff) |
mesa/sso: replace Shader binding point with _Shader
To avoid NULL pointer check a default pipeline object is installed in
_Shader when no program is current
The spec say that UseProgram/UseShaderProgramEXT/ActiveProgramEXT got an
higher priority over the pipeline object. When default program is
uninstall, the pipeline is used if any was bound.
Note: A careful rename need to be done now...
V2: formating improvement
V3 (idr):
* Build fix. The original patch added calls to _mesa_use_shader_program
with 4 parameters, but the fourth parameter isn't added to that
function until a much later patch. Just drop that parameter for now.
* Trivial reformatting.
* Updated comment of gl_context::_Shader
v4 (idr): Reformat spec quotations to look like spec quotations. Update
comments describing what gl_context::_Shader can point to. Bot
suggested by Eric.
Reviewed-by: Ian Romanick <[email protected]>
Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src/mesa/main/shaderapi.c')
-rw-r--r-- | src/mesa/main/shaderapi.c | 97 |
1 files changed, 94 insertions, 3 deletions
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 5060cbb0ba7..f0d345a143b 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -44,6 +44,7 @@ #include "main/hash.h" #include "main/hash_table.h" #include "main/mtypes.h" +#include "main/pipelineobj.h" #include "main/shaderapi.h" #include "main/shaderobj.h" #include "main/transformfeedback.h" @@ -144,6 +145,8 @@ _mesa_free_shader_state(struct gl_context *ctx) _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); /* Extended for ARB_separate_shader_objects */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL); + assert(ctx->Shader.RefCount == 1); mtx_destroy(&ctx->Shader.Mutex); } @@ -1541,7 +1544,31 @@ _mesa_UseProgram(GLhandleARB program) shProg = NULL; } - _mesa_use_program(ctx, shProg); + /* The "Dependencies on EXT_separate_shader_objects" section of the + * ARB_separate_shader_object spec says: + * + * "The executable code for an individual shader stage is taken from + * the current program for that stage. If there is a current program + * object for any shader stage or for uniform updates established by + * UseProgram, UseShaderProgramEXT, or ActiveProgramEXT, the current + * program for that stage (if any) is considered current. Otherwise, + * if there is a bound program pipeline object ..." + */ + if (program) { + /* Attach shader state to the binding point */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader); + /* Update the program */ + _mesa_use_program(ctx, shProg); + } else { + /* Must be done first: detach the progam */ + _mesa_use_program(ctx, shProg); + /* Unattach shader_state binding point */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default); + /* If a pipeline was bound, rebind it */ + if (ctx->Pipeline.Current) { + _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name); + } + } } @@ -1815,7 +1842,41 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program) } } - _mesa_use_shader_program(ctx, type, shProg); + /* The "Dependencies on EXT_separate_shader_objects" section of the + * ARB_separate_shader_object spec says: + * + * "The executable code for an individual shader stage is taken from + * the current program for that stage. If there is a current program + * object for any shader stage or for uniform updates established by + * UseProgram, UseShaderProgramEXT, or ActiveProgramEXT, the current + * program for that stage (if any) is considered current. Otherwise, + * if there is a bound program pipeline object ..." + */ + if (program) { + /* Attach shader state to the binding point */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader); + /* Update the program */ + _mesa_use_shader_program(ctx, type, shProg); + } else { + /* Must be done first: detach the progam */ + _mesa_use_shader_program(ctx, type, shProg); + + /* Nothing remains current */ + if (!ctx->Shader.CurrentVertexProgram && + !ctx->Shader.CurrentGeometryProgram && + !ctx->Shader.CurrentFragmentProgram && + !ctx->Shader.ActiveProgram) { + + /* Unattach shader_state binding point */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, + ctx->Pipeline.Default); + + /* If a pipeline was bound, rebind it */ + if (ctx->Pipeline.Current) { + _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name); + } + } + } } @@ -1830,7 +1891,37 @@ _mesa_ActiveProgramEXT(GLuint program) ? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT") : NULL; - _mesa_active_program(ctx, shProg, "glActiveProgramEXT"); + /* The "Dependencies on EXT_separate_shader_objects" section of the + * ARB_separate_shader_object spec says: + * + * "The executable code for an individual shader stage is taken from + * the current program for that stage. If there is a current program + * object for any shader stage or for uniform updates established by + * UseProgram, UseShaderProgramEXT, or ActiveProgramEXT, the current + * program for that stage (if any) is considered current. Otherwise, + * if there is a bound program pipeline object ..." + */ + if (shProg != NULL) { + /* Attach shader state to the binding point */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader); + _mesa_active_program(ctx, shProg, "glActiveProgramEXT"); + } else { + /* Must be done first: unset the current active progam */ + _mesa_active_program(ctx, shProg, "glActiveProgramEXT"); + + /* Nothing remains current */ + if (!ctx->Shader.CurrentVertexProgram && !ctx->Shader.CurrentGeometryProgram && + !ctx->Shader.CurrentFragmentProgram && !ctx->Shader.ActiveProgram) { + + /* Unattach shader_state binding point */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default); + /* If a pipeline was bound, rebind it */ + if (ctx->Pipeline.Current) { + _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name); + } + } + } + return; } |