~ubuntu-branches/ubuntu/vivid/clutter-1.0/vivid-proposed

« back to all changes in this revision

Viewing changes to clutter/cogl/gles/cogl-gles2-wrapper.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-07-18 17:21:49 UTC
  • mfrom: (1.2.1 upstream) (4.1.3 experimental)
  • Revision ID: james.westby@ubuntu.com-20100718172149-j6s9u4chocaoykme
Tags: 1.2.12-1
* New upstream release.
* debian/libclutter-1.0-0.symbols,
  debian/rules:
  - Add a symbols file.
* debian/rules,
  debian/source/format:
  - Switch to source format 3.0 (quilt).
* debian/control.in:
  - Standards-Version is 3.9.0, no changes needed.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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, write to the
20
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
 
 * Boston, MA 02111-1307, USA.
22
 
 */
23
 
 
24
 
#ifdef HAVE_CONFIG_H
25
 
#include "config.h"
26
 
#endif
27
 
 
28
 
#include <clutter/clutter-fixed.h>
29
 
#include <string.h>
30
 
#include <math.h>
31
 
 
32
 
/* We don't want to get the remaps from the gl* functions to the
33
 
   cogl_wrap_gl* functions in this file because we need to be able to
34
 
   call the base version */
35
 
#define COGL_GLES2_WRAPPER_NO_REMAP 1
36
 
 
37
 
#include "cogl.h"
38
 
#include "cogl-gles2-wrapper.h"
39
 
#include "cogl-fixed-vertex-shader.h"
40
 
#include "cogl-fixed-fragment-shader.h"
41
 
#include "cogl-context.h"
42
 
#include "cogl-shader-private.h"
43
 
#include "cogl-program.h"
44
 
#include "cogl-internal.h"
45
 
 
46
 
#define _COGL_GET_GLES2_WRAPPER(wvar, retval)                   \
47
 
  CoglGles2Wrapper *wvar;                                       \
48
 
  {                                                             \
49
 
    CoglContext *__ctxvar = _cogl_context_get_default ();       \
50
 
    if (__ctxvar == NULL) return retval;                        \
51
 
    wvar = &__ctxvar->gles2;                                    \
52
 
  }
53
 
 
54
 
#define _COGL_GLES2_CHANGE_SETTING(w, var, val) \
55
 
  do                                            \
56
 
    if ((w)->settings.var != (val))             \
57
 
      {                                         \
58
 
        (w)->settings.var = (val);              \
59
 
        (w)->settings_dirty = TRUE;             \
60
 
      }                                         \
61
 
  while (0)
62
 
 
63
 
#define _COGL_GLES2_CHANGE_UNIFORM(w, flag, var, val)           \
64
 
  do                                                            \
65
 
    if ((w)->var != (val))                                      \
66
 
      {                                                         \
67
 
        (w)->var = (val);                                       \
68
 
        (w)->dirty_uniforms |= COGL_GLES2_DIRTY_ ## flag;       \
69
 
      }                                                         \
70
 
  while (0)
71
 
 
72
 
#define COGL_GLES2_WRAPPER_VERTEX_ATTRIB    0
73
 
#define COGL_GLES2_WRAPPER_COLOR_ATTRIB     1
74
 
#define COGL_GLES2_WRAPPER_NORMAL_ATTRIB    2
75
 
 
76
 
 
77
 
static GLuint
78
 
cogl_gles2_wrapper_create_shader (GLenum type, const char *source)
79
 
{
80
 
  GLuint shader;
81
 
  GLint source_len = strlen (source);
82
 
  GLint status;
83
 
 
84
 
  shader = glCreateShader (type);
85
 
  glShaderSource (shader, 1, &source, &source_len);
86
 
  glCompileShader (shader);
87
 
 
88
 
  glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
89
 
 
90
 
  if (!status)
91
 
    {
92
 
      char shader_log[1024];
93
 
      GLint len;
94
 
 
95
 
      glGetShaderInfoLog (shader, sizeof (shader_log) - 1, &len, shader_log);
96
 
      shader_log[len] = '\0';
97
 
 
98
 
      g_critical ("%s", shader_log);
99
 
 
100
 
      glDeleteShader (shader);
101
 
 
102
 
      return 0;
103
 
    }
104
 
 
105
 
  return shader;
106
 
}
107
 
 
108
 
static void
109
 
initialize_texture_units (CoglGles2Wrapper *w)
110
 
{
111
 
  /* We save the active texture unit since we may need to temporarily
112
 
   * change this to initialise each new texture unit and we want to
113
 
   * restore the active unit afterwards */
114
 
  int initial_active_unit = w->active_texture_unit;
115
 
  GLint prev_mode;
116
 
  int i;
117
 
 
118
 
  /* We will need to set the matrix mode to GL_TEXTURE to
119
 
   * initialise any new texture units, so we save the current
120
 
   * mode for restoring afterwards */
121
 
  GE( cogl_wrap_glGetIntegerv (CGL_MATRIX_MODE, &prev_mode));
122
 
 
123
 
  for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
124
 
    {
125
 
      CoglGles2WrapperTextureUnit *new_unit;
126
 
 
127
 
      new_unit = w->texture_units + i;
128
 
      memset (new_unit, 0, sizeof (CoglGles2WrapperTextureUnit));
129
 
 
130
 
      w->active_texture_unit = i;
131
 
      GE( cogl_wrap_glMatrixMode (GL_TEXTURE));
132
 
      GE( cogl_wrap_glLoadIdentity ());
133
 
    }
134
 
 
135
 
  GE( cogl_wrap_glMatrixMode ((GLenum) prev_mode));
136
 
 
137
 
  w->settings.texture_units = 0;
138
 
 
139
 
  w->active_texture_unit = initial_active_unit;
140
 
}
141
 
 
142
 
void
143
 
cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
144
 
{
145
 
  GLfloat default_fog_color[4] = { 0, 0, 0, 0 };
146
 
 
147
 
  memset (wrapper, 0, sizeof (CoglGles2Wrapper));
148
 
 
149
 
  /* Initialize the stacks */
150
 
  cogl_wrap_glMatrixMode (GL_PROJECTION);
151
 
  cogl_wrap_glLoadIdentity ();
152
 
  cogl_wrap_glMatrixMode (GL_MODELVIEW);
153
 
  cogl_wrap_glLoadIdentity ();
154
 
 
155
 
  /* The gl*ActiveTexture wrappers will initialise the texture
156
 
   * stack for the texture unit when it's first activated */
157
 
  cogl_wrap_glActiveTexture (GL_TEXTURE0);
158
 
  cogl_wrap_glClientActiveTexture (GL_TEXTURE0);
159
 
 
160
 
  /* Initialize the fogging options */
161
 
  cogl_wrap_glDisable (GL_FOG);
162
 
  cogl_wrap_glFogf (GL_FOG_MODE, GL_LINEAR);
163
 
  cogl_wrap_glFogf (GL_FOG_DENSITY, 1.0);
164
 
  cogl_wrap_glFogf (GL_FOG_START, 0);
165
 
  cogl_wrap_glFogf (GL_FOG_END, 1);
166
 
  cogl_wrap_glFogfv (GL_FOG_COLOR, default_fog_color);
167
 
 
168
 
  /* Initialize alpha testing */
169
 
  cogl_wrap_glDisable (GL_ALPHA_TEST);
170
 
  cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f);
171
 
 
172
 
  initialize_texture_units (wrapper);
173
 
}
174
 
 
175
 
static gboolean
176
 
cogl_gles2_settings_equal (const CoglGles2WrapperSettings *a,
177
 
                           const CoglGles2WrapperSettings *b,
178
 
                           gboolean vertex_tests,
179
 
                           gboolean fragment_tests)
180
 
{
181
 
  if (a->texture_units != b->texture_units)
182
 
    return FALSE;
183
 
 
184
 
  if (fragment_tests)
185
 
    {
186
 
      if (a->alpha_test_enabled != b->alpha_test_enabled)
187
 
        return FALSE;
188
 
      if (a->alpha_test_enabled && a->alpha_test_func != b->alpha_test_func)
189
 
        return FALSE;
190
 
    }
191
 
 
192
 
  if (a->fog_enabled != b->fog_enabled)
193
 
    return FALSE;
194
 
 
195
 
  if (vertex_tests && a->fog_enabled && a->fog_mode != b->fog_mode)
196
 
    return FALSE;
197
 
 
198
 
  return TRUE;
199
 
}
200
 
 
201
 
