#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"
#include "program/program.h"
#include "program/prog_parameter.h"
#include "util/ralloc.h"
+#include "util/bitscan.h"
/**
* Delete a pipeline object.
use_program_stages(ctx, shProg, stages, pipe);
}
-void GLAPIENTRY
-_mesa_ActiveShaderProgram_no_error(GLuint pipeline, GLuint program)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_shader_program *shProg = NULL;
- struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
-
- if (program)
- shProg = _mesa_lookup_shader_program(ctx, program);
-
- /* Object is created by any Pipeline call but glGenProgramPipelines,
- * glIsProgramPipeline and GetProgramPipelineInfoLog
- */
- pipe->EverBound = GL_TRUE;
-
- _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg);
-}
-
-/**
- * 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;
}
void GLAPIENTRY
-_mesa_BindProgramPipeline_no_error(GLuint pipeline)
+_mesa_ActiveShaderProgram_no_error(GLuint pipeline, GLuint program)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_pipeline_object *newObj = NULL;
-
- /* Rebinding the same pipeline object: no change.
- */
- if (ctx->_Shader->Name == pipeline)
- return;
-
- /* Get pointer to new pipeline object (newObj)
- */
- if (pipeline) {
- /* non-default pipeline object */
- newObj = _mesa_lookup_pipeline_object(ctx, pipeline);
-
- /* Object is created by any Pipeline call but glGenProgramPipelines,
- * glIsProgramPipeline and GetProgramPipelineInfoLog
- */
- newObj->EverBound = GL_TRUE;
- }
-
- _mesa_bind_pipeline(ctx, newObj);
+ 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)
_mesa_program_init_subroutine_defaults(ctx, prog);
}
}
+
+ _mesa_update_vertex_processing_mode(ctx);
+ _mesa_update_allow_draw_out_of_order(ctx);
}
}
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
_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
{
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
_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines)
{
static GLuint msg_id = 0;
- _mesa_gl_debug(ctx, &msg_id,
- MESA_DEBUG_SOURCE_API,
- MESA_DEBUG_TYPE_PORTABILITY,
- MESA_DEBUG_SEVERITY_MEDIUM,
- "glValidateProgramPipeline: pipeline %u does not meet "
- "strict OpenGL ES 3.1 requirements and may not be "
- "portable across desktop hardware\n",
- pipe->Name);
+ _mesa_gl_debugf(ctx, &msg_id,
+ MESA_DEBUG_SOURCE_API,
+ MESA_DEBUG_TYPE_PORTABILITY,
+ MESA_DEBUG_SEVERITY_MEDIUM,
+ "glValidateProgramPipeline: pipeline %u does not meet "
+ "strict OpenGL ES 3.1 requirements and may not be "
+ "portable across desktop hardware\n",
+ pipe->Name);
}
pipe->Validated = GL_TRUE;