/** * Check compatibility of pipeline's program */ void GLAPIENTRY _mesa_ValidateProgramPipeline(GLuint pipeline) { GET_CURRENT_CONTEXT(ctx); struct gl_pipeline_object *pipe = 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)); }
/** * 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); }
/** * Prior to drawing anything with glBegin, glDrawArrays, etc. this function * is called to see if it's valid to render. This involves checking that * the current shader is valid and the framebuffer is complete. * It also check the current pipeline object is valid if any. * If an error is detected it'll be recorded here. * \return GL_TRUE if OK to render, GL_FALSE if not */ GLboolean _mesa_valid_to_render(struct gl_context *ctx, const char *where) { /* This depends on having up to date derived state (shaders) */ if (ctx->NewState) _mesa_update_state(ctx); if (ctx->API == API_OPENGL_COMPAT) { /* Any shader stages that are not supplied by the GLSL shader and have * assembly shaders enabled must now be validated. */ if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(vertex program not valid)", where); return GL_FALSE; } if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) { if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(fragment program not valid)", where); return GL_FALSE; } /* If drawing to integer-valued color buffers, there must be an * active fragment shader (GL_EXT_texture_integer). */ if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(integer format but no fragment shader)", where); return GL_FALSE; } } } /* A pipeline object is bound */ if (ctx->_Shader->Name && !ctx->_Shader->Validated) { if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgramPipeline failed to validate the " "pipeline"); return GL_FALSE; } } /* If a program is active and SSO not in use, check if validation of * samplers succeeded for the active program. */ if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) { char errMsg[100]; if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram, errMsg, 100)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg); return GL_FALSE; } } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "%s(incomplete framebuffer)", where); return GL_FALSE; } if (!check_blend_func_error(ctx)) { return GL_FALSE; } #ifdef DEBUG if (ctx->_Shader->Flags & GLSL_LOG) { struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram; gl_shader_stage i; for (i = 0; i < MESA_SHADER_STAGES; i++) { if (shProg[i] == NULL || shProg[i]->_Used || shProg[i]->_LinkedShaders[i] == NULL) continue; /* This is the first time this shader is being used. * Append shader's constants/uniforms to log file. * * Only log data for the program target that matches the shader * target. It's possible to have a program bound to the vertex * shader target that also supplied a fragment shader. If that * program isn't also bound to the fragment shader target we don't * want to log its fragment data. */ _mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]); } for (i = 0; i < MESA_SHADER_STAGES; i++) { if (shProg[i] != NULL) shProg[i]->_Used = GL_TRUE; } } #endif return GL_TRUE; }