static CoglGles2WrapperShader *
202
 
cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
203
 
{
204
 
  GString *shader_source;
205
 
  GLuint shader_obj;
206
 
  CoglGles2WrapperShader *shader;
207
 
  GSList *node;
208
 
  int i;
209
 
  int n_texture_units = 0;
210
 
 
211
 
  _COGL_GET_GLES2_WRAPPER (w, NULL);
212
 
 
213
 
  /* Check if we already have a vertex shader for these settings */
214
 
  for (node = w->compiled_vertex_shaders; node; node = node->next)
215
 
    if (cogl_gles2_settings_equal (settings,
216
 
                                   &((CoglGles2WrapperShader *)
217
 
                                     node->data)->settings,
218
 
                                   TRUE, FALSE))
219
 
      return (CoglGles2WrapperShader *) node->data;
220
 
 
221
 
  /* Otherwise create a new shader */
222
 
  shader_source = g_string_new (cogl_fixed_vertex_shader_per_vertex_attribs);
223
 
 
224
 
  for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
225
 
    if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
226
 
      g_string_append_printf (shader_source,
227
 
                              "attribute vec4 multi_tex_coord_attrib%d;\n",
228
 
                              i);
229
 
 
230
 
  /* Find the biggest enabled texture unit index */
231
 
  for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
232
 
    if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
233
 
      n_texture_units = i + 1;
234
 
 
235
 
  g_string_append (shader_source, cogl_fixed_vertex_shader_transform_matrices);
236
 
  g_string_append (shader_source, cogl_fixed_vertex_shader_output_variables);
237
 
 
238
 
  if (n_texture_units > 0)
239
 
    {
240
 
      g_string_append_printf (shader_source,
241
 
                              "uniform mat4           texture_matrix[%d];\n",
242
 
                              n_texture_units);
243
 
 
244
 
      g_string_append_printf (shader_source,
245
 
                              "varying vec2       tex_coord[%d];",
246
 
                              n_texture_units);
247
 
    }
248
 
 
249
 
  g_string_append (shader_source, cogl_fixed_vertex_shader_fogging_options);
250
 
  g_string_append (shader_source, cogl_fixed_vertex_shader_main_start);
251
 
 
252
 
  for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
253
 
    if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
254
 
      {
255
 
        g_string_append_printf (shader_source,
256
 
                                "transformed_tex_coord = "
257
 
                                "texture_matrix[%d] "
258
 
                                " * multi_tex_coord_attrib%d;\n",
259
 
                                i, i);
260
 
        g_string_append_printf (shader_source,
261
 
                                "tex_coord[%d] = transformed_tex_coord.st "
262
 
                                " / transformed_tex_coord.q;\n",
263
 
                                i);
264
 
      }
265
 
 
266
 
  g_string_append (shader_source, cogl_fixed_vertex_shader_frag_color_start);
267
 
 
268
 
  if (settings->fog_enabled)
269
 
    {
270
 
      g_string_append (shader_source, cogl_fixed_vertex_shader_fog_start);
271
 
 
272
 
      switch (settings->fog_mode)
273
 
        {
274
 
        case GL_EXP:
275
 
          g_string_append (shader_source, cogl_fixed_vertex_shader_fog_exp);
276
 
          break;
277
 
 
278
 
        case GL_EXP2:
279
 
          g_string_append (shader_source, cogl_fixed_vertex_shader_fog_exp2);
280
 
          break;
281
 
 
282
 
        default:
283
 
          g_string_append (shader_source, cogl_fixed_vertex_shader_fog_linear);
284
 
          break;
285
 
        }
286
 
 
287
 
      g_string_append (shader_source, cogl_fixed_vertex_shader_fog_end);
288
 
    }
289
 
 
290
 
  g_string_append (shader_source, cogl_fixed_vertex_shader_end);
291
 
 
292
 
  shader_obj = cogl_gles2_wrapper_create_shader (GL_VERTEX_SHADER,
293
 
                                                 shader_source->str);
294
 
 
295
 
  g_string_free (shader_source, TRUE);
296
 
 
297
 
  if (shader_obj == 0)
298
 
    return NULL;
299
 
 
300
 
  shader = g_slice_new (CoglGles2WrapperShader);
301
 
  shader->shader = shader_obj;
302
 
  shader->settings = *settings;
303
 
 
304
 
  w->compiled_vertex_shaders = g_slist_prepend (w->compiled_vertex_shaders,
305
 
                                                shader);
306
 
 
307
 
  return shader;
308
 
}
309
 
 
310
 
static CoglGles2WrapperShader *
311
 
cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
312
 
{
313
 
  GString *shader_source;
314
 
  GLuint shader_obj;
315
 
  CoglGles2WrapperShader *shader;
316
 
  GSList *node;
317
 
  int i;
318
 
  int n_texture_units = 0;
319
 
 
320
 
  _COGL_GET_GLES2_WRAPPER (w, NULL);
321
 
 
322
 
  /* Check if we already have a fragment shader for these settings */
323
 
  for (node = w->compiled_fragment_shaders; node; node = node->next)
324
 
    if (cogl_gles2_settings_equal (settings,
325
 
                                   &((CoglGles2WrapperShader *)
326
 
                                     node->data)->settings,
327
 
                                   FALSE, TRUE))
328
 
      return (CoglGles2WrapperShader *) node->data;
329
 
 
330
 
  /* Otherwise create a new shader */
331
 
  shader_source = g_string_new (cogl_fixed_fragment_shader_variables_start);
332
 
 
333
 
  /* Find the biggest enabled texture unit index */
334
 
  for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
335
 
    if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
336
 
      n_texture_units = i + 1;
337
 
 
338
 
  g_string_append (shader_source, cogl_fixed_fragment_shader_inputs);
339
 
 
340
 
  if (n_texture_units > 0)
341
 
    {
342
 
      g_string_append_printf (shader_source,
343
 
                              "varying vec2       tex_coord[%d];\n",
344
 
                              n_texture_units);
345
 
 
346
 
      g_string_append (shader_source, cogl_fixed_fragment_shader_texturing_options);
347
 
      g_string_append_printf (shader_source,
348
 
                              "uniform sampler2D  texture_unit[%d];\n",
349
 
                              n_texture_units);
350
 
    }
351
 
 
352
 
  g_string_append (shader_source, cogl_fixed_fragment_shader_fogging_options);
353
 
 
354
 
  g_string_append (shader_source, cogl_fixed_fragment_shader_main_declare);
355
 
 
356
 
  g_string_append (shader_source, cogl_fixed_fragment_shader_main_start);
357
 
 
358
 
  /* This pointless extra variable is needed to work around an
359
 
     apparent bug in the PowerVR drivers. Without it the alpha
360
 
     blending seems to stop working */
361
 
  g_string_append (shader_source,
362
 
                   "vec4 frag_color_copy = frag_color;\n");
363
 
  g_string_append (shader_source, "gl_FragColor = frag_color;\n");
364
 
 
365
 
  for (i = 0; i < n_texture_units; i++)
366
 
    if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
367
 
      {
368
 
        if (COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY (settings->texture_units, i))
369
 
          /* If the texture only has an alpha channel (eg, with the textures
370
 
             from the pango renderer) then the RGB components will be
371
 
             black. We want to use the RGB from the current color in that
372
 
             case */
373
 
          g_string_append_printf (shader_source,
374
 
                                  "gl_FragColor.a *= "
375
 
                                  "texture2D (texture_unit[%d], "
376
 
                                  "tex_coord[%d]).a;\n",
377
 
                                  i, i);
378
 
        else
379
 
          g_string_append_printf (shader_source,
380
 
                                  "gl_FragColor *= "
381
 
                                  "texture2D (texture_unit[%d], "
382
 
                                  "tex_coord[%d]);\n",
383
 
                                  i, i);
384
 
      }
385
 
 
386
 
  if (settings->fog_enabled)
387
 
    g_string_append (shader_source, cogl_fixed_fragment_shader_fog);
388
 
 
389
 
  if (settings->alpha_test_enabled)
390
 
    switch (settings->alpha_test_func)
391
 
      {
392
 
      case GL_NEVER:
393
 
        g_string_append (shader_source,
394
 
                         cogl_fixed_fragment_shader_alpha_never);
395
 
        break;
396
 
      case GL_LESS:
397
 
        g_string_append (shader_source,
398
 
                         cogl_fixed_fragment_shader_alpha_less);
399
 
        break;
400
 
      case GL_EQUAL:
401
 
        g_string_append (shader_source,
402
 
                         cogl_fixed_fragment_shader_alpha_equal);
403
 
        break;
404
 
      case GL_LEQUAL:
405
 
        g_string_append (shader_source,
406
 
                         cogl_fixed_fragment_shader_alpha_lequal);
407
 
        break;
408
 
      case GL_GREATER:
409
 
        g_string_append (shader_source,
410
 
                         cogl_fixed_fragment_shader_alpha_greater);
411
 
        break;
412
 
      case GL_NOTEQUAL:
413
 
        g_string_append (shader_source,
414
 
                         cogl_fixed_fragment_shader_alpha_notequal);
415
 
        break;
416
 
      case GL_GEQUAL:
417
 
        g_string_append (shader_source,
418
 
                         cogl_fixed_fragment_shader_alpha_gequal);
419
 
      }
420
 
 
421
 
  g_string_append (shader_source, cogl_fixed_fragment_shader_end);
422
 
 
423
 
  shader_obj = cogl_gles2_wrapper_create_shader (GL_FRAGMENT_SHADER,
424
 
                                                 shader_source->str);
425
 
 
426
 
  g_string_free (shader_source, TRUE);
427
 
 
428
 
  if (shader_obj == 0)
429
 
    return NULL;
430
 
 
431
 
  shader = g_slice_new (CoglGles2WrapperShader);
432
 
  shader->shader = shader_obj;
433
 
  shader->settings = *settings;
434
 
 
435
 
  w->compiled_fragment_shaders = g_slist_prepend (w->compiled_fragment_shaders,
436
 
                                                  shader);
437
 
 
438
 
  return shader;
439
 
}
440
 
 
441
 
