#include <stdbool.h>
#include "main/glheader.h"
#include "main/context.h"
-#include "main/dispatch.h"
#include "main/enums.h"
#include "main/hash.h"
#include "main/mtypes.h"
#include "main/pipelineobj.h"
#include "main/shaderapi.h"
#include "main/shaderobj.h"
+#include "main/state.h"
#include "main/transformfeedback.h"
#include "main/uniforms.h"
#include "compiler/glsl/glsl_parser_extras.h"
{
unsigned i;
- _mesa_reference_program(ctx, &obj->_CurrentFragmentProgram, NULL);
-
for (i = 0; i < MESA_SHADER_STAGES; i++) {
_mesa_reference_program(ctx, &obj->CurrentProgram[i], NULL);
_mesa_reference_shader_program(ctx, &obj->ReferencedPrograms[i], NULL);
return NULL;
else
return (struct gl_pipeline_object *)
- _mesa_HashLookup(ctx->Pipeline.Objects, id);
+ _mesa_HashLookupLocked(ctx->Pipeline.Objects, id);
}
/**
save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
{
if (obj->Name > 0) {
- _mesa_HashInsert(ctx->Pipeline.Objects, obj->Name, obj);
+ _mesa_HashInsertLocked(ctx->Pipeline.Objects, obj->Name, obj);
}
}
remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
{
if (obj->Name > 0) {
- _mesa_HashRemove(ctx->Pipeline.Objects, obj->Name);
+ _mesa_HashRemoveLocked(ctx->Pipeline.Objects, obj->Name);
}
}
_mesa_use_program(ctx, stage, shProg, prog, pipe);
}
+static void
+use_program_stages(struct gl_context *ctx, struct gl_shader_program *shProg,
+ GLbitfield stages, struct gl_pipeline_object *pipe) {
+
+ /* Enable individual stages from the program as requested by the
+ * application. If there is no shader for a requested stage in the
+ * program, _mesa_use_shader_program will enable fixed-function processing
+ * as dictated by the spec.
+ *
+ * Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
+ * says:
+ *
+ * "If UseProgramStages is called with program set to zero or with a
+ * program object that contains no executable code for the given
+ * stages, it is as if the pipeline object has no programmable stage
+ * configured for the indicated shader stages."
+ */
+ if ((stages & GL_VERTEX_SHADER_BIT) != 0)
+ use_program_stage(ctx, GL_VERTEX_SHADER, shProg, pipe);
+
+ if ((stages & GL_FRAGMENT_SHADER_BIT) != 0)
+ use_program_stage(ctx, GL_FRAGMENT_SHADER, shProg, pipe);
+
+ if ((stages & GL_GEOMETRY_SHADER_BIT) != 0)
+ use_program_stage(ctx, GL_GEOMETRY_SHADER, shProg, pipe);
+
+ if ((stages & GL_TESS_CONTROL_SHADER_BIT) != 0)
+ use_program_stage(ctx, GL_TESS_CONTROL_SHADER, shProg, pipe);
+
+ if ((stages & GL_TESS_EVALUATION_SHADER_BIT) != 0)
+ use_program_stage(ctx, GL_TESS_EVALUATION_SHADER, shProg, pipe);
+
+ if ((stages & GL_COMPUTE_SHADER_BIT) != 0)
+ use_program_stage(ctx, GL_COMPUTE_SHADER, shProg, pipe);
+
+ pipe->Validated = false;
+}
+
+void GLAPIENTRY
+_mesa_UseProgramStages_no_error(GLuint pipeline, GLbitfield stages,
+ GLuint prog)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_pipeline_object *pipe =
+ _mesa_lookup_pipeline_object(ctx, pipeline);
+ struct gl_shader_program *shProg = NULL;
+
+ if (prog)
+ shProg = _mesa_lookup_shader_program(ctx, prog);
+
+ /* Object is created by any Pipeline call but glGenProgramPipelines,
+ * glIsProgramPipeline and GetProgramPipelineInfoLog
+ */
+ pipe->EverBound = GL_TRUE;
+
+ use_program_stages(ctx, shProg, stages, pipe);
+}
+
/**
* Bound program to severals stages of the pipeline
*/
}
}
- /* Enable individual stages from the program as requested by the
- * application. If there is no shader for a requested stage in the
- * program, _mesa_use_shader_program will enable fixed-function processing
- * as dictated by the spec.
- *
- * Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
- * says:
- *
- * "If UseProgramStages is called with program set to zero or with a
- * program object that contains no executable code for the given
- * stages, it is as if the pipeline object has no programmable stage
- * configured for the indicated shader stages."
- */
- if ((stages & GL_VERTEX_SHADER_BIT) != 0)
- use_program_stage(ctx, GL_VERTEX_SHADER, shProg, pipe);
-
- if ((stages & GL_FRAGMENT_SHADER_BIT) != 0)
- use_program_stage(ctx, GL_FRAGMENT_SHADER, shProg, pipe);
-
- if ((stages & GL_GEOMETRY_SHADER_BIT) != 0)
- use_program_stage(ctx, GL_GEOMETRY_SHADER, shProg, pipe);
-
- if ((stages & GL_TESS_CONTROL_SHADER_BIT) != 0)
- use_program_stage(ctx, GL_TESS_CONTROL_SHADER, shProg, pipe);
-
- if ((stages & GL_TESS_EVALUATION_SHADER_BIT) != 0)
- use_program_stage(ctx, GL_TESS_EVALUATION_SHADER, shProg, pipe);
-
- if ((stages & GL_COMPUTE_SHADER_BIT) != 0)
- use_program_stage(ctx, GL_COMPUTE_SHADER, shProg, pipe);
-
- pipe->Validated = false;
+ use_program_stages(ctx, shProg, stages, pipe);
}
-/**
- * Use the named shader program for subsequent glUniform calls (if pipeline
- * bound)
- */
-void GLAPIENTRY
-_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program)
+static ALWAYS_INLINE void
+active_shader_program(struct gl_context *ctx, GLuint pipeline, GLuint program,
+ bool no_error)
{
- GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg = NULL;
struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glActiveShaderProgram(%u, %u)\n", pipeline, program);
-
- if (program != 0) {
- shProg = _mesa_lookup_shader_program_err(ctx, program,
- "glActiveShaderProgram(program)");
- if (shProg == NULL)
- return;
+ if (program) {
+ if (no_error) {
+ shProg = _mesa_lookup_shader_program(ctx, program);
+ } else {
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glActiveShaderProgram(program)");
+ if (shProg == NULL)
+ return;
+ }
}
- if (!pipe) {
+ if (!no_error && !pipe) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)");
return;
}
*/
pipe->EverBound = GL_TRUE;
- if ((shProg != NULL) && !shProg->data->LinkStatus) {
+ if (!no_error && shProg != NULL && !shProg->data->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glActiveShaderProgram(program %u not linked)", shProg->Name);
return;
_mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg);
}
+void GLAPIENTRY
+_mesa_ActiveShaderProgram_no_error(GLuint pipeline, GLuint program)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ active_shader_program(ctx, pipeline, program, true);
+}
+
/**
- * Make program of the pipeline current
+ * Use the named shader program for subsequent glUniform calls (if pipeline
+ * bound)
*/
void GLAPIENTRY
-_mesa_BindProgramPipeline(GLuint pipeline)
+_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program)
{
GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glActiveShaderProgram(%u, %u)\n", pipeline, program);
+
+ active_shader_program(ctx, pipeline, program, false);
+}
+
+static ALWAYS_INLINE void
+bind_program_pipeline(struct gl_context *ctx, GLuint pipeline, bool no_error)
+{
struct gl_pipeline_object *newObj = NULL;
if (MESA_VERBOSE & VERBOSE_API)
* - by BindProgramPipeline if the current transform feedback
* object is active and not paused;
*/
- if (_mesa_is_xfb_active_and_unpaused(ctx)) {
+ if (!no_error && _mesa_is_xfb_active_and_unpaused(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBindProgramPipeline(transform feedback active)");
return;
if (pipeline) {
/* non-default pipeline object */
newObj = _mesa_lookup_pipeline_object(ctx, pipeline);
- if (!newObj) {
+ if (!no_error && !newObj) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBindProgramPipeline(non-gen name)");
return;
_mesa_bind_pipeline(ctx, newObj);
}
+void GLAPIENTRY
+_mesa_BindProgramPipeline_no_error(GLuint pipeline)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_program_pipeline(ctx, pipeline, true);
+}
+
+/**
+ * Make program of the pipeline current
+ */
+void GLAPIENTRY
+_mesa_BindProgramPipeline(GLuint pipeline)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_program_pipeline(ctx, pipeline, false);
+}
+
void
_mesa_bind_pipeline(struct gl_context *ctx,
struct gl_pipeline_object *pipe)
* considered current."
*/
if (&ctx->Shader != ctx->_Shader) {
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+
if (pipe != NULL) {
/* Bound the pipeline to the current program and
* restore the pipeline state
ctx->Pipeline.Default);
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
-
for (i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_program *prog = ctx->_Shader->CurrentProgram[i];
if (prog) {
_mesa_program_init_subroutine_defaults(ctx, prog);
}
}
+
+ _mesa_update_vertex_processing_mode(ctx);
}
}
create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines,
bool dsa)
{
- const char *func;
+ const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
GLuint first;
GLint i;
- func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
-
- if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func);
- return;
- }
-
- if (!pipelines) {
+ if (!pipelines)
return;
- }
first = _mesa_HashFindFreeKeyBlock(ctx->Pipeline.Objects, n);
save_pipeline_object(ctx, obj);
pipelines[i] = first + i;
}
+}
+static void
+create_program_pipelines_err(struct gl_context *ctx, GLsizei n,
+ GLuint *pipelines, bool dsa)
+{
+ const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func);
+ return;
+ }
+
+ create_program_pipelines(ctx, n, pipelines, dsa);
+}
+
+void GLAPIENTRY
+_mesa_GenProgramPipelines_no_error(GLsizei n, GLuint *pipelines)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_program_pipelines(ctx, n, pipelines, false);
}
void GLAPIENTRY
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glGenProgramPipelines(%d, %p)\n", n, pipelines);
- create_program_pipelines(ctx, n, pipelines, false);
+ create_program_pipelines_err(ctx, n, pipelines, false);
+}
+
+void GLAPIENTRY
+_mesa_CreateProgramPipelines_no_error(GLsizei n, GLuint *pipelines)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_program_pipelines(ctx, n, pipelines, true);
}
void GLAPIENTRY
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glCreateProgramPipelines(%d, %p)\n", n, pipelines);
- create_program_pipelines(ctx, n, pipelines, true);
+ create_program_pipelines_err(ctx, n, pipelines, true);
}
/**