/** Currently bound pipeline object. See _mesa_BindProgramPipeline() */
struct gl_pipeline_object *Current;
+ /* Default Object to ensure that _Shader is never NULL */
+ struct gl_pipeline_object *Default;
+
/** Pipeline objects */
struct _mesa_HashTable *Objects;
};
struct gl_pipeline_shader_state Pipeline; /**< GLSL pipeline shader object state */
struct gl_pipeline_object Shader; /**< GLSL shader object state */
+
+ /**
+ * Current active shader pipeline state
+ *
+ * Almost all internal users want ::_Shader instead of ::Shader. The
+ * exceptions are bits of legacy GLSL API that do not know about separate
+ * shader objects.
+ *
+ * If a program is active via \c glUseProgram, this will point to
+ * \c ::Shader.
+ *
+ * If a program pipeline is active via \c glBindProgramPipeline, this will
+ * point to \c ::Pipeline.Current.
+ *
+ * If neither a program nor a program pipeline is active, this will point to
+ * \c ::Pipeline.Default. This ensures that \c ::_Shader will never be
+ * \c NULL.
+ */
+ struct gl_pipeline_object *_Shader;
+
struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES];
struct gl_query_state Query; /**< occlusion, timer queries */
#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"
_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);
}
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);
+ }
+ }
}
}
}
- _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);
+ }
+ }
+ }
}
? _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;
}