static void
442
 
cogl_gles2_wrapper_get_locations (GLuint program,
443
 
                                  CoglGles2WrapperSettings *settings,
444
 
                                  CoglGles2WrapperUniforms *uniforms,
445
 
                                  CoglGles2WrapperAttributes *attribs)
446
 
{
447
 
  int i;
448
 
 
449
 
  uniforms->mvp_matrix_uniform
450
 
    = glGetUniformLocation (program, "mvp_matrix");
451
 
  uniforms->modelview_matrix_uniform
452
 
    = glGetUniformLocation (program, "modelview_matrix");
453
 
 
454
 
  for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
455
 
    if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
456
 
      {
457
 
        char *matrix_var_name = g_strdup_printf ("texture_matrix[%d]", i);
458
 
        char *sampler_var_name = g_strdup_printf ("texture_unit[%d]", i);
459
 
        char *tex_coord_var_name =
460
 
          g_strdup_printf ("multi_tex_coord_attrib%d", i);
461
 
 
462
 
        uniforms->texture_matrix_uniforms[i]
463
 
          = glGetUniformLocation (program, matrix_var_name);
464
 
        uniforms->texture_sampler_uniforms[i]
465
 
          = glGetUniformLocation (program, sampler_var_name);
466
 
        attribs->multi_texture_coords[i]
467
 
          = glGetAttribLocation (program, tex_coord_var_name);
468
 
 
469
 
        g_free (tex_coord_var_name);
470
 
        g_free (sampler_var_name);
471
 
        g_free (matrix_var_name);
472
 
      }
473
 
    else
474
 
      {
475
 
        uniforms->texture_matrix_uniforms[i] = -1;
476
 
        uniforms->texture_sampler_uniforms[i] = -1;
477
 
        attribs->multi_texture_coords[i] = -1;
478
 
      }
479
 
 
480
 
  uniforms->fog_density_uniform
481
 
    = glGetUniformLocation (program, "fog_density");
482
 
  uniforms->fog_start_uniform
483
 
    = glGetUniformLocation (program, "fog_start");
484
 
  uniforms->fog_end_uniform
485
 
    = glGetUniformLocation (program, "fog_end");
486
 
  uniforms->fog_color_uniform
487
 
    = glGetUniformLocation (program, "fog_color");
488
 
 
489
 
  uniforms->alpha_test_ref_uniform
490
 
    = glGetUniformLocation (program, "alpha_test_ref");
491
 
}
492
 
 
493
 
static void
494
 
cogl_gles2_wrapper_bind_attributes (GLuint program)
495
 
{
496
 
  glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB,
497
 
                        "vertex_attrib");
498
 
  glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB,
499
 
                        "color_attrib");
500
 
  glBindAttribLocation (program, COGL_GLES2_WRAPPER_NORMAL_ATTRIB,
501
 
                        "normal_attrib");
502
 
}
503
 
 
504
 
static CoglGles2WrapperProgram *
505
 
cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
506
 
{
507
 
  GSList *node;
508
 
  CoglGles2WrapperProgram *program;
509
 
  CoglGles2WrapperShader *vertex_shader, *fragment_shader;
510
 
  GLint status;
511
 
  gboolean custom_vertex_shader = FALSE, custom_fragment_shader = FALSE;
512
 
  CoglProgram *user_program = NULL;
513
 
  int i;
514
 
 
515
 
  _COGL_GET_GLES2_WRAPPER (w, NULL);
516
 
 
517
 
  /* Check if we've already got a program for these settings */
518
 
  for (node = w->compiled_programs; node; node = node->next)
519
 
    {
520
 
      program = (CoglGles2WrapperProgram *) node->data;
521
 
 
522
 
      if (cogl_gles2_settings_equal (settings, &program->settings, TRUE, TRUE)
523
 
          && program->settings.user_program == settings->user_program)
524
 
        return (CoglGles2WrapperProgram *) node->data;
525
 
    }
526
 
 
527
 
  /* Otherwise create a new program */
528
 
 
529
 
  /* Check whether the currently used custom program has vertex and
530
 
     fragment shaders */
531
 
  if (w->settings.user_program != COGL_INVALID_HANDLE)
532
 
    {
533
 
      user_program
534
 
        = _cogl_program_pointer_from_handle (w->settings.user_program);
535
 
 
536
 
      for (node = user_program->attached_shaders; node; node = node->next)
537
 
        {
538
 
          CoglShader *shader
539
 
            = _cogl_shader_pointer_from_handle ((CoglHandle) node->data);
540
 
 
541
 
          if (shader->type == COGL_SHADER_TYPE_VERTEX)
542
 
            custom_vertex_shader = TRUE;
543
 
          else if (shader->type == COGL_SHADER_TYPE_FRAGMENT)
544
 
            custom_fragment_shader = TRUE;
545
 
        }
546
 
    }
547
 
 
548
 
  /* Get or create the fixed functionality shaders for these settings
549
 
     if there is no custom replacement */
550
 
  if (!custom_vertex_shader)
551
 
    {
552
 
      vertex_shader = cogl_gles2_get_vertex_shader (settings);
553
 
      if (vertex_shader == NULL)
554
 
        return NULL;
555
 
    }
556
 
  if (!custom_fragment_shader)
557
 
    {
558
 
      fragment_shader = cogl_gles2_get_fragment_shader (settings);
559
 
      if (fragment_shader == NULL)
560
 
        return NULL;
561
 
    }
562
 
 
563
 
  program = g_slice_new (CoglGles2WrapperProgram);
564
 
 
565
 
  program->program = glCreateProgram ();
566
 
  if (!custom_vertex_shader)
567
 
    glAttachShader (program->program, vertex_shader->shader);
568
 
  if (!custom_fragment_shader)
569
 
    glAttachShader (program->program, fragment_shader->shader);
570
 
  if (user_program)
571
 
    for (node = user_program->attached_shaders; node; node = node->next)
572
 
      {
573
 
        CoglShader *shader
574
 
          = _cogl_shader_pointer_from_handle ((CoglHandle) node->data);
575
 
        glAttachShader (program->program, shader->gl_handle);
576
 
      }
577
 
  cogl_gles2_wrapper_bind_attributes (program->program);
578
 
  glLinkProgram (program->program);
579
 
 
580
 
  glGetProgramiv (program->program, GL_LINK_STATUS, &status);
581
 
 
582
 
  if (!status)
583
 
    {
584
 
      char shader_log[1024];
585
 
      GLint len;
586
 
 
587
 
      glGetProgramInfoLog (program->program, sizeof (shader_log) - 1, &len, shader_log);
588
 
      shader_log[len] = '\0';
589
 
 
590
 
      g_critical ("%s", shader_log);
591
 
 
592
 
      glDeleteProgram (program->program);
593
 
      g_slice_free (CoglGles2WrapperProgram, program);
594
 
 
595
 
      return NULL;
596
 
    }
597
 
 
598
 
  program->settings = *settings;
599
 
 
600
 
  cogl_gles2_wrapper_get_locations (program->program,
601
 
                                    &program->settings,
602
 
                                    &program->uniforms,
603
 
                                    &program->attributes);
604
 
 
605
 
  /* We haven't tried to get a location for any of the custom uniforms
606
 
     yet */
607
 
  for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
608
 
    program->custom_uniforms[i] = COGL_GLES2_UNBOUND_CUSTOM_UNIFORM;
609
 
 
610
 
  w->compiled_programs = g_slist_append (w->compiled_programs, program);
611
 
 
612
 
  return program;
613
 
}
614
 
 
615
 
