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-util.h"
33
#include "cogl-context-private.h"
34
#include "cogl-texture-private.h"
36
#include "cogl-pipeline.h"
37
#include "cogl-pipeline-layer-private.h"
38
#include "cogl-pipeline-layer-state-private.h"
39
#include "cogl-pipeline-layer-state.h"
40
#include "cogl-node-private.h"
41
#include "cogl-pipeline-opengl-private.h"
42
#include "cogl-context-private.h"
43
#include "cogl-texture-private.h"
46
_cogl_pipeline_layer_free (CoglPipelineLayer *layer);
48
/* This type was made deprecated before the cogl_is_pipeline_layer
49
function was ever exposed in the public headers so there's no need
50
to make the cogl_is_pipeline_layer function public. We use INTERNAL
51
so that the cogl_is_* function won't get defined */
52
COGL_OBJECT_INTERNAL_DEFINE (PipelineLayer, pipeline_layer);
56
_cogl_pipeline_layer_get_authority (CoglPipelineLayer *layer,
57
unsigned long difference)
59
CoglPipelineLayer *authority = layer;
60
while (!(authority->differences & difference))
61
authority = _cogl_pipeline_layer_get_parent (authority);
66
_cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer)
68
CoglPipelineLayer *authority =
69
_cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_UNIT);
70
return authority->unit_index;
74
_cogl_pipeline_layer_has_alpha (CoglPipelineLayer *layer)
76
CoglPipelineLayer *combine_authority =
77
_cogl_pipeline_layer_get_authority (layer,
78
COGL_PIPELINE_LAYER_STATE_COMBINE);
79
CoglPipelineLayerBigState *big_state = combine_authority->big_state;
80
CoglPipelineLayer *tex_authority;
81
CoglPipelineLayer *snippets_authority;
83
/* has_alpha maintains the alpha status for the GL_PREVIOUS layer */
85
/* For anything but the default texture combine we currently just
86
* assume it may result in an alpha value < 1
88
* FIXME: we could do better than this. */
89
if (big_state->texture_combine_alpha_func !=
90
COGL_PIPELINE_COMBINE_FUNC_MODULATE ||
91
big_state->texture_combine_alpha_src[0] !=
92
COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS ||
93
big_state->texture_combine_alpha_op[0] !=
94
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA ||
95
big_state->texture_combine_alpha_src[1] !=
96
COGL_PIPELINE_COMBINE_SOURCE_TEXTURE ||
97
big_state->texture_combine_alpha_op[1] !=
98
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA)
103
/* NB: A layer may have a combine mode set on it but not yet
104
* have an associated texture which would mean we'd fallback
105
* to the default texture which doesn't have an alpha component
108
_cogl_pipeline_layer_get_authority (layer,
109
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
110
if (tex_authority->texture &&
111
cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT)
116
/* All bets are off if the layer contains any snippets */
117
snippets_authority = _cogl_pipeline_layer_get_authority
118
(layer, COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS);
119
if (!COGL_LIST_EMPTY (&snippets_authority->big_state->vertex_snippets))
121
snippets_authority = _cogl_pipeline_layer_get_authority
122
(layer, COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS);
123
if (!COGL_LIST_EMPTY (&snippets_authority->big_state->fragment_snippets))
130
_cogl_get_n_args_for_combine_func (CoglPipelineCombineFunc func)
134
case COGL_PIPELINE_COMBINE_FUNC_REPLACE:
136
case COGL_PIPELINE_COMBINE_FUNC_MODULATE:
137
case COGL_PIPELINE_COMBINE_FUNC_ADD:
138
case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED:
139
case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT:
140
case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB:
141
case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA:
143
case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE:
150
_cogl_pipeline_layer_init_multi_property_sparse_state (
151
CoglPipelineLayer *layer,
152
CoglPipelineLayerState change)
154
CoglPipelineLayer *authority;
156
/* Nothing to initialize in these cases since they are all comprised
157
* of one member which we expect to immediately be overwritten. */
158
if (!(change & COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY))
161
authority = _cogl_pipeline_layer_get_authority (layer, change);
165
/* XXX: avoid using a default: label so we get a warning if we
166
* don't explicitly handle a newly defined state-group here. */
167
case COGL_PIPELINE_LAYER_STATE_UNIT:
168
case COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE:
169
case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA:
170
case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS:
171
case COGL_PIPELINE_LAYER_STATE_USER_MATRIX:
172
case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT:
173
g_return_if_reached ();
175
/* XXX: technically we could probably even consider these as
176
* single property state-groups from the pov that currently the
177
* corresponding property setters always update all of the values
178
* at the same time. */
179
case COGL_PIPELINE_LAYER_STATE_FILTERS:
180
layer->min_filter = authority->min_filter;
181
layer->mag_filter = authority->mag_filter;
183
case COGL_PIPELINE_LAYER_STATE_WRAP_MODES:
184
layer->wrap_mode_s = authority->wrap_mode_s;
185
layer->wrap_mode_t = authority->wrap_mode_t;
186
layer->wrap_mode_p = authority->wrap_mode_p;
188
case COGL_PIPELINE_LAYER_STATE_COMBINE:
192
CoglPipelineLayerBigState *src_big_state = authority->big_state;
193
CoglPipelineLayerBigState *dest_big_state = layer->big_state;
194
GLint func = src_big_state->texture_combine_rgb_func;
196
dest_big_state->texture_combine_rgb_func = func;
197
n_args = _cogl_get_n_args_for_combine_func (func);
198
for (i = 0; i < n_args; i++)
200
dest_big_state->texture_combine_rgb_src[i] =
201
src_big_state->texture_combine_rgb_src[i];
202
dest_big_state->texture_combine_rgb_op[i] =
203
src_big_state->texture_combine_rgb_op[i];
206
func = src_big_state->texture_combine_alpha_func;
207
dest_big_state->texture_combine_alpha_func = func;
208
n_args = _cogl_get_n_args_for_combine_func (func);
209
for (i = 0; i < n_args; i++)
211
dest_big_state->texture_combine_alpha_src[i] =
212
src_big_state->texture_combine_alpha_src[i];
213
dest_big_state->texture_combine_alpha_op[i] =
214
src_big_state->texture_combine_alpha_op[i];
218
case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS:
219
_cogl_pipeline_snippet_list_copy (&layer->big_state->vertex_snippets,
220
&authority->big_state->
223
case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS:
224
_cogl_pipeline_snippet_list_copy (&layer->big_state->fragment_snippets,
225
&authority->big_state->
231
/* NB: If a layer has descendants we can't modify the layer
232
* NB: If the layer is owned and the owner has descendants we can't
235
* This function will allocate a new derived layer if you are trying
236
* to change the state of a layer with dependants (as described above)
237
* so you must always check the return value.
239
* If a new layer is returned it will be owned by required_owner.
240
* (NB: a layer is always modified with respect to a pipeline - the
243
* required_owner can only by NULL for new, currently unowned layers
244
* with no dependants.
247
_cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
248
CoglPipelineLayer *layer,
249
CoglPipelineLayerState change)
251
CoglTextureUnit *unit;
253
/* Identify the case where the layer is new with no owner or
254
* dependants and so we don't need to do anything. */
255
if (COGL_LIST_EMPTY (&COGL_NODE (layer)->children) &&
256
layer->owner == NULL)
257
goto init_layer_state;
259
/* We only allow a NULL required_owner for new layers */
260
_COGL_RETURN_VAL_IF_FAIL (required_owner != NULL, layer);
263
* A modification of a layer is indirectly also a modification of
264
* its owner so first make sure to flush the journal of any
265
* references to the current owner state and if necessary perform
266
* a copy-on-write for the required_owner if it has dependants.
268
_cogl_pipeline_pre_change_notify (required_owner,
269
COGL_PIPELINE_STATE_LAYERS,
273
/* Unlike pipelines; layers are simply considered immutable once
274
* they have dependants - either direct children, or another
275
* pipeline as an owner.
277
if (!COGL_LIST_EMPTY (&COGL_NODE (layer)->children) ||
278
layer->owner != required_owner)
280
CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer);
281
if (layer->owner == required_owner)
282
_cogl_pipeline_remove_layer_difference (required_owner, layer, FALSE);
283
_cogl_pipeline_add_layer_difference (required_owner, new, FALSE);
284
cogl_object_unref (new);
286
goto init_layer_state;
289
/* Note: At this point we know there is only one pipeline dependant on
290
* this layer (required_owner), and there are no other layers
291
* dependant on this layer so it's ok to modify it. */
293
_cogl_pipeline_fragend_layer_change_notify (required_owner, layer, change);
294
_cogl_pipeline_vertend_layer_change_notify (required_owner, layer, change);
295
_cogl_pipeline_progend_layer_change_notify (required_owner, layer, change);
297
/* If the layer being changed is the same as the last layer we
298
* flushed to the corresponding texture unit then we keep a track of
299
* the changes so we can try to minimize redundant OpenGL calls if
300
* the same layer is flushed again.
302
unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
303
if (unit->layer == layer)
304
unit->layer_changes_since_flush |= change;
309
required_owner->age++;
311
if (change & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE &&
312
!layer->has_big_state)
314
layer->big_state = g_slice_new (CoglPipelineLayerBigState);
315
layer->has_big_state = TRUE;
318
/* Note: conceptually we have just been notified that a single
319
* property value is about to change, but since some state-groups
320
* contain multiple properties and 'layer' is about to take over
321
* being the authority for the property's corresponding state-group
322
* we need to maintain the integrity of the other property values
325
* To ensure this we handle multi-property state-groups by copying
326
* all the values from the old-authority to the new...
328
* We don't have to worry about non-sparse property groups since
329
* we never take over being an authority for such properties so
330
* they automatically maintain integrity.
332
if (change & COGL_PIPELINE_LAYER_STATE_ALL_SPARSE &&
333
!(layer->differences & change))
335
_cogl_pipeline_layer_init_multi_property_sparse_state (layer, change);
336
layer->differences |= change;
343
_cogl_pipeline_layer_unparent (CoglNode *layer)
346
_cogl_pipeline_node_unparent_real (layer);
350
_cogl_pipeline_layer_set_parent (CoglPipelineLayer *layer,
351
CoglPipelineLayer *parent)
354
_cogl_pipeline_node_set_parent_real (COGL_NODE (layer),
356
_cogl_pipeline_layer_unparent,
361
_cogl_pipeline_layer_copy (CoglPipelineLayer *src)
363
CoglPipelineLayer *layer = g_slice_new (CoglPipelineLayer);
365
_cogl_pipeline_node_init (COGL_NODE (layer));
368
layer->index = src->index;
369
layer->differences = 0;
370
layer->has_big_state = FALSE;
372
_cogl_pipeline_layer_set_parent (layer, src);
374
return _cogl_pipeline_layer_object_new (layer);
377
/* XXX: This is duplicated logic; the same as for
378
* _cogl_pipeline_prune_redundant_ancestry it would be nice to find a
379
* way to consolidate these functions! */
381
_cogl_pipeline_layer_prune_redundant_ancestry (CoglPipelineLayer *layer)
383
CoglPipelineLayer *new_parent = _cogl_pipeline_layer_get_parent (layer);
385
/* walk up past ancestors that are now redundant and potentially
386
* reparent the layer. */
387
while (_cogl_pipeline_layer_get_parent (new_parent) &&
388
(new_parent->differences | layer->differences) ==
390
new_parent = _cogl_pipeline_layer_get_parent (new_parent);
392
_cogl_pipeline_layer_set_parent (layer, new_parent);
395
/* Determine the mask of differences between two layers.
397
* XXX: If layers and pipelines could both be cast to a common Tree
398
* type of some kind then we could have a unified
399
* compare_differences() function.
402
_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0,
403
CoglPipelineLayer *layer1)
405
GSList *head0 = NULL;
406
GSList *head1 = NULL;
407
CoglPipelineLayer *node0;
408
CoglPipelineLayer *node1;
412
GSList *common_ancestor0;
413
GSList *common_ancestor1;
414
unsigned long layers_difference = 0;
418
* 1) Walk the ancestors of each layer to the root node, adding a
419
* pointer to each ancester node to two linked lists
421
* 2) Compare the lists to find the nodes where they start to
422
* differ marking the common_ancestor node for each list.
424
* 3) For each list now iterate starting after the common_ancestor
425
* nodes ORing each nodes ->difference mask into the final
429
for (node0 = layer0; node0; node0 = _cogl_pipeline_layer_get_parent (node0))
431
GSList *link = alloca (sizeof (GSList));
437
for (node1 = layer1; node1; node1 = _cogl_pipeline_layer_get_parent (node1))
439
GSList *link = alloca (sizeof (GSList));
446
/* NB: There's no point looking at the head entries since we know both layers
447
* must have the same default layer as their root node. */
448
common_ancestor0 = head0;
449
common_ancestor1 = head1;
452
count = MIN (len0, len1) - 1;
455
if (head0->data != head1->data)
457
common_ancestor0 = head0;
458
common_ancestor1 = head1;
463
for (head0 = common_ancestor0->next; head0; head0 = head0->next)
466
layers_difference |= node0->differences;
468
for (head1 = common_ancestor1->next; head1; head1 = head1->next)
471
layers_difference |= node1->differences;
474
return layers_difference;
478
layer_state_equal (CoglPipelineLayerStateIndex state_index,
479
CoglPipelineLayer **authorities0,
480
CoglPipelineLayer **authorities1,
481
CoglPipelineLayerStateComparitor comparitor)
483
return comparitor (authorities0[state_index], authorities1[state_index]);
487
_cogl_pipeline_layer_resolve_authorities (CoglPipelineLayer *layer,
488
unsigned long differences,
489
CoglPipelineLayer **authorities)
491
unsigned long remaining = differences;
492
CoglPipelineLayer *authority = layer;
496
unsigned long found = authority->differences & remaining;
502
for (i = 0; TRUE; i++)
504
unsigned long state = (1L<<i);
507
authorities[i] = authority;
508
else if (state > found)
516
while ((authority = _cogl_pipeline_layer_get_parent (authority)));
518
g_assert (remaining == 0);
522
_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
523
CoglPipelineLayer *layer1,
524
unsigned long differences_mask,
525
CoglPipelineEvalFlags flags)
527
unsigned long layers_difference;
528
CoglPipelineLayer *authorities0[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
529
CoglPipelineLayer *authorities1[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
531
if (layer0 == layer1)
535
_cogl_pipeline_layer_compare_differences (layer0, layer1);
537
/* Only compare the sparse state groups requested by the caller... */
538
layers_difference &= differences_mask;
540
_cogl_pipeline_layer_resolve_authorities (layer0,
543
_cogl_pipeline_layer_resolve_authorities (layer1,
547
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE)
549
CoglPipelineLayerStateIndex state_index =
550
COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX;
551
if (!_cogl_pipeline_layer_texture_type_equal (authorities0[state_index],
552
authorities1[state_index],
557
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
559
CoglPipelineLayerStateIndex state_index =
560
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX;
561
if (!_cogl_pipeline_layer_texture_data_equal (authorities0[state_index],
562
authorities1[state_index],
567
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE &&
568
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
569
authorities0, authorities1,
570
_cogl_pipeline_layer_combine_state_equal))
573
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT &&
574
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
575
authorities0, authorities1,
576
_cogl_pipeline_layer_combine_constant_equal))
579
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FILTERS &&
580
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
581
authorities0, authorities1,
582
_cogl_pipeline_layer_filters_equal))
585
if (layers_difference & COGL_PIPELINE_LAYER_STATE_WRAP_MODES &&
586
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
587
authorities0, authorities1,
588
_cogl_pipeline_layer_wrap_modes_equal))
591
if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX &&
592
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
593
authorities0, authorities1,
594
_cogl_pipeline_layer_user_matrix_equal))
597
if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS &&
598
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
599
authorities0, authorities1,
600
_cogl_pipeline_layer_point_sprite_coords_equal))
603
if (layers_difference & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS &&
604
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
605
authorities0, authorities1,
606
_cogl_pipeline_layer_vertex_snippets_equal))
609
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS &&
610
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
611
authorities0, authorities1,
612
_cogl_pipeline_layer_fragment_snippets_equal))
619
_cogl_pipeline_layer_free (CoglPipelineLayer *layer)
621
_cogl_pipeline_layer_unparent (COGL_NODE (layer));
623
if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA &&
624
layer->texture != NULL)
625
cogl_object_unref (layer->texture);
627
if (layer->differences & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS)
628
_cogl_pipeline_snippet_list_free (&layer->big_state->vertex_snippets);
630
if (layer->differences & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
631
_cogl_pipeline_snippet_list_free (&layer->big_state->fragment_snippets);
633
if (layer->differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE)
634
g_slice_free (CoglPipelineLayerBigState, layer->big_state);
636
g_slice_free (CoglPipelineLayer, layer);
640
_cogl_pipeline_init_default_layers (void)
642
CoglPipelineLayer *layer = g_slice_new0 (CoglPipelineLayer);
643
CoglPipelineLayerBigState *big_state =
644
g_slice_new0 (CoglPipelineLayerBigState);
645
CoglPipelineLayer *new;
647
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
649
_cogl_pipeline_node_init (COGL_NODE (layer));
653
layer->differences = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE;
655
layer->unit_index = 0;
657
layer->texture = NULL;
658
layer->texture_type = COGL_TEXTURE_TYPE_2D;
660
layer->mag_filter = COGL_PIPELINE_FILTER_LINEAR;
661
layer->min_filter = COGL_PIPELINE_FILTER_LINEAR;
663
layer->wrap_mode_s = COGL_PIPELINE_WRAP_MODE_AUTOMATIC;
664
layer->wrap_mode_t = COGL_PIPELINE_WRAP_MODE_AUTOMATIC;
665
layer->wrap_mode_p = COGL_PIPELINE_WRAP_MODE_AUTOMATIC;
667
layer->big_state = big_state;
668
layer->has_big_state = TRUE;
670
/* Choose the same default combine mode as OpenGL:
671
* RGBA = MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */
672
big_state->texture_combine_rgb_func =
673
COGL_PIPELINE_COMBINE_FUNC_MODULATE;
674
big_state->texture_combine_rgb_src[0] =
675
COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS;
676
big_state->texture_combine_rgb_src[1] =
677
COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
678
big_state->texture_combine_rgb_op[0] =
679
COGL_PIPELINE_COMBINE_OP_SRC_COLOR;
680
big_state->texture_combine_rgb_op[1] =
681
COGL_PIPELINE_COMBINE_OP_SRC_COLOR;
682
big_state->texture_combine_alpha_func =
683
COGL_PIPELINE_COMBINE_FUNC_MODULATE;
684
big_state->texture_combine_alpha_src[0] =
685
COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS;
686
big_state->texture_combine_alpha_src[1] =
687
COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
688
big_state->texture_combine_alpha_op[0] =
689
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA;
690
big_state->texture_combine_alpha_op[1] =
691
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA;
693
big_state->point_sprite_coords = FALSE;
695
cogl_matrix_init_identity (&big_state->matrix);
697
ctx->default_layer_0 = _cogl_pipeline_layer_object_new (layer);
699
/* TODO: we should make default_layer_n comprise of two
700
* descendants of default_layer_0:
701
* - the first descendant should change the texture combine
702
* to what we expect is most commonly used for multitexturing
703
* - the second should revert the above change.
705
* why? the documentation for how a new layer is initialized
706
* doesn't say that layers > 0 have different defaults so unless
707
* we change the documentation we can't use different defaults,
708
* but if the user does what we expect and changes the
709
* texture combine then we can revert the authority to the
710
* first descendant which means we can maximize the number
711
* of layers with a common ancestor.
713
* The main problem will be that we'll need to disable the
714
* optimizations for flattening the ancestry when we make
715
* the second descendant which reverts the state.
717
ctx->default_layer_n = _cogl_pipeline_layer_copy (layer);
718
new = _cogl_pipeline_set_layer_unit (NULL, ctx->default_layer_n, 1);
719
g_assert (new == ctx->default_layer_n);
720
/* Since we passed a newly allocated layer we don't expect that
721
* _set_layer_unit() will have to allocate *another* layer. */
723
/* Finally we create a dummy dependant for ->default_layer_n which
724
* effectively ensures that ->default_layer_n and ->default_layer_0
727
ctx->dummy_layer_dependant =
728
_cogl_pipeline_layer_copy (ctx->default_layer_n);
732
_cogl_pipeline_layer_pre_paint (CoglPipelineLayer *layer)
734
CoglPipelineLayer *texture_authority;
737
_cogl_pipeline_layer_get_authority (layer,
738
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
740
if (texture_authority->texture != NULL)
742
CoglTexturePrePaintFlags flags = 0;
743
CoglPipelineFilter min_filter;
744
CoglPipelineFilter mag_filter;
746
_cogl_pipeline_layer_get_filters (layer, &min_filter, &mag_filter);
748
if (min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST
749
|| min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST
750
|| min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR
751
|| min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR)
752
flags |= COGL_TEXTURE_NEEDS_MIPMAP;
754
_cogl_texture_pre_paint (texture_authority->texture, flags);
758
/* Determines if we need to handle the RGB and A texture combining
759
* separately or is the same function used for both channel masks and
760
* with the same arguments...
763
_cogl_pipeline_layer_needs_combine_separate
764
(CoglPipelineLayer *combine_authority)
766
CoglPipelineLayerBigState *big_state = combine_authority->big_state;
770
if (big_state->texture_combine_rgb_func !=
771
big_state->texture_combine_alpha_func)
774
n_args = _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func);
776
for (i = 0; i < n_args; i++)
778
if (big_state->texture_combine_rgb_src[i] !=
779
big_state->texture_combine_alpha_src[i])
783
* We can allow some variation of the source operands without
784
* needing a separation...
786
* "A = REPLACE (CONSTANT[A])" + either of the following...
787
* "RGB = REPLACE (CONSTANT[RGB])"
788
* "RGB = REPLACE (CONSTANT[A])"
790
* can be combined as:
791
* "RGBA = REPLACE (CONSTANT)" or
792
* "RGBA = REPLACE (CONSTANT[A])" or
794
* And "A = REPLACE (1-CONSTANT[A])" + either of the following...
795
* "RGB = REPLACE (1-CONSTANT)" or
796
* "RGB = REPLACE (1-CONSTANT[A])"
798
* can be combined as:
799
* "RGBA = REPLACE (1-CONSTANT)" or
800
* "RGBA = REPLACE (1-CONSTANT[A])"
802
switch (big_state->texture_combine_alpha_op[i])
805
switch (big_state->texture_combine_rgb_op[i])
814
case GL_ONE_MINUS_SRC_ALPHA:
815
switch (big_state->texture_combine_rgb_op[i])
817
case GL_ONE_MINUS_SRC_COLOR:
818
case GL_ONE_MINUS_SRC_ALPHA:
825
return FALSE; /* impossible */