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, write to the
20
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
* Boston, MA 02111-1307, USA.
28
#include <clutter/clutter-fixed.h>
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
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"
46
#define _COGL_GET_GLES2_WRAPPER(wvar, retval) \
47
CoglGles2Wrapper *wvar; \
49
CoglContext *__ctxvar = _cogl_context_get_default (); \
50
if (__ctxvar == NULL) return retval; \
51
wvar = &__ctxvar->gles2; \
54
#define _COGL_GLES2_CHANGE_SETTING(w, var, val) \
56
if ((w)->settings.var != (val)) \
58
(w)->settings.var = (val); \
59
(w)->settings_dirty = TRUE; \
63
#define _COGL_GLES2_CHANGE_UNIFORM(w, flag, var, val) \
65
if ((w)->var != (val)) \
68
(w)->dirty_uniforms |= COGL_GLES2_DIRTY_ ## flag; \
72
#define COGL_GLES2_WRAPPER_VERTEX_ATTRIB 0
73
#define COGL_GLES2_WRAPPER_COLOR_ATTRIB 1
74
#define COGL_GLES2_WRAPPER_NORMAL_ATTRIB 2
78
cogl_gles2_wrapper_create_shader (GLenum type, const char *source)
81
GLint source_len = strlen (source);
84
shader = glCreateShader (type);
85
glShaderSource (shader, 1, &source, &source_len);
86
glCompileShader (shader);
88
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
92
char shader_log[1024];
95
glGetShaderInfoLog (shader, sizeof (shader_log) - 1, &len, shader_log);
96
shader_log[len] = '\0';
98
g_critical ("%s", shader_log);
100
glDeleteShader (shader);
109
initialize_texture_units (CoglGles2Wrapper *w)
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;
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));
123
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
125
CoglGles2WrapperTextureUnit *new_unit;
127
new_unit = w->texture_units + i;
128
memset (new_unit, 0, sizeof (CoglGles2WrapperTextureUnit));
130
w->active_texture_unit = i;
131
GE( cogl_wrap_glMatrixMode (GL_TEXTURE));
132
GE( cogl_wrap_glLoadIdentity ());
135
GE( cogl_wrap_glMatrixMode ((GLenum) prev_mode));
137
w->settings.texture_units = 0;
139
w->active_texture_unit = initial_active_unit;
143
cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
145
GLfloat default_fog_color[4] = { 0, 0, 0, 0 };
147
memset (wrapper, 0, sizeof (CoglGles2Wrapper));
149
/* Initialize the stacks */
150
cogl_wrap_glMatrixMode (GL_PROJECTION);
151
cogl_wrap_glLoadIdentity ();
152
cogl_wrap_glMatrixMode (GL_MODELVIEW);
153
cogl_wrap_glLoadIdentity ();
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);
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);
168
/* Initialize alpha testing */
169
cogl_wrap_glDisable (GL_ALPHA_TEST);
170
cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f);
172
initialize_texture_units (wrapper);
176
cogl_gles2_settings_equal (const CoglGles2WrapperSettings *a,
177
const CoglGles2WrapperSettings *b,
178
gboolean vertex_tests,
179
gboolean fragment_tests)
181
if (a->texture_units != b->texture_units)
186
if (a->alpha_test_enabled != b->alpha_test_enabled)
188
if (a->alpha_test_enabled && a->alpha_test_func != b->alpha_test_func)
192
if (a->fog_enabled != b->fog_enabled)
195
if (vertex_tests && a->fog_enabled && a->fog_mode != b->fog_mode)
201
static CoglGles2WrapperShader *
202
cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
204
GString *shader_source;
206
CoglGles2WrapperShader *shader;
209
int n_texture_units = 0;
211
_COGL_GET_GLES2_WRAPPER (w, NULL);
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,
219
return (CoglGles2WrapperShader *) node->data;
221
/* Otherwise create a new shader */
222
shader_source = g_string_new (cogl_fixed_vertex_shader_per_vertex_attribs);
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",
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;
235
g_string_append (shader_source, cogl_fixed_vertex_shader_transform_matrices);
236
g_string_append (shader_source, cogl_fixed_vertex_shader_output_variables);
238
if (n_texture_units > 0)
240
g_string_append_printf (shader_source,
241
"uniform mat4 texture_matrix[%d];\n",
244
g_string_append_printf (shader_source,
245
"varying vec2 tex_coord[%d];",
249
g_string_append (shader_source, cogl_fixed_vertex_shader_fogging_options);
250
g_string_append (shader_source, cogl_fixed_vertex_shader_main_start);
252
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
253
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
255
g_string_append_printf (shader_source,
256
"transformed_tex_coord = "
257
"texture_matrix[%d] "
258
" * multi_tex_coord_attrib%d;\n",
260
g_string_append_printf (shader_source,
261
"tex_coord[%d] = transformed_tex_coord.st "
262
" / transformed_tex_coord.q;\n",
266
g_string_append (shader_source, cogl_fixed_vertex_shader_frag_color_start);
268
if (settings->fog_enabled)
270
g_string_append (shader_source, cogl_fixed_vertex_shader_fog_start);
272
switch (settings->fog_mode)
275
g_string_append (shader_source, cogl_fixed_vertex_shader_fog_exp);
279
g_string_append (shader_source, cogl_fixed_vertex_shader_fog_exp2);
283
g_string_append (shader_source, cogl_fixed_vertex_shader_fog_linear);
287
g_string_append (shader_source, cogl_fixed_vertex_shader_fog_end);
290
g_string_append (shader_source, cogl_fixed_vertex_shader_end);
292
shader_obj = cogl_gles2_wrapper_create_shader (GL_VERTEX_SHADER,
295
g_string_free (shader_source, TRUE);
300
shader = g_slice_new (CoglGles2WrapperShader);
301
shader->shader = shader_obj;
302
shader->settings = *settings;
304
w->compiled_vertex_shaders = g_slist_prepend (w->compiled_vertex_shaders,
310
static CoglGles2WrapperShader *
311
cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
313
GString *shader_source;
315
CoglGles2WrapperShader *shader;
318
int n_texture_units = 0;
320
_COGL_GET_GLES2_WRAPPER (w, NULL);
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,
328
return (CoglGles2WrapperShader *) node->data;
330
/* Otherwise create a new shader */
331
shader_source = g_string_new (cogl_fixed_fragment_shader_variables_start);
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;
338
g_string_append (shader_source, cogl_fixed_fragment_shader_inputs);
340
if (n_texture_units > 0)
342
g_string_append_printf (shader_source,
343
"varying vec2 tex_coord[%d];\n",
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",
352
g_string_append (shader_source, cogl_fixed_fragment_shader_fogging_options);
354
g_string_append (shader_source, cogl_fixed_fragment_shader_main_declare);
356
g_string_append (shader_source, cogl_fixed_fragment_shader_main_start);
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");
365
for (i = 0; i < n_texture_units; i++)
366
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
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
373
g_string_append_printf (shader_source,
375
"texture2D (texture_unit[%d], "
376
"tex_coord[%d]).a;\n",
379
g_string_append_printf (shader_source,
381
"texture2D (texture_unit[%d], "
386
if (settings->fog_enabled)
387
g_string_append (shader_source, cogl_fixed_fragment_shader_fog);
389
if (settings->alpha_test_enabled)
390
switch (settings->alpha_test_func)
393
g_string_append (shader_source,
394
cogl_fixed_fragment_shader_alpha_never);
397
g_string_append (shader_source,
398
cogl_fixed_fragment_shader_alpha_less);
401
g_string_append (shader_source,
402
cogl_fixed_fragment_shader_alpha_equal);
405
g_string_append (shader_source,
406
cogl_fixed_fragment_shader_alpha_lequal);
409
g_string_append (shader_source,
410
cogl_fixed_fragment_shader_alpha_greater);
413
g_string_append (shader_source,
414
cogl_fixed_fragment_shader_alpha_notequal);
417
g_string_append (shader_source,
418
cogl_fixed_fragment_shader_alpha_gequal);
421
g_string_append (shader_source, cogl_fixed_fragment_shader_end);
423
shader_obj = cogl_gles2_wrapper_create_shader (GL_FRAGMENT_SHADER,
426
g_string_free (shader_source, TRUE);
431
shader = g_slice_new (CoglGles2WrapperShader);
432
shader->shader = shader_obj;
433
shader->settings = *settings;
435
w->compiled_fragment_shaders = g_slist_prepend (w->compiled_fragment_shaders,
442
cogl_gles2_wrapper_get_locations (GLuint program,
443
CoglGles2WrapperSettings *settings,
444
CoglGles2WrapperUniforms *uniforms,
445
CoglGles2WrapperAttributes *attribs)
449
uniforms->mvp_matrix_uniform
450
= glGetUniformLocation (program, "mvp_matrix");
451
uniforms->modelview_matrix_uniform
452
= glGetUniformLocation (program, "modelview_matrix");
454
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
455
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
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);
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);
469
g_free (tex_coord_var_name);
470
g_free (sampler_var_name);
471
g_free (matrix_var_name);
475
uniforms->texture_matrix_uniforms[i] = -1;
476
uniforms->texture_sampler_uniforms[i] = -1;
477
attribs->multi_texture_coords[i] = -1;
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");
489
uniforms->alpha_test_ref_uniform
490
= glGetUniformLocation (program, "alpha_test_ref");
494
cogl_gles2_wrapper_bind_attributes (GLuint program)
496
glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB,
498
glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB,
500
glBindAttribLocation (program, COGL_GLES2_WRAPPER_NORMAL_ATTRIB,
504
static CoglGles2WrapperProgram *
505
cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
508
CoglGles2WrapperProgram *program;
509
CoglGles2WrapperShader *vertex_shader, *fragment_shader;
511
gboolean custom_vertex_shader = FALSE, custom_fragment_shader = FALSE;
512
CoglProgram *user_program = NULL;
515
_COGL_GET_GLES2_WRAPPER (w, NULL);
517
/* Check if we've already got a program for these settings */
518
for (node = w->compiled_programs; node; node = node->next)
520
program = (CoglGles2WrapperProgram *) node->data;
522
if (cogl_gles2_settings_equal (settings, &program->settings, TRUE, TRUE)
523
&& program->settings.user_program == settings->user_program)
524
return (CoglGles2WrapperProgram *) node->data;
527
/* Otherwise create a new program */
529
/* Check whether the currently used custom program has vertex and
531
if (w->settings.user_program != COGL_INVALID_HANDLE)
534
= _cogl_program_pointer_from_handle (w->settings.user_program);
536
for (node = user_program->attached_shaders; node; node = node->next)
539
= _cogl_shader_pointer_from_handle ((CoglHandle) node->data);
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;
548
/* Get or create the fixed functionality shaders for these settings
549
if there is no custom replacement */
550
if (!custom_vertex_shader)
552
vertex_shader = cogl_gles2_get_vertex_shader (settings);
553
if (vertex_shader == NULL)
556
if (!custom_fragment_shader)
558
fragment_shader = cogl_gles2_get_fragment_shader (settings);
559
if (fragment_shader == NULL)
563
program = g_slice_new (CoglGles2WrapperProgram);
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);
571
for (node = user_program->attached_shaders; node; node = node->next)
574
= _cogl_shader_pointer_from_handle ((CoglHandle) node->data);
575
glAttachShader (program->program, shader->gl_handle);
577
cogl_gles2_wrapper_bind_attributes (program->program);
578
glLinkProgram (program->program);
580
glGetProgramiv (program->program, GL_LINK_STATUS, &status);
584
char shader_log[1024];
587
glGetProgramInfoLog (program->program, sizeof (shader_log) - 1, &len, shader_log);
588
shader_log[len] = '\0';
590
g_critical ("%s", shader_log);
592
glDeleteProgram (program->program);
593
g_slice_free (CoglGles2WrapperProgram, program);
598
program->settings = *settings;
600
cogl_gles2_wrapper_get_locations (program->program,
603
&program->attributes);
605
/* We haven't tried to get a location for any of the custom uniforms
607
for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
608
program->custom_uniforms[i] = COGL_GLES2_UNBOUND_CUSTOM_UNIFORM;
610
w->compiled_programs = g_slist_append (w->compiled_programs, program);
616
cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
621
for (node = wrapper->compiled_programs; node; node = next)
624
glDeleteProgram (((CoglGles2WrapperProgram *) node->data)->program);
625
g_slist_free1 (node);
627
wrapper->compiled_programs = NULL;
629
for (node = wrapper->compiled_vertex_shaders; node; node = next)
632
glDeleteShader (((CoglGles2WrapperShader *) node->data)->shader);
633
g_slist_free1 (node);
635
wrapper->compiled_vertex_shaders = NULL;
637
for (node = wrapper->compiled_fragment_shaders; node; node = next)
640
glDeleteShader (((CoglGles2WrapperShader *) node->data)->shader);
641
g_slist_free1 (node);
643
wrapper->compiled_fragment_shaders = NULL;
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);
651
cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num)
653
CoglGles2WrapperTextureUnit *texture_unit;
659
wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_MVP_MATRIX
660
| COGL_GLES2_DIRTY_MODELVIEW_MATRIX;
664
wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_MVP_MATRIX;
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;
676
cogl_wrap_glPushMatrix ()
681
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
683
/* Get a pointer to the old and new matrix position and increment
685
switch (w->matrix_mode)
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;
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;
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;
716
/* Copy the old matrix to the new position */
717
memcpy (dst, src, sizeof (float) * 16);
721
cogl_wrap_glPopMatrix ()
723
CoglGles2WrapperTextureUnit *texture_unit;
724
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
726
/* Decrement the stack pointer */
727
switch (w->matrix_mode)
731
w->modelview_stack_pos = (w->modelview_stack_pos - 1)
732
& (COGL_GLES2_MODELVIEW_STACK_SIZE - 1);
736
w->projection_stack_pos = (w->projection_stack_pos - 1)
737
& (COGL_GLES2_PROJECTION_STACK_SIZE - 1);
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);
747
/* Update the matrix in the program object */
748
cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
752
cogl_wrap_glMatrixMode (GLenum mode)
754
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
756
w->matrix_mode = mode;
760
cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper)
762
CoglGles2WrapperTextureUnit *texture_unit;
764
switch (wrapper->matrix_mode)
768
return wrapper->modelview_stack + wrapper->modelview_stack_pos * 16;
771
return wrapper->projection_stack + wrapper->projection_stack_pos * 16;
774
texture_unit = wrapper->texture_units + wrapper->active_texture_unit;
775
return texture_unit->texture_stack
776
+ texture_unit->texture_stack_pos * 16;
781
cogl_wrap_glLoadIdentity ()
785
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
787
matrix = cogl_gles2_get_matrix_stack_top (w);
788
memset (matrix, 0, sizeof (float) * 16);
794
cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
798
cogl_gles2_wrapper_mult_matrix (float *dst, const float *a, const float *b)
802
for (i = 0; i < 4; i++)
803
for (j = 0; j < 4; j++)
806
for (k = 0; k < 4; k++)
807
sum += a[k * 4 + j] * b[i * 4 + k];
808
dst[i * 4 + j] = sum;
813
cogl_wrap_glMultMatrix (const float *m)
815
float new_matrix[16];
818
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
820
old_matrix = cogl_gles2_get_matrix_stack_top (w);
822
cogl_gles2_wrapper_mult_matrix (new_matrix, old_matrix, m);
824
memcpy (old_matrix, new_matrix, sizeof (float) * 16);
826
cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
830
cogl_wrap_glMultMatrixf (const GLfloat *m)
832
cogl_wrap_glMultMatrix (m);
836
cogl_wrap_glLoadMatrixf (const GLfloat *m)
840
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
842
old_matrix = cogl_gles2_get_matrix_stack_top (w);
844
memcpy (old_matrix, m, sizeof (float) * 16);
846
cogl_gles2_wrapper_update_matrix (w, w->matrix_mode);
850
cogl_wrap_glFrustumf (GLfloat left, GLfloat right,
851
GLfloat bottom, GLfloat top,
852
GLfloat z_near, GLfloat z_far)
855
float two_near = (2 * z_near);
857
memset (matrix, 0, sizeof (matrix));
859
matrix[0] = two_near / (right - left);
860
matrix[5] = two_near / (top - bottom);
861
matrix[8] = (right + left)
863
matrix[9] = (top + bottom)
865
matrix[10] = - (z_far + z_near)
868
matrix[14] = -two_near * (z_far)
871
cogl_wrap_glMultMatrix (matrix);
875
cogl_wrap_glScalef (GLfloat x, GLfloat y, GLfloat z)
879
memset (matrix, 0, sizeof (matrix));
885
cogl_wrap_glMultMatrix (matrix);
889
cogl_wrap_glTranslatef (GLfloat x, GLfloat y, GLfloat z)
893
memset (matrix, 0, sizeof (matrix));
902
cogl_wrap_glMultMatrix (matrix);
906
cogl_wrap_glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
912
float anglef = (angle) * G_PI / 180.0f;
913
float c = cosf (anglef);
914
float s = sinf (anglef);
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;
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;
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;
936
cogl_wrap_glMultMatrix (matrix);
940
cogl_wrap_glOrthof (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
941
GLfloat near, GLfloat far)
944
float xrange = (right - left);
945
float yrange = (top - bottom);
946
float zrange = (far - near);
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;
957
cogl_wrap_glMultMatrix (matrix);
961
cogl_wrap_glVertexPointer (GLint size, GLenum type, GLsizei stride,
962
const GLvoid *pointer)
964
glVertexAttribPointer (COGL_GLES2_WRAPPER_VERTEX_ATTRIB, size, type,
965
GL_FALSE, stride, pointer);
969
cogl_wrap_glTexCoordPointer (GLint size, GLenum type, GLsizei stride,
970
const GLvoid *pointer)
973
CoglGles2WrapperTextureUnit *texture_unit;
974
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
976
active_unit = w->active_client_texture_unit;
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;
984
w->dirty_attribute_pointers
985
|= COGL_GLES2_DIRTY_TEX_COORD_VERTEX_ATTRIB;
989
cogl_wrap_glColorPointer (GLint size, GLenum type, GLsizei stride,
990
const GLvoid *pointer)
992
glVertexAttribPointer (COGL_GLES2_WRAPPER_COLOR_ATTRIB, size, type,
993
GL_TRUE, stride, pointer);
997
cogl_wrap_glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer)
999
glVertexAttribPointer (COGL_GLES2_WRAPPER_NORMAL_ATTRIB, 1, type,
1000
GL_FALSE, stride, pointer);
1004
cogl_gles2_do_set_uniform (GLint location, CoglBoxedValue *value)
1006
switch (value->type)
1008
case COGL_BOXED_NONE:
1011
case COGL_BOXED_INT:
1015
if (value->count == 1)
1016
ptr = value->v.int_value;
1018
ptr = value->v.int_array;
1020
switch (value->size)
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;
1030
case COGL_BOXED_FLOAT:
1034
if (value->count == 1)
1035
ptr = value->v.float_value;
1037
ptr = value->v.float_array;
1039
switch (value->size)
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;
1049
case COGL_BOXED_MATRIX:
1053
if (value->count == 1)
1054
ptr = value->v.matrix;
1056
ptr = value->v.float_array;
1058
switch (value->size)
1061
glUniformMatrix2fv (location, value->count, value->transpose, ptr);
1064
glUniformMatrix3fv (location, value->count, value->transpose, ptr);
1067
glUniformMatrix4fv (location, value->count, value->transpose, ptr);
1076
cogl_wrap_prepare_for_draw (void)
1078
CoglGles2WrapperProgram *program;
1080
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1082
/* Check if we need to switch programs */
1083
if (w->settings_dirty)
1085
/* Find or create a program for the current settings */
1086
program = cogl_gles2_wrapper_get_program (&w->settings);
1088
if (program == NULL)
1089
/* Can't compile a shader so there is nothing we can do */
1092
/* Start using it if we aren't already */
1093
if (w->current_program != program)
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;
1101
w->settings_dirty = FALSE;
1104
program = w->current_program;
1106
/* Make sure all of the uniforms are up to date */
1107
if (w->dirty_uniforms)
1109
if ((w->dirty_uniforms & (COGL_GLES2_DIRTY_MVP_MATRIX
1110
| COGL_GLES2_DIRTY_MODELVIEW_MATRIX)))
1112
float mvp_matrix[16];
1113
const float *modelview_matrix = w->modelview_stack
1114
+ w->modelview_stack_pos * 16;
1116
cogl_gles2_wrapper_mult_matrix (mvp_matrix,
1118
+ w->projection_stack_pos * 16,
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);
1128
if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_MATRICES))
1132
/* TODO - we should probably have a per unit dirty flag too */
1134
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
1136
CoglGles2WrapperTextureUnit *texture_unit;
1137
GLint uniform = program->uniforms.texture_matrix_uniforms[i];
1139
texture_unit = w->texture_units + i;
1141
glUniformMatrix4fv (uniform, 1, GL_FALSE,
1142
texture_unit->texture_stack
1143
+ texture_unit->texture_stack_pos * 16);
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);
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,
1162
if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_UNITS))
1166
/* TODO - we should probably have a per unit dirty flag too */
1168
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
1170
GLint uniform = program->uniforms.texture_sampler_uniforms[i];
1173
glUniform1i (uniform, i);
1177
w->dirty_uniforms = 0;
1180
if (w->dirty_custom_uniforms)
1184
if (w->settings.user_program != COGL_INVALID_HANDLE)
1186
CoglProgram *user_program
1187
= _cogl_program_pointer_from_handle (w->settings.user_program);
1188
const char *uniform_name;
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]))
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]);
1204
w->dirty_custom_uniforms = 0;
1207
if (w->dirty_attribute_pointers
1208
& COGL_GLES2_DIRTY_TEX_COORD_VERTEX_ATTRIB)
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))
1216
GLint tex_coord_var_index;
1217
CoglGles2WrapperTextureUnit *texture_unit;
1219
texture_unit = w->texture_units + w->active_texture_unit;
1220
if (!texture_unit->texture_coords_enabled)
1223
/* TODO - we should probably have a per unit dirty flag too */
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,
1231
texture_unit->texture_coords_stride,
1232
texture_unit->texture_coords_pointer);
1236
if (w->dirty_vertex_attrib_enables)
1240
/* TODO - coverage test */
1242
/* TODO - we should probably have a per unit dirty flag too */
1244
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
1246
CoglGles2WrapperTextureUnit *texture_unit
1247
= w->texture_units + w->active_texture_unit;
1248
GLint attrib = program->attributes.multi_texture_coords[i];
1252
if (texture_unit->texture_coords_enabled)
1253
glEnableVertexAttribArray (attrib);
1255
glDisableVertexAttribArray (attrib);
1259
w->dirty_vertex_attrib_enables = 0;
1264
cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
1266
cogl_wrap_prepare_for_draw ();
1268
glDrawArrays (mode, first, count);
1272
cogl_wrap_glDrawElements (GLenum mode, GLsizei count, GLenum type,
1273
const GLvoid *indices)
1275
cogl_wrap_prepare_for_draw ();
1277
glDrawElements (mode, count, type, indices);
1281
cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture,
1282
GLenum internal_format)
1284
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1286
glBindTexture (target, texture);
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
1291
if (COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY (w->settings.texture_units,
1292
w->active_texture_unit)
1293
!= (internal_format == GL_ALPHA))
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;
1303
cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param)
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. */
1311
cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params)
1313
/* FIXME: Currently needed to support texture combining using
1314
* COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT */
1318
cogl_wrap_glClientActiveTexture (GLenum texture)
1320
int texture_unit_index = texture - GL_TEXTURE0;
1321
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1323
if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS)
1324
w->active_client_texture_unit = texture_unit_index;
1328
cogl_wrap_glActiveTexture (GLenum texture)
1330
int texture_unit_index = texture - GL_TEXTURE0;
1331
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1333
glActiveTexture (texture);
1335
if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS)
1336
w->active_texture_unit = texture_unit_index;
1340
cogl_wrap_glEnable (GLenum cap)
1342
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1347
if (!COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
1348
w->active_texture_unit))
1350
COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units,
1351
w->active_texture_unit,
1353
w->settings_dirty = TRUE;
1358
_COGL_GLES2_CHANGE_SETTING (w, fog_enabled, TRUE);
1362
_COGL_GLES2_CHANGE_SETTING (w, alpha_test_enabled, TRUE);
1371
cogl_wrap_glDisable (GLenum cap)
1373
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1378
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
1379
w->active_texture_unit))
1381
COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units,
1382
w->active_texture_unit,
1384
w->settings_dirty = TRUE;
1389
_COGL_GLES2_CHANGE_SETTING (w, fog_enabled, FALSE);
1393
_COGL_GLES2_CHANGE_SETTING (w, alpha_test_enabled, FALSE);
1402
cogl_wrap_glEnableClientState (GLenum array)
1404
CoglGles2WrapperTextureUnit *texture_unit;
1405
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1409
case GL_VERTEX_ARRAY:
1410
glEnableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB);
1412
case GL_TEXTURE_COORD_ARRAY:
1413
/* TODO - review if this should be in w->settings? */
1415
texture_unit = w->texture_units + w->active_texture_unit;
1416
if (texture_unit->texture_coords_enabled != 1)
1418
texture_unit->texture_coords_enabled = 1;
1419
w->dirty_vertex_attrib_enables
1420
|= COGL_GLES2_DIRTY_TEX_COORD_ATTRIB_ENABLES;
1423
case GL_COLOR_ARRAY:
1424
glEnableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB);
1426
case GL_NORMAL_ARRAY:
1427
glEnableVertexAttribArray (COGL_GLES2_WRAPPER_NORMAL_ATTRIB);
1433
cogl_wrap_glDisableClientState (GLenum array)
1435
CoglGles2WrapperTextureUnit *texture_unit;
1436
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1440
case GL_VERTEX_ARRAY:
1441
glDisableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB);
1443
case GL_TEXTURE_COORD_ARRAY:
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)
1449
texture_unit->texture_coords_enabled = 0;
1450
w->dirty_vertex_attrib_enables
1451
|= COGL_GLES2_DIRTY_TEX_COORD_ATTRIB_ENABLES;
1454
case GL_COLOR_ARRAY:
1455
glDisableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB);
1457
case GL_NORMAL_ARRAY:
1458
glDisableVertexAttribArray (COGL_GLES2_WRAPPER_NORMAL_ATTRIB);
1464
cogl_wrap_glAlphaFunc (GLenum func, GLclampf ref)
1466
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1470
else if (ref > 1.0f)
1473
_COGL_GLES2_CHANGE_SETTING (w, alpha_test_func, func);
1474
_COGL_GLES2_CHANGE_UNIFORM (w, ALPHA_TEST_REF, alpha_test_ref, ref);
1478
cogl_wrap_glColor4f (GLclampf r, GLclampf g, GLclampf b, GLclampf a)
1480
glVertexAttrib4f (COGL_GLES2_WRAPPER_COLOR_ATTRIB, r, g, b, a);
1484
cogl_wrap_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1486
glVertexAttrib4f (COGL_GLES2_WRAPPER_COLOR_ATTRIB,
1487
r/255.0, g/255.0, b/255.0, a/255.0);
1491
cogl_wrap_glClipPlanef (GLenum plane, GLfloat *equation)
1497
cogl_wrap_glGetIntegerv (GLenum pname, GLint *params)
1499
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1503
case GL_MAX_CLIP_PLANES:
1507
case CGL_MATRIX_MODE:
1508
*params = w->matrix_mode;
1512
glGetIntegerv (pname, params);
1518
cogl_wrap_glGetFloatv (GLenum pname, GLfloat *params)
1520
CoglGles2WrapperTextureUnit *texture_unit;
1522
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1526
case GL_MODELVIEW_MATRIX:
1527
memcpy (params, w->modelview_stack + w->modelview_stack_pos * 16,
1528
sizeof (GLfloat) * 16);
1531
case GL_PROJECTION_MATRIX:
1532
memcpy (params, w->projection_stack + w->projection_stack_pos * 16,
1533
sizeof (GLfloat) * 16);
1536
case GL_TEXTURE_MATRIX:
1537
texture_unit = w->texture_units + w->active_texture_unit;
1539
texture_unit->texture_stack
1540
+ texture_unit->texture_stack_pos * 16,
1541
sizeof (GLfloat) * 16);
1545
glGetFloatv (GL_VIEWPORT, params);
1551
cogl_wrap_glFogf (GLenum pname, GLfloat param)
1553
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1558
_COGL_GLES2_CHANGE_SETTING (w, fog_mode, param);
1561
case GL_FOG_DENSITY:
1562
_COGL_GLES2_CHANGE_UNIFORM (w, FOG_DENSITY, fog_density,
1567
_COGL_GLES2_CHANGE_UNIFORM (w, FOG_START, fog_start,
1572
_COGL_GLES2_CHANGE_UNIFORM (w, FOG_END, fog_end,
1579
cogl_wrap_glFogfv (GLenum pname, const GLfloat *params)
1582
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1584
if (pname == GL_FOG_COLOR)
1586
for (i = 0; i < 4; i++)
1587
w->fog_color[i] = (params[i]);
1589
w->dirty_uniforms |= COGL_GLES2_DIRTY_FOG_COLOR;
1594
cogl_wrap_glTexParameteri (GLenum target, GLenum pname, GLfloat param)
1596
if (pname != GL_GENERATE_MIPMAP)
1597
glTexParameteri (target, pname, param);
1601
cogl_wrap_glMaterialfv (GLenum face, GLenum pname, const GLfloat *params)
1603
/* FIXME: the GLES 2 backend doesn't yet support lighting so this
1604
function can't do anything */
1608
_cogl_gles2_clear_cache_for_program (CoglHandle user_program)
1610
GSList *node, *next, *last = NULL;
1611
CoglGles2WrapperProgram *program;
1613
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
1615
/* Remove any cached programs that link against this custom program */
1616
for (node = w->compiled_programs; node; node = next)
1619
program = (CoglGles2WrapperProgram *) node->data;
1621
if (program->settings.user_program == user_program)
1623
glDeleteProgram (program->program);
1628
w->compiled_programs = next;
1630
g_slist_free1 (node);