示例#1
0
/**
 * 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;
}
示例#2
0
/**
 * 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;
}