cally: Do not use deprecated functions
[profile/ivi/clutter.git] / clutter / cogl / cogl / driver / gles / cogl-program.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2008,2009 Intel Corporation.
7  *
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.
12  *
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.
17  *
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/>.
20  *
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "cogl.h"
29
30 #include "cogl-internal.h"
31 #include "cogl-context.h"
32 #include "cogl-handle.h"
33
34 #ifdef HAVE_COGL_GLES2
35
36 #include <string.h>
37
38 #include "cogl-shader-private.h"
39 #include "cogl-program.h"
40
41 static void _cogl_program_free (CoglProgram *program);
42
43 COGL_HANDLE_DEFINE (Program, program);
44 COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (program);
45
46 static void
47 _cogl_program_free (CoglProgram *program)
48 {
49   int i;
50
51   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
52
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);
57
58   _cogl_gles2_clear_cache_for_program ((CoglHandle) program);
59
60   if (ctx->drv.gles2.settings.user_program == (CoglHandle) program)
61     {
62       ctx->drv.gles2.settings.user_program = COGL_INVALID_HANDLE;
63       ctx->drv.gles2.settings_dirty = TRUE;
64     }
65
66   for (i = 0; i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS; i++)
67     {
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);
72     }
73
74   g_slice_free (CoglProgram, program);
75 }
76
77 CoglHandle
78 cogl_create_program (void)
79 {
80   CoglProgram *program;
81
82   program = g_slice_new0 (CoglProgram);
83
84   return _cogl_program_handle_new (program);
85 }
86
87 void
88 cogl_program_attach_shader (CoglHandle program_handle,
89                             CoglHandle shader_handle)
90 {
91   CoglProgram *program;
92
93   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
94
95   if (!cogl_is_program (program_handle) || !cogl_is_shader (shader_handle))
96     return;
97
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));
102
103   /* Whenever the shader changes we will need to relink the program
104      with the fixed functionality shaders so we should forget the
105      cached programs */
106   _cogl_gles2_clear_cache_for_program (program);
107 }
108
109 void
110 cogl_program_link (CoglHandle handle)
111 {
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 */
115 }
116
117 void
118 cogl_program_use (CoglHandle handle)
119 {
120   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
121
122   g_return_if_fail (handle == COGL_INVALID_HANDLE ||
123                     cogl_is_program (handle));
124
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--;
129
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;
135 }
136
137 int
138 cogl_program_get_uniform_location (CoglHandle   handle,
139                                    const char *uniform_name)
140 {
141   int i;
142   CoglProgram *program;
143
144   if (!cogl_is_program (handle))
145     return -1;
146
147   program = _cogl_program_pointer_from_handle (handle);
148
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))
156       return i;
157
158   if (i < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS)
159     {
160       program->custom_uniform_names[i] = g_strdup (uniform_name);
161       return i;
162     }
163   else
164     /* We've run out of space for new uniform names so just pretend it
165        isn't there */
166     return -1;
167 }
168
169 static void
170 cogl_program_uniform_x (CoglHandle handle,
171                         int uniform_no,
172                         int size,
173                         int count,
174                         CoglBoxedType type,
175                         gsize value_size,
176                         gconstpointer value)
177 {
178   CoglProgram *program = handle;
179
180   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
181
182   g_return_if_fail (cogl_is_program (handle));
183   g_return_if_fail (program != NULL);
184
185   if (uniform_no >= 0 && uniform_no < COGL_PROGRAM_NUM_CUSTOM_UNIFORMS
186       && size >= 1 && size <= 4 && count >= 1)
187     {
188       CoglBoxedValue *bv = program->custom_uniforms + uniform_no;
189
190       if (count == 1)
191         {
192           if (bv->count > 1)
193             g_free (bv->v.array);
194
195           memcpy (bv->v.float_value, value, value_size);
196         }
197       else
198         {
199           if (bv->count > 1)
200             {
201               if (bv->count != count || bv->size != size || bv->type != type)
202                 {
203                   g_free (bv->v.array);
204                   bv->v.array = g_malloc (count * value_size);
205                 }
206             }
207           else
208             bv->v.array = g_malloc (count * value_size);
209
210           memcpy (bv->v.array, value, count * value_size);
211         }
212
213       bv->type = type;
214       bv->size = size;
215       bv->count = count;
216
217       program->dirty_custom_uniforms |= 1 << uniform_no;
218     }
219 }
220
221 void
222 cogl_program_uniform_1f (int uniform_no,
223                          float  value)
224 {
225   cogl_program_uniform_float (uniform_no, 1, 1, &value);
226 }
227
228 void
229 cogl_program_set_uniform_1f (CoglHandle handle,
230                              int uniform_location,
231                              float value)
232 {
233   cogl_program_uniform_x (handle,
234                           uniform_location, 1, 1, COGL_BOXED_FLOAT,
235                           sizeof (float), &value);
236 }
237
238 void
239 cogl_program_uniform_1i (int uniform_no,
240                          int    value)
241 {
242   cogl_program_uniform_int (uniform_no, 1, 1, &value);
243 }
244
245 void
246 cogl_program_set_uniform_1i (CoglHandle handle,
247                              int uniform_location,
248                              int value)
249 {
250   cogl_program_uniform_x (handle,
251                           uniform_location, 1, 1, COGL_BOXED_INT,
252                           sizeof (int), &value);
253 }
254
255 void
256 cogl_program_uniform_float (int  uniform_no,
257                             int     size,
258                             int     count,
259                             const GLfloat *value)
260 {
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);
265 }
266
267 void
268 cogl_program_set_uniform_float (CoglHandle handle,
269                                 int uniform_location,
270                                 int n_components,
271                                 int count,
272                                 const float *value)
273 {
274   cogl_program_uniform_x (handle,
275                           uniform_location, n_components, count,
276                           COGL_BOXED_FLOAT,
277                           sizeof (float) * n_components, value);
278 }
279
280 void
281 cogl_program_uniform_int (int  uniform_no,
282                           int   size,
283                           int   count,
284                           const GLint *value)
285 {
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);
290 }
291
292 void
293 cogl_program_set_uniform_int (CoglHandle handle,
294                               int uniform_location,
295                               int n_components,
296                               int count,
297                               const int *value)
298 {
299   cogl_program_uniform_x (handle,
300                           uniform_location, n_components, count,
301                           COGL_BOXED_INT,
302                           sizeof (int) * n_components, value);
303 }
304
305 void
306 cogl_program_set_uniform_matrix (CoglHandle handle,
307                                  int uniform_location,
308                                  int dimensions,
309                                  int count,
310                                  gboolean transpose,
311                                  const float *value)
312 {
313   CoglProgram *program = handle;
314   CoglBoxedValue *bv;
315
316   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
317
318   g_return_if_fail (cogl_is_program (handle));
319
320   bv = program->custom_uniforms + uniform_location;
321
322   cogl_program_uniform_x (ctx->current_program,
323                           uniform_location, dimensions, count,
324                           COGL_BOXED_MATRIX,
325                           sizeof (float) * dimensions * dimensions , value);
326
327   bv->transpose = transpose;
328 }
329
330 void
331 cogl_program_uniform_matrix (int   uniform_no,
332                              int      size,
333                              int      count,
334                              gboolean  transpose,
335                              const float  *value)
336 {
337   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
338   cogl_program_set_uniform_matrix (ctx->current_program,
339                                    uniform_no, size, count, transpose, value);
340 }
341
342 #else /* HAVE_COGL_GLES2 */
343
344 /* No support on regular OpenGL 1.1 */
345
346 CoglHandle
347 cogl_create_program (void)
348 {
349   return COGL_INVALID_HANDLE;
350 }
351
352 gboolean
353 cogl_is_program (CoglHandle handle)
354 {
355   return FALSE;
356 }
357
358 CoglHandle
359 cogl_program_ref (CoglHandle handle)
360 {
361   return COGL_INVALID_HANDLE;
362 }
363
364 void
365 cogl_program_unref (CoglHandle handle)
366 {
367 }
368
369 void
370 cogl_program_attach_shader (CoglHandle program_handle,
371                             CoglHandle shader_handle)
372 {
373 }
374
375 void
376 cogl_program_link (CoglHandle program_handle)
377 {
378 }
379
380 void
381 cogl_program_use (CoglHandle program_handle)
382 {
383 }
384
385 int
386 cogl_program_get_uniform_location (CoglHandle   program_handle,
387                                    const char *uniform_name)
388 {
389   return 0;
390 }
391
392 void
393 cogl_program_uniform_1f (int uniform_no,
394                          float  value)
395 {
396 }
397
398 void
399 cogl_program_uniform_1i (int uniform_no,
400                          int    value)
401 {
402 }
403
404 void
405 cogl_program_uniform_float (int  uniform_no,
406                             int     size,
407                             int     count,
408                             const GLfloat *value)
409 {
410 }
411
412 void
413 cogl_program_uniform_int (int  uniform_no,
414                           int     size,
415                           int     count,
416                           const int *value)
417 {
418 }
419
420 void
421 cogl_program_uniform_matrix (int   uniform_no,
422                              int      size,
423                              int      count,
424                              gboolean  transpose,
425                              const GLfloat  *value)
426 {
427 }
428
429
430 #endif /* HAVE_COGL_GLES2 */
431
432 CoglShaderLanguage
433 _cogl_program_get_language (CoglHandle handle)
434 {
435   return COGL_SHADER_LANGUAGE_GLSL;
436 }
437