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; }