void
616
 
cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
617
 
{
618
 
  GSList *node, *next;
619
 
  int i;
620
 
 
621
 
  for (node = wrapper->compiled_programs; node; node = next)
622
 
    {
623
 
      next = node->next;
624
 
      glDeleteProgram (((CoglGles2WrapperProgram *) node->data)->program);
625
 
      g_slist_free1 (node);
626
 
    }
627
 
  wrapper->compiled_programs = NULL;
628
 
 
629
 
  for (node = wrapper->compiled_vertex_shaders; node; node = next)
630
 
    {
631
 
      next = node->next;
632
 
      glDeleteShader (((CoglGles2WrapperShader *) node->data)->shader);
633
 
      g_slist_free1 (node);
634
 
    }
635
 
  wrapper->compiled_vertex_shaders = NULL;
636
 
 
637
 
  for (node = wrapper->compiled_fragment_shaders; node; node = next)
638
 
    {
639
 
      next = node->next;
640
 
      glDeleteShader (((CoglGles2WrapperShader *) node->data)->shader);
641
 
      g_slist_free1 (node);
642
 
    }
643
 
  wrapper->compiled_fragment_shaders = NULL;
644
 
 
645
 
  for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
646
 
    if (wrapper->custom_uniforms[i].count > 1)
647
 
      g_free (wrapper->custom_uniforms[i].v.array);
648
 
}
649
 
 
650
 
static void
651
 
cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num)
652
 
{
653
 
  CoglGles2WrapperTextureUnit *texture_unit;
654
 
 
655
 
  switch (matrix_num)
656
 
    {
657
 
    default:
658
 
    case GL_MODELVIEW:
659
 
      wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_MVP_MATRIX
660
 
        | COGL_GLES2_DIRTY_MODELVIEW_MATRIX;
661
 
      break;
662
 
 
663
 
    case GL_PROJECTION:
664
 
      wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_MVP_MATRIX;
665
 
      break;
666
 
 
667
 
    case GL_TEXTURE:
668
 
      wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_TEXTURE_MATRICES;
669
 
      texture_unit = wrapper->texture_units + wrapper->active_texture_unit;
670
 
      texture_unit->dirty_matrix = 1;
671
 
      break;
672
 
    }
673
 
}
674
 
 
675
 
void
676
 
cogl_wrap_glPushMatrix ()
677
 
{
678
 
  const float *src;
679
 
  float *dst;
680
 
 
681
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
682
 
 
683
 
  /* Get a pointer to the old and new matrix position and increment
684
 
     the stack pointer */
685
 
  switch (w->matrix_mode)
686
 
    {
687
 
    default:
688
 
    case GL_MODELVIEW:
689
 
      src = w->modelview_stack + w->modelview_stack_pos * 16;
690
 
      w->modelview_stack_pos = (w->modelview_stack_pos + 1)
691
 
        & (COGL_GLES2_MODELVIEW_STACK_SIZE - 1);
692
 
      dst = w->modelview_stack + w->modelview_stack_pos * 16;
693
 
      break;
694
 
 
695
 
    case GL_PROJECTION:
696
 
      src = w->projection_stack + w->projection_stack_pos * 16;
697
 
      w->projection_stack_pos = (w->projection_stack_pos + 1)
698
 
        & (COGL_GLES2_PROJECTION_STACK_SIZE - 1);
699
 
      dst = w->projection_stack + w->projection_stack_pos * 16;
700
 
      break;
701
 
 
702
 
    case GL_TEXTURE:
703
 
      {
704
 
        CoglGles2WrapperTextureUnit *texture_unit;
705
 
        texture_unit = w->texture_units + w->active_texture_unit;
706
 
        src = texture_unit->texture_stack
707
 
              + texture_unit->texture_stack_pos * 16;
708
 
        texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos + 1)
709
 
          & (COGL_GLES2_TEXTURE_STACK_SIZE - 1);
710
 
        dst = texture_unit->texture_stack
711
 
              + texture_unit->texture_stack_pos * 16;
712
 
        break;
713
 
      }
714
 
    }
715
 
 
716
 
  /* Copy the old matrix to the new position */
717
 
  memcpy (dst, src, sizeof (float) * 16);
718
 
}
719
 
 
720
 
void
721
 
cogl_wrap_glPopMatrix ()
722
 
{
723
 
  CoglGles2WrapperTextureUnit *texture_unit;
724
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
725
 
 
726
 
  /* Decrement the stack pointer */
727
 
  switch (w->matrix_mode)
728
 
    {
729
 
    default:
730
 
    case GL_MODELVIEW:
731
 
      w->modelview_stack_pos = (w->modelview_stack_pos - 1)
732
 
        & (COGL_GLES2_MODELVIEW_STACK_SIZE - 1);
733
 
      break;
734
 
 
735
 
    case GL_PROJECTION:
736
 
      w->projection_stack_pos = (w->projection_stack_pos - 1)
737
 
        & (COGL_GLES2_PROJECTION_STACK_SIZE - 1);
738
 
      break;
739
 
 
740
 
    case GL_TEXTURE:
741
 
      texture_unit = w->texture_units + w->active_texture_unit;
742
 
      texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos - 1)
743
 
        & (COGL_GLES2_TEXTURE_STACK_SIZE - 1);
744
 
      break;
745
 
    }
746
 
 
747
 
  /* Update the matrix in the program object */
748
 
  cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
749
 
}
750
 
 
751
 
void
752
 
cogl_wrap_glMatrixMode (GLenum mode)
753
 
{
754
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
755
 
 
756
 
  w->matrix_mode = mode;
757
 
}
758
 
 
759
 
static float *
760
 
cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper)
761
 
{
762
 
  CoglGles2WrapperTextureUnit *texture_unit;
763
 
 
764
 
  switch (wrapper->matrix_mode)
765
 
    {
766
 
    default:
767
 
    case GL_MODELVIEW:
768
 
      return wrapper->modelview_stack + wrapper->modelview_stack_pos * 16;
769
 
 
770
 
    case GL_PROJECTION:
771
 
      return wrapper->projection_stack + wrapper->projection_stack_pos * 16;
772
 
 
773
 
    case GL_TEXTURE:
774
 
      texture_unit = wrapper->texture_units + wrapper->active_texture_unit;
775
 
      return texture_unit->texture_stack
776
 
        + texture_unit->texture_stack_pos * 16;
777
 
    }
778
 
}
779
 
 
780
 
void
781
 
cogl_wrap_glLoadIdentity ()
782
 
{
783
 
  float *matrix;
784
 
 
785
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
786
 
 
787
 
  matrix = cogl_gles2_get_matrix_stack_top (w);
788
 
  memset (matrix, 0, sizeof (float) * 16);
789
 
  matrix[0] = 1.0f;
790
 
  matrix[5] = 1.0f;
791
 
  matrix[10] = 1.0f;
792
 
  matrix[15] = 1.0f;
793
 
 
794
 
  cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
795
 
}
796
 
 
797
 
static void
798
 
cogl_gles2_wrapper_mult_matrix (float *dst, const float *a, const float *b)
799
 
