struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_TYPES];
struct gl_query_state Query; /**< occlusion, timer queries */
diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c
index 7a56c67..c805cdf 100644
--- a/src/mesa/main/pipelineobj.c
+++ b/src/mesa/main/pipelineobj.c
@@ -97,6 +97,10 @@ _mesa_init_pipeline(struct gl_context *ctx)
ctx->Pipeline.Objects = _mesa_NewHashTable();
ctx->Pipeline.PipelineObj = NULL;
+
+ /* Install a default Pipeline */
+ ctx->Pipeline.Default = _mesa_new_pipeline_object(ctx, 0);
+ _mesa_reference_pipeline_object(ctx,&ctx->_Shader, ctx->Pipeline.Default);
}
@@ -120,6 +124,10 @@ _mesa_free_pipeline_data(struct gl_context *ctx)
{
_mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx);
_mesa_DeleteHashTable(ctx->Pipeline.Objects);
+
+ _mesa_reference_pipeline_object(ctx,&ctx->_Shader, NULL);
+ _mesa_delete_pipeline_object(ctx, ctx->Pipeline.Default);
+
}
/**
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index a86a429..1092287 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -43,6 +43,7 @@
#include "main/hash.h"
#include "main/mfeatures.h"
#include "main/mtypes.h"
+#include "main/pipelineobj.h"
#include "main/shaderapi.h"
#include "main/shaderobj.h"
#include "main/transformfeedback.h"
@@ -138,6 +139,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);
_glthread_DESTROY_MUTEX(ctx->Shader.Mutex);
}
@@ -1453,7 +1456,29 @@ _mesa_UseProgram(GLhandleARB program)
shProg = NULL;
}
- _mesa_use_program(ctx, shProg);
+ /*
+ * 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.PipelineObj) {
+ _mesa_BindProgramPipeline (ctx->Pipeline.PipelineObj->Name);
+ }
+ }
}
@@ -1769,7 +1794,37 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
}
}
- _mesa_use_shader_program(ctx, type, shProg);
+ /*
+ * 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,&ctx->Shader);
+ } else {
+ /* Must be done first: detach the progam */
+ _mesa_use_shader_program(ctx, type, shProg,&ctx->Shader);
+
+ /* Nothing remains current */
+ if ( ctx->Shader.CurrentVertexProgram == NULL&&
+ ctx->Shader.CurrentGeometryProgram == NULL&&
+ ctx->Shader.CurrentFragmentProgram == NULL&&
+ ctx->Shader.ActiveProgram == NULL) {
+
+ /* 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.PipelineObj) {
+ _mesa_BindProgramPipeline (ctx->Pipeline.PipelineObj->Name);
+ }
+ }
+ }
}
@@ -1784,7 +1839,37 @@ _mesa_ActiveProgramEXT(GLuint program)
? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT")
: NULL;
- _mesa_active_program(ctx, shProg, "glActiveProgramEXT");
+ /*
+ * 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 == NULL&&
+ ctx->Shader.CurrentGeometryProgram == NULL&&
+ ctx->Shader.CurrentFragmentProgram == NULL&&
+ ctx->Shader.ActiveProgram == NULL) {
+
+ /* 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.PipelineObj) {
+ _mesa_BindProgramPipeline (ctx->Pipeline.PipelineObj->Name);
+ }
+ }
+ }
+
return;
}