diff options
author | Gregory Hainaut <gregory.hainaut@gmail.com> | 2013-05-03 19:44:13 +0200 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2014-03-25 10:25:25 -0700 |
commit | 9e9fac4714791c2a76728d66243380017273b5f3 (patch) | |
tree | f9671d3dfe3b96bcc5ac57382769fb6c3f337278 | |
parent | 78578b759943cb198d34eedc00b3408c1599f6ec (diff) |
mesa/sso: Implement _mesa_BindProgramPipeline
Test become green in piglit:
The updated ext_transform_feedback-api-errors:useprogstage_noactive useprogstage_active bind_pipeline
arb_separate_shader_object-GetProgramPipelineiv
arb_separate_shader_object-IsProgramPipeline
For the moment I reuse Driver.UseProgram but I guess it will be better
to create a UseProgramStages functions. Opinion is welcome
V2: formatting & rename
V3 (idr):
* Change spec references to core OpenGL versions instead of issues in the
extension spec.
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | src/mesa/main/pipelineobj.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c index b639e9bc913..7245b7802b9 100644 --- a/src/mesa/main/pipelineobj.c +++ b/src/mesa/main/pipelineobj.c @@ -369,6 +369,75 @@ _mesa_ActiveShaderProgram(GLuint pipeline, GLuint program) void GLAPIENTRY _mesa_BindProgramPipeline(GLuint pipeline) { + GET_CURRENT_CONTEXT(ctx); + struct gl_pipeline_object *newObj = NULL; + + /* Rebinding the same pipeline object: no change. + */ + if (ctx->_Shader->Name == pipeline) + return; + + /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1 + * spec says: + * + * "The error INVALID_OPERATION is generated: + * + * ... + * + * - by BindProgramPipeline if the current transform feedback + * object is active and not paused; + */ + if (_mesa_is_xfb_active_and_unpaused(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindProgramPipeline(transform feedback active)"); + return; + } + + /* Get pointer to new pipeline object (newObj) + */ + if (pipeline) { + /* non-default pipeline object */ + newObj = lookup_pipeline_object(ctx, pipeline); + if (!newObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindProgramPipeline(non-gen name)"); + return; + } + + /* Object is created by any Pipeline call but glGenProgramPipelines, + * glIsProgramPipeline and GetProgramPipelineInfoLog + */ + newObj->EverBound = GL_TRUE; + } + + /* First bind the Pipeline to pipeline binding point */ + _mesa_reference_pipeline_object(ctx, &ctx->Pipeline.Current, newObj); + + /* Section 2.11.3 (Program Objects) of the OpenGL 4.1 spec says: + * + * "If there is a current program object established by UseProgram, + * that program is considered current for all stages. Otherwise, if + * there is a bound program pipeline object (see section 2.11.4), the + * program bound to the appropriate stage of the pipeline object is + * considered current." + */ + if (&ctx->Shader != ctx->_Shader) { + if (pipeline) { + /* Bound the pipeline to the current program and + * restore the pipeline state + */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, newObj); + } else { + /* Unbind the pipeline */ + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, + ctx->Pipeline.Default); + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + + if (ctx->Driver.UseProgram) + ctx->Driver.UseProgram(ctx, NULL); + } } /** |