{
800
 
  int i, j, k;
801
 
 
802
 
  for (i = 0; i < 4; i++)
803
 
    for (j = 0; j < 4; j++)
804
 
      {
805
 
        float sum = 0.0f;
806
 
        for (k = 0; k < 4; k++)
807
 
          sum += a[k * 4 + j] * b[i * 4 + k];
808
 
        dst[i * 4 + j] = sum;
809
 
      }
810
 
}
811
 
 
812
 
static void
813
 
cogl_wrap_glMultMatrix (const float *m)
814
 
{
815
 
  float new_matrix[16];
816
 
  float *old_matrix;
817
 
 
818
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
819
 
 
820
 
  old_matrix = cogl_gles2_get_matrix_stack_top (w);
821
 
 
822
 
  cogl_gles2_wrapper_mult_matrix (new_matrix, old_matrix, m);
823
 
 
824
 
  memcpy (old_matrix, new_matrix, sizeof (float) * 16);
825
 
 
826
 
  cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
827
 
}
828
 
 
829
 
void
830
 
cogl_wrap_glMultMatrixf (const GLfloat *m)
831
 
{
832
 
  cogl_wrap_glMultMatrix (m);
833
 
}
834
 
 
835
 
void
836
 
cogl_wrap_glLoadMatrixf (const GLfloat *m)
837
 
{
838
 
  float *old_matrix;
839
 
 
840
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
841
 
 
842
 
  old_matrix = cogl_gles2_get_matrix_stack_top (w);
843
 
 
844
 
  memcpy (old_matrix, m, sizeof (float) * 16);
845
 
 
846
 
  cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
847
 
}
848
 
 
849
 
void
850
 
cogl_wrap_glFrustumf (GLfloat left, GLfloat right,
851
 
                      GLfloat bottom, GLfloat top,
852
 
                      GLfloat z_near, GLfloat z_far)
853
 
{
854
 
  float matrix[16];
855
 
  float two_near =  (2 * z_near);
856
 
 
857
 
  memset (matrix, 0, sizeof (matrix));
858
 
 
859
 
  matrix[0] = two_near /  (right - left);
860
 
  matrix[5] = two_near /  (top - bottom);
861
 
  matrix[8] =  (right + left)
862
 
    /  (right - left);
863
 
  matrix[9] =  (top + bottom)
864
 
    /  (top - bottom);
865
 
  matrix[10] = - (z_far + z_near)
866
 
    /  (z_far - z_near);
867
 
  matrix[11] = -1.0f;
868
 
  matrix[14] = -two_near *  (z_far)
869
 
    /  (z_far - z_near);
870
 
 
871
 
  cogl_wrap_glMultMatrix (matrix);
872
 
}
873
 
 
874
 
void
875
 
cogl_wrap_glScalef (GLfloat x, GLfloat y, GLfloat z)
876
 
{
877
 
  float matrix[16];
878
 
 
879
 
  memset (matrix, 0, sizeof (matrix));
880
 
  matrix[0] =  (x);
881
 
  matrix[5] =  (y);
882
 
  matrix[10] =  (z);
883
 
  matrix[15] = 1.0f;
884
 
 
885
 
  cogl_wrap_glMultMatrix (matrix);
886
 
}
887
 
 
888
 
void
889
 
cogl_wrap_glTranslatef (GLfloat x, GLfloat y, GLfloat z)
890
 
{
891
 
  float matrix[16];
892
 
 
893
 
  memset (matrix, 0, sizeof (matrix));
894
 
  matrix[0] = 1.0f;
895
 
  matrix[5] = 1.0f;
896
 
  matrix[10] = 1.0f;
897
 
  matrix[12] =  (x);
898
 
  matrix[13] =  (y);
899
 
  matrix[14] =  (z);
900
 
  matrix[15] = 1.0f;
901
 
 
902
 
  cogl_wrap_glMultMatrix (matrix);
903
 
}
904
 
 
905
 
void
906
 
cogl_wrap_glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
907
 
{
908
 
  float matrix[16];
909
 
  float xf =  (x);
910
 
  float yf =  (y);
911
 
  float zf =  (z);
912
 
  float anglef =  (angle) * G_PI / 180.0f;
913
 
  float c = cosf (anglef);
914
 
  float s = sinf (anglef);
915
 
 
916
 
  matrix[0]  = xf * xf * (1.0f - c) + c;
917
 
  matrix[1]  = yf * xf * (1.0f - c) + zf * s;
918
 
  matrix[2]  = xf * zf * (1.0f - c) - yf * s;
919
 
  matrix[3]  = 0.0f;
920
 
 
921
 
  matrix[4]  = xf * yf * (1.0f - c) - zf * s;
922
 
  matrix[5]  = yf * yf * (1.0f - c) + c;
923
 
  matrix[6]  = yf * zf * (1.0f - c) + xf * s;
924
 
  matrix[7]  = 0.0f;
925
 
 
926
 
  matrix[8]  = xf * zf * (1.0f - c) + yf * s;
927
 
  matrix[9]  = yf * zf * (1.0f - c) - xf * s;
928
 
  matrix[10] = zf * zf * (1.0f - c) + c;
929
 
  matrix[11] = 0.0f;
930
 
 
931
 
  matrix[12] = 0.0f;
932
 
  matrix[13] = 0.0f;
933
 
  matrix[14] = 0.0f;
934
 
  matrix[15] = 1.0f;
935
 
 
936
 
  cogl_wrap_glMultMatrix (matrix);
937
 
}
938
 
 
939
 
void
940
 
cogl_wrap_glOrthof (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
941
 
                    GLfloat near, GLfloat far)
942
 
{
943
 
  float matrix[16];
944
 
  float xrange =  (right - left);
945
 
  float yrange =  (top - bottom);
946
 
  float zrange =  (far - near);
947
 
 
948
 
  memset (matrix, 0, sizeof (matrix));
949
 
  matrix[0] = 2.0f / xrange;
950
 
  matrix[5] = 2.0f / yrange;
951
 
  matrix[10] = 2.0f / zrange;
952
 
  matrix[12] =  (right + left) / xrange;
953
 
  matrix[13] =  (top + bottom) / yrange;
954
 
  matrix[14] =  (far + near) / zrange;
955
 
  matrix[15] = 1.0f;
956
 
 
957
 
  cogl_wrap_glMultMatrix (matrix);
958
 
}
959
 
 
960
 
void
961
 
cogl_wrap_glVertexPointer (GLint size, GLenum type, GLsizei stride,
962
 
                           const GLvoid *pointer)
963
 
{
964
 
  glVertexAttribPointer (COGL_GLES2_WRAPPER_VERTEX_ATTRIB, size, type,
965
 
                         GL_FALSE, stride, pointer);
966
 
}
967
 
 
968
 
void
969
 
cogl_wrap_glTexCoordPointer (GLint size, GLenum type, GLsizei stride,
970
 
                             const GLvoid *pointer)
971
 
{
972
 
  int active_unit;
973
 
  CoglGles2WrapperTextureUnit *texture_unit;
974
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
975
 
 
976
 
  active_unit = w->active_client_texture_unit;
977
 
 
978
 
  texture_unit = w->texture_units + active_unit;
979
 
  texture_unit->texture_coords_size = size;
980
 
  texture_unit->texture_coords_type = type;
981
 
  texture_unit->texture_coords_stride = stride;
982
 
  texture_unit->texture_coords_pointer = pointer;
983
 
 
984
 
  w->dirty_attribute_pointers
985
 
    |= COGL_GLES2_DIRTY_TEX_COORD_VERTEX_ATTRIB;
986
 
}
987
 
 
988
 
void
989
 
cogl_wrap_glColorPointer (GLint size, GLenum type, GLsizei stride,
990
 
                          const GLvoid *pointer)
991
 
{
992
 
  glVertexAttribPointer (COGL_GLES2_WRAPPER_COLOR_ATTRIB, size, type,
993
 
                         GL_TRUE, stride, pointer);
994
 
}
995
 
 
996
 
void
997
 
cogl_wrap_glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer)
998
 
{
999
 
  glVertexAttribPointer (COGL_GLES2_WRAPPER_NORMAL_ATTRIB, 1, type,
1000
 
                         GL_FALSE, stride, pointer);
1001
 
}
1002
 
 
1003
 
static void
1004
 
cogl_gles2_do_set_uniform (GLint location, CoglBoxedValue *value)
1005
 
