示例#1
0
void
_cogl_shader_compile_real (CoglHandle handle,
                           CoglPipeline *pipeline)
{
  CoglShader *shader = handle;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

#ifdef HAVE_COGL_GL
  if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
    {
#ifdef COGL_GL_DEBUG
      GLenum gl_error;
#endif

      if (shader->gl_handle)
        return;

      GE (ctx, glGenPrograms (1, &shader->gl_handle));

      GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));

      if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
        g_message ("user ARBfp program:\n%s", shader->source);

#ifdef COGL_GL_DEBUG
      _cogl_gl_util_clear_gl_errors (ctx);
#endif
      ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB,
                            GL_PROGRAM_FORMAT_ASCII_ARB,
                            strlen (shader->source),
                            shader->source);
#ifdef COGL_GL_DEBUG
      gl_error = _cogl_gl_util_get_error (ctx);
      if (gl_error != GL_NO_ERROR)
        {
          g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s",
                     G_STRLOC,
                     gl_error,
                     shader->source,
                     ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB));
        }
#endif
    }
  else
#endif
    {
      GLenum gl_type;
      GLint status;

      if (shader->gl_handle)
        {
          CoglPipeline *prev = shader->compilation_pipeline;

          /* XXX: currently the only things that will affect the
           * boilerplate for user shaders, apart from driver features,
           * are the pipeline layer-indices and texture-unit-indices
           */
          if (pipeline == prev ||
              _cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline))
            return;
        }

      if (shader->gl_handle)
        delete_shader (shader);

      switch (shader->type)
        {
        case COGL_SHADER_TYPE_VERTEX:
          gl_type = GL_VERTEX_SHADER;
          break;
        case COGL_SHADER_TYPE_FRAGMENT:
          gl_type = GL_FRAGMENT_SHADER;
          break;
        default:
          g_assert_not_reached ();
          break;
        }

      shader->gl_handle = ctx->glCreateShader (gl_type);

      _cogl_glsl_shader_set_source_with_boilerplate (ctx,
                                                     shader->gl_handle,
                                                     gl_type,
                                                     pipeline,
                                                     1,
                                                     (const char **)
                                                      &shader->source,
                                                     NULL);

      GE (ctx, glCompileShader (shader->gl_handle));

      shader->compilation_pipeline = cogl_object_ref (pipeline);

      GE (ctx, glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
      if (!status)
        {
          char buffer[512];
          int len = 0;

          ctx->glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
          buffer[len] = '\0';

          g_warning ("Failed to compile GLSL program:\n"
                     "src:\n%s\n"
                     "error:\n%s\n",
                     shader->source,
                     buffer);
        }
    }
}
static CoglBool
_cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline,
                                  unsigned long pipelines_difference)
{
  CoglPipelineShaderState *shader_state = get_shader_state (pipeline);
  GLuint gl_program;
  UpdateConstantsState state;

  _COGL_GET_CONTEXT (ctx, FALSE);

  if (shader_state->source)
    {
      GLenum gl_error;
      COGL_STATIC_COUNTER (fragend_arbfp_compile_counter,
                           "arbfp compile counter",
                           "Increments each time a new ARBfp "
                           "program is compiled",
                           0 /* no application private data */);

      COGL_COUNTER_INC (_cogl_uprof_context, fragend_arbfp_compile_counter);

      g_string_append (shader_state->source,
                       "MOV result.color,output;\n");
      g_string_append (shader_state->source, "END\n");

      if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
        g_message ("pipeline program:\n%s", shader_state->source->str);

      GE (ctx, glGenPrograms (1, &shader_state->gl_program));

      GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB,
                              shader_state->gl_program));

      while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
        ;
      ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB,
                            GL_PROGRAM_FORMAT_ASCII_ARB,
                            shader_state->source->len,
                            shader_state->source->str);
      if (ctx->glGetError () != GL_NO_ERROR)
        {
          g_warning ("\n%s\n%s",
                     shader_state->source->str,
                     ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB));
        }

      shader_state->source = NULL;
    }

  gl_program = shader_state->gl_program;

  GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, gl_program));
  _cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_ARBFP);

  state.unit = 0;
  state.shader_state = shader_state;
  /* If this arbfp program was last used with a different pipeline
   * then we need to ensure we update all program.local params */
  state.update_all =
    pipeline != shader_state->last_used_for_pipeline;
  cogl_pipeline_foreach_layer (pipeline,
                               update_constants_cb,
                               &state);

  /* We need to track what pipeline used this arbfp program last since
   * we will need to update program.local params when switching
   * between different pipelines. */
  shader_state->last_used_for_pipeline = pipeline;

  return TRUE;
}