4
* An object oriented GL/GLES Abstraction/Utility Layer
6
* Copyright (C) 2008,2009,2010 Intel Corporation.
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library. If not, see
20
* <http://www.gnu.org/licenses/>.
25
* Robert Bragg <robert@linux.intel.com>
32
#include "cogl-debug.h"
33
#include "cogl-pipeline-opengl-private.h"
34
#include "cogl-pipeline-private.h"
35
#include "cogl-context-private.h"
36
#include "cogl-texture-private.h"
37
#include "cogl-framebuffer-private.h"
38
#include "cogl-offscreen.h"
40
/* This is needed to set the color attribute on GLES2 */
41
#ifdef HAVE_COGL_GLES2
42
#include "cogl-pipeline-progend-glsl-private.h"
49
* GL/GLES compatability defines for pipeline thingies:
52
/* These aren't defined in the GLES headers */
53
#ifndef GL_POINT_SPRITE
54
#define GL_POINT_SPRITE 0x8861
56
#ifndef GL_COORD_REPLACE
57
#define GL_COORD_REPLACE 0x8862
59
#ifndef GL_CLAMP_TO_BORDER
60
#define GL_CLAMP_TO_BORDER 0x812d
65
texture_unit_init (CoglTextureUnit *unit, int index_)
68
unit->enabled_gl_target = 0;
71
unit->is_foreign = FALSE;
72
unit->dirty_gl_texture = FALSE;
73
unit->matrix_stack = _cogl_matrix_stack_new ();
76
unit->layer_changes_since_flush = 0;
77
unit->texture_storage_changed = FALSE;
81
texture_unit_free (CoglTextureUnit *unit)
84
cogl_object_unref (unit->layer);
85
cogl_object_unref (unit->matrix_stack);
89
_cogl_get_texture_unit (int index_)
91
_COGL_GET_CONTEXT (ctx, NULL);
93
if (ctx->texture_units->len < (index_ + 1))
96
int prev_len = ctx->texture_units->len;
97
ctx->texture_units = g_array_set_size (ctx->texture_units, index_ + 1);
98
for (i = prev_len; i <= index_; i++)
100
CoglTextureUnit *unit =
101
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
103
texture_unit_init (unit, i);
107
return &g_array_index (ctx->texture_units, CoglTextureUnit, index_);
111
_cogl_destroy_texture_units (void)
115
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
117
for (i = 0; i < ctx->texture_units->len; i++)
119
CoglTextureUnit *unit =
120
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
121
texture_unit_free (unit);
123
g_array_free (ctx->texture_units, TRUE);
127
_cogl_set_active_texture_unit (int unit_index)
129
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
131
if (ctx->active_texture_unit != unit_index)
133
GE (ctx, glActiveTexture (GL_TEXTURE0 + unit_index));
134
ctx->active_texture_unit = unit_index;
138
/* Note: _cogl_bind_gl_texture_transient conceptually has slightly
139
* different semantics to OpenGL's glBindTexture because Cogl never
140
* cares about tracking multiple textures bound to different targets
141
* on the same texture unit.
143
* glBindTexture lets you bind multiple textures to a single texture
144
* unit if they are bound to different targets. So it does something
146
* unit->current_texture[target] = texture;
148
* Cogl only lets you associate one texture with the currently active
149
* texture unit, so the target is basically a redundant parameter
150
* that's implicitly set on that texture.
152
* Technically this is just a thin wrapper around glBindTexture so
153
* actually it does have the GL semantics but it seems worth
154
* mentioning the conceptual difference in case anyone wonders why we
155
* don't associate the gl_texture with a gl_target in the
159
_cogl_bind_gl_texture_transient (GLenum gl_target,
163
CoglTextureUnit *unit;
165
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
167
/* We choose to always make texture unit 1 active for transient
168
* binds so that in the common case where multitexturing isn't used
169
* we can simply ignore the state of this texture unit. Notably we
170
* didn't use a large texture unit (.e.g. (GL_MAX_TEXTURE_UNITS - 1)
171
* in case the driver doesn't have a sparse data structure for
174
_cogl_set_active_texture_unit (1);
175
unit = _cogl_get_texture_unit (1);
177
/* NB: If we have previously bound a foreign texture to this texture
178
* unit we don't know if that texture has since been deleted and we
179
* are seeing the texture name recycled */
180
if (unit->gl_texture == gl_texture &&
181
!unit->dirty_gl_texture &&
185
GE (ctx, glBindTexture (gl_target, gl_texture));
187
unit->dirty_gl_texture = TRUE;
188
unit->is_foreign = is_foreign;
192
_cogl_delete_gl_texture (GLuint gl_texture)
196
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
198
for (i = 0; i < ctx->texture_units->len; i++)
200
CoglTextureUnit *unit =
201
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
203
if (unit->gl_texture == gl_texture)
205
unit->gl_texture = 0;
207
unit->dirty_gl_texture = FALSE;
211
GE (ctx, glDeleteTextures (1, &gl_texture));
214
/* Whenever the underlying GL texture storage of a CoglTexture is
215
* changed (e.g. due to migration out of a texture atlas) then we are
216
* notified. This lets us ensure that we reflush that texture's state
217
* if it is reused again with the same texture unit.
220
_cogl_pipeline_texture_storage_change_notify (CoglTexture *texture)
224
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
226
for (i = 0; i < ctx->texture_units->len; i++)
228
CoglTextureUnit *unit =
229
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
232
_cogl_pipeline_layer_get_texture (unit->layer) == texture)
233
unit->texture_storage_changed = TRUE;
235
/* NB: the texture may be bound to multiple texture units so
236
* we continue to check the rest */
241
set_glsl_program (GLuint gl_program)
243
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
245
if (ctx->current_gl_program != gl_program)
249
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
251
ctx->glUseProgram (gl_program);
252
if (ctx->glGetError () == GL_NO_ERROR)
253
ctx->current_gl_program = gl_program;
256
GE( ctx, glUseProgram (0) );
257
ctx->current_gl_program = 0;
263
_cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type)
265
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
267
/* If we're changing program type... */
268
if (type != ctx->current_fragment_program_type)
270
/* ... disable the old type */
271
switch (ctx->current_fragment_program_type)
273
case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
274
/* If the program contains a vertex shader then we shouldn't
276
if (ctx->current_vertex_program_type !=
277
COGL_PIPELINE_PROGRAM_TYPE_GLSL)
278
set_glsl_program (0);
281
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
283
GE( ctx, glDisable (GL_FRAGMENT_PROGRAM_ARB) );
287
case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
288
/* don't need to to anything */
292
/* ... and enable the new type */
295
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
297
GE( ctx, glEnable (GL_FRAGMENT_PROGRAM_ARB) );
301
case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
302
case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
303
/* don't need to to anything */
308
if (type == COGL_PIPELINE_PROGRAM_TYPE_GLSL)
310
#ifdef COGL_PIPELINE_FRAGEND_GLSL
311
set_glsl_program (gl_program);
315
g_warning ("Unexpected use of GLSL fragend!");
317
#endif /* COGL_PIPELINE_FRAGEND_GLSL */
319
#ifndef COGL_PIPELINE_FRAGEND_ARBFP
320
else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP)
321
g_warning ("Unexpected use of ARBFP fragend!");
322
#endif /* COGL_PIPELINE_FRAGEND_ARBFP */
324
ctx->current_fragment_program_type = type;
328
_cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type)
330
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
332
/* If we're changing program type... */
333
if (type != ctx->current_vertex_program_type)
335
/* ... disable the old type */
336
switch (ctx->current_vertex_program_type)
338
case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
339
/* If the program contains a fragment shader then we shouldn't
341
if (ctx->current_fragment_program_type !=
342
COGL_PIPELINE_PROGRAM_TYPE_GLSL)
343
set_glsl_program (0);
346
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
347
/* It doesn't make sense to enable ARBfp for the vertex program */
348
g_assert_not_reached ();
351
case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
352
/* don't need to to anything */
356
/* ... and enable the new type */
359
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
360
/* It doesn't make sense to enable ARBfp for the vertex program */
361
g_assert_not_reached ();
364
case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
365
case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
366
/* don't need to to anything */
371
if (type == COGL_PIPELINE_PROGRAM_TYPE_GLSL)
373
#ifdef COGL_PIPELINE_VERTEND_GLSL
374
set_glsl_program (gl_program);
378
g_warning ("Unexpected use of GLSL vertend!");
380
#endif /* COGL_PIPELINE_VERTEND_GLSL */
382
#ifndef COGL_PIPELINE_VERTEND_ARBFP
383
else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP)
384
g_warning ("Unexpected use of ARBFP vertend!");
385
#endif /* COGL_PIPELINE_VERTEND_ARBFP */
387
ctx->current_vertex_program_type = type;
390
#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
393
blend_factor_uses_constant (GLenum blend_factor)
395
return (blend_factor == GL_CONSTANT_COLOR ||
396
blend_factor == GL_ONE_MINUS_CONSTANT_COLOR ||
397
blend_factor == GL_CONSTANT_ALPHA ||
398
blend_factor == GL_ONE_MINUS_CONSTANT_ALPHA);
404
flush_depth_state (CoglContext *ctx,
405
CoglDepthState *depth_state)
407
if (ctx->depth_test_enabled_cache != depth_state->test_enabled)
409
if (depth_state->test_enabled == TRUE)
410
GE (ctx, glEnable (GL_DEPTH_TEST));
412
GE (ctx, glDisable (GL_DEPTH_TEST));
413
ctx->depth_test_enabled_cache = depth_state->test_enabled;
416
if (ctx->depth_test_function_cache != depth_state->test_function &&
417
depth_state->test_enabled == TRUE)
419
GE (ctx, glDepthFunc (depth_state->test_function));
420
ctx->depth_test_function_cache = depth_state->test_function;
423
if (ctx->depth_writing_enabled_cache != depth_state->write_enabled)
425
GE (ctx, glDepthMask (depth_state->write_enabled ?
426
GL_TRUE : GL_FALSE));
427
ctx->depth_writing_enabled_cache = depth_state->write_enabled;
430
if (ctx->driver != COGL_DRIVER_GLES1 &&
431
(ctx->depth_range_near_cache != depth_state->range_near ||
432
ctx->depth_range_far_cache != depth_state->range_far))
434
if (ctx->driver == COGL_DRIVER_GLES2)
435
GE (ctx, glDepthRangef (depth_state->range_near,
436
depth_state->range_far));
438
GE (ctx, glDepthRange (depth_state->range_near,
439
depth_state->range_far));
441
ctx->depth_range_near_cache = depth_state->range_near;
442
ctx->depth_range_far_cache = depth_state->range_far;
447
_cogl_pipeline_flush_color_blend_alpha_depth_state (
448
CoglPipeline *pipeline,
449
unsigned long pipelines_difference,
450
CoglBool skip_gl_color)
452
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
454
/* On GLES2 we'll flush the color later */
455
if (ctx->driver != COGL_DRIVER_GLES2 &&
458
if ((pipelines_difference & COGL_PIPELINE_STATE_COLOR) ||
459
/* Assume if we were previously told to skip the color, then
460
* the current color needs updating... */
461
ctx->current_pipeline_skip_gl_color)
463
CoglPipeline *authority =
464
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
465
GE (ctx, glColor4ub (cogl_color_get_red_byte (&authority->color),
466
cogl_color_get_green_byte (&authority->color),
467
cogl_color_get_blue_byte (&authority->color),
468
cogl_color_get_alpha_byte (&authority->color)));
472
if (pipelines_difference & COGL_PIPELINE_STATE_BLEND)
474
CoglPipeline *authority =
475
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND);
476
CoglPipelineBlendState *blend_state =
477
&authority->big_state->blend_state;
479
/* GLES 1 only has glBlendFunc */
480
if (ctx->driver == COGL_DRIVER_GLES1)
482
GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb,
483
blend_state->blend_dst_factor_rgb));
485
#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
488
if (blend_factor_uses_constant (blend_state->blend_src_factor_rgb) ||
489
blend_factor_uses_constant (blend_state
490
->blend_src_factor_alpha) ||
491
blend_factor_uses_constant (blend_state->blend_dst_factor_rgb) ||
492
blend_factor_uses_constant (blend_state->blend_dst_factor_alpha))
495
cogl_color_get_red_float (&blend_state->blend_constant);
497
cogl_color_get_green_float (&blend_state->blend_constant);
499
cogl_color_get_blue_float (&blend_state->blend_constant);
501
cogl_color_get_alpha_float (&blend_state->blend_constant);
504
GE (ctx, glBlendColor (red, green, blue, alpha));
507
if (ctx->glBlendEquationSeparate &&
508
blend_state->blend_equation_rgb !=
509
blend_state->blend_equation_alpha)
511
glBlendEquationSeparate (blend_state->blend_equation_rgb,
512
blend_state->blend_equation_alpha));
514
GE (ctx, glBlendEquation (blend_state->blend_equation_rgb));
516
if (ctx->glBlendFuncSeparate &&
517
(blend_state->blend_src_factor_rgb !=
518
blend_state->blend_src_factor_alpha ||
519
(blend_state->blend_dst_factor_rgb !=
520
blend_state->blend_dst_factor_alpha)))
521
GE (ctx, glBlendFuncSeparate (blend_state->blend_src_factor_rgb,
522
blend_state->blend_dst_factor_rgb,
523
blend_state->blend_src_factor_alpha,
524
blend_state->blend_dst_factor_alpha));
526
GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb,
527
blend_state->blend_dst_factor_rgb));
532
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
534
if (ctx->driver != COGL_DRIVER_GLES2)
536
/* Under GLES2 the alpha function is implemented as part of the
538
if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC |
539
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE))
541
CoglPipeline *authority =
542
_cogl_pipeline_get_authority (pipeline,
543
COGL_PIPELINE_STATE_ALPHA_FUNC);
544
CoglPipelineAlphaFuncState *alpha_state =
545
&authority->big_state->alpha_state;
547
/* NB: Currently the Cogl defines are compatible with the GL ones: */
548
GE (ctx, glAlphaFunc (alpha_state->alpha_func,
549
alpha_state->alpha_func_reference));
552
/* Under GLES2 the lighting parameters are implemented as uniforms
554
if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING)
556
CoglPipeline *authority =
557
_cogl_pipeline_get_authority (pipeline,
558
COGL_PIPELINE_STATE_LIGHTING);
559
CoglPipelineLightingState *lighting_state =
560
&authority->big_state->lighting_state;
562
GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT,
563
lighting_state->ambient));
564
GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,
565
lighting_state->diffuse));
566
GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,
567
lighting_state->specular));
568
GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION,
569
lighting_state->emission));
570
GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS,
571
&lighting_state->shininess));
577
if (pipelines_difference & COGL_PIPELINE_STATE_DEPTH)
579
CoglPipeline *authority =
580
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
581
CoglDepthState *depth_state = &authority->big_state->depth_state;
583
flush_depth_state (ctx, depth_state);
586
if (pipelines_difference & COGL_PIPELINE_STATE_LOGIC_OPS)
588
CoglPipeline *authority =
589
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LOGIC_OPS);
590
CoglPipelineLogicOpsState *logic_ops_state = &authority->big_state->logic_ops_state;
591
CoglColorMask color_mask = logic_ops_state->color_mask;
593
if (ctx->current_draw_buffer)
594
color_mask &= ctx->current_draw_buffer->color_mask;
596
GE (ctx, glColorMask (!!(color_mask & COGL_COLOR_MASK_RED),
597
!!(color_mask & COGL_COLOR_MASK_GREEN),
598
!!(color_mask & COGL_COLOR_MASK_BLUE),
599
!!(color_mask & COGL_COLOR_MASK_ALPHA)));
600
ctx->current_gl_color_mask = color_mask;
603
if (pipelines_difference & COGL_PIPELINE_STATE_CULL_FACE)
605
CoglPipeline *authority =
606
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_CULL_FACE);
607
CoglPipelineCullFaceState *cull_face_state
608
= &authority->big_state->cull_face_state;
610
if (cull_face_state->mode == COGL_PIPELINE_CULL_FACE_MODE_NONE)
611
GE( ctx, glDisable (GL_CULL_FACE) );
614
CoglBool invert_winding;
616
GE( ctx, glEnable (GL_CULL_FACE) );
618
switch (cull_face_state->mode)
620
case COGL_PIPELINE_CULL_FACE_MODE_NONE:
621
g_assert_not_reached ();
623
case COGL_PIPELINE_CULL_FACE_MODE_FRONT:
624
GE( ctx, glCullFace (GL_FRONT) );
627
case COGL_PIPELINE_CULL_FACE_MODE_BACK:
628
GE( ctx, glCullFace (GL_BACK) );
631
case COGL_PIPELINE_CULL_FACE_MODE_BOTH:
632
GE( ctx, glCullFace (GL_FRONT_AND_BACK) );
636
/* If we are painting to an offscreen framebuffer then we
637
need to invert the winding of the front face because
638
everything is painted upside down */
639
invert_winding = cogl_is_offscreen (ctx->current_draw_buffer);
641
switch (cull_face_state->front_winding)
643
case COGL_WINDING_CLOCKWISE:
644
GE( ctx, glFrontFace (invert_winding ? GL_CCW : GL_CW) );
647
case COGL_WINDING_COUNTER_CLOCKWISE:
648
GE( ctx, glFrontFace (invert_winding ? GL_CW : GL_CCW) );
654
if (pipeline->real_blend_enable != ctx->gl_blend_enable_cache)
656
if (pipeline->real_blend_enable)
657
GE (ctx, glEnable (GL_BLEND));
659
GE (ctx, glDisable (GL_BLEND));
660
/* XXX: we shouldn't update any other blend state if blending
662
ctx->gl_blend_enable_cache = pipeline->real_blend_enable;
667
get_max_activateable_texture_units (void)
669
_COGL_GET_CONTEXT (ctx, 0);
671
if (G_UNLIKELY (ctx->max_activateable_texture_units == -1))
678
if (ctx->driver == COGL_DRIVER_GL)
680
/* GL_MAX_TEXTURE_COORDS is provided for both GLSL and ARBfp. It
681
defines the number of texture coordinates that can be
682
uploaded (but doesn't necessarily relate to how many texture
683
images can be sampled) */
684
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) ||
685
cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
686
/* Previously this code subtracted the value by one but there
687
was no explanation for why it did this and it doesn't seem
688
to make sense so it has been removed */
689
GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_COORDS,
690
values + n_values++));
692
/* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL but
694
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
695
GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
696
values + n_values++));
698
#endif /* HAVE_COGL_GL */
700
#ifdef HAVE_COGL_GLES2
701
if (ctx->driver == COGL_DRIVER_GLES2)
703
GE (ctx, glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, values + n_values));
704
/* Two of the vertex attribs need to be used for the position
706
values[n_values++] -= 2;
708
GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
709
values + n_values++));
713
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) /* not GLES2 */
714
if (ctx->driver != COGL_DRIVER_GLES2)
716
/* GL_MAX_TEXTURE_UNITS defines the number of units that are
717
usable from the fixed function pipeline, therefore it isn't
718
available in GLES2. These are also tied to the number of
719
texture coordinates that can be uploaded so it should be less
720
than that available from the shader extensions */
721
GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_UNITS,
722
values + n_values++));
727
g_assert (n_values <= G_N_ELEMENTS (values) &&
730
/* Use the maximum value */
731
ctx->max_activateable_texture_units = values[0];
732
for (i = 1; i < n_values; i++)
733
ctx->max_activateable_texture_units =
734
MAX (values[i], ctx->max_activateable_texture_units);
737
return ctx->max_activateable_texture_units;
743
unsigned long *layer_differences;
744
} CoglPipelineFlushLayerState;
747
flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data)
749
CoglPipelineFlushLayerState *flush_state = user_data;
750
int unit_index = flush_state->i;
751
CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index);
752
unsigned long layers_difference =
753
flush_state->layer_differences[unit_index];
755
_COGL_GET_CONTEXT (ctx, FALSE);
757
/* There may not be enough texture units so we can bail out if
760
if (G_UNLIKELY (unit_index >= get_max_activateable_texture_units ()))
762
static CoglBool shown_warning = FALSE;
766
g_warning ("Your hardware does not have enough texture units"
767
"to handle this many texture layers");
768
shown_warning = TRUE;
773
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
775
CoglTexture *texture = _cogl_pipeline_layer_get_texture_real (layer);
780
switch (_cogl_pipeline_layer_get_texture_type (layer))
782
case COGL_TEXTURE_TYPE_2D:
783
texture = COGL_TEXTURE (ctx->default_gl_texture_2d_tex);
785
case COGL_TEXTURE_TYPE_3D:
786
texture = COGL_TEXTURE (ctx->default_gl_texture_3d_tex);
788
case COGL_TEXTURE_TYPE_RECTANGLE:
789
texture = COGL_TEXTURE (ctx->default_gl_texture_rect_tex);
793
cogl_texture_get_gl_texture (texture,
797
_cogl_set_active_texture_unit (unit_index);
799
/* NB: There are several Cogl components and some code in
800
* Clutter that will temporarily bind arbitrary GL textures to
801
* query and modify texture object parameters. If you look at
802
* _cogl_bind_gl_texture_transient() you can see we make sure
803
* that such code always binds to texture unit 1 which means we
804
* can't rely on the unit->gl_texture state if unit->index == 1.
806
* Because texture unit 1 is a bit special we actually defer any
807
* necessary glBindTexture for it until the end of
808
* _cogl_pipeline_flush_gl_state().
810
* NB: we get notified whenever glDeleteTextures is used (see
811
* _cogl_delete_gl_texture()) where we invalidate
812
* unit->gl_texture references to deleted textures so it's safe
813
* to compare unit->gl_texture with gl_texture. (Without the
814
* hook it would be possible to delete a GL texture and create a
815
* new one with the same name and comparing unit->gl_texture and
816
* gl_texture wouldn't detect that.)
818
* NB: for foreign textures we don't know how the deletion of
819
* the GL texture objects correspond to the deletion of the
820
* CoglTextures so if there was previously a foreign texture
821
* associated with the texture unit then we can't assume that we
822
* aren't seeing a recycled texture name so we have to bind.
824
if (unit->gl_texture != gl_texture || unit->is_foreign)
827
unit->dirty_gl_texture = TRUE;
829
GE (ctx, glBindTexture (gl_target, gl_texture));
830
unit->gl_texture = gl_texture;
831
unit->gl_target = gl_target;
834
unit->is_foreign = _cogl_texture_is_foreign (texture);
836
/* The texture_storage_changed boolean indicates if the
837
* CoglTexture's underlying GL texture storage has changed since
838
* it was flushed to the texture unit. We've just flushed the
839
* latest state so we can reset this. */
840
unit->texture_storage_changed = FALSE;
843
if ((layers_difference & COGL_PIPELINE_LAYER_STATE_SAMPLER) &&
844
(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
846
const CoglSamplerCacheEntry *sampler_state;
848
sampler_state = _cogl_pipeline_layer_get_sampler_state (layer);
850
GE( ctx, glBindSampler (unit_index, sampler_state->sampler_object) );
853
/* Under GLES2 the fragment shader will use gl_PointCoord instead of
854
replacing the texture coordinates */
855
#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GL)
856
if (ctx->driver != COGL_DRIVER_GLES2 &&
857
(layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS))
859
CoglPipelineState change = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
860
CoglPipelineLayer *authority =
861
_cogl_pipeline_layer_get_authority (layer, change);
862
CoglPipelineLayerBigState *big_state = authority->big_state;
864
_cogl_set_active_texture_unit (unit_index);
866
GE (ctx, glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE,
867
big_state->point_sprite_coords));
871
cogl_object_ref (layer);
872
if (unit->layer != NULL)
873
cogl_object_unref (unit->layer);
876
unit->layer_changes_since_flush = 0;
884
_cogl_pipeline_flush_common_gl_state (CoglPipeline *pipeline,
885
unsigned long pipelines_difference,
886
unsigned long *layer_differences,
887
CoglBool skip_gl_color)
889
CoglPipelineFlushLayerState state;
891
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
893
_cogl_pipeline_flush_color_blend_alpha_depth_state (pipeline,
894
pipelines_difference,
898
state.layer_differences = layer_differences;
899
_cogl_pipeline_foreach_layer_internal (pipeline,
900
flush_layers_common_gl_state_cb,
904
/* Re-assert the layer's wrap modes on the given CoglTexture.
906
* Note: we don't simply forward the wrap modes to layer->texture
907
* since the actual texture being used may have been overridden.
910
_cogl_pipeline_layer_forward_wrap_modes (CoglPipelineLayer *layer,
911
CoglTexture *texture)
913
CoglSamplerCacheWrapMode wrap_mode_s, wrap_mode_t, wrap_mode_p;
914
GLenum gl_wrap_mode_s, gl_wrap_mode_t, gl_wrap_mode_p;
919
_cogl_pipeline_layer_get_wrap_modes (layer,
924
/* Update the wrap mode on the texture object. The texture backend
925
should cache the value so that it will be a no-op if the object
926
already has the same wrap mode set. The backend is best placed to
927
do this because it knows how many of the coordinates will
928
actually be used (ie, a 1D texture only cares about the 's'
929
coordinate but a 3D texture would use all three). GL uses the
930
wrap mode as part of the texture object state but we are
931
pretending it's part of the per-layer environment state. This
932
will break if the application tries to use different modes in
933
different layers using the same texture. */
935
if (wrap_mode_s == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC)
936
gl_wrap_mode_s = GL_CLAMP_TO_EDGE;
938
gl_wrap_mode_s = wrap_mode_s;
940
if (wrap_mode_t == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC)
941
gl_wrap_mode_t = GL_CLAMP_TO_EDGE;
943
gl_wrap_mode_t = wrap_mode_t;
945
if (wrap_mode_p == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC)
946
gl_wrap_mode_p = GL_CLAMP_TO_EDGE;
948
gl_wrap_mode_p = wrap_mode_p;
950
_cogl_texture_set_wrap_mode_parameters (texture,
956
/* OpenGL associates the min/mag filters and repeat modes with the
957
* texture object not the texture unit so we always have to re-assert
958
* the filter and repeat modes whenever we use a texture since it may
959
* be referenced by multiple pipelines with different modes.
961
* This function is bypassed in favour of sampler objects if
962
* GL_ARB_sampler_objects is advertised. This fallback won't work if
963
* the same texture is bound to multiple layers with different sampler
967
foreach_texture_unit_update_filter_and_wrap_modes (void)
971
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
973
for (i = 0; i < ctx->texture_units->len; i++)
975
CoglTextureUnit *unit =
976
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
980
CoglTexture *texture = _cogl_pipeline_layer_get_texture (unit->layer);
984
CoglPipelineFilter min;
985
CoglPipelineFilter mag;
987
_cogl_pipeline_layer_get_filters (unit->layer, &min, &mag);
988
_cogl_texture_set_filters (texture, min, mag);
990
_cogl_pipeline_layer_forward_wrap_modes (unit->layer, texture);
999
unsigned long *layer_differences;
1000
} CoglPipelineCompareLayersState;
1003
compare_layer_differences_cb (CoglPipelineLayer *layer, void *user_data)
1005
CoglPipelineCompareLayersState *state = user_data;
1006
CoglTextureUnit *unit = _cogl_get_texture_unit (state->i);
1008
if (unit->layer == layer)
1009
state->layer_differences[state->i] = unit->layer_changes_since_flush;
1010
else if (unit->layer)
1012
state->layer_differences[state->i] = unit->layer_changes_since_flush;
1013
state->layer_differences[state->i] |=
1014
_cogl_pipeline_layer_compare_differences (layer, unit->layer);
1017
state->layer_differences[state->i] = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE;
1019
/* XXX: There is always a possibility that a CoglTexture's
1020
* underlying GL texture storage has been changed since it was last
1021
* bound to a texture unit which is why we have a callback into
1022
* _cogl_pipeline_texture_storage_change_notify whenever a textures
1023
* underlying GL texture storage changes which will set the
1024
* unit->texture_intern_changed flag. If we see that's been set here
1025
* then we force an update of the texture state...
1027
if (unit->texture_storage_changed)
1028
state->layer_differences[state->i] |=
1029
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
1038
const CoglPipelineFragend *fragend;
1039
CoglPipeline *pipeline;
1040
unsigned long *layer_differences;
1041
CoglBool error_adding_layer;
1042
CoglBool added_layer;
1043
} CoglPipelineFragendAddLayerState;
1047
fragend_add_layer_cb (CoglPipelineLayer *layer,
1050
CoglPipelineFragendAddLayerState *state = user_data;
1051
const CoglPipelineFragend *fragend = state->fragend;
1052
CoglPipeline *pipeline = state->pipeline;
1053
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
1055
/* Either generate per layer code snippets or setup the
1056
* fixed function glTexEnv for each layer... */
1057
if (G_LIKELY (fragend->add_layer (pipeline,
1059
state->layer_differences[unit_index])))
1060
state->added_layer = TRUE;
1063
state->error_adding_layer = TRUE;
1072
CoglFramebuffer *framebuffer;
1073
const CoglPipelineVertend *vertend;
1074
CoglPipeline *pipeline;
1075
unsigned long *layer_differences;
1076
CoglBool error_adding_layer;
1077
CoglBool added_layer;
1078
} CoglPipelineVertendAddLayerState;
1082
vertend_add_layer_cb (CoglPipelineLayer *layer,
1085
CoglPipelineVertendAddLayerState *state = user_data;
1086
const CoglPipelineVertend *vertend = state->vertend;
1087
CoglPipeline *pipeline = state->pipeline;
1088
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
1090
/* Either enerate per layer code snippets or setup the
1091
* fixed function matrix uniforms for each layer... */
1092
if (G_LIKELY (vertend->add_layer (pipeline,
1094
state->layer_differences[unit_index],
1095
state->framebuffer)))
1096
state->added_layer = TRUE;
1099
state->error_adding_layer = TRUE;
1107
* _cogl_pipeline_flush_gl_state:
1109
* Details of override options:
1110
* ->fallback_mask: is a bitmask of the pipeline layers that need to be
1111
* replaced with the default, fallback textures. The fallback textures are
1112
* fully transparent textures so they hopefully wont contribute to the
1113
* texture combining.
1115
* The intention of fallbacks is to try and preserve
1116
* the number of layers the user is expecting so that texture coordinates
1117
* they gave will mostly still correspond to the textures they intended, and
1118
* have a fighting chance of looking close to their originally intended
1121
* ->disable_mask: is a bitmask of the pipeline layers that will simply have
1122
* texturing disabled. It's only really intended for disabling all layers
1123
* > X; i.e. we'd expect to see a contiguous run of 0 starting from the LSB
1124
* and at some point the remaining bits flip to 1. It might work to disable
1125
* arbitrary layers; though I'm not sure a.t.m how OpenGL would take to
1128
* The intention of the disable_mask is for emitting geometry when the user
1129
* hasn't supplied enough texture coordinates for all the layers and it's
1130
* not possible to auto generate default texture coordinates for those
1133
* ->layer0_override_texture: forcibly tells us to bind this GL texture name for
1134
* layer 0 instead of plucking the gl_texture from the CoglTexture of layer
1137
* The intention of this is for any primitives that supports sliced textures.
1138
* The code will can iterate each of the slices and re-flush the pipeline
1139
* forcing the GL texture of each slice in turn.
1141
* ->wrap_mode_overrides: overrides the wrap modes set on each
1142
* layer. This is used to implement the automatic wrap mode.
1144
* XXX: It might also help if we could specify a texture matrix for code
1145
* dealing with slicing that would be multiplied with the users own matrix.
1147
* Normaly texture coords in the range [0, 1] refer to the extents of the
1148
* texture, but when your GL texture represents a slice of the real texture
1149
* (from the users POV) then a texture matrix would be a neat way of
1150
* transforming the mapping for each slice.
1152
* Currently for textured rectangles we manually calculate the texture
1153
* coords for each slice based on the users given coords, but this solution
1154
* isn't ideal, and can't be used with CoglVertexBuffers.
1157
_cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
1158
CoglFramebuffer *framebuffer,
1159
CoglBool skip_gl_color,
1160
int n_tex_coord_attribs)
1162
unsigned long pipelines_difference;
1164
unsigned long *layer_differences;
1166
CoglTextureUnit *unit1;
1168
COGL_STATIC_TIMER (pipeline_flush_timer,
1169
"Mainloop", /* parent */
1171
"The time spent flushing material state",
1172
0 /* no application private data */);
1174
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
1176
COGL_TIMER_START (_cogl_uprof_context, pipeline_flush_timer);
1178
if (ctx->current_pipeline == pipeline)
1180
/* Bail out asap if we've been asked to re-flush the already current
1181
* pipeline and we can see the pipeline hasn't changed */
1182
if (ctx->current_pipeline_age == pipeline->age &&
1183
ctx->current_pipeline_skip_gl_color == skip_gl_color)
1186
pipelines_difference = ctx->current_pipeline_changes_since_flush;
1188
else if (ctx->current_pipeline)
1190
pipelines_difference = ctx->current_pipeline_changes_since_flush;
1191
pipelines_difference |=
1192
_cogl_pipeline_compare_differences (ctx->current_pipeline,
1196
pipelines_difference = COGL_PIPELINE_STATE_ALL_SPARSE;
1198
/* Get a layer_differences mask for each layer to be flushed */
1199
n_layers = cogl_pipeline_get_n_layers (pipeline);
1202
CoglPipelineCompareLayersState state;
1203
layer_differences = g_alloca (sizeof (unsigned long *) * n_layers);
1204
memset (layer_differences, 0, sizeof (layer_differences));
1206
state.layer_differences = layer_differences;
1207
_cogl_pipeline_foreach_layer_internal (pipeline,
1208
compare_layer_differences_cb,
1212
layer_differences = NULL;
1214
/* Make sure we generate the texture coordinate array to be at least
1215
the number of layers. This is important because the vertend will
1216
try to pass along the corresponding varying for each layer
1217
regardless of whether the fragment shader is actually using
1218
it. Also it is possible that the application is assuming that if
1219
the attribute isn't passed then it will default to 0,0. This is
1220
what test-cogl-primitive does */
1221
if (n_layers > n_tex_coord_attribs)
1222
n_tex_coord_attribs = n_layers;
1224
/* First flush everything that's the same regardless of which
1225
* pipeline backend is being used...
1227
* 1) top level state:
1228
* glColor (or skip if a vertex attribute is being used for color)
1230
* alpha test state (except for GLES 2.0)
1232
* 2) then foreach layer:
1233
* determine gl_target/gl_texture
1236
* Note: After _cogl_pipeline_flush_common_gl_state you can expect
1237
* all state of the layers corresponding texture unit to be
1240
_cogl_pipeline_flush_common_gl_state (pipeline,
1241
pipelines_difference,
1245
/* Now flush the fragment processing state according to the current
1246
* fragment processing backend.
1248
* Note: Some of the backends may not support the current pipeline
1249
* configuration and in that case it will report an error and we
1250
* will fallback to a different backend.
1252
* NB: if pipeline->backend != COGL_PIPELINE_FRAGEND_UNDEFINED then
1253
* we have previously managed to successfully flush this pipeline
1254
* with the given backend so we will simply use that to avoid
1255
* fallback code paths.
1258
if (pipeline->fragend == COGL_PIPELINE_FRAGEND_UNDEFINED)
1259
_cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_DEFAULT);
1261
for (i = pipeline->fragend;
1262
i < G_N_ELEMENTS (_cogl_pipeline_fragends);
1263
i++, _cogl_pipeline_set_fragend (pipeline, i))
1265
const CoglPipelineFragend *fragend = _cogl_pipeline_fragends[i];
1266
CoglPipelineFragendAddLayerState state;
1268
/* E.g. For fragends generating code they can setup their
1269
* scratch buffers here... */
1270
if (G_UNLIKELY (!fragend->start (pipeline,
1272
pipelines_difference,
1273
n_tex_coord_attribs)))
1276
state.fragend = fragend;
1277
state.pipeline = pipeline;
1278
state.layer_differences = layer_differences;
1279
state.error_adding_layer = FALSE;
1280
state.added_layer = FALSE;
1281
_cogl_pipeline_foreach_layer_internal (pipeline,
1282
fragend_add_layer_cb,
1285
if (G_UNLIKELY (state.error_adding_layer))
1288
if (!state.added_layer &&
1289
fragend->passthrough &&
1290
G_UNLIKELY (!fragend->passthrough (pipeline)))
1293
/* For fragends generating code they may compile and link their
1294
* programs here, update any uniforms and tell OpenGL to use
1297
if (G_UNLIKELY (!fragend->end (pipeline, pipelines_difference)))
1303
if (G_UNLIKELY (i >= G_N_ELEMENTS (_cogl_pipeline_fragends)))
1304
g_warning ("No usable pipeline fragment backend was found!");
1306
/* Now flush the vertex processing state according to the current
1307
* vertex processing backend.
1310
if (pipeline->vertend == COGL_PIPELINE_VERTEND_UNDEFINED)
1311
_cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_DEFAULT);
1313
for (i = pipeline->vertend;
1314
i < G_N_ELEMENTS (_cogl_pipeline_vertends);
1315
i++, _cogl_pipeline_set_vertend (pipeline, i))
1317
const CoglPipelineVertend *vertend = _cogl_pipeline_vertends[i];
1318
CoglPipelineVertendAddLayerState state;
1320
/* E.g. For vertends generating code they can setup their
1321
* scratch buffers here... */
1322
if (G_UNLIKELY (!vertend->start (pipeline,
1324
pipelines_difference,
1325
n_tex_coord_attribs)))
1328
state.framebuffer = framebuffer;
1329
state.vertend = vertend;
1330
state.pipeline = pipeline;
1331
state.layer_differences = layer_differences;
1332
state.error_adding_layer = FALSE;
1333
state.added_layer = FALSE;
1334
_cogl_pipeline_foreach_layer_internal (pipeline,
1335
vertend_add_layer_cb,
1338
if (G_UNLIKELY (state.error_adding_layer))
1341
/* For vertends generating code they may compile and link their
1342
* programs here, update any uniforms and tell OpenGL to use
1345
if (G_UNLIKELY (!vertend->end (pipeline, pipelines_difference)))
1351
if (G_UNLIKELY (i >= G_N_ELEMENTS (_cogl_pipeline_vertends)))
1352
g_warning ("No usable pipeline vertex backend was found!");
1354
for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
1355
if (_cogl_pipeline_progends[i]->end)
1356
_cogl_pipeline_progends[i]->end (pipeline, pipelines_difference,
1357
n_tex_coord_attribs);
1359
/* FIXME: This reference is actually resulting in lots of
1360
* copy-on-write reparenting because one-shot pipelines end up
1361
* living for longer than necessary and so any later modification of
1362
* the parent will cause a copy-on-write.
1364
* XXX: The issue should largely go away when we switch to using
1365
* weak pipelines for overrides.
1367
cogl_object_ref (pipeline);
1368
if (ctx->current_pipeline != NULL)
1369
cogl_object_unref (ctx->current_pipeline);
1370
ctx->current_pipeline = pipeline;
1371
ctx->current_pipeline_changes_since_flush = 0;
1372
ctx->current_pipeline_skip_gl_color = skip_gl_color;
1373
ctx->current_pipeline_age = pipeline->age;
1377
/* We can't assume the color will be retained between flushes on
1378
GLES2 because the generic attribute values are not stored as part
1379
of the program object so they could be overridden by any
1380
attribute changes in another program */
1381
#ifdef HAVE_COGL_GLES2
1382
if (ctx->driver == COGL_DRIVER_GLES2 && !skip_gl_color)
1385
CoglPipeline *authority =
1386
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
1387
int name_index = COGL_ATTRIBUTE_COLOR_NAME_INDEX;
1390
_cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index);
1391
if (attribute != -1)
1393
glVertexAttrib4f (attribute,
1394
cogl_color_get_red_float (&authority->color),
1395
cogl_color_get_green_float (&authority->color),
1396
cogl_color_get_blue_float (&authority->color),
1397
cogl_color_get_alpha_float (&authority->color)));
1401
/* Give any progends a chance to update any uniforms that might not
1402
depend on the material state. This is used on GLES2 to update the
1404
for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
1405
if (_cogl_pipeline_progends[i]->pre_paint)
1406
_cogl_pipeline_progends[i]->pre_paint (pipeline, framebuffer);
1408
/* Handle the fact that OpenGL associates texture filter and wrap
1409
* modes with the texture objects not the texture units... */
1410
if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
1411
foreach_texture_unit_update_filter_and_wrap_modes ();
1413
/* If this pipeline has more than one layer then we always need
1414
* to make sure we rebind the texture for unit 1.
1416
* NB: various components of Cogl may temporarily bind arbitrary
1417
* textures to texture unit 1 so they can query and modify texture
1418
* object parameters. cogl-pipeline.c (See
1419
* _cogl_bind_gl_texture_transient)
1421
unit1 = _cogl_get_texture_unit (1);
1422
if (cogl_pipeline_get_n_layers (pipeline) > 1 && unit1->dirty_gl_texture)
1424
_cogl_set_active_texture_unit (1);
1425
GE (ctx, glBindTexture (unit1->gl_target, unit1->gl_texture));
1426
unit1->dirty_gl_texture = FALSE;
1429
COGL_TIMER_STOP (_cogl_uprof_context, pipeline_flush_timer);