{
1006
 
  switch (value->type)
1007
 
    {
1008
 
    case COGL_BOXED_NONE:
1009
 
      break;
1010
 
 
1011
 
    case COGL_BOXED_INT:
1012
 
      {
1013
 
        gint *ptr;
1014
 
 
1015
 
        if (value->count == 1)
1016
 
          ptr = value->v.int_value;
1017
 
        else
1018
 
          ptr = value->v.int_array;
1019
 
 
1020
 
        switch (value->size)
1021
 
          {
1022
 
          case 1: glUniform1iv (location, value->count, ptr); break;
1023
 
          case 2: glUniform2iv (location, value->count, ptr); break;
1024
 
          case 3: glUniform3iv (location, value->count, ptr); break;
1025
 
          case 4: glUniform4iv (location, value->count, ptr); break;
1026
 
          }
1027
 
      }
1028
 
      break;
1029
 
 
1030
 
    case COGL_BOXED_FLOAT:
1031
 
      {
1032
 
        gfloat *ptr;
1033
 
 
1034
 
        if (value->count == 1)
1035
 
          ptr = value->v.float_value;
1036
 
        else
1037
 
          ptr = value->v.float_array;
1038
 
 
1039
 
        switch (value->size)
1040
 
          {
1041
 
          case 1: glUniform1fv (location, value->count, ptr); break;
1042
 
          case 2: glUniform2fv (location, value->count, ptr); break;
1043
 
          case 3: glUniform3fv (location, value->count, ptr); break;
1044
 
          case 4: glUniform4fv (location, value->count, ptr); break;
1045
 
          }
1046
 
      }
1047
 
      break;
1048
 
 
1049
 
    case COGL_BOXED_MATRIX:
1050
 
      {
1051
 
        gfloat *ptr;
1052
 
 
1053
 
        if (value->count == 1)
1054
 
          ptr = value->v.matrix;
1055
 
        else
1056
 
          ptr = value->v.float_array;
1057
 
 
1058
 
        switch (value->size)
1059
 
          {
1060
 
          case 2:
1061
 
            glUniformMatrix2fv (location, value->count, value->transpose, ptr);
1062
 
            break;
1063
 
          case 3:
1064
 
            glUniformMatrix3fv (location, value->count, value->transpose, ptr);
1065
 
            break;
1066
 
          case 4:
1067
 
            glUniformMatrix4fv (location, value->count, value->transpose, ptr);
1068
 
            break;
1069
 
          }
1070
 
      }
1071
 
      break;
1072
 
    }
1073
 
}
1074
 
 
1075
 
static void
1076
 
cogl_wrap_prepare_for_draw (void)
1077
 
{
1078
 
  CoglGles2WrapperProgram *program;
1079
 
 
1080
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1081
 
 
1082
 
  /* Check if we need to switch programs */
1083
 
  if (w->settings_dirty)
1084
 
    {
1085
 
      /* Find or create a program for the current settings */
1086
 
      program = cogl_gles2_wrapper_get_program (&w->settings);
1087
 
 
1088
 
      if (program == NULL)
1089
 
        /* Can't compile a shader so there is nothing we can do */
1090
 
        return;
1091
 
 
1092
 
      /* Start using it if we aren't already */
1093
 
      if (w->current_program != program)
1094
 
        {
1095
 
          glUseProgram (program->program);
1096
 
          w->current_program = program;
1097
 
          /* All of the uniforms are probably now out of date */
1098
 
          w->dirty_uniforms = COGL_GLES2_DIRTY_ALL;
1099
 
          w->dirty_custom_uniforms = (1 << COGL_GLES2_NUM_CUSTOM_UNIFORMS) - 1;
1100
 
        }
1101
 
      w->settings_dirty = FALSE;
1102
 
    }
1103
 
  else
1104
 
    program = w->current_program;
1105
 
 
1106
 
  /* Make sure all of the uniforms are up to date */
1107
 
  if (w->dirty_uniforms)
1108
 
    {
1109
 
      if ((w->dirty_uniforms & (COGL_GLES2_DIRTY_MVP_MATRIX
1110
 
                                | COGL_GLES2_DIRTY_MODELVIEW_MATRIX)))
1111
 
        {
1112
 
          float mvp_matrix[16];
1113
 
          const float *modelview_matrix = w->modelview_stack
1114
 
            + w->modelview_stack_pos * 16;
1115
 
 
1116
 
          cogl_gles2_wrapper_mult_matrix (mvp_matrix,
1117
 
                                          w->projection_stack
1118
 
                                          + w->projection_stack_pos * 16,
1119
 
                                          modelview_matrix);
1120
 
 
1121
 
          if (program->uniforms.mvp_matrix_uniform != -1)
1122
 
            glUniformMatrix4fv (program->uniforms.mvp_matrix_uniform, 1,
1123
 
                                GL_FALSE, mvp_matrix);
1124
 
          if (program->uniforms.modelview_matrix_uniform != -1)
1125
 
            glUniformMatrix4fv (program->uniforms.modelview_matrix_uniform, 1,
1126
 
                                GL_FALSE, modelview_matrix);
1127
 
        }
1128
 
      if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_MATRICES))
1129
 
        {
1130
 
          int i;
1131
 
 
1132
 
          /* TODO - we should probably have a per unit dirty flag too */
1133
 
 
1134
 
          for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
1135
 
            {
1136
 
              CoglGles2WrapperTextureUnit *texture_unit;
1137
 
              GLint uniform = program->uniforms.texture_matrix_uniforms[i];
1138
 
 
1139
 
              texture_unit = w->texture_units + i;
1140
 
              if (uniform != -1)
1141
 
                glUniformMatrix4fv (uniform, 1, GL_FALSE,
1142
 
                                    texture_unit->texture_stack
1143
 
                                      + texture_unit->texture_stack_pos * 16);
1144
 
            }
1145
 
        }
1146
 
 
1147
 
      if ((w->dirty_uniforms & COGL_GLES2_DIRTY_FOG_DENSITY)
1148
 
          && program->uniforms.fog_density_uniform != -1)
1149
 
        glUniform1f (program->uniforms.fog_density_uniform, w->fog_density);
1150
 
      if ((w->dirty_uniforms & COGL_GLES2_DIRTY_FOG_START)
1151
 
          && program->uniforms.fog_start_uniform != -1)
1152
 
        glUniform1f (program->uniforms.fog_start_uniform, w->fog_start);
1153
 
      if ((w->dirty_uniforms & COGL_GLES2_DIRTY_FOG_END)
1154
 
          && program->uniforms.fog_end_uniform != -1)
1155
 
        glUniform1f (program->uniforms.fog_end_uniform, w->fog_end);
1156
 
 
1157
 
      if ((w->dirty_uniforms & COGL_GLES2_DIRTY_ALPHA_TEST_REF)
1158
 
          && program->uniforms.alpha_test_ref_uniform != -1)
1159
 
        glUniform1f (program->uniforms.alpha_test_ref_uniform,
1160
 
                     w->alpha_test_ref);
1161
 
 
1162
 
      if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_UNITS))
1163
 
        {
1164
 
          int i;
1165
 
 
1166
 
          /* TODO - we should probably have a per unit dirty flag too */
1167
 
 
1168
 
          for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
1169
 
            {
1170
 
              GLint uniform = program->uniforms.texture_sampler_uniforms[i];
1171
 
 
1172
 
              if (uniform != -1)
1173
 
                glUniform1i (uniform, i);
1174
 
            }
1175
 
        }
1176
 
 
1177
 
      w->dirty_uniforms = 0;
1178
 
    }
1179
 
 
1180
 
  if (w->dirty_custom_uniforms)
1181
 
    {
1182
 
      int i;
1183
 
 
1184
 
      if (w->settings.user_program != COGL_INVALID_HANDLE)
1185
 
        {
1186
 
          CoglProgram *user_program
1187
 
            = _cogl_program_pointer_from_handle (w->settings.user_program);
1188
 
          const char *uniform_name;
1189
 
 
1190
 
          for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
1191
 
            if ((w->dirty_custom_uniforms & (1 << i))
1192
 
                && (uniform_name = user_program->custom_uniform_names[i]))
1193
 
              {
1194
 
                if (program->custom_uniforms[i]
1195
 
                    == COGL_GLES2_UNBOUND_CUSTOM_UNIFORM)
1196
 
                  program->custom_uniforms[i]
1197
 
                    = glGetUniformLocation (program->program, uniform_name);
1198
 
                if (program->custom_uniforms[i] >= 0)
1199
 
                  cogl_gles2_do_set_uniform (program->custom_uniforms[i],
1200
 
                                             &w->custom_uniforms[i]);
1201
 
              }
1202
 
        }
1203
 
 
1204
 
      w->dirty_custom_uniforms = 0;
1205
 
    }
