/** * 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. * 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(GLcontext *ctx, const char *where) { if (ctx->Shader.CurrentProgram) { /* using shaders */ if (!ctx->Shader.CurrentProgram->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader not linked), where"); return GL_FALSE; } #if 0 /* not normally enabled */ { char errMsg[100]; if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram, errMsg)) { _mesa_warning(ctx, "Shader program %u is invalid: %s", ctx->Shader.CurrentProgram->Name, errMsg); } } #endif } else { if (ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(vertex program not valid)", where); return GL_FALSE; } if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(fragment program not valid)", where); 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; } #ifdef DEBUG if (ctx->Shader.Flags & GLSL_LOG) { struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; if (shProg) { if (!shProg->_Used) { /* This is the first time this shader is being used. * Append shader's constants/uniforms to log file. */ GLuint i; for (i = 0; i < shProg->NumShaders; i++) { struct gl_shader *sh = shProg->Shaders[i]; if (sh->Type == GL_VERTEX_SHADER) { _mesa_append_uniforms_to_file(sh, &shProg->VertexProgram->Base); } else if (sh->Type == GL_FRAGMENT_SHADER) { _mesa_append_uniforms_to_file(sh, &shProg->FragmentProgram->Base); } } shProg->_Used = GL_TRUE; } } } #endif return GL_TRUE; }
/** * 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; }