2011-09-08 23:40:06 +00:00
|
|
|
/*
|
|
|
|
* Cogl
|
|
|
|
*
|
|
|
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008,2009,2010 Intel Corporation.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Robert Bragg <robert@linux.intel.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-10-13 21:34:30 +00:00
|
|
|
#include "cogl-util.h"
|
2011-09-23 08:43:05 +00:00
|
|
|
#include "cogl-context-private.h"
|
|
|
|
#include "cogl-texture-private.h"
|
|
|
|
|
2011-09-08 23:40:06 +00:00
|
|
|
#include "cogl-pipeline.h"
|
|
|
|
#include "cogl-pipeline-layer-private.h"
|
|
|
|
#include "cogl-pipeline-layer-state-private.h"
|
|
|
|
#include "cogl-pipeline-layer-state.h"
|
|
|
|
#include "cogl-node-private.h"
|
|
|
|
#include "cogl-pipeline-opengl-private.h"
|
|
|
|
#include "cogl-context-private.h"
|
2011-10-12 15:56:40 +00:00
|
|
|
#include "cogl-texture-private.h"
|
2011-09-08 23:40:06 +00:00
|
|
|
|
2013-03-26 11:17:55 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2011-09-08 23:40:06 +00:00
|
|
|
static void
|
|
|
|
_cogl_pipeline_layer_free (CoglPipelineLayer *layer);
|
|
|
|
|
|
|
|
/* This type was made deprecated before the cogl_is_pipeline_layer
|
|
|
|
function was ever exposed in the public headers so there's no need
|
|
|
|
to make the cogl_is_pipeline_layer function public. We use INTERNAL
|
|
|
|
so that the cogl_is_* function won't get defined */
|
|
|
|
COGL_OBJECT_INTERNAL_DEFINE (PipelineLayer, pipeline_layer);
|
|
|
|
|
|
|
|
|
|
|
|
CoglPipelineLayer *
|
|
|
|
_cogl_pipeline_layer_get_authority (CoglPipelineLayer *layer,
|
|
|
|
unsigned long difference)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *authority = layer;
|
|
|
|
while (!(authority->differences & difference))
|
|
|
|
authority = _cogl_pipeline_layer_get_parent (authority);
|
|
|
|
return authority;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
_cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *authority =
|
|
|
|
_cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_UNIT);
|
|
|
|
return authority->unit_index;
|
|
|
|
}
|
|
|
|
|
Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.
Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.
Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.
So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.
Instead of gsize we now use size_t
For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-04-16 20:56:40 +00:00
|
|
|
CoglBool
|
2011-09-08 23:40:06 +00:00
|
|
|
_cogl_pipeline_layer_has_alpha (CoglPipelineLayer *layer)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *combine_authority =
|
|
|
|
_cogl_pipeline_layer_get_authority (layer,
|
|
|
|
COGL_PIPELINE_LAYER_STATE_COMBINE);
|
|
|
|
CoglPipelineLayerBigState *big_state = combine_authority->big_state;
|
|
|
|
CoglPipelineLayer *tex_authority;
|
2011-11-25 17:59:52 +00:00
|
|
|
CoglPipelineLayer *snippets_authority;
|
2011-09-08 23:40:06 +00:00
|
|
|
|
|
|
|
/* has_alpha maintains the alpha status for the GL_PREVIOUS layer */
|
|
|
|
|
|
|
|
/* For anything but the default texture combine we currently just
|
|
|
|
* assume it may result in an alpha value < 1
|
|
|
|
*
|
|
|
|
* FIXME: we could do better than this. */
|
|
|
|
if (big_state->texture_combine_alpha_func !=
|
|
|
|
COGL_PIPELINE_COMBINE_FUNC_MODULATE ||
|
|
|
|
big_state->texture_combine_alpha_src[0] !=
|
|
|
|
COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS ||
|
|
|
|
big_state->texture_combine_alpha_op[0] !=
|
|
|
|
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA ||
|
|
|
|
big_state->texture_combine_alpha_src[1] !=
|
|
|
|
COGL_PIPELINE_COMBINE_SOURCE_TEXTURE ||
|
|
|
|
big_state->texture_combine_alpha_op[1] !=
|
|
|
|
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NB: A layer may have a combine mode set on it but not yet
|
|
|
|
* have an associated texture which would mean we'd fallback
|
|
|
|
* to the default texture which doesn't have an alpha component
|
|
|
|
*/
|
|
|
|
tex_authority =
|
|
|
|
_cogl_pipeline_layer_get_authority (layer,
|
|
|
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
|
|
|
|
if (tex_authority->texture &&
|
|
|
|
cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-11-25 17:59:52 +00:00
|
|
|
/* All bets are off if the layer contains any snippets */
|
2011-11-28 19:58:15 +00:00
|
|
|
snippets_authority = _cogl_pipeline_layer_get_authority
|
|
|
|
(layer, COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS);
|
|
|
|
if (!COGL_LIST_EMPTY (&snippets_authority->big_state->vertex_snippets))
|
|
|
|
return TRUE;
|
2011-11-25 17:59:52 +00:00
|
|
|
snippets_authority = _cogl_pipeline_layer_get_authority
|
|
|
|
(layer, COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS);
|
|
|
|
if (!COGL_LIST_EMPTY (&snippets_authority->big_state->fragment_snippets))
|
|
|
|
return TRUE;
|
|
|
|
|
2011-09-08 23:40:06 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
_cogl_get_n_args_for_combine_func (CoglPipelineCombineFunc func)
|
|
|
|
{
|
|
|
|
switch (func)
|
|
|
|
{
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_REPLACE:
|
|
|
|
return 1;
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_MODULATE:
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_ADD:
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED:
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT:
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB:
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA:
|
|
|
|
return 2;
|
|
|
|
case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE:
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-26 11:17:55 +00:00
|
|
|
void
|
|
|
|
_cogl_pipeline_layer_copy_differences (CoglPipelineLayer *dest,
|
|
|
|
CoglPipelineLayer *src,
|
|
|
|
unsigned long differences)
|
|
|
|
{
|
|
|
|
CoglPipelineLayerBigState *big_dest, *big_src;
|
|
|
|
|
|
|
|
if ((differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE) &&
|
|
|
|
!dest->has_big_state)
|
|
|
|
{
|
|
|
|
dest->big_state = g_slice_new (CoglPipelineLayerBigState);
|
|
|
|
dest->has_big_state = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
big_dest = dest->big_state;
|
|
|
|
big_src = src->big_state;
|
|
|
|
|
|
|
|
dest->differences |= differences;
|
|
|
|
|
|
|
|
while (differences)
|
|
|
|
{
|
|
|
|
int index = _cogl_util_ffs (differences) - 1;
|
|
|
|
|
|
|
|
differences &= ~(1 << index);
|
|
|
|
|
|
|
|
/* This convoluted switch statement is just here so that we'll
|
|
|
|
* get a warning if a new state is added without handling it
|
|
|
|
* here */
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_COUNT:
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_UNIT_INDEX:
|
|
|
|
g_warn_if_reached ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX:
|
|
|
|
dest->texture_type = src->texture_type;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX:
|
|
|
|
dest->texture = src->texture;
|
|
|
|
if (dest->texture)
|
|
|
|
cogl_object_ref (dest->texture);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_SAMPLER_INDEX:
|
|
|
|
dest->sampler_cache_entry = src->sampler_cache_entry;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX:
|
|
|
|
{
|
|
|
|
CoglPipelineCombineFunc func;
|
|
|
|
int n_args, i;
|
|
|
|
|
|
|
|
func = big_src->texture_combine_rgb_func;
|
|
|
|
big_dest->texture_combine_rgb_func = func;
|
|
|
|
n_args = _cogl_get_n_args_for_combine_func (func);
|
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
big_dest->texture_combine_rgb_src[i] =
|
|
|
|
big_src->texture_combine_rgb_src[i];
|
|
|
|
big_dest->texture_combine_rgb_op[i] =
|
|
|
|
big_src->texture_combine_rgb_op[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
func = big_src->texture_combine_alpha_func;
|
|
|
|
big_dest->texture_combine_alpha_func = func;
|
|
|
|
n_args = _cogl_get_n_args_for_combine_func (func);
|
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
big_dest->texture_combine_alpha_src[i] =
|
|
|
|
big_src->texture_combine_alpha_src[i];
|
|
|
|
big_dest->texture_combine_alpha_op[i] =
|
|
|
|
big_src->texture_combine_alpha_op[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX:
|
|
|
|
memcpy (big_dest->texture_combine_constant,
|
|
|
|
big_src->texture_combine_constant,
|
|
|
|
sizeof (big_dest->texture_combine_constant));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX:
|
|
|
|
big_dest->point_sprite_coords = big_src->point_sprite_coords;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX:
|
|
|
|
_cogl_pipeline_snippet_list_copy (&big_dest->vertex_snippets,
|
|
|
|
&big_src->vertex_snippets);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX:
|
|
|
|
_cogl_pipeline_snippet_list_copy (&big_dest->fragment_snippets,
|
|
|
|
&big_src->fragment_snippets);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-08 23:40:06 +00:00
|
|
|
static void
|
|
|
|
_cogl_pipeline_layer_init_multi_property_sparse_state (
|
|
|
|
CoglPipelineLayer *layer,
|
|
|
|
CoglPipelineLayerState change)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *authority;
|
|
|
|
|
|
|
|
/* Nothing to initialize in these cases since they are all comprised
|
|
|
|
* of one member which we expect to immediately be overwritten. */
|
|
|
|
if (!(change & COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY))
|
|
|
|
return;
|
|
|
|
|
|
|
|
authority = _cogl_pipeline_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
switch (change)
|
|
|
|
{
|
|
|
|
/* XXX: avoid using a default: label so we get a warning if we
|
|
|
|
* don't explicitly handle a newly defined state-group here. */
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_UNIT:
|
2012-02-09 12:52:45 +00:00
|
|
|
case COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE:
|
2011-09-08 23:40:06 +00:00
|
|
|
case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA:
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS:
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_USER_MATRIX:
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT:
|
2012-04-04 21:20:04 +00:00
|
|
|
case COGL_PIPELINE_LAYER_STATE_SAMPLER:
|
2011-09-08 23:40:06 +00:00
|
|
|
g_return_if_reached ();
|
|
|
|
|
|
|
|
/* XXX: technically we could probably even consider these as
|
|
|
|
* single property state-groups from the pov that currently the
|
|
|
|
* corresponding property setters always update all of the values
|
|
|
|
* at the same time. */
|
|
|
|
case COGL_PIPELINE_LAYER_STATE_COMBINE:
|
|
|
|
{
|
|
|
|
int n_args;
|
|
|
|
int i;
|
|
|
|
CoglPipelineLayerBigState *src_big_state = authority->big_state;
|
|
|
|
CoglPipelineLayerBigState *dest_big_state = layer->big_state;
|
|
|
|
GLint func = src_big_state->texture_combine_rgb_func;
|
|
|
|
|
|
|
|
dest_big_state->texture_combine_rgb_func = func;
|
|
|
|
n_args = _cogl_get_n_args_for_combine_func (func);
|
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
dest_big_state->texture_combine_rgb_src[i] =
|
|
|
|
src_big_state->texture_combine_rgb_src[i];
|
|
|
|
dest_big_state->texture_combine_rgb_op[i] =
|
|
|
|
src_big_state->texture_combine_rgb_op[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
func = src_big_state->texture_combine_alpha_func;
|
|
|
|
dest_big_state->texture_combine_alpha_func = func;
|
|
|
|
n_args = _cogl_get_n_args_for_combine_func (func);
|
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
dest_big_state->texture_combine_alpha_src[i] =
|
|
|
|
src_big_state->texture_combine_alpha_src[i];
|
|
|
|
dest_big_state->texture_combine_alpha_op[i] =
|
|
|
|
src_big_state->texture_combine_alpha_op[i];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-11-28 19:58:15 +00:00
|
|
|
case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS:
|
|
|
|
_cogl_pipeline_snippet_list_copy (&layer->big_state->vertex_snippets,
|
|
|
|
&authority->big_state->
|
|
|
|
vertex_snippets);
|
|
|
|
break;
|
2011-11-25 17:36:03 +00:00
|
|
|
case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS:
|
|
|
|
_cogl_pipeline_snippet_list_copy (&layer->big_state->fragment_snippets,
|
|
|
|
&authority->big_state->
|
|
|
|
fragment_snippets);
|
|
|
|
break;
|
2011-09-08 23:40:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NB: If a layer has descendants we can't modify the layer
|
|
|
|
* NB: If the layer is owned and the owner has descendants we can't
|
|
|
|
* modify the layer.
|
|
|
|
*
|
|
|
|
* This function will allocate a new derived layer if you are trying
|
|
|
|
* to change the state of a layer with dependants (as described above)
|
|
|
|
* so you must always check the return value.
|
|
|
|
*
|
|
|
|
* If a new layer is returned it will be owned by required_owner.
|
|
|
|
* (NB: a layer is always modified with respect to a pipeline - the
|
|
|
|
* "required_owner")
|
|
|
|
*
|
|
|
|
* required_owner can only by NULL for new, currently unowned layers
|
|
|
|
* with no dependants.
|
|
|
|
*/
|
|
|
|
CoglPipelineLayer *
|
|
|
|
_cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
|
|
|
|
CoglPipelineLayer *layer,
|
|
|
|
CoglPipelineLayerState change)
|
|
|
|
{
|
|
|
|
CoglTextureUnit *unit;
|
|
|
|
|
|
|
|
/* Identify the case where the layer is new with no owner or
|
|
|
|
* dependants and so we don't need to do anything. */
|
|
|
|
if (COGL_LIST_EMPTY (&COGL_NODE (layer)->children) &&
|
|
|
|
layer->owner == NULL)
|
|
|
|
goto init_layer_state;
|
|
|
|
|
|
|
|
/* We only allow a NULL required_owner for new layers */
|
2011-10-13 21:34:30 +00:00
|
|
|
_COGL_RETURN_VAL_IF_FAIL (required_owner != NULL, layer);
|
2011-09-08 23:40:06 +00:00
|
|
|
|
|
|
|
/* Chain up:
|
|
|
|
* A modification of a layer is indirectly also a modification of
|
|
|
|
* its owner so first make sure to flush the journal of any
|
|
|
|
* references to the current owner state and if necessary perform
|
|
|
|
* a copy-on-write for the required_owner if it has dependants.
|
|
|
|
*/
|
|
|
|
_cogl_pipeline_pre_change_notify (required_owner,
|
|
|
|
COGL_PIPELINE_STATE_LAYERS,
|
|
|
|
NULL,
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
/* Unlike pipelines; layers are simply considered immutable once
|
|
|
|
* they have dependants - either direct children, or another
|
|
|
|
* pipeline as an owner.
|
|
|
|
*/
|
|
|
|
if (!COGL_LIST_EMPTY (&COGL_NODE (layer)->children) ||
|
|
|
|
layer->owner != required_owner)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer);
|
|
|
|
if (layer->owner == required_owner)
|
|
|
|
_cogl_pipeline_remove_layer_difference (required_owner, layer, FALSE);
|
|
|
|
_cogl_pipeline_add_layer_difference (required_owner, new, FALSE);
|
|
|
|
cogl_object_unref (new);
|
|
|
|
layer = new;
|
|
|
|
goto init_layer_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note: At this point we know there is only one pipeline dependant on
|
|
|
|
* this layer (required_owner), and there are no other layers
|
|
|
|
* dependant on this layer so it's ok to modify it. */
|
|
|
|
|
2012-09-28 17:37:40 +00:00
|
|
|
/* NB: Although layers can have private state associated with them
|
|
|
|
* by multiple backends we know that a layer can't be *changed* if
|
|
|
|
* it has multiple dependants so if we reach here we know we only
|
|
|
|
* have a single owner and can only be associated with a single
|
|
|
|
* backend that needs to be notified of the layer change...
|
|
|
|
*/
|
|
|
|
if (required_owner->progend != COGL_PIPELINE_PROGEND_UNDEFINED)
|
|
|
|
{
|
|
|
|
const CoglPipelineProgend *progend =
|
|
|
|
_cogl_pipeline_progends[required_owner->progend];
|
|
|
|
const CoglPipelineFragend *fragend =
|
|
|
|
_cogl_pipeline_fragends[progend->fragend];
|
|
|
|
const CoglPipelineVertend *vertend =
|
|
|
|
_cogl_pipeline_vertends[progend->vertend];
|
|
|
|
|
|
|
|
if (fragend->layer_pre_change_notify)
|
|
|
|
fragend->layer_pre_change_notify (required_owner, layer, change);
|
|
|
|
if (vertend->layer_pre_change_notify)
|
|
|
|
vertend->layer_pre_change_notify (required_owner, layer, change);
|
|
|
|
if (progend->layer_pre_change_notify)
|
|
|
|
progend->layer_pre_change_notify (required_owner, layer, change);
|
|
|
|
}
|
2011-09-08 23:40:06 +00:00
|
|
|
|
|
|
|
/* If the layer being changed is the same as the last layer we
|
|
|
|
* flushed to the corresponding texture unit then we keep a track of
|
|
|
|
* the changes so we can try to minimize redundant OpenGL calls if
|
|
|
|
* the same layer is flushed again.
|
|
|
|
*/
|
|
|
|
unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
|
|
|
|
if (unit->layer == layer)
|
|
|
|
unit->layer_changes_since_flush |= change;
|
|
|
|
|
|
|
|
init_layer_state:
|
|
|
|
|
|
|
|
if (required_owner)
|
|
|
|
required_owner->age++;
|
|
|
|
|
|
|
|
if (change & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE &&
|
|
|
|
!layer->has_big_state)
|
|
|
|
{
|
|
|
|
layer->big_state = g_slice_new (CoglPipelineLayerBigState);
|
|
|
|
layer->has_big_state = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note: conceptually we have just been notified that a single
|
|
|
|
* property value is about to change, but since some state-groups
|
|
|
|
* contain multiple properties and 'layer' is about to take over
|
|
|
|
* being the authority for the property's corresponding state-group
|
|
|
|
* we need to maintain the integrity of the other property values
|
|
|
|
* too.
|
|
|
|
*
|
|
|
|
* To ensure this we handle multi-property state-groups by copying
|
|
|
|
* all the values from the old-authority to the new...
|
|
|
|
*
|
|
|
|
* We don't have to worry about non-sparse property groups since
|
|
|
|
* we never take over being an authority for such properties so
|
|
|
|
* they automatically maintain integrity.
|
|
|
|
*/
|
|
|
|
if (change & COGL_PIPELINE_LAYER_STATE_ALL_SPARSE &&
|
|
|
|
!(layer->differences & change))
|
|
|
|
{
|
|
|
|
_cogl_pipeline_layer_init_multi_property_sparse_state (layer, change);
|
|
|
|
layer->differences |= change;
|
|
|
|
}
|
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_pipeline_layer_unparent (CoglNode *layer)
|
|
|
|
{
|
|
|
|
/* Chain up */
|
|
|
|
_cogl_pipeline_node_unparent_real (layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_pipeline_layer_set_parent (CoglPipelineLayer *layer,
|
|
|
|
CoglPipelineLayer *parent)
|
|
|
|
{
|
|
|
|
/* Chain up */
|
|
|
|
_cogl_pipeline_node_set_parent_real (COGL_NODE (layer),
|
|
|
|
COGL_NODE (parent),
|
|
|
|
_cogl_pipeline_layer_unparent,
|
|
|
|
TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
CoglPipelineLayer *
|
|
|
|
_cogl_pipeline_layer_copy (CoglPipelineLayer *src)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *layer = g_slice_new (CoglPipelineLayer);
|
|
|
|
|
|
|
|
_cogl_pipeline_node_init (COGL_NODE (layer));
|
|
|
|
|
|
|
|
layer->owner = NULL;
|
|
|
|
layer->index = src->index;
|
|
|
|
layer->differences = 0;
|
|
|
|
layer->has_big_state = FALSE;
|
|
|
|
|
|
|
|
_cogl_pipeline_layer_set_parent (layer, src);
|
|
|
|
|
|
|
|
return _cogl_pipeline_layer_object_new (layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: This is duplicated logic; the same as for
|
|
|
|
* _cogl_pipeline_prune_redundant_ancestry it would be nice to find a
|
|
|
|
* way to consolidate these functions! */
|
|
|
|
void
|
|
|
|
_cogl_pipeline_layer_prune_redundant_ancestry (CoglPipelineLayer *layer)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *new_parent = _cogl_pipeline_layer_get_parent (layer);
|
|
|
|
|
|
|
|
/* walk up past ancestors that are now redundant and potentially
|
|
|
|
* reparent the layer. */
|
|
|
|
while (_cogl_pipeline_layer_get_parent (new_parent) &&
|
|
|
|
(new_parent->differences | layer->differences) ==
|
|
|
|
layer->differences)
|
|
|
|
new_parent = _cogl_pipeline_layer_get_parent (new_parent);
|
|
|
|
|
|
|
|
_cogl_pipeline_layer_set_parent (layer, new_parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine the mask of differences between two layers.
|
|
|
|
*
|
|
|
|
* XXX: If layers and pipelines could both be cast to a common Tree
|
|
|
|
* type of some kind then we could have a unified
|
|
|
|
* compare_differences() function.
|
|
|
|
*/
|
|
|
|
unsigned long
|
|
|
|
_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0,
|
|
|
|
CoglPipelineLayer *layer1)
|
|
|
|
{
|
2011-09-20 20:58:26 +00:00
|
|
|
GSList *head0 = NULL;
|
|
|
|
GSList *head1 = NULL;
|
2011-09-08 23:40:06 +00:00
|
|
|
CoglPipelineLayer *node0;
|
|
|
|
CoglPipelineLayer *node1;
|
2011-09-20 20:58:26 +00:00
|
|
|
int len0 = 0;
|
|
|
|
int len1 = 0;
|
2011-09-08 23:40:06 +00:00
|
|
|
int count;
|
2011-09-20 20:58:26 +00:00
|
|
|
GSList *common_ancestor0;
|
|
|
|
GSList *common_ancestor1;
|
2011-09-08 23:40:06 +00:00
|
|
|
unsigned long layers_difference = 0;
|
|
|
|
|
|
|
|
/* Algorithm:
|
|
|
|
*
|
|
|
|
* 1) Walk the ancestors of each layer to the root node, adding a
|
2011-09-20 20:58:26 +00:00
|
|
|
* pointer to each ancester node to two linked lists
|
2011-09-08 23:40:06 +00:00
|
|
|
*
|
2011-09-20 20:58:26 +00:00
|
|
|
* 2) Compare the lists to find the nodes where they start to
|
|
|
|
* differ marking the common_ancestor node for each list.
|
2011-09-08 23:40:06 +00:00
|
|
|
*
|
2011-09-20 20:58:26 +00:00
|
|
|
* 3) For each list now iterate starting after the common_ancestor
|
|
|
|
* nodes ORing each nodes ->difference mask into the final
|
|
|
|
* differences mask.
|
2011-09-08 23:40:06 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
for (node0 = layer0; node0; node0 = _cogl_pipeline_layer_get_parent (node0))
|
2011-09-20 20:58:26 +00:00
|
|
|
{
|
|
|
|
GSList *link = alloca (sizeof (GSList));
|
|
|
|
link->next = head0;
|
|
|
|
link->data = node0;
|
|
|
|
head0 = link;
|
|
|
|
len0++;
|
|
|
|
}
|
2011-09-08 23:40:06 +00:00
|
|
|
for (node1 = layer1; node1; node1 = _cogl_pipeline_layer_get_parent (node1))
|
|
|
|
{
|
2011-09-20 20:58:26 +00:00
|
|
|
GSList *link = alloca (sizeof (GSList));
|
|
|
|
link->next = head1;
|
|
|
|
link->data = node1;
|
|
|
|
head1 = link;
|
|
|
|
len1++;
|
2011-09-08 23:40:06 +00:00
|
|
|
}
|
|
|
|
|
2011-09-20 20:58:26 +00:00
|
|
|
/* NB: There's no point looking at the head entries since we know both layers
|
|
|
|
* must have the same default layer as their root node. */
|
|
|
|
common_ancestor0 = head0;
|
|
|
|
common_ancestor1 = head1;
|
|
|
|
head0 = head0->next;
|
|
|
|
head1 = head1->next;
|
|
|
|
count = MIN (len0, len1) - 1;
|
|
|
|
while (count--)
|
2011-09-08 23:40:06 +00:00
|
|
|
{
|
2011-09-20 20:58:26 +00:00
|
|
|
if (head0->data != head1->data)
|
2011-09-08 23:40:06 +00:00
|
|
|
break;
|
2011-09-20 20:58:26 +00:00
|
|
|
common_ancestor0 = head0;
|
|
|
|
common_ancestor1 = head1;
|
|
|
|
head0 = head0->next;
|
|
|
|
head1 = head1->next;
|
2011-09-08 23:40:06 +00:00
|
|
|
}
|
|
|
|
|
2011-09-20 20:58:26 +00:00
|
|
|
for (head0 = common_ancestor0->next; head0; head0 = head0->next)
|
2011-09-08 23:40:06 +00:00
|
|
|
{
|
2011-09-20 20:58:26 +00:00
|
|
|
node0 = head0->data;
|
|
|
|
layers_difference |= node0->differences;
|
|
|
|
}
|
|
|
|
for (head1 = common_ancestor1->next; head1; head1 = head1->next)
|
|
|
|
{
|
|
|
|
node1 = head1->data;
|
2011-09-08 23:40:06 +00:00
|
|
|
layers_difference |= node1->differences;
|
|
|
|
}
|
|
|
|
|
|
|
|
return layers_difference;
|
|
|
|
}
|
|
|
|
|
Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.
Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.
Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.
So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.
Instead of gsize we now use size_t
For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-04-16 20:56:40 +00:00
|
|
|
static CoglBool
|
2011-09-08 23:40:06 +00:00
|
|
|
layer_state_equal (CoglPipelineLayerStateIndex state_index,
|
|
|
|
CoglPipelineLayer **authorities0,
|
|
|
|
CoglPipelineLayer **authorities1,
|
|
|
|
CoglPipelineLayerStateComparitor comparitor)
|
|
|
|
{
|
|
|
|
return comparitor (authorities0[state_index], authorities1[state_index]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_cogl_pipeline_layer_resolve_authorities (CoglPipelineLayer *layer,
|
|
|
|
unsigned long differences,
|
|
|
|
CoglPipelineLayer **authorities)
|
|
|
|
{
|
|
|
|
unsigned long remaining = differences;
|
|
|
|
CoglPipelineLayer *authority = layer;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
unsigned long found = authority->differences & remaining;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (found == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (i = 0; TRUE; i++)
|
|
|
|
{
|
|
|
|
unsigned long state = (1L<<i);
|
|
|
|
|
|
|
|
if (state & found)
|
|
|
|
authorities[i] = authority;
|
|
|
|
else if (state > found)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
remaining &= ~found;
|
|
|
|
if (remaining == 0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
while ((authority = _cogl_pipeline_layer_get_parent (authority)));
|
|
|
|
|
|
|
|
g_assert (remaining == 0);
|
|
|
|
}
|
|
|
|
|
Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.
Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.
Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.
So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.
Instead of gsize we now use size_t
For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-04-16 20:56:40 +00:00
|
|
|
CoglBool
|
2011-09-08 23:40:06 +00:00
|
|
|
_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
|
|
|
|
CoglPipelineLayer *layer1,
|
|
|
|
unsigned long differences_mask,
|
|
|
|
CoglPipelineEvalFlags flags)
|
|
|
|
{
|
|
|
|
unsigned long layers_difference;
|
|
|
|
CoglPipelineLayer *authorities0[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
|
|
|
|
CoglPipelineLayer *authorities1[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
|
|
|
|
|
|
|
|
if (layer0 == layer1)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
layers_difference =
|
|
|
|
_cogl_pipeline_layer_compare_differences (layer0, layer1);
|
|
|
|
|
|
|
|
/* Only compare the sparse state groups requested by the caller... */
|
|
|
|
layers_difference &= differences_mask;
|
|
|
|
|
|
|
|
_cogl_pipeline_layer_resolve_authorities (layer0,
|
|
|
|
layers_difference,
|
|
|
|
authorities0);
|
|
|
|
_cogl_pipeline_layer_resolve_authorities (layer1,
|
|
|
|
layers_difference,
|
|
|
|
authorities1);
|
|
|
|
|
2012-02-09 12:52:45 +00:00
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE)
|
2011-09-08 23:40:06 +00:00
|
|
|
{
|
|
|
|
CoglPipelineLayerStateIndex state_index =
|
2012-02-09 12:52:45 +00:00
|
|
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX;
|
|
|
|
if (!_cogl_pipeline_layer_texture_type_equal (authorities0[state_index],
|
|
|
|
authorities1[state_index],
|
|
|
|
flags))
|
2011-09-08 23:40:06 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
|
|
|
|
{
|
|
|
|
CoglPipelineLayerStateIndex state_index =
|
|
|
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX;
|
|
|
|
if (!_cogl_pipeline_layer_texture_data_equal (authorities0[state_index],
|
|
|
|
authorities1[state_index],
|
|
|
|
flags))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE &&
|
|
|
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
|
|
|
|
authorities0, authorities1,
|
|
|
|
_cogl_pipeline_layer_combine_state_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT &&
|
|
|
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
|
|
|
|
authorities0, authorities1,
|
|
|
|
_cogl_pipeline_layer_combine_constant_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2012-04-04 21:20:04 +00:00
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_SAMPLER &&
|
|
|
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_SAMPLER_INDEX,
|
2011-09-08 23:40:06 +00:00
|
|
|
authorities0, authorities1,
|
2012-04-04 21:20:04 +00:00
|
|
|
_cogl_pipeline_layer_sampler_equal))
|
2011-09-08 23:40:06 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX &&
|
|
|
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
|
|
|
|
authorities0, authorities1,
|
|
|
|
_cogl_pipeline_layer_user_matrix_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS &&
|
|
|
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
|
|
|
|
authorities0, authorities1,
|
|
|
|
_cogl_pipeline_layer_point_sprite_coords_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2011-11-28 19:58:15 +00:00
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS &&
|
|
|
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
|
|
|
|
authorities0, authorities1,
|
|
|
|
_cogl_pipeline_layer_vertex_snippets_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2011-11-25 17:36:03 +00:00
|
|
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS &&
|
|
|
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
|
|
|
|
authorities0, authorities1,
|
|
|
|
_cogl_pipeline_layer_fragment_snippets_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2011-09-08 23:40:06 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_pipeline_layer_free (CoglPipelineLayer *layer)
|
|
|
|
{
|
|
|
|
_cogl_pipeline_layer_unparent (COGL_NODE (layer));
|
|
|
|
|
|
|
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA &&
|
|
|
|
layer->texture != NULL)
|
|
|
|
cogl_object_unref (layer->texture);
|
|
|
|
|
2011-11-28 19:58:15 +00:00
|
|
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS)
|
|
|
|
_cogl_pipeline_snippet_list_free (&layer->big_state->vertex_snippets);
|
|
|
|
|
2011-11-25 17:36:03 +00:00
|
|
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
|
|
|
|
_cogl_pipeline_snippet_list_free (&layer->big_state->fragment_snippets);
|
|
|
|
|
2011-09-08 23:40:06 +00:00
|
|
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE)
|
|
|
|
g_slice_free (CoglPipelineLayerBigState, layer->big_state);
|
|
|
|
|
|
|
|
g_slice_free (CoglPipelineLayer, layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_cogl_pipeline_init_default_layers (void)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *layer = g_slice_new0 (CoglPipelineLayer);
|
|
|
|
CoglPipelineLayerBigState *big_state =
|
|
|
|
g_slice_new0 (CoglPipelineLayerBigState);
|
|
|
|
CoglPipelineLayer *new;
|
|
|
|
|
|
|
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
|
|
|
|
|
|
|
_cogl_pipeline_node_init (COGL_NODE (layer));
|
|
|
|
|
|
|
|
layer->index = 0;
|
|
|
|
|
|
|
|
layer->differences = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE;
|
|
|
|
|
|
|
|
layer->unit_index = 0;
|
|
|
|
|
|
|
|
layer->texture = NULL;
|
2012-02-09 12:52:45 +00:00
|
|
|
layer->texture_type = COGL_TEXTURE_TYPE_2D;
|
2011-09-08 23:40:06 +00:00
|
|
|
|
2012-04-04 21:20:04 +00:00
|
|
|
layer->sampler_cache_entry =
|
|
|
|
_cogl_sampler_cache_get_default_entry (ctx->sampler_cache);
|
2011-09-08 23:40:06 +00:00
|
|
|
|
|
|
|
layer->big_state = big_state;
|
|
|
|
layer->has_big_state = TRUE;
|
|
|
|
|
|
|
|
/* Choose the same default combine mode as OpenGL:
|
|
|
|
* RGBA = MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */
|
|
|
|
big_state->texture_combine_rgb_func =
|
|
|
|
COGL_PIPELINE_COMBINE_FUNC_MODULATE;
|
|
|
|
big_state->texture_combine_rgb_src[0] =
|
|
|
|
COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS;
|
|
|
|
big_state->texture_combine_rgb_src[1] =
|
|
|
|
COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
|
|
|
|
big_state->texture_combine_rgb_op[0] =
|
|
|
|
COGL_PIPELINE_COMBINE_OP_SRC_COLOR;
|
|
|
|
big_state->texture_combine_rgb_op[1] =
|
|
|
|
COGL_PIPELINE_COMBINE_OP_SRC_COLOR;
|
|
|
|
big_state->texture_combine_alpha_func =
|
|
|
|
COGL_PIPELINE_COMBINE_FUNC_MODULATE;
|
|
|
|
big_state->texture_combine_alpha_src[0] =
|
|
|
|
COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS;
|
|
|
|
big_state->texture_combine_alpha_src[1] =
|
|
|
|
COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
|
|
|
|
big_state->texture_combine_alpha_op[0] =
|
|
|
|
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA;
|
|
|
|
big_state->texture_combine_alpha_op[1] =
|
|
|
|
COGL_PIPELINE_COMBINE_OP_SRC_ALPHA;
|
|
|
|
|
|
|
|
big_state->point_sprite_coords = FALSE;
|
|
|
|
|
|
|
|
cogl_matrix_init_identity (&big_state->matrix);
|
|
|
|
|
|
|
|
ctx->default_layer_0 = _cogl_pipeline_layer_object_new (layer);
|
|
|
|
|
|
|
|
/* TODO: we should make default_layer_n comprise of two
|
|
|
|
* descendants of default_layer_0:
|
|
|
|
* - the first descendant should change the texture combine
|
|
|
|
* to what we expect is most commonly used for multitexturing
|
|
|
|
* - the second should revert the above change.
|
|
|
|
*
|
|
|
|
* why? the documentation for how a new layer is initialized
|
|
|
|
* doesn't say that layers > 0 have different defaults so unless
|
|
|
|
* we change the documentation we can't use different defaults,
|
|
|
|
* but if the user does what we expect and changes the
|
|
|
|
* texture combine then we can revert the authority to the
|
|
|
|
* first descendant which means we can maximize the number
|
|
|
|
* of layers with a common ancestor.
|
|
|
|
*
|
|
|
|
* The main problem will be that we'll need to disable the
|
|
|
|
* optimizations for flattening the ancestry when we make
|
|
|
|
* the second descendant which reverts the state.
|
|
|
|
*/
|
|
|
|
ctx->default_layer_n = _cogl_pipeline_layer_copy (layer);
|
|
|
|
new = _cogl_pipeline_set_layer_unit (NULL, ctx->default_layer_n, 1);
|
|
|
|
g_assert (new == ctx->default_layer_n);
|
|
|
|
/* Since we passed a newly allocated layer we don't expect that
|
|
|
|
* _set_layer_unit() will have to allocate *another* layer. */
|
|
|
|
|
|
|
|
/* Finally we create a dummy dependant for ->default_layer_n which
|
|
|
|
* effectively ensures that ->default_layer_n and ->default_layer_0
|
|
|
|
* remain immutable.
|
|
|
|
*/
|
|
|
|
ctx->dummy_layer_dependant =
|
|
|
|
_cogl_pipeline_layer_copy (ctx->default_layer_n);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_cogl_pipeline_layer_pre_paint (CoglPipelineLayer *layer)
|
|
|
|
{
|
|
|
|
CoglPipelineLayer *texture_authority;
|
|
|
|
|
|
|
|
texture_authority =
|
|
|
|
_cogl_pipeline_layer_get_authority (layer,
|
|
|
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
|
|
|
|
|
|
|
|
if (texture_authority->texture != NULL)
|
|
|
|
{
|
|
|
|
CoglTexturePrePaintFlags flags = 0;
|
|
|
|
CoglPipelineFilter min_filter;
|
|
|
|
CoglPipelineFilter mag_filter;
|
|
|
|
|
|
|
|
_cogl_pipeline_layer_get_filters (layer, &min_filter, &mag_filter);
|
|
|
|
|
|
|
|
if (min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST
|
|
|
|
|| min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST
|
|
|
|
|| min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR
|
|
|
|
|| min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR)
|
|
|
|
flags |= COGL_TEXTURE_NEEDS_MIPMAP;
|
|
|
|
|
|
|
|
_cogl_texture_pre_paint (texture_authority->texture, flags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determines if we need to handle the RGB and A texture combining
|
|
|
|
* separately or is the same function used for both channel masks and
|
|
|
|
* with the same arguments...
|
|
|
|
*/
|
Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.
Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.
Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.
So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.
Instead of gsize we now use size_t
For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-04-16 20:56:40 +00:00
|
|
|
CoglBool
|
2011-09-08 23:40:06 +00:00
|
|
|
_cogl_pipeline_layer_needs_combine_separate
|
|
|
|
(CoglPipelineLayer *combine_authority)
|
|
|
|
{
|
|
|
|
CoglPipelineLayerBigState *big_state = combine_authority->big_state;
|
|
|
|
int n_args;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (big_state->texture_combine_rgb_func !=
|
|
|
|
big_state->texture_combine_alpha_func)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
n_args = _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func);
|
|
|
|
|
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
if (big_state->texture_combine_rgb_src[i] !=
|
|
|
|
big_state->texture_combine_alpha_src[i])
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We can allow some variation of the source operands without
|
|
|
|
* needing a separation...
|
|
|
|
*
|
|
|
|
* "A = REPLACE (CONSTANT[A])" + either of the following...
|
|
|
|
* "RGB = REPLACE (CONSTANT[RGB])"
|
|
|
|
* "RGB = REPLACE (CONSTANT[A])"
|
|
|
|
*
|
|
|
|
* can be combined as:
|
|
|
|
* "RGBA = REPLACE (CONSTANT)" or
|
|
|
|
* "RGBA = REPLACE (CONSTANT[A])" or
|
|
|
|
*
|
|
|
|
* And "A = REPLACE (1-CONSTANT[A])" + either of the following...
|
|
|
|
* "RGB = REPLACE (1-CONSTANT)" or
|
|
|
|
* "RGB = REPLACE (1-CONSTANT[A])"
|
|
|
|
*
|
|
|
|
* can be combined as:
|
|
|
|
* "RGBA = REPLACE (1-CONSTANT)" or
|
|
|
|
* "RGBA = REPLACE (1-CONSTANT[A])"
|
|
|
|
*/
|
|
|
|
switch (big_state->texture_combine_alpha_op[i])
|
|
|
|
{
|
|
|
|
case GL_SRC_ALPHA:
|
|
|
|
switch (big_state->texture_combine_rgb_op[i])
|
|
|
|
{
|
|
|
|
case GL_SRC_COLOR:
|
|
|
|
case GL_SRC_ALPHA:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GL_ONE_MINUS_SRC_ALPHA:
|
|
|
|
switch (big_state->texture_combine_rgb_op[i])
|
|
|
|
{
|
|
|
|
case GL_ONE_MINUS_SRC_COLOR:
|
|
|
|
case GL_ONE_MINUS_SRC_ALPHA:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE; /* impossible */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|