1206
 
 
1207
 
  if (w->dirty_attribute_pointers
1208
 
      & COGL_GLES2_DIRTY_TEX_COORD_VERTEX_ATTRIB)
1209
 
    {
1210
 
      int i;
1211
 
 
1212
 
      /* TODO - coverage test */
1213
 
      for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
1214
 
        if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units, i))
1215
 
          {
1216
 
            GLint tex_coord_var_index;
1217
 
            CoglGles2WrapperTextureUnit *texture_unit;
1218
 
 
1219
 
            texture_unit = w->texture_units + w->active_texture_unit;
1220
 
            if (!texture_unit->texture_coords_enabled)
1221
 
              continue;
1222
 
 
1223
 
            /* TODO - we should probably have a per unit dirty flag too */
1224
 
 
1225
 
            /* TODO - coverage test */
1226
 
            tex_coord_var_index = program->attributes.multi_texture_coords[i];
1227
 
            glVertexAttribPointer (tex_coord_var_index,
1228
 
                                   texture_unit->texture_coords_size,
1229
 
                                   texture_unit->texture_coords_type,
1230
 
                                   GL_FALSE,
1231
 
                                   texture_unit->texture_coords_stride,
1232
 
                                   texture_unit->texture_coords_pointer);
1233
 
          }
1234
 
    }
1235
 
 
1236
 
  if (w->dirty_vertex_attrib_enables)
1237
 
    {
1238
 
      int i;
1239
 
 
1240
 
      /* TODO - coverage test */
1241
 
 
1242
 
      /* TODO - we should probably have a per unit dirty flag too */
1243
 
 
1244
 
      for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
1245
 
        {
1246
 
          CoglGles2WrapperTextureUnit *texture_unit
1247
 
            = w->texture_units + w->active_texture_unit;
1248
 
          GLint attrib = program->attributes.multi_texture_coords[i];
1249
 
 
1250
 
          if (attrib != -1)
1251
 
            {
1252
 
              if (texture_unit->texture_coords_enabled)
1253
 
                glEnableVertexAttribArray (attrib);
1254
 
              else
1255
 
                glDisableVertexAttribArray (attrib);
1256
 
            }
1257
 
        }
1258
 
 
1259
 
      w->dirty_vertex_attrib_enables = 0;
1260
 
    }
1261
 
}
1262
 
 
1263
 
void
1264
 
cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
1265
 
{
1266
 
  cogl_wrap_prepare_for_draw ();
1267
 
 
1268
 
  glDrawArrays (mode, first, count);
1269
 
}
1270
 
 
1271
 
void
1272
 
cogl_wrap_glDrawElements (GLenum mode, GLsizei count, GLenum type,
1273
 
                          const GLvoid *indices)
1274
 
{
1275
 
  cogl_wrap_prepare_for_draw ();
1276
 
 
1277
 
  glDrawElements (mode, count, type, indices);
1278
 
}
1279
 
 
1280
 
void
1281
 
cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture,
1282
 
                                 GLenum internal_format)
1283
 
{
1284
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1285
 
 
1286
 
  glBindTexture (target, texture);
1287
 
 
1288
 
  /* We need to keep track of whether the texture is alpha-only
1289
 
     because the emulation of GL_MODULATE needs to work differently in
1290
 
     that case */
1291
 
  if (COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY (w->settings.texture_units,
1292
 
                                             w->active_texture_unit)
1293
 
      != (internal_format == GL_ALPHA))
1294
 
    {
1295
 
      COGL_GLES2_TEXTURE_UNIT_SET_ALPHA_ONLY (w->settings.texture_units,
1296
 
                                              w->active_texture_unit,
1297
 
                                              internal_format == GL_ALPHA);
1298
 
      w->settings_dirty = TRUE;
1299
 
    }
1300
 
}
1301
 
 
1302
 
void
1303
 
cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param)
1304
 
{
1305
 
  /* This function is only used to set the texture mode once to
1306
 
     GL_MODULATE. The shader is hard-coded to modulate the texture so
1307
 
     nothing needs to be done here. */
1308
 
}
1309
 
 
1310
 
void
1311
 
cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params)
1312
 
{
1313
 
  /* FIXME: Currently needed to support texture combining using
1314
 
   * COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT */
1315
 
}
1316
 
 
1317
 
void
1318
 
cogl_wrap_glClientActiveTexture (GLenum texture)
1319
 
{
1320
 
  int texture_unit_index = texture - GL_TEXTURE0;
1321
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1322
 
 
1323
 
  if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS)
1324
 
    w->active_client_texture_unit = texture_unit_index;
1325
 
}
1326
 
 
1327
 
void
1328
 
cogl_wrap_glActiveTexture (GLenum texture)
1329
 
{
1330
 
  int texture_unit_index = texture - GL_TEXTURE0;
1331
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1332
 
 
1333
 
  glActiveTexture (texture);
1334
 
 
1335
 
  if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS)
1336
 
    w->active_texture_unit = texture_unit_index;
1337
 
}
1338
 
 
1339
 
void
1340
 
cogl_wrap_glEnable (GLenum cap)
1341
 
{
1342
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1343
 
 
1344
 
  switch (cap)
1345
 
    {
1346
 
    case GL_TEXTURE_2D:
1347
 
      if (!COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
1348
 
                                               w->active_texture_unit))
1349
 
        {
1350
 
          COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units,
1351
 
                                               w->active_texture_unit,
1352
 
                                               TRUE);
1353
 
          w->settings_dirty = TRUE;
1354
 
        }
1355
 
      break;
1356
 
 
1357
 
    case GL_FOG:
1358
 
      _COGL_GLES2_CHANGE_SETTING (w, fog_enabled, TRUE);
1359
 
      break;
1360
 
 
1361
 
    case GL_ALPHA_TEST:
1362
 
      _COGL_GLES2_CHANGE_SETTING (w, alpha_test_enabled, TRUE);
1363
 
      break;
1364
 
 
1365
 
    default:
1366
 
      glEnable (cap);
1367
 
    }
1368
 
}
1369
 
 
1370
 
void
1371
 
cogl_wrap_glDisable (GLenum cap)
1372
 
{
1373
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1374
 
 
1375
 
  switch (cap)
1376
 
    {
1377
 
    case GL_TEXTURE_2D:
1378
 
      if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
1379
 
                                              w->active_texture_unit))
1380
 
        {
1381
 
          COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units,
1382
 
                                               w->active_texture_unit,
1383
 
                                               FALSE);
1384
 
          w->settings_dirty = TRUE;
1385
 
        }
1386
 
      break;
1387
 
 
1388
 
    case GL_FOG:
1389
 
      _COGL_GLES2_CHANGE_SETTING (w, fog_enabled, FALSE);
1390
 
      break;
1391
 
 
1392
 
    case GL_ALPHA_TEST:
1393
 
      _COGL_GLES2_CHANGE_SETTING (w, alpha_test_enabled, FALSE);
1394
 
      break;
1395
 
 
1396
 
    default:
1397
 
      glDisable (cap);
1398
 
    }
1399
 
}
1400
 
 
1401
 
void
1402
 
cogl_wrap_glEnableClientState (GLenum array)
1403
 
{
1404
 
  CoglGles2WrapperTextureUnit *texture_unit;
1405
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1406
 
 
1407
 
  switch (array)
1408
 
    {
1409
 
    case GL_VERTEX_ARRAY:
1410
 
      glEnableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB);
1411
 
      break;
1412
 
    case GL_TEXTURE_COORD_ARRAY:
1413
 
      /* TODO - review if this should be in w->settings? */
1414
 
 
1415
 
      texture_unit = w->texture_units + w->active_texture_unit;
1416
 
      if (texture_unit->texture_coords_enabled != 1)
1417
 
        {
1418
 
          texture_unit->texture_coords_enabled = 1;
1419
 
          w->dirty_vertex_attrib_enables
1420
 
            |= COGL_GLES2_DIRTY_TEX_COORD_ATTRIB_ENABLES;
1421
 
        }
1422
 
      break;
1423
 
    case GL_COLOR_ARRAY:
1424
 
      glEnableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB);
