4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
28 #include "cogl-shader-private.h"
29 #include "cogl-shader-boilerplate.h"
30 #include "cogl-internal.h"
31 #include "cogl-context-private.h"
32 #include "cogl-handle.h"
38 static void _cogl_shader_free (CoglShader *shader);
40 COGL_HANDLE_DEFINE (Shader, shader);
41 COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (shader);
43 #ifndef GL_FRAGMENT_SHADER
44 #define GL_FRAGMENT_SHADER 0x8B30
46 #ifndef GL_VERTEX_SHADER
47 #define GL_VERTEX_SHADER 0x8B31
51 _cogl_shader_free (CoglShader *shader)
53 /* Frees shader resources but its handle is not
54 released! Do that separately before this! */
55 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
58 if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
60 if (shader->gl_handle)
61 GE (ctx, glDeletePrograms (1, &shader->gl_handle));
65 if (shader->gl_handle)
66 GE (ctx, glDeleteShader (shader->gl_handle));
68 g_slice_free (CoglShader, shader);
72 cogl_create_shader (CoglShaderType type)
76 _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
80 case COGL_SHADER_TYPE_VERTEX:
81 case COGL_SHADER_TYPE_FRAGMENT:
84 g_warning ("Unexpected shader type (0x%08lX) given to "
85 "cogl_create_shader", (unsigned long) type);
86 return COGL_INVALID_HANDLE;
89 shader = g_slice_new (CoglShader);
90 shader->language = COGL_SHADER_LANGUAGE_GLSL;
91 shader->gl_handle = 0;
92 #ifdef HAVE_COGL_GLES2
93 shader->n_tex_coord_attribs = 0;
97 return _cogl_shader_handle_new (shader);
101 delete_shader (CoglShader *shader)
103 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
106 if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
108 if (shader->gl_handle)
109 GE (ctx, glDeletePrograms (1, &shader->gl_handle));
114 if (shader->gl_handle)
115 GE (ctx, glDeleteShader (shader->gl_handle));
118 shader->gl_handle = 0;
122 cogl_shader_source (CoglHandle handle,
126 CoglShaderLanguage language;
128 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
130 if (!cogl_is_shader (handle))
136 if (strncmp (source, "!!ARBfp1.0", 10) == 0)
137 language = COGL_SHADER_LANGUAGE_ARBFP;
140 language = COGL_SHADER_LANGUAGE_GLSL;
142 /* Delete the old object if the language is changing... */
143 if (G_UNLIKELY (language != shader->language) &&
145 delete_shader (shader);
147 shader->source = g_strdup (source);
149 shader->language = language;
153 cogl_shader_compile (CoglHandle handle)
155 CoglShader *shader = handle;
157 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
159 if (!cogl_is_shader (handle))
162 if (ctx->driver == COGL_DRIVER_GL)
163 _cogl_shader_compile_real (shader, 0 /* ignored */);
165 /* XXX: For GLES2 we don't actually compile anything until the
166 * shader gets used so we have an opportunity to add some
167 * boilerplate to the shader.
169 * At the end of the day this is obviously a badly designed API
170 * given that we are having to lie to the user. It was a mistake to
171 * so thinly wrap the OpenGL shader API and the current plan is to
172 * replace it with a pipeline snippets API. */
176 _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
177 GLenum shader_gl_type,
178 int n_tex_coord_attribs,
180 const char **strings_in,
181 const GLint *lengths_in)
183 const char *vertex_boilerplate;
184 const char *fragment_boilerplate;
186 const char **strings = g_alloca (sizeof (char *) * (count_in + 3));
187 GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 3));
189 char *tex_coord_declarations = NULL;
191 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
193 if (ctx->driver == COGL_DRIVER_GLES2)
195 vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE_GLES2;
196 fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE_GLES2;
200 vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE_GL;
201 fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE_GL;
204 if (ctx->driver == COGL_DRIVER_GLES2 &&
205 cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
207 static const char texture_3d_extension[] =
208 "#extension GL_OES_texture_3D : enable\n";
209 strings[count] = texture_3d_extension;
210 lengths[count++] = sizeof (texture_3d_extension) - 1;
213 if (shader_gl_type == GL_VERTEX_SHADER)
215 strings[count] = vertex_boilerplate;
216 lengths[count++] = strlen (vertex_boilerplate);
218 else if (shader_gl_type == GL_FRAGMENT_SHADER)
220 strings[count] = fragment_boilerplate;
221 lengths[count++] = strlen (fragment_boilerplate);
224 if (ctx->driver == COGL_DRIVER_GLES2 &&
227 GString *declarations = g_string_new (NULL);
229 g_string_append_printf (declarations,
230 "varying vec4 _cogl_tex_coord[%d];\n",
231 n_tex_coord_attribs);
233 if (shader_gl_type == GL_VERTEX_SHADER)
237 g_string_append_printf (declarations,
238 "uniform mat4 cogl_texture_matrix[%d];\n",
239 n_tex_coord_attribs);
241 for (i = 0; i < n_tex_coord_attribs; i++)
242 g_string_append_printf (declarations,
243 "attribute vec4 cogl_tex_coord%d_in;\n",
247 tex_coord_declarations = g_string_free (declarations, FALSE);
248 strings[count] = tex_coord_declarations;
249 lengths[count++] = -1; /* null terminated */
252 memcpy (strings + count, strings_in, sizeof (char *) * count_in);
254 memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in);
259 for (i = 0; i < count_in; i++)
260 lengths[count + i] = -1; /* null terminated */
264 if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
266 GString *buf = g_string_new (NULL);
269 g_string_append_printf (buf,
271 shader_gl_type == GL_VERTEX_SHADER ?
272 "vertex" : "fragment");
273 for (i = 0; i < count; i++)
274 if (lengths[i] != -1)
275 g_string_append_len (buf, strings[i], lengths[i]);
277 g_string_append (buf, strings[i]);
279 g_message ("%s", buf->str);
281 g_string_free (buf, TRUE);
284 GE( ctx, glShaderSource (shader_gl_handle, count,
285 (const char **) strings, lengths) );
287 g_free (tex_coord_declarations);
291 _cogl_shader_compile_real (CoglHandle handle,
292 int n_tex_coord_attribs)
294 CoglShader *shader = handle;
296 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
299 if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
305 if (shader->gl_handle)
308 GE (ctx, glGenPrograms (1, &shader->gl_handle));
310 GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));
312 if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
313 g_message ("user ARBfp program:\n%s", shader->source);
316 while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
319 ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB,
320 GL_PROGRAM_FORMAT_ASCII_ARB,
321 strlen (shader->source),
324 gl_error = ctx->glGetError ();
325 if (gl_error != GL_NO_ERROR)
327 g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s",
331 ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB));
340 if (shader->gl_handle
341 #ifdef HAVE_COGL_GLES2
343 (ctx->driver != COGL_DRIVER_GLES2 ||
344 shader->n_tex_coord_attribs == n_tex_coord_attribs)
349 if (shader->gl_handle)
350 delete_shader (shader);
352 switch (shader->type)
354 case COGL_SHADER_TYPE_VERTEX:
355 gl_type = GL_VERTEX_SHADER;
357 case COGL_SHADER_TYPE_FRAGMENT:
358 gl_type = GL_FRAGMENT_SHADER;
361 g_assert_not_reached ();
365 shader->gl_handle = ctx->glCreateShader (gl_type);
367 _cogl_shader_set_source_with_boilerplate (shader->gl_handle,
371 (const char **) &shader->source,
374 GE (ctx, glCompileShader (shader->gl_handle));
376 #ifdef HAVE_COGL_GLES2
377 shader->n_tex_coord_attribs = n_tex_coord_attribs;
381 if (!cogl_shader_is_compiled (handle))
383 char *log = cogl_shader_get_info_log (handle);
384 g_warning ("Failed to compile GLSL program:\nsrc:\n%s\nerror:\n%s\n",
394 cogl_shader_get_info_log (CoglHandle handle)
398 _COGL_GET_CONTEXT (ctx, NULL);
400 if (!cogl_is_shader (handle))
406 if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
408 /* ARBfp exposes a program error string, but since cogl_program
409 * doesn't have any API to query an error log it is not currently
411 return g_strdup ("");
419 /* We don't normally compile the shader when the user calls
420 * cogl_shader_compile() because we want to be able to add
421 * boilerplate code that depends on how it ends up finally being
424 * Here we force an early compile if the user is interested in
425 * log information to increase the chance that the log will be
426 * useful! We have to guess the number of texture coordinate
427 * attributes that may be used since that affects the
428 * boilerplate. We use four so that the shader will still
429 * compile if the user is using more than one
430 * layer. Unfortunately this is likely to end up causing it to
431 * be compiled again when we know the actual number of layers */
432 if (!shader->gl_handle)
433 _cogl_shader_compile_real (handle, 4);
435 ctx->glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
437 return g_strdup (buffer);
442 cogl_shader_get_type (CoglHandle handle)
446 _COGL_GET_CONTEXT (ctx, COGL_SHADER_TYPE_VERTEX);
448 if (!cogl_is_shader (handle))
450 g_warning ("Non shader handle type passed to cogl_shader_get_type");
451 return COGL_SHADER_TYPE_VERTEX;
459 cogl_shader_is_compiled (CoglHandle handle)
461 #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
465 _COGL_GET_CONTEXT (ctx, FALSE);
467 if (!cogl_is_shader (handle))
473 if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
478 /* FIXME: We currently have an arbitrary limit of 4 texture
479 * coordinate attributes since our API means we have to add
480 * some boilerplate to the users GLSL program (for GLES2)
481 * before we actually know how many attributes are in use.
483 * 4 will probably be enough (or at least that limitation should
484 * be enough until we can replace this API with the pipeline
485 * snippets API) but if it isn't then the shader won't compile,
486 * through no fault of the user.
488 * To some extent this is just a symptom of bad API design; it
489 * was a mistake for Cogl to so thinly wrap the OpenGL shader
490 * API. Eventually we plan for this whole API will be deprecated
491 * by the pipeline snippets framework.
493 if (!shader->gl_handle)
494 _cogl_shader_compile_real (handle, 4);
496 GE (ctx, glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
497 if (status == GL_TRUE)