4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2008,2009 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/>.
30 #include "cogl-internal.h"
31 #include "cogl-context.h"
32 #include "cogl-handle.h"
34 #ifdef HAVE_COGL_GLES2
38 #include "cogl-shader-private.h"
39 #include "cogl-program.h"
41 static void _cogl_program_free (CoglProgram *program);
43 COGL_HANDLE_DEFINE (Program, program);
44 COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (program);
47 _cogl_program_free (CoglProgram *program)
51 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
53 /* Unref all of the attached shaders */
54 g_slist_foreach (program->attached_shaders, (GFunc) cogl_handle_unref, NULL);
55 /* Destroy the list */
56 g_slist_free (program->attached_shaders);
58 _cogl_gles2_clear_cache_for_program ((CoglHandle) program);
60 if (ctx->drv.gles2.settings.user_program == (CoglHandle) program)
62 ctx->drv.gles2.settings.user_program = COGL_INVALID_HANDLE;
63 ctx->drv.gles2.settings_dirty = TRUE;
66 for (i = 0; i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS; i++)
68 if (program->custom_uniform_names[i])
69 g_free (program->custom_uniform_names[i]);
70 if (program->custom_uniforms[i].count > 1)
71 g_free (program->custom_uniforms[i].v.array);
74 g_slice_free (CoglProgram, program);
78 cogl_create_program (void)
82 program = g_slice_new0 (CoglProgram);
84 return _cogl_program_handle_new (program);
88 cogl_program_attach_shader (CoglHandle program_handle,
89 CoglHandle shader_handle)
93 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
95 if (!cogl_is_program (program_handle) || !cogl_is_shader (shader_handle))
98 program = _cogl_program_pointer_from_handle (program_handle);
99 program->attached_shaders
100 = g_slist_prepend (program->attached_shaders,
101 cogl_handle_ref (shader_handle));
103 /* Whenever the shader changes we will need to relink the program
104 with the fixed functionality shaders so we should forget the
106 _cogl_gles2_clear_cache_for_program (program);
110 cogl_program_link (CoglHandle handle)
112 /* There's no point in linking the program here because it will have
113 to be relinked with a different fixed functionality shader
114 whenever the settings change */
118 cogl_program_use (CoglHandle handle)
120 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
122 g_return_if_fail (handle == COGL_INVALID_HANDLE ||
123 cogl_is_program (handle));
125 if (ctx->current_program == 0 && handle != 0)
126 ctx->legacy_state_set++;
127 else if (handle == 0 && ctx->current_program != 0)
128 ctx->legacy_state_set--;
130 if (handle != COGL_INVALID_HANDLE)
131 cogl_handle_ref (handle);
132 if (ctx->current_program != COGL_INVALID_HANDLE)
133 cogl_handle_unref (ctx->current_program);
134 ctx->current_program = handle;
138 cogl_program_get_uniform_location (CoglHandle handle,
139 const char *uniform_name)
142 CoglProgram *program;
144 if (!cogl_is_program (handle))
147 program = _cogl_program_pointer_from_handle (handle);
149 /* We can't just ask the GL program object for the uniform location
150 directly because it will change every time the program is linked
151 with a new fixed functionality shader. Instead we make our own
152 mapping of uniform numbers and cache the names */
153 for (i = 0; program->custom_uniform_names[i]
154 && i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS; i++)
155 if (!strcmp (program->custom_uniform_names[i], uniform_name))
158 if (i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS)
160 program->custom_uniform_names[i] = g_strdup (uniform_name);
164 /* We've run out of space for new uniform names so just pretend it
170 cogl_program_uniform_x (CoglHandle handle,
178 CoglProgram *program = handle;
180 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
182 g_return_if_fail (cogl_is_program (handle));
183 g_return_if_fail (program != NULL);
185 if (uniform_no >= 0 && uniform_no < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS
186 && size >= 1 && size <= 4 && count >= 1)
188 CoglBoxedValue *bv = program->custom_uniforms + uniform_no;
193 g_free (bv->v.array);
195 memcpy (bv->v.float_value, value, value_size);
201 if (bv->count != count || bv->size != size || bv->type != type)
203 g_free (bv->v.array);
204 bv->v.array = g_malloc (count * value_size);
208 bv->v.array = g_malloc (count * value_size);
210 memcpy (bv->v.array, value, count * value_size);
217 program->dirty_custom_uniforms |= 1 << uniform_no;
222 cogl_program_uniform_1f (int uniform_no,
225 cogl_program_uniform_float (uniform_no, 1, 1, &value);
229 cogl_program_set_uniform_1f (CoglHandle handle,
230 int uniform_location,
233 cogl_program_uniform_x (handle,
234 uniform_location, 1, 1, COGL_BOXED_FLOAT,
235 sizeof (float), &value);
239 cogl_program_uniform_1i (int uniform_no,
242 cogl_program_uniform_int (uniform_no, 1, 1, &value);
246 cogl_program_set_uniform_1i (CoglHandle handle,
247 int uniform_location,
250 cogl_program_uniform_x (handle,
251 uniform_location, 1, 1, COGL_BOXED_INT,
252 sizeof (int), &value);
256 cogl_program_uniform_float (int uniform_no,
259 const GLfloat *value)
261 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
262 cogl_program_uniform_x (ctx->current_program,
263 uniform_no, size, count, COGL_BOXED_FLOAT,
264 sizeof (float) * size, value);
268 cogl_program_set_uniform_float (CoglHandle handle,
269 int uniform_location,
274 cogl_program_uniform_x (handle,
275 uniform_location, n_components, count,
277 sizeof (float) * n_components, value);
281 cogl_program_uniform_int (int uniform_no,
286 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
287 cogl_program_uniform_x (ctx->current_program,
288 uniform_no, size, count, COGL_BOXED_INT,
289 sizeof (int) * size, value);
293 cogl_program_set_uniform_int (CoglHandle handle,
294 int uniform_location,
299 cogl_program_uniform_x (handle,
300 uniform_location, n_components, count,
302 sizeof (int) * n_components, value);
306 cogl_program_set_uniform_matrix (CoglHandle handle,
307 int uniform_location,
313 CoglProgram *program = handle;
316 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
318 g_return_if_fail (cogl_is_program (handle));
320 bv = program->custom_uniforms + uniform_location;
322 cogl_program_uniform_x (ctx->current_program,
323 uniform_location, dimensions, count,
325 sizeof (float) * dimensions * dimensions , value);
327 bv->transpose = transpose;
331 cogl_program_uniform_matrix (int uniform_no,
337 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
338 cogl_program_set_uniform_matrix (ctx->current_program,
339 uniform_no, size, count, transpose, value);
342 #else /* HAVE_COGL_GLES2 */
344 /* No support on regular OpenGL 1.1 */
347 cogl_create_program (void)
349 return COGL_INVALID_HANDLE;
353 cogl_is_program (CoglHandle handle)
359 cogl_program_ref (CoglHandle handle)
361 return COGL_INVALID_HANDLE;
365 cogl_program_unref (CoglHandle handle)
370 cogl_program_attach_shader (CoglHandle program_handle,
371 CoglHandle shader_handle)
376 cogl_program_link (CoglHandle program_handle)
381 cogl_program_use (CoglHandle program_handle)
386 cogl_program_get_uniform_location (CoglHandle program_handle,
387 const char *uniform_name)
393 cogl_program_uniform_1f (int uniform_no,
399 cogl_program_uniform_1i (int uniform_no,
405 cogl_program_uniform_float (int uniform_no,
408 const GLfloat *value)
413 cogl_program_uniform_int (int uniform_no,
421 cogl_program_uniform_matrix (int uniform_no,
425 const GLfloat *value)
430 #endif /* HAVE_COGL_GLES2 */
433 _cogl_program_get_language (CoglHandle handle)
435 return COGL_SHADER_LANGUAGE_GLSL;