1425
 
      break;
1426
 
    case GL_NORMAL_ARRAY:
1427
 
      glEnableVertexAttribArray (COGL_GLES2_WRAPPER_NORMAL_ATTRIB);
1428
 
      break;
1429
 
    }
1430
 
}
1431
 
 
1432
 
void
1433
 
cogl_wrap_glDisableClientState (GLenum array)
1434
 
{
1435
 
  CoglGles2WrapperTextureUnit *texture_unit;
1436
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1437
 
 
1438
 
  switch (array)
1439
 
    {
1440
 
    case GL_VERTEX_ARRAY:
1441
 
      glDisableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB);
1442
 
      break;
1443
 
    case GL_TEXTURE_COORD_ARRAY:
1444
 
 
1445
 
      texture_unit = w->texture_units + w->active_texture_unit;
1446
 
      /* TODO - review if this should be in w->settings? */
1447
 
      if (texture_unit->texture_coords_enabled != 0)
1448
 
        {
1449
 
          texture_unit->texture_coords_enabled = 0;
1450
 
          w->dirty_vertex_attrib_enables
1451
 
            |= COGL_GLES2_DIRTY_TEX_COORD_ATTRIB_ENABLES;
1452
 
        }
1453
 
      break;
1454
 
    case GL_COLOR_ARRAY:
1455
 
      glDisableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB);
1456
 
      break;
1457
 
    case GL_NORMAL_ARRAY:
1458
 
      glDisableVertexAttribArray (COGL_GLES2_WRAPPER_NORMAL_ATTRIB);
1459
 
      break;
1460
 
    }
1461
 
}
1462
 
 
1463
 
void
1464
 
cogl_wrap_glAlphaFunc (GLenum func, GLclampf ref)
1465
 
{
1466
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1467
 
 
1468
 
  if (ref < 0.0f)
1469
 
    ref = 0.0f;
1470
 
  else if (ref > 1.0f)
1471
 
    ref = 1.0f;
1472
 
 
1473
 
  _COGL_GLES2_CHANGE_SETTING (w, alpha_test_func, func);
1474
 
  _COGL_GLES2_CHANGE_UNIFORM (w, ALPHA_TEST_REF, alpha_test_ref, ref);
1475
 
}
1476
 
 
1477
 
void
1478
 
cogl_wrap_glColor4f (GLclampf r, GLclampf g, GLclampf b, GLclampf a)
1479
 
{
1480
 
  glVertexAttrib4f (COGL_GLES2_WRAPPER_COLOR_ATTRIB, r, g, b, a);
1481
 
}
1482
 
 
1483
 
void
1484
 
cogl_wrap_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1485
 
{
1486
 
  glVertexAttrib4f (COGL_GLES2_WRAPPER_COLOR_ATTRIB,
1487
 
                    r/255.0, g/255.0, b/255.0, a/255.0);
1488
 
}
1489
 
 
1490
 
void
1491
 
cogl_wrap_glClipPlanef (GLenum plane, GLfloat *equation)
1492
 
{
1493
 
  /* FIXME */
1494
 
}
1495
 
 
1496
 
void
1497
 
cogl_wrap_glGetIntegerv (GLenum pname, GLint *params)
1498
 
{
1499
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1500
 
 
1501
 
  switch (pname)
1502
 
    {
1503
 
    case GL_MAX_CLIP_PLANES:
1504
 
      *params = 0;
1505
 
      break;
1506
 
 
1507
 
    case CGL_MATRIX_MODE:
1508
 
      *params = w->matrix_mode;
1509
 
      break;
1510
 
 
1511
 
    default:
1512
 
      glGetIntegerv (pname, params);
1513
 
      break;
1514
 
    }
1515
 
}
1516
 
 
1517
 
void
1518
 
cogl_wrap_glGetFloatv (GLenum pname, GLfloat *params)
1519
 
{
1520
 
  CoglGles2WrapperTextureUnit *texture_unit;
1521
 
 
1522
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1523
 
 
1524
 
  switch (pname)
1525
 
    {
1526
 
    case GL_MODELVIEW_MATRIX:
1527
 
      memcpy (params, w->modelview_stack + w->modelview_stack_pos * 16,
1528
 
              sizeof (GLfloat) * 16);
1529
 
      break;
1530
 
 
1531
 
    case GL_PROJECTION_MATRIX:
1532
 
      memcpy (params, w->projection_stack + w->projection_stack_pos * 16,
1533
 
              sizeof (GLfloat) * 16);
1534
 
      break;
1535
 
 
1536
 
    case GL_TEXTURE_MATRIX:
1537
 
      texture_unit = w->texture_units + w->active_texture_unit;
1538
 
      memcpy (params,
1539
 
              texture_unit->texture_stack
1540
 
               + texture_unit->texture_stack_pos * 16,
1541
 
              sizeof (GLfloat) * 16);
1542
 
      break;
1543
 
 
1544
 
    case GL_VIEWPORT:
1545
 
      glGetFloatv (GL_VIEWPORT, params);
1546
 
      break;
1547
 
    }
1548
 
}
1549
 
 
1550
 
void
1551
 
cogl_wrap_glFogf (GLenum pname, GLfloat param)
1552
 
{
1553
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1554
 
 
1555
 
  switch (pname)
1556
 
    {
1557
 
    case GL_FOG_MODE:
1558
 
      _COGL_GLES2_CHANGE_SETTING (w, fog_mode, param);
1559
 
      break;
1560
 
 
1561
 
    case GL_FOG_DENSITY:
1562
 
      _COGL_GLES2_CHANGE_UNIFORM (w, FOG_DENSITY, fog_density,
1563
 
                                   (param));
1564
 
      break;
1565
 
 
1566
 
    case GL_FOG_START:
1567
 
      _COGL_GLES2_CHANGE_UNIFORM (w, FOG_START, fog_start,
1568
 
                                   (param));
1569
 
      break;
1570
 
 
1571
 
    case GL_FOG_END:
1572
 
      _COGL_GLES2_CHANGE_UNIFORM (w, FOG_END, fog_end,
1573
 
                                   (param));
1574
 
      break;
1575
 
    }
1576
 
}
1577
 
 
1578
 
void
1579
 
cogl_wrap_glFogfv (GLenum pname, const GLfloat *params)
1580
 
{
1581
 
  int i;
1582
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1583
 
 
1584
 
  if (pname == GL_FOG_COLOR)
1585
 
    {
1586
 
      for (i = 0; i < 4; i++)
1587
 
        w->fog_color[i] =  (params[i]);
1588
 
 
1589
 
      w->dirty_uniforms |= COGL_GLES2_DIRTY_FOG_COLOR;
1590
 
    }
1591
 
}
1592
 
 
1593
 
void
1594
 
cogl_wrap_glTexParameteri (GLenum target, GLenum pname, GLfloat param)
1595
 
{
1596
 
  if (pname != GL_GENERATE_MIPMAP)
1597
 
    glTexParameteri (target, pname, param);
1598
 
}
1599
 
 
1600
 
void
1601
 
cogl_wrap_glMaterialfv (GLenum face, GLenum pname, const GLfloat *params)
1602
 
{
1603
 
  /* FIXME: the GLES 2 backend doesn't yet support lighting so this
1604
 
     function can't do anything */
1605
 
}
1606
 
 
1607
 
void
1608
 
_cogl_gles2_clear_cache_for_program (CoglHandle user_program)
1609
 
{
1610
 
  GSList *node, *next, *last = NULL;
1611
 
  CoglGles2WrapperProgram *program;
1612
 
 
1613
 
  _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1614
 
 
1615
 
  /* Remove any cached programs that link against this custom program */
1616
 
  for (node = w->compiled_programs; node; node = next)
1617
 
    {
1618
 
      next = node->next;
1619
 
      program = (CoglGles2WrapperProgram *) node->data;
1620
 
 
1621
 
      if (program->settings.user_program == user_program)
1622
 
        {
1623
 
          glDeleteProgram (program->program);
1624
 
 
1625
 
          if (last)
1626
 
            last->next = next;
1627
 
          else
1628
 
            w->compiled_programs = next;
1629
 
 
1630
 
          g_slist_free1 (node);
1631
 
        }
1632
 
      else
1633
 
        last = node;
1634
 
    }
1635
 
}