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 */