void GLAPIENTRY _mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { GET_CURRENT_CONTEXT(ctx); struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); if (!pipe) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramPipelineInfoLog(pipeline)"); return; } if (bufSize < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramPipelineInfoLog(bufSize)"); return; } if (pipe->InfoLog) _mesa_copy_string(infoLog, bufSize, length, pipe->InfoLog); else *length = 0; }
/** * Use the named shader program for subsequent glUniform calls (if pipeline * bound) */ void GLAPIENTRY _mesa_ActiveShaderProgram(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 != 0) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glActiveShaderProgram(program)"); if (shProg == NULL) return; } if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)"); return; } /* Object is created by any Pipeline call but glGenProgramPipelines, * glIsProgramPipeline and GetProgramPipelineInfoLog */ pipe->EverBound = GL_TRUE; if ((shProg != NULL) && !shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(program %u not linked)", shProg->Name); return; } _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg); }
/** * Determine if ID is the name of an pipeline object. * * \param id ID of the potential pipeline object. * \return \c GL_TRUE if \c id is the name of a pipeline object, * \c GL_FALSE otherwise. */ GLboolean GLAPIENTRY _mesa_IsProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); struct gl_pipeline_object *obj = _mesa_lookup_pipeline_object(ctx, pipeline); if (obj == NULL) return GL_FALSE; return obj->EverBound; }
/** * Determine if ID is the name of an pipeline object. * * \param id ID of the potential pipeline object. * \return \c GL_TRUE if \c id is the name of a pipeline object, * \c GL_FALSE otherwise. */ GLboolean GLAPIENTRY _mesa_IsProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glIsProgramPipeline(%u)\n", pipeline); struct gl_pipeline_object *obj = _mesa_lookup_pipeline_object(ctx, pipeline); if (obj == NULL) return GL_FALSE; return obj->EverBound; }
/** * Make program of the pipeline current */ void GLAPIENTRY _mesa_BindProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); struct gl_pipeline_object *newObj = NULL; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBindProgramPipeline(%u)\n", pipeline); /* 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 = _mesa_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; } _mesa_bind_pipeline(ctx, newObj); }
/** * Check compatibility of pipeline's program */ void GLAPIENTRY _mesa_ValidateProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgramPipeline(pipeline)"); return; } _mesa_validate_program_pipeline(ctx, pipe, (ctx->_Shader->Name == pipe->Name)); }
/** * Delete a set of pipeline objects. * * \param n Number of pipeline objects to delete. * \param ids pipeline of \c n pipeline object IDs. */ void GLAPIENTRY _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) { GET_CURRENT_CONTEXT(ctx); GLsizei i; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glDeleteProgramPipelines(%d, %p)\n", n, pipelines); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)"); return; } for (i = 0; i < n; i++) { struct gl_pipeline_object *obj = _mesa_lookup_pipeline_object(ctx, pipelines[i]); if (obj) { assert(obj->Name == pipelines[i]); /* If the pipeline object is currently bound, the spec says "If an * object that is currently bound is deleted, the binding for that * object reverts to zero and no program pipeline object becomes * current." */ if (obj == ctx->Pipeline.Current) { _mesa_BindProgramPipeline(0); } /* The ID is immediately freed for re-use */ remove_pipeline_object(ctx, obj); /* Unreference the pipeline object. * If refcount hits zero, the object will be deleted. */ _mesa_reference_pipeline_object(ctx, &obj, NULL); } } }
/** * Check compatibility of pipeline's program */ void GLAPIENTRY _mesa_ValidateProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glValidateProgramPipeline(%u)\n", pipeline); struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgramPipeline(pipeline)"); return; } /* ValidateProgramPipeline should not throw errors when pipeline validation * fails and should instead only update the validation status. We pass * false for IsBound to avoid an error being thrown. */ _mesa_validate_program_pipeline(ctx, pipe, false); }
/** * glGetProgramPipelineiv() - get pipeline shader state. */ void GLAPIENTRY _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) { GET_CURRENT_CONTEXT(ctx); struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); /* Are geometry shaders available in this context? */ const bool has_gs = _mesa_has_geometry_shaders(ctx); const bool has_tess = _mesa_has_tessellation(ctx);; if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramPipelineiv(pipeline)"); return; } /* Object is created by any Pipeline call but glGenProgramPipelines, * glIsProgramPipeline and GetProgramPipelineInfoLog */ pipe->EverBound = GL_TRUE; switch (pname) { case GL_ACTIVE_PROGRAM: *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0; return; case GL_INFO_LOG_LENGTH: *params = pipe->InfoLog ? strlen(pipe->InfoLog) + 1 : 0; return; case GL_VALIDATE_STATUS: *params = pipe->Validated; return; case GL_VERTEX_SHADER: *params = pipe->CurrentProgram[MESA_SHADER_VERTEX] ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name : 0; return; case GL_TESS_EVALUATION_SHADER: if (!has_tess) break; *params = pipe->CurrentProgram[MESA_SHADER_TESS_EVAL] ? pipe->CurrentProgram[MESA_SHADER_TESS_EVAL]->Name : 0; return; case GL_TESS_CONTROL_SHADER: if (!has_tess) break; *params = pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] ? pipe->CurrentProgram[MESA_SHADER_TESS_CTRL]->Name : 0; return; case GL_GEOMETRY_SHADER: if (!has_gs) break; *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY] ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name : 0; return; case GL_FRAGMENT_SHADER: *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT] ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name : 0; return; default: break; } _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)", _mesa_enum_to_string(pname)); }
/** * Bound program to severals stages of the pipeline */ void GLAPIENTRY _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) { GET_CURRENT_CONTEXT(ctx); struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); struct gl_shader_program *shProg = NULL; GLbitfield any_valid_stages; if (!pipe) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(pipeline)"); return; } /* Object is created by any Pipeline call but glGenProgramPipelines, * glIsProgramPipeline and GetProgramPipelineInfoLog */ pipe->EverBound = GL_TRUE; /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec says: * * "If stages is not the special value ALL_SHADER_BITS, and has a bit * set that is not recognized, the error INVALID_VALUE is generated." */ any_valid_stages = GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT; if (_mesa_has_geometry_shaders(ctx)) any_valid_stages |= GL_GEOMETRY_SHADER_BIT; if (_mesa_has_tessellation(ctx)) any_valid_stages |= GL_TESS_CONTROL_SHADER_BIT | GL_TESS_EVALUATION_SHADER_BIT; if (stages != GL_ALL_SHADER_BITS && (stages & ~any_valid_stages) != 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glUseProgramStages(Stages)"); return; } /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1 * spec says: * * "The error INVALID_OPERATION is generated: * * ... * * - by UseProgramStages if the program pipeline object it refers * to is current and the current transform feedback object is * active and not paused; */ if (ctx->_Shader == pipe) { if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(transform feedback active)"); return; } } if (program) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgramStages"); if (shProg == NULL) return; /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec * says: * * "If the program object named by program was linked without the * PROGRAM_SEPARABLE parameter set, or was not linked successfully, * the error INVALID_OPERATION is generated and the corresponding * shader stages in the pipeline program pipeline object are not * modified." */ if (!shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(program not linked)"); return; } if (!shProg->SeparateShader) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(program wasn't linked with the " "PROGRAM_SEPARABLE flag)"); return; } } /* 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) _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, shProg, pipe); if ((stages & GL_FRAGMENT_SHADER_BIT) != 0) _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg, pipe); if ((stages & GL_GEOMETRY_SHADER_BIT) != 0) _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER, shProg, pipe); if ((stages & GL_TESS_CONTROL_SHADER_BIT) != 0) _mesa_use_shader_program(ctx, GL_TESS_CONTROL_SHADER, shProg, pipe); if ((stages & GL_TESS_EVALUATION_SHADER_BIT) != 0) _mesa_use_shader_program(ctx, GL_TESS_EVALUATION_SHADER, shProg, pipe); }