2009-04-27 10:48:12 -04:00
|
|
|
/*
|
|
|
|
* Cogl
|
|
|
|
*
|
|
|
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
|
|
|
*
|
2010-04-26 05:01:43 -04:00
|
|
|
* Copyright (C) 2008,2009,2010 Intel Corporation.
|
2009-04-27 10:48:12 -04:00
|
|
|
*
|
|
|
|
* 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
|
2010-04-08 07:21:04 -04:00
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
2010-03-01 07:56:10 -05:00
|
|
|
*
|
|
|
|
*
|
2009-04-27 10:48:12 -04:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Robert Bragg <robert@linux.intel.com>
|
|
|
|
*/
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "cogl.h"
|
2010-07-25 16:36:41 -04:00
|
|
|
#include "cogl-debug.h"
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
#include "cogl-internal.h"
|
|
|
|
#include "cogl-context.h"
|
2010-06-22 09:02:17 -04:00
|
|
|
#include "cogl-object.h"
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
|
|
|
#include "cogl-material-private.h"
|
2010-07-09 21:53:38 -04:00
|
|
|
#include "cogl-material-opengl-private.h"
|
2009-01-29 08:40:37 -05:00
|
|
|
#include "cogl-texture-private.h"
|
2009-05-10 19:40:41 -04:00
|
|
|
#include "cogl-blend-string.h"
|
2010-02-10 13:18:30 -05:00
|
|
|
#include "cogl-journal-private.h"
|
2010-04-08 07:21:04 -04:00
|
|
|
#include "cogl-color-private.h"
|
|
|
|
#include "cogl-profile.h"
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
|
|
|
#include <glib.h>
|
2009-11-17 19:26:09 -05:00
|
|
|
#include <glib/gprintf.h>
|
2008-12-23 18:35:49 -05:00
|
|
|
#include <string.h>
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
#define COGL_MATERIAL_LAYER(X) ((CoglMaterialLayer *)(X))
|
|
|
|
|
|
|
|
typedef gboolean (*CoglMaterialStateComparitor) (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1);
|
|
|
|
|
|
|
|
static CoglMaterialLayer *_cogl_material_layer_copy (CoglMaterialLayer *layer);
|
2009-11-11 07:50:48 -05:00
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
static void _cogl_material_free (CoglMaterial *tex);
|
|
|
|
static void _cogl_material_layer_free (CoglMaterialLayer *layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
static void _cogl_material_add_layer_difference (CoglMaterial *material,
|
|
|
|
CoglMaterialLayer *layer,
|
|
|
|
gboolean inc_n_layers);
|
|
|
|
static void handle_automatic_blend_enable (CoglMaterial *material,
|
|
|
|
CoglMaterialState changes);
|
2010-07-08 06:49:31 -04:00
|
|
|
static void recursively_free_layer_caches (CoglMaterial *material);
|
2010-08-09 11:01:17 -04:00
|
|
|
static gboolean _cogl_material_is_weak (CoglMaterial *material);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-07-09 22:40:47 -04:00
|
|
|
const CoglMaterialBackend *_cogl_material_backends[COGL_MATERIAL_N_BACKENDS];
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
#ifdef COGL_MATERIAL_BACKEND_GLSL
|
|
|
|
#include "cogl-material-glsl-private.h"
|
|
|
|
#endif
|
|
|
|
#ifdef COGL_MATERIAL_BACKEND_ARBFP
|
|
|
|
#include "cogl-material-arbfp-private.h"
|
|
|
|
#endif
|
|
|
|
#ifdef COGL_MATERIAL_BACKEND_FIXED
|
|
|
|
#include "cogl-material-fixed-private.h"
|
2010-04-26 05:01:43 -04:00
|
|
|
#endif
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
COGL_OBJECT_DEFINE (Material, material);
|
2010-07-09 12:59:16 -04:00
|
|
|
COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (material);
|
2010-07-09 13:46:31 -04:00
|
|
|
/* This type was made deprecated before the cogl_is_material_layer
|
|
|
|
function was ever exposed in the public headers so there's no need
|
|
|
|
to make the cogl_is_material_layer function public. We use INTERNAL
|
|
|
|
so that the cogl_is_* function won't get defined */
|
|
|
|
COGL_OBJECT_INTERNAL_DEFINE (MaterialLayer, material_layer);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2009-05-10 19:40:41 -04:00
|
|
|
GQuark
|
|
|
|
_cogl_material_error_quark (void)
|
|
|
|
{
|
|
|
|
return g_quark_from_static_string ("cogl-material-error-quark");
|
|
|
|
}
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
static void
|
|
|
|
_cogl_material_node_init (CoglMaterialNode *node)
|
|
|
|
{
|
|
|
|
node->parent = NULL;
|
|
|
|
node->has_children = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_node_set_parent_real (CoglMaterialNode *node,
|
|
|
|
CoglMaterialNode *parent,
|
2010-08-09 11:01:17 -04:00
|
|
|
CoglMaterialNodeUnparentVFunc unparent,
|
|
|
|
gboolean take_strong_reference)
|
2010-07-08 06:49:31 -04:00
|
|
|
{
|
2010-08-09 11:01:17 -04:00
|
|
|
/* NB: the old parent may indirectly be keeping the new parent alive
|
|
|
|
* so we have to ref the new parent before unrefing the old.
|
|
|
|
*
|
|
|
|
* Note: we take a reference here regardless of
|
|
|
|
* take_strong_reference because weak children may need special
|
|
|
|
* handling when the parent disposes itself which relies on a
|
|
|
|
* consistent link to all weak nodes. Once the node is linked to its
|
|
|
|
* parent then we remove the reference at the end if
|
|
|
|
* take_strong_reference == FALSE. */
|
2010-07-08 06:49:31 -04:00
|
|
|
cogl_object_ref (parent);
|
|
|
|
|
|
|
|
if (node->parent)
|
|
|
|
unparent (node);
|
|
|
|
|
|
|
|
if (G_UNLIKELY (parent->has_children))
|
|
|
|
parent->children = g_list_prepend (parent->children, node);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parent->has_children = TRUE;
|
|
|
|
parent->first_child = node;
|
|
|
|
parent->children = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
node->parent = parent;
|
2010-08-09 11:01:17 -04:00
|
|
|
|
|
|
|
/* Now that there is a consistent parent->child link we can remove
|
|
|
|
* the parent reference if no reference was requested. If it turns
|
|
|
|
* out that the new parent was only being kept alive by the old
|
|
|
|
* parent then it will be disposed of here. */
|
|
|
|
if (!take_strong_reference)
|
|
|
|
cogl_object_unref (parent);
|
2010-07-08 06:49:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_node_unparent_real (CoglMaterialNode *node)
|
|
|
|
{
|
|
|
|
CoglMaterialNode *parent = node->parent;
|
|
|
|
|
|
|
|
if (parent == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_return_if_fail (parent->has_children);
|
|
|
|
|
|
|
|
if (parent->first_child == node)
|
|
|
|
{
|
|
|
|
if (parent->children)
|
|
|
|
{
|
|
|
|
parent->first_child = parent->children->data;
|
|
|
|
parent->children =
|
|
|
|
g_list_delete_link (parent->children, parent->children);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
parent->has_children = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
parent->children = g_list_remove (parent->children, node);
|
|
|
|
|
|
|
|
cogl_object_unref (parent);
|
|
|
|
|
|
|
|
node->parent = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_cogl_material_node_foreach_child (CoglMaterialNode *node,
|
|
|
|
CoglMaterialNodeChildCallback callback,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
if (node->has_children)
|
|
|
|
{
|
|
|
|
callback (node->first_child, user_data);
|
|
|
|
g_list_foreach (node->children, (GFunc)callback, user_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/*
|
|
|
|
* This initializes the first material owned by the Cogl context. All
|
|
|
|
* subsequently instantiated materials created via the cogl_material_new()
|
|
|
|
* API will initially be a copy of this material.
|
|
|
|
*
|
|
|
|
* The default material is the topmost ancester for all materials.
|
|
|
|
*/
|
2009-11-11 07:50:48 -05:00
|
|
|
void
|
|
|
|
_cogl_material_init_default_material (void)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
|
|
|
/* Create new - blank - material */
|
2009-11-11 07:50:48 -05:00
|
|
|
CoglMaterial *material = g_slice_new0 (CoglMaterial);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialBigState *big_state = g_slice_new0 (CoglMaterialBigState);
|
|
|
|
CoglMaterialLightingState *lighting_state = &big_state->lighting_state;
|
|
|
|
CoglMaterialAlphaFuncState *alpha_state = &big_state->alpha_state;
|
|
|
|
CoglMaterialBlendState *blend_state = &big_state->blend_state;
|
2010-05-26 06:33:32 -04:00
|
|
|
CoglMaterialDepthState *depth_state = &big_state->depth_state;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2009-11-11 07:50:48 -05:00
|
|
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
/* Take this opportunity to setup the fragment processing backends... */
|
|
|
|
#ifdef COGL_MATERIAL_BACKEND_GLSL
|
2010-07-09 22:40:47 -04:00
|
|
|
_cogl_material_backends[COGL_MATERIAL_BACKEND_GLSL] =
|
|
|
|
&_cogl_material_glsl_backend;
|
2010-06-15 11:44:52 -04:00
|
|
|
#endif
|
|
|
|
#ifdef COGL_MATERIAL_BACKEND_ARBFP
|
2010-07-09 22:40:47 -04:00
|
|
|
_cogl_material_backends[COGL_MATERIAL_BACKEND_ARBFP] =
|
|
|
|
&_cogl_material_arbfp_backend;
|
2010-06-15 11:44:52 -04:00
|
|
|
#endif
|
|
|
|
#ifdef COGL_MATERIAL_BACKEND_FIXED
|
2010-07-09 22:40:47 -04:00
|
|
|
_cogl_material_backends[COGL_MATERIAL_BACKEND_FIXED] =
|
|
|
|
&_cogl_material_fixed_backend;
|
2010-06-15 11:44:52 -04:00
|
|
|
#endif
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_init (COGL_MATERIAL_NODE (material));
|
|
|
|
|
2010-05-27 15:04:49 -04:00
|
|
|
material->is_weak = FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
material->journal_ref_count = 0;
|
2010-04-26 05:01:43 -04:00
|
|
|
material->backend = COGL_MATERIAL_BACKEND_UNDEFINED;
|
2010-04-08 07:21:04 -04:00
|
|
|
material->differences = COGL_MATERIAL_STATE_ALL_SPARSE;
|
|
|
|
|
|
|
|
material->real_blend_enable = FALSE;
|
|
|
|
|
|
|
|
material->blend_enable = COGL_MATERIAL_BLEND_ENABLE_AUTOMATIC;
|
|
|
|
material->layer_differences = NULL;
|
|
|
|
material->n_layers = 0;
|
|
|
|
|
|
|
|
material->big_state = big_state;
|
|
|
|
material->has_big_state = TRUE;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-05-18 19:36:31 -04:00
|
|
|
material->static_breadcrumb = "default material";
|
|
|
|
material->has_static_breadcrumb = TRUE;
|
|
|
|
|
2010-05-27 10:19:15 -04:00
|
|
|
material->age = 0;
|
|
|
|
|
2008-12-23 18:35:49 -05:00
|
|
|
/* Use the same defaults as the GL spec... */
|
2010-04-08 07:21:04 -04:00
|
|
|
cogl_color_init_from_4ub (&material->color, 0xff, 0xff, 0xff, 0xff);
|
2008-12-23 18:35:49 -05:00
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
/* Use the same defaults as the GL spec... */
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state->ambient[0] = 0.2;
|
|
|
|
lighting_state->ambient[1] = 0.2;
|
|
|
|
lighting_state->ambient[2] = 0.2;
|
|
|
|
lighting_state->ambient[3] = 1.0;
|
|
|
|
|
|
|
|
lighting_state->diffuse[0] = 0.8;
|
|
|
|
lighting_state->diffuse[1] = 0.8;
|
|
|
|
lighting_state->diffuse[2] = 0.8;
|
|
|
|
lighting_state->diffuse[3] = 1.0;
|
|
|
|
|
|
|
|
lighting_state->specular[0] = 0;
|
|
|
|
lighting_state->specular[1] = 0;
|
|
|
|
lighting_state->specular[2] = 0;
|
|
|
|
lighting_state->specular[3] = 1.0;
|
|
|
|
|
|
|
|
lighting_state->emission[0] = 0;
|
|
|
|
lighting_state->emission[1] = 0;
|
|
|
|
lighting_state->emission[2] = 0;
|
|
|
|
lighting_state->emission[3] = 1.0;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-07-20 12:34:04 -04:00
|
|
|
lighting_state->shininess = 0.0f;
|
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
/* Use the same defaults as the GL spec... */
|
2010-04-08 07:21:04 -04:00
|
|
|
alpha_state->alpha_func = COGL_MATERIAL_ALPHA_FUNC_ALWAYS;
|
|
|
|
alpha_state->alpha_func_reference = 0.0;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
/* Not the same as the GL default, but seems saner... */
|
2009-05-10 19:40:41 -04:00
|
|
|
#ifndef HAVE_COGL_GLES
|
2010-04-08 07:21:04 -04:00
|
|
|
blend_state->blend_equation_rgb = GL_FUNC_ADD;
|
|
|
|
blend_state->blend_equation_alpha = GL_FUNC_ADD;
|
|
|
|
blend_state->blend_src_factor_alpha = GL_ONE;
|
|
|
|
blend_state->blend_dst_factor_alpha = GL_ONE_MINUS_SRC_ALPHA;
|
|
|
|
cogl_color_init_from_4ub (&blend_state->blend_constant,
|
|
|
|
0x00, 0x00, 0x00, 0x00);
|
2009-05-10 19:40:41 -04:00
|
|
|
#endif
|
2010-04-08 07:21:04 -04:00
|
|
|
blend_state->blend_src_factor_rgb = GL_ONE;
|
|
|
|
blend_state->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
big_state->user_program = COGL_INVALID_HANDLE;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-05-26 06:33:32 -04:00
|
|
|
/* The same as the GL defaults */
|
|
|
|
depth_state->depth_test_enabled = FALSE;
|
|
|
|
depth_state->depth_test_function = COGL_DEPTH_TEST_FUNCTION_LESS;
|
|
|
|
depth_state->depth_writing_enabled = TRUE;
|
|
|
|
depth_state->depth_range_near = 0;
|
|
|
|
depth_state->depth_range_far = 1;
|
|
|
|
|
2010-03-22 05:32:17 -04:00
|
|
|
big_state->point_size = 1.0f;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
ctx->default_material = _cogl_material_object_new (material);
|
2009-11-11 07:50:48 -05:00
|
|
|
}
|
|
|
|
|
2010-05-27 15:04:49 -04:00
|
|
|
static void
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_unparent (CoglMaterialNode *material)
|
2010-05-27 15:04:49 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
/* Chain up */
|
|
|
|
_cogl_material_node_unparent_real (material);
|
|
|
|
}
|
2010-05-27 15:04:49 -04:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
static gboolean
|
|
|
|
recursively_free_layer_caches_cb (CoglMaterialNode *node,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
recursively_free_layer_caches (COGL_MATERIAL (node));
|
|
|
|
return TRUE;
|
2010-05-27 15:04:49 -04:00
|
|
|
}
|
|
|
|
|
2010-06-10 14:03:57 -04:00
|
|
|
/* This recursively frees the layers_cache of a material and all of
|
|
|
|
* its descendants.
|
|
|
|
*
|
|
|
|
* For instance if we change a materials ->layer_differences list
|
|
|
|
* then that material and all of its descendants may now have
|
|
|
|
* incorrect layer caches. */
|
|
|
|
static void
|
|
|
|
recursively_free_layer_caches (CoglMaterial *material)
|
|
|
|
{
|
|
|
|
/* Note: we maintain the invariable that if a material already has a
|
|
|
|
* dirty layers_cache then so do all of its descendants. */
|
|
|
|
if (material->layers_cache_dirty)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (G_UNLIKELY (material->layers_cache != material->short_layers_cache))
|
|
|
|
g_slice_free1 (sizeof (CoglMaterialLayer *) * material->n_layers,
|
|
|
|
material->layers_cache);
|
|
|
|
material->layers_cache_dirty = TRUE;
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
|
|
|
|
recursively_free_layer_caches_cb,
|
|
|
|
NULL);
|
2010-06-10 14:03:57 -04:00
|
|
|
}
|
|
|
|
|
2010-05-27 15:04:49 -04:00
|
|
|
static void
|
2010-08-09 11:01:17 -04:00
|
|
|
_cogl_material_set_parent (CoglMaterial *material,
|
|
|
|
CoglMaterial *parent,
|
|
|
|
gboolean take_strong_reference)
|
2010-05-27 15:04:49 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
/* Chain up */
|
|
|
|
_cogl_material_node_set_parent_real (COGL_MATERIAL_NODE (material),
|
|
|
|
COGL_MATERIAL_NODE (parent),
|
2010-08-09 11:01:17 -04:00
|
|
|
_cogl_material_unparent,
|
|
|
|
take_strong_reference);
|
2010-06-14 17:20:27 -04:00
|
|
|
|
|
|
|
/* Since we just changed the ancestry of the material its cache of
|
|
|
|
* layers could now be invalid so free it... */
|
|
|
|
if (material->differences & COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
recursively_free_layer_caches (material);
|
2010-06-10 14:03:57 -04:00
|
|
|
|
|
|
|
/* If the fragment processing backend is also caching state along
|
2010-07-08 06:49:31 -04:00
|
|
|
* with the material that depends on the material's ancestry then it
|
2010-06-10 14:03:57 -04:00
|
|
|
* may be notified here...
|
|
|
|
*/
|
|
|
|
if (material->backend != COGL_MATERIAL_BACKEND_UNDEFINED &&
|
2010-07-09 22:40:47 -04:00
|
|
|
_cogl_material_backends[material->backend]->material_set_parent_notify)
|
|
|
|
{
|
|
|
|
const CoglMaterialBackend *backend =
|
|
|
|
_cogl_material_backends[material->backend];
|
|
|
|
backend->material_set_parent_notify (material);
|
|
|
|
}
|
2010-05-27 15:04:49 -04:00
|
|
|
}
|
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
static void
|
|
|
|
_cogl_material_promote_weak_ancestors (CoglMaterial *strong)
|
|
|
|
{
|
|
|
|
CoglMaterialNode *n;
|
|
|
|
|
|
|
|
g_return_if_fail (!strong->is_weak);
|
|
|
|
|
|
|
|
for (n = COGL_MATERIAL_NODE (strong)->parent; n; n = n->parent)
|
|
|
|
{
|
|
|
|
CoglMaterial *material = COGL_MATERIAL (n);
|
|
|
|
|
|
|
|
cogl_object_ref (material);
|
|
|
|
|
|
|
|
if (!material->is_weak)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_revert_weak_ancestors (CoglMaterial *strong)
|
|
|
|
{
|
|
|
|
CoglMaterial *parent = _cogl_material_get_parent (strong);
|
|
|
|
CoglMaterialNode *n;
|
|
|
|
|
|
|
|
g_return_if_fail (!strong->is_weak);
|
|
|
|
|
|
|
|
if (!parent || !parent->is_weak)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (n = COGL_MATERIAL_NODE (strong)->parent; n; n = n->parent)
|
|
|
|
{
|
|
|
|
CoglMaterial *material = COGL_MATERIAL (n);
|
|
|
|
|
|
|
|
cogl_object_unref (material);
|
|
|
|
|
|
|
|
if (!material->is_weak)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* XXX: Always have an eye out for opportunities to lower the cost of
|
|
|
|
* cogl_material_copy. */
|
2010-08-09 11:01:17 -04:00
|
|
|
static CoglMaterial *
|
|
|
|
_cogl_material_copy (CoglMaterial *src, gboolean is_weak)
|
2009-11-11 07:50:48 -05:00
|
|
|
{
|
|
|
|
CoglMaterial *material = g_slice_new (CoglMaterial);
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_init (COGL_MATERIAL_NODE (material));
|
2009-11-11 07:50:48 -05:00
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
material->is_weak = is_weak;
|
2010-05-27 15:04:49 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
material->journal_ref_count = 0;
|
|
|
|
|
|
|
|
material->differences = 0;
|
|
|
|
|
|
|
|
material->has_big_state = FALSE;
|
|
|
|
|
|
|
|
/* NB: real_blend_enable isn't a sparse property, it's valid for
|
|
|
|
* every material node so we have fast access to it. */
|
|
|
|
material->real_blend_enable = src->real_blend_enable;
|
|
|
|
|
|
|
|
/* XXX:
|
|
|
|
* consider generalizing the idea of "cached" properties. These
|
|
|
|
* would still have an authority like other sparse properties but
|
|
|
|
* you wouldn't have to walk up the ancestry to find the authority
|
|
|
|
* because the value would be cached directly in each material.
|
|
|
|
*/
|
|
|
|
|
|
|
|
material->layers_cache_dirty = TRUE;
|
|
|
|
material->deprecated_get_layers_list_dirty = TRUE;
|
|
|
|
|
|
|
|
material->backend = src->backend;
|
2010-06-10 14:03:57 -04:00
|
|
|
material->backend_priv_set_mask = 0;
|
2009-11-11 07:50:48 -05:00
|
|
|
|
2010-05-18 19:36:31 -04:00
|
|
|
material->has_static_breadcrumb = FALSE;
|
|
|
|
|
2010-05-27 10:19:15 -04:00
|
|
|
material->age = 0;
|
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
_cogl_material_set_parent (material, src, !is_weak);
|
|
|
|
|
|
|
|
/* The semantics for copying a weak material are that we promote all
|
|
|
|
* weak ancestors to temporarily become strong materials until the
|
|
|
|
* copy is freed. */
|
|
|
|
if (!is_weak)
|
|
|
|
_cogl_material_promote_weak_ancestors (material);
|
2010-06-10 14:03:57 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
return _cogl_material_object_new (material);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
CoglMaterial *
|
2010-08-09 11:01:17 -04:00
|
|
|
cogl_material_copy (CoglMaterial *src)
|
|
|
|
{
|
|
|
|
return _cogl_material_copy (src, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
CoglMaterial *
|
|
|
|
_cogl_material_weak_copy (CoglMaterial *material,
|
|
|
|
CoglMaterialDestroyCallback callback,
|
|
|
|
void *user_data)
|
2010-05-27 15:04:49 -04:00
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
CoglMaterial *copy;
|
2010-05-27 15:04:49 -04:00
|
|
|
CoglMaterial *copy_material;
|
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
copy = _cogl_material_copy (material, TRUE);
|
2010-05-27 15:04:49 -04:00
|
|
|
copy_material = COGL_MATERIAL (copy);
|
2010-08-09 11:01:17 -04:00
|
|
|
copy_material->destroy_callback = callback;
|
|
|
|
copy_material->destroy_data = user_data;
|
2010-05-27 15:04:49 -04:00
|
|
|
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
CoglMaterial *
|
2009-11-11 07:50:48 -05:00
|
|
|
cogl_material_new (void)
|
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
CoglMaterial *new;
|
2010-05-18 19:36:31 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
_COGL_GET_CONTEXT (ctx, NULL);
|
2009-11-11 07:50:48 -05:00
|
|
|
|
2010-05-18 19:36:31 -04:00
|
|
|
new = cogl_material_copy (ctx->default_material);
|
|
|
|
_cogl_material_set_static_breadcrumb (new, "new");
|
|
|
|
return new;
|
2009-11-11 07:50:48 -05:00
|
|
|
}
|
|
|
|
|
2010-04-26 05:01:43 -04:00
|
|
|
static void
|
|
|
|
_cogl_material_backend_free_priv (CoglMaterial *material)
|
|
|
|
{
|
|
|
|
if (material->backend != COGL_MATERIAL_BACKEND_UNDEFINED &&
|
2010-07-09 22:40:47 -04:00
|
|
|
_cogl_material_backends[material->backend]->free_priv)
|
|
|
|
{
|
|
|
|
const CoglMaterialBackend *backend =
|
|
|
|
_cogl_material_backends[material->backend];
|
|
|
|
backend->free_priv (material);
|
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
static gboolean
|
|
|
|
destroy_weak_children_cb (CoglMaterialNode *node,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
CoglMaterial *material = COGL_MATERIAL (node);
|
|
|
|
|
|
|
|
if (_cogl_material_is_weak (material))
|
|
|
|
{
|
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
|
|
|
|
destroy_weak_children_cb,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
material->destroy_callback (material, material->destroy_data);
|
|
|
|
_cogl_material_unparent (COGL_MATERIAL_NODE (material));
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
static void
|
|
|
|
_cogl_material_free (CoglMaterial *material)
|
|
|
|
{
|
2010-08-09 11:01:17 -04:00
|
|
|
if (!material->is_weak)
|
|
|
|
_cogl_material_revert_weak_ancestors (material);
|
|
|
|
|
|
|
|
/* Weak materials don't take a reference on their parent */
|
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
|
|
|
|
destroy_weak_children_cb,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
g_assert (!COGL_MATERIAL_NODE (material)->has_children);
|
|
|
|
|
2010-04-26 05:01:43 -04:00
|
|
|
_cogl_material_backend_free_priv (material);
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_unparent (COGL_MATERIAL_NODE (material));
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (material->differences & COGL_MATERIAL_STATE_USER_SHADER &&
|
|
|
|
material->big_state->user_program)
|
|
|
|
cogl_handle_unref (material->big_state->user_program);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (material->differences & COGL_MATERIAL_STATE_NEEDS_BIG_STATE)
|
|
|
|
g_slice_free (CoglMaterialBigState, material->big_state);
|
2009-02-19 04:01:18 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (material->differences & COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
{
|
|
|
|
g_list_foreach (material->layer_differences,
|
2010-06-22 09:02:17 -04:00
|
|
|
(GFunc)cogl_object_unref, NULL);
|
2010-04-08 07:21:04 -04:00
|
|
|
g_list_free (material->layer_differences);
|
|
|
|
}
|
2009-02-19 04:01:18 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
g_slice_free (CoglMaterial, material);
|
|
|
|
}
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_get_real_blend_enabled (CoglMaterial *material)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2009-04-02 06:50:44 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
return material->real_blend_enable;
|
|
|
|
}
|
2009-04-02 06:50:44 -04:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
inline CoglMaterial *
|
|
|
|
_cogl_material_get_parent (CoglMaterial *material)
|
|
|
|
{
|
|
|
|
CoglMaterialNode *parent_node = COGL_MATERIAL_NODE (material)->parent;
|
|
|
|
return COGL_MATERIAL (parent_node);
|
|
|
|
}
|
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
CoglMaterial *
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_get_authority (CoglMaterial *material,
|
|
|
|
unsigned long difference)
|
|
|
|
{
|
|
|
|
CoglMaterial *authority = material;
|
|
|
|
while (!(authority->differences & difference))
|
2010-07-08 06:49:31 -04:00
|
|
|
authority = _cogl_material_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
return authority;
|
|
|
|
}
|
2009-02-19 04:01:18 -05:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
/* XXX: Think twice before making this non static since it is used
|
|
|
|
* heavily and we expect the compiler to inline it...
|
|
|
|
*/
|
|
|
|
static CoglMaterialLayer *
|
|
|
|
_cogl_material_layer_get_parent (CoglMaterialLayer *layer)
|
|
|
|
{
|
|
|
|
CoglMaterialNode *parent_node = COGL_MATERIAL_NODE (layer)->parent;
|
|
|
|
return COGL_MATERIAL_LAYER (parent_node);
|
|
|
|
}
|
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
CoglMaterialLayer *
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_layer_get_authority (CoglMaterialLayer *layer,
|
|
|
|
unsigned long difference)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *authority = layer;
|
|
|
|
while (!(authority->differences & difference))
|
2010-07-08 06:49:31 -04:00
|
|
|
authority = _cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
return authority;
|
2009-06-17 18:31:11 -04:00
|
|
|
}
|
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
int
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_layer_get_unit_index (CoglMaterialLayer *layer)
|
2009-06-17 18:31:11 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *authority =
|
|
|
|
_cogl_material_layer_get_authority (layer, COGL_MATERIAL_LAYER_STATE_UNIT);
|
|
|
|
return authority->unit_index;
|
2009-02-19 04:01:18 -05:00
|
|
|
}
|
|
|
|
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
static void
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_layers_cache (CoglMaterial *material)
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Note: we assume this material is a _LAYERS authority */
|
|
|
|
int n_layers;
|
|
|
|
CoglMaterial *current;
|
|
|
|
int layers_found;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (G_LIKELY (!material->layers_cache_dirty) ||
|
|
|
|
material->n_layers == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
material->layers_cache_dirty = FALSE;
|
|
|
|
|
|
|
|
n_layers = material->n_layers;
|
|
|
|
if (G_LIKELY (n_layers < G_N_ELEMENTS (material->short_layers_cache)))
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
material->layers_cache = material->short_layers_cache;
|
|
|
|
memset (material->layers_cache, 0,
|
|
|
|
sizeof (CoglMaterialLayer *) *
|
|
|
|
G_N_ELEMENTS (material->short_layers_cache));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
material->layers_cache =
|
|
|
|
g_slice_alloc0 (sizeof (CoglMaterialLayer *) * n_layers);
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Notes:
|
2010-04-26 05:01:43 -04:00
|
|
|
*
|
2010-04-08 07:21:04 -04:00
|
|
|
* Each material doesn't have to contain a complete list of the layers
|
|
|
|
* it depends on, some of them are indirectly referenced through the
|
|
|
|
* material's ancestors.
|
|
|
|
*
|
|
|
|
* material->layer_differences only contains a list of layers that
|
|
|
|
* have changed in relation to its parent.
|
2010-04-26 05:01:43 -04:00
|
|
|
*
|
2010-04-08 07:21:04 -04:00
|
|
|
* material->layer_differences is not maintained sorted, but it
|
|
|
|
* won't contain multiple layers corresponding to a particular
|
|
|
|
* ->unit_index.
|
|
|
|
*
|
|
|
|
* Some of the ancestor materials may reference layers with
|
|
|
|
* ->unit_index values >= n_layers so we ignore them.
|
|
|
|
*
|
|
|
|
* As we ascend through the ancestors we are searching for any
|
|
|
|
* CoglMaterialLayers corresponding to the texture ->unit_index
|
|
|
|
* values in the range [0,n_layers-1]. As soon as a pointer is found
|
|
|
|
* we ignore layers of further ancestors with the same ->unit_index
|
|
|
|
* values.
|
2010-04-26 05:01:43 -04:00
|
|
|
*/
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layers_found = 0;
|
2010-07-08 06:49:31 -04:00
|
|
|
for (current = material;
|
|
|
|
_cogl_material_get_parent (current);
|
|
|
|
current = _cogl_material_get_parent (current))
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (!(current->differences & COGL_MATERIAL_STATE_LAYERS))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (l = current->layer_differences; l; l = l->next)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *layer = l->data;
|
|
|
|
int unit_index = _cogl_material_layer_get_unit_index (layer);
|
|
|
|
|
|
|
|
if (unit_index < n_layers && !material->layers_cache[unit_index])
|
|
|
|
{
|
|
|
|
material->layers_cache[unit_index] = layer;
|
|
|
|
layers_found++;
|
|
|
|
if (layers_found == n_layers)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_warn_if_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: add public cogl_material_foreach_layer but instead of passing
|
|
|
|
* a CoglMaterialLayer pointer to the callback we should pass a
|
|
|
|
* layer_index instead. */
|
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_foreach_layer (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayerCallback callback,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
CoglMaterial *authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LAYERS);
|
|
|
|
int n_layers;
|
|
|
|
int i;
|
|
|
|
gboolean cont;
|
|
|
|
|
|
|
|
n_layers = authority->n_layers;
|
|
|
|
if (n_layers == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_cogl_material_update_layers_cache (authority);
|
|
|
|
|
|
|
|
for (i = 0, cont = TRUE; i < n_layers && cont == TRUE; i++)
|
|
|
|
cont = callback (authority->layers_cache[i], user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
layer_has_alpha_cb (CoglMaterialLayer *layer, void *data)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *combine_authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_COMBINE);
|
|
|
|
CoglMaterialLayerBigState *big_state = combine_authority->big_state;
|
|
|
|
CoglMaterialLayer *tex_authority;
|
|
|
|
gboolean *has_alpha = data;
|
|
|
|
|
|
|
|
/* 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 != GL_MODULATE ||
|
|
|
|
big_state->texture_combine_alpha_src[0] != GL_PREVIOUS ||
|
|
|
|
big_state->texture_combine_alpha_op[0] != GL_SRC_ALPHA ||
|
|
|
|
big_state->texture_combine_alpha_src[0] != GL_TEXTURE ||
|
|
|
|
big_state->texture_combine_alpha_op[0] != GL_SRC_ALPHA)
|
|
|
|
{
|
|
|
|
*has_alpha = TRUE;
|
|
|
|
/* return FALSE to stop iterating layers... */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_TEXTURE);
|
|
|
|
if (tex_authority->texture &&
|
|
|
|
cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT)
|
|
|
|
{
|
|
|
|
*has_alpha = TRUE;
|
|
|
|
/* return FALSE to stop iterating layers... */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*has_alpha = FALSE;
|
|
|
|
/* return FALSE to continue iterating layers... */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
static CoglMaterial *
|
|
|
|
_cogl_material_get_user_program (CoglMaterial *material)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), NULL);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_USER_SHADER);
|
|
|
|
|
|
|
|
return authority->big_state->user_program;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_needs_blending_enabled (CoglMaterial *material,
|
|
|
|
unsigned long changes,
|
|
|
|
const CoglColor *override_color)
|
|
|
|
{
|
|
|
|
CoglMaterial *enable_authority;
|
|
|
|
CoglMaterial *blend_authority;
|
|
|
|
CoglMaterialBlendState *blend_state;
|
|
|
|
CoglMaterialBlendEnable enabled;
|
|
|
|
unsigned long other_state;
|
|
|
|
|
|
|
|
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_BLENDING))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
enable_authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_BLEND_ENABLE);
|
|
|
|
|
|
|
|
enabled = enable_authority->blend_enable;
|
|
|
|
if (enabled != COGL_MATERIAL_BLEND_ENABLE_AUTOMATIC)
|
|
|
|
return enabled == COGL_MATERIAL_BLEND_ENABLE_ENABLED ? TRUE : FALSE;
|
|
|
|
|
|
|
|
blend_authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_BLEND);
|
|
|
|
|
|
|
|
blend_state = &blend_authority->big_state->blend_state;
|
|
|
|
|
|
|
|
/* We are trying to identify awkward cases that are equivalent to
|
|
|
|
* blending being disable, where the output is simply GL_SRC_COLOR.
|
|
|
|
*
|
|
|
|
* Note: we assume that all OpenGL drivers will identify the simple
|
|
|
|
* case of ADD (ONE, ZERO) as equivalent to blending being disabled.
|
|
|
|
*
|
|
|
|
* We should update this when we add support for more blend
|
|
|
|
* functions...
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef HAVE_COGL_GLES
|
|
|
|
/* GLES 1 can't change the function or have separate alpha factors */
|
|
|
|
if (blend_state->blend_equation_rgb != GL_FUNC_ADD ||
|
|
|
|
blend_state->blend_equation_alpha != GL_FUNC_ADD)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (blend_state->blend_src_factor_alpha != GL_ONE ||
|
|
|
|
blend_state->blend_dst_factor_alpha != GL_ONE_MINUS_SRC_ALPHA)
|
|
|
|
return TRUE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (blend_state->blend_src_factor_rgb != GL_ONE ||
|
|
|
|
blend_state->blend_dst_factor_rgb != GL_ONE_MINUS_SRC_ALPHA)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* Given the above constraints, it's now a case of finding any
|
|
|
|
* SRC_ALPHA that != 1 */
|
|
|
|
|
|
|
|
/* In the case of a layer state change we need to check everything
|
|
|
|
* else first since they contribute to the has_alpha status of the
|
|
|
|
* GL_PREVIOUS layer. */
|
|
|
|
if (changes & COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
changes = COGL_MATERIAL_STATE_AFFECTS_BLENDING;
|
|
|
|
|
|
|
|
/* XXX: we don't currently handle specific changes in an optimal way*/
|
|
|
|
changes = COGL_MATERIAL_STATE_AFFECTS_BLENDING;
|
|
|
|
|
|
|
|
if ((override_color && cogl_color_get_alpha_byte (override_color) != 0xff))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (changes & COGL_MATERIAL_STATE_COLOR)
|
|
|
|
{
|
|
|
|
CoglColor tmp;
|
|
|
|
cogl_material_get_color (material, &tmp);
|
|
|
|
if (cogl_color_get_alpha_byte (&tmp) != 0xff)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We can't make any assumptions about the alpha channel if the user
|
|
|
|
* is using an unknown fragment shader.
|
|
|
|
*
|
|
|
|
* TODO: check that it isn't just a vertex shader!
|
|
|
|
*/
|
|
|
|
if (changes & COGL_MATERIAL_STATE_USER_SHADER)
|
|
|
|
{
|
|
|
|
if (_cogl_material_get_user_program (material) != COGL_INVALID_HANDLE)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: we should only need to look at these if lighting is enabled
|
|
|
|
*/
|
|
|
|
if (changes & COGL_MATERIAL_STATE_LIGHTING)
|
|
|
|
{
|
|
|
|
CoglColor tmp;
|
|
|
|
|
|
|
|
cogl_material_get_ambient (material, &tmp);
|
|
|
|
if (cogl_color_get_alpha_byte (&tmp) != 0xff)
|
|
|
|
return TRUE;
|
|
|
|
cogl_material_get_diffuse (material, &tmp);
|
|
|
|
if (cogl_color_get_alpha_byte (&tmp) != 0xff)
|
|
|
|
return TRUE;
|
|
|
|
cogl_material_get_specular (material, &tmp);
|
|
|
|
if (cogl_color_get_alpha_byte (&tmp) != 0xff)
|
|
|
|
return TRUE;
|
|
|
|
cogl_material_get_emission (material, &tmp);
|
|
|
|
if (cogl_color_get_alpha_byte (&tmp) != 0xff)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changes & COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
{
|
|
|
|
/* has_alpha tracks the alpha status of the GL_PREVIOUS layer.
|
|
|
|
* To start with that's defined by the material color which
|
|
|
|
* must be fully opaque if we got this far. */
|
|
|
|
gboolean has_alpha = FALSE;
|
|
|
|
_cogl_material_foreach_layer (material,
|
|
|
|
layer_has_alpha_cb,
|
|
|
|
&has_alpha);
|
|
|
|
if (has_alpha)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* So far we have only checked the property that has been changed so
|
|
|
|
* we now need to check all the other properties too. */
|
|
|
|
other_state = COGL_MATERIAL_STATE_AFFECTS_BLENDING & ~changes;
|
|
|
|
if (other_state &&
|
|
|
|
_cogl_material_needs_blending_enabled (material,
|
|
|
|
other_state,
|
|
|
|
NULL))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-07-09 22:40:47 -04:00
|
|
|
void
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_set_backend (CoglMaterial *material, int backend)
|
|
|
|
{
|
|
|
|
_cogl_material_backend_free_priv (material);
|
|
|
|
material->backend = backend;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_copy_differences (CoglMaterial *dest,
|
|
|
|
CoglMaterial *src,
|
|
|
|
unsigned long differences)
|
|
|
|
{
|
|
|
|
CoglMaterialBigState *big_state;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_COLOR)
|
|
|
|
dest->color = src->color;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_BLEND_ENABLE)
|
|
|
|
dest->blend_enable = src->blend_enable;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (dest->differences & COGL_MATERIAL_STATE_LAYERS &&
|
|
|
|
dest->layer_differences)
|
|
|
|
{
|
|
|
|
g_list_foreach (dest->layer_differences,
|
2010-06-22 09:02:17 -04:00
|
|
|
(GFunc)cogl_object_unref,
|
2010-04-08 07:21:04 -04:00
|
|
|
NULL);
|
|
|
|
g_list_free (dest->layer_differences);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (l = src->layer_differences; l; l = l->next)
|
|
|
|
{
|
|
|
|
/* NB: a layer can't have more than one ->owner so we can't
|
|
|
|
* simply take a references on each of the original
|
|
|
|
* layer_differences, we have to derive new layers from the
|
|
|
|
* originals instead. */
|
|
|
|
CoglMaterialLayer *copy = _cogl_material_layer_copy (l->data);
|
|
|
|
_cogl_material_add_layer_difference (dest, copy, FALSE);
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_unref (copy);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
2010-08-08 08:09:27 -04:00
|
|
|
|
|
|
|
/* Note: we initialize n_layers after adding the layer differences
|
|
|
|
* since the act of adding the layers will initialize n_layers to 0
|
|
|
|
* because dest isn't initially a STATE_LAYERS authority. */
|
|
|
|
dest->n_layers = src->n_layers;
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_NEEDS_BIG_STATE)
|
|
|
|
{
|
|
|
|
if (!dest->has_big_state)
|
|
|
|
{
|
|
|
|
dest->big_state = g_slice_new (CoglMaterialBigState);
|
|
|
|
dest->has_big_state = TRUE;
|
|
|
|
}
|
|
|
|
big_state = dest->big_state;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto check_for_blending_change;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_LIGHTING)
|
|
|
|
{
|
|
|
|
memcpy (&big_state->lighting_state,
|
|
|
|
&src->big_state->lighting_state,
|
|
|
|
sizeof (CoglMaterialLightingState));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_ALPHA_FUNC)
|
|
|
|
{
|
|
|
|
memcpy (&big_state->alpha_state,
|
|
|
|
&src->big_state->alpha_state,
|
|
|
|
sizeof (CoglMaterialAlphaFuncState));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_BLEND)
|
|
|
|
{
|
|
|
|
memcpy (&big_state->blend_state,
|
|
|
|
&src->big_state->blend_state,
|
|
|
|
sizeof (CoglMaterialBlendState));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_STATE_USER_SHADER)
|
|
|
|
{
|
|
|
|
if (src->big_state->user_program)
|
|
|
|
big_state->user_program =
|
|
|
|
cogl_handle_ref (src->big_state->user_program);
|
2010-06-09 08:53:34 -04:00
|
|
|
else
|
2010-04-08 07:21:04 -04:00
|
|
|
big_state->user_program = COGL_INVALID_HANDLE;
|
2009-06-17 18:31:11 -04:00
|
|
|
}
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-05-26 06:33:32 -04:00
|
|
|
if (differences & COGL_MATERIAL_STATE_DEPTH)
|
|
|
|
{
|
|
|
|
memcpy (&big_state->depth_state,
|
|
|
|
&src->big_state->depth_state,
|
|
|
|
sizeof (CoglMaterialDepthState));
|
|
|
|
}
|
|
|
|
|
2010-07-09 20:36:22 -04:00
|
|
|
if (differences & COGL_MATERIAL_STATE_FOG)
|
|
|
|
{
|
|
|
|
memcpy (&big_state->fog_state,
|
|
|
|
&src->big_state->fog_state,
|
|
|
|
sizeof (CoglMaterialFogState));
|
|
|
|
}
|
|
|
|
|
2010-03-22 05:32:17 -04:00
|
|
|
if (differences & COGL_MATERIAL_STATE_POINT_SIZE)
|
|
|
|
big_state->point_size = src->big_state->point_size;
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* XXX: we shouldn't bother doing this in most cases since
|
|
|
|
* _copy_differences is typically used to initialize material state
|
|
|
|
* by copying it from the current authority, so it's not actually
|
|
|
|
* *changing* anything.
|
|
|
|
*/
|
|
|
|
check_for_blending_change:
|
|
|
|
if (differences & COGL_MATERIAL_STATE_AFFECTS_BLENDING)
|
|
|
|
handle_automatic_blend_enable (dest, differences);
|
|
|
|
|
|
|
|
dest->differences |= differences;
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
2009-06-17 18:31:11 -04:00
|
|
|
|
2010-04-26 05:01:43 -04:00
|
|
|
static void
|
2010-08-08 08:41:15 -04:00
|
|
|
_cogl_material_initialize_sparse_state (CoglMaterial *dest,
|
|
|
|
CoglMaterial *src,
|
|
|
|
CoglMaterialState state)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
if (dest == src)
|
2010-04-26 05:01:43 -04:00
|
|
|
return;
|
|
|
|
|
2010-08-08 08:41:15 -04:00
|
|
|
g_return_if_fail (state & COGL_MATERIAL_STATE_ALL_SPARSE);
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (state != COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
_cogl_material_copy_differences (dest, src, state);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dest->n_layers = src->n_layers;
|
|
|
|
dest->layer_differences = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2010-07-08 06:49:31 -04:00
|
|
|
check_if_strong_cb (CoglMaterialNode *node, void *user_data)
|
2010-05-27 15:04:49 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *material = COGL_MATERIAL (node);
|
2010-05-27 15:04:49 -04:00
|
|
|
gboolean *has_strong_child = user_data;
|
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
if (!_cogl_material_is_weak (material))
|
2010-05-27 15:04:49 -04:00
|
|
|
{
|
|
|
|
*has_strong_child = TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-08-09 11:01:17 -04:00
|
|
|
|
2010-05-27 15:04:49 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
has_strong_children (CoglMaterial *material)
|
|
|
|
{
|
|
|
|
gboolean has_strong_child = FALSE;
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
|
|
|
|
check_if_strong_cb,
|
|
|
|
&has_strong_child);
|
2010-05-27 15:04:49 -04:00
|
|
|
return has_strong_child;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2010-08-09 11:01:17 -04:00
|
|
|
_cogl_material_is_weak (CoglMaterial *material)
|
|
|
|
{
|
|
|
|
if (material->is_weak && !has_strong_children (material))
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
reparent_children_cb (CoglMaterialNode *node,
|
|
|
|
void *user_data)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *material = COGL_MATERIAL (node);
|
2010-05-27 15:04:49 -04:00
|
|
|
CoglMaterial *parent = user_data;
|
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
_cogl_material_set_parent (material, parent, TRUE);
|
2010-05-27 15:04:49 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_pre_change_notify (CoglMaterial *material,
|
|
|
|
CoglMaterialState change,
|
|
|
|
const CoglColor *new_color)
|
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
|
|
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
|
|
|
|
|
|
|
/* If primitives have been logged in the journal referencing the
|
|
|
|
* current state of this material we need to flush the journal
|
|
|
|
* before we can modify it... */
|
|
|
|
if (material->journal_ref_count)
|
|
|
|
{
|
|
|
|
gboolean skip_journal_flush = FALSE;
|
|
|
|
|
|
|
|
/* XXX: We don't usually need to flush the journal just due to
|
|
|
|
* color changes since material colors are logged in the
|
|
|
|
* journal's vertex buffer. The exception is when the change in
|
|
|
|
* color enables or disables the need for blending. */
|
|
|
|
if (change == COGL_MATERIAL_STATE_COLOR)
|
|
|
|
{
|
|
|
|
gboolean will_need_blending =
|
|
|
|
_cogl_material_needs_blending_enabled (material,
|
|
|
|
change,
|
|
|
|
new_color);
|
|
|
|
gboolean blend_enable = material->real_blend_enable ? TRUE : FALSE;
|
|
|
|
|
|
|
|
if (will_need_blending == blend_enable)
|
|
|
|
skip_journal_flush = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!skip_journal_flush)
|
|
|
|
_cogl_journal_flush ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The fixed function backend has no private state and can't
|
|
|
|
* do anything special to handle small material changes so we may as
|
|
|
|
* well try to find a better backend whenever the material changes.
|
|
|
|
*
|
|
|
|
* The programmable backends may be able to cache a lot of the code
|
|
|
|
* they generate and only need to update a small section of that
|
|
|
|
* code in response to a material change therefore we don't want to
|
|
|
|
* try searching for another backend when the material changes.
|
|
|
|
*/
|
|
|
|
if (material->backend == COGL_MATERIAL_BACKEND_FIXED)
|
|
|
|
_cogl_material_set_backend (material, COGL_MATERIAL_BACKEND_UNDEFINED);
|
|
|
|
|
|
|
|
if (material->backend != COGL_MATERIAL_BACKEND_UNDEFINED &&
|
2010-07-09 22:40:47 -04:00
|
|
|
_cogl_material_backends[material->backend]->material_pre_change_notify)
|
|
|
|
{
|
|
|
|
const CoglMaterialBackend *backend =
|
|
|
|
_cogl_material_backends[material->backend];
|
|
|
|
backend->material_pre_change_notify (material, change, new_color);
|
|
|
|
}
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
/* There may be an arbitrary tree of descendants of this material;
|
|
|
|
* any of which may indirectly depend on this material as the
|
|
|
|
* authority for some set of properties. (Meaning for example that
|
|
|
|
* one of its descendants derives its color or blending state from
|
|
|
|
* this material.)
|
2010-04-08 07:21:04 -04:00
|
|
|
*
|
|
|
|
* We can't modify any property that this material is the authority
|
|
|
|
* for unless we create another material to take its place first and
|
|
|
|
* make sure descendants reference this new material instead.
|
|
|
|
*/
|
2010-08-09 11:01:17 -04:00
|
|
|
|
|
|
|
/* The simplest descendants to handle are weak materials; we simply
|
|
|
|
* destroy them if we are modifying a material they depend on. This
|
|
|
|
* means weak materials never cause us to do a copy-on-write. */
|
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
|
|
|
|
destroy_weak_children_cb,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* If there are still children remaining though we'll need to
|
|
|
|
* perform a copy-on-write and reparent the dependants as children
|
|
|
|
* of the copy. */
|
|
|
|
if (COGL_MATERIAL_NODE (material)->has_children)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterial *new_authority;
|
2010-07-08 06:49:31 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
COGL_STATIC_COUNTER (material_copy_on_write_counter,
|
|
|
|
"material copy on write counter",
|
|
|
|
"Increments each time a material "
|
|
|
|
"must be copied to allow modification",
|
|
|
|
0 /* no application private data */);
|
|
|
|
|
|
|
|
COGL_COUNTER_INC (_cogl_uprof_context, material_copy_on_write_counter);
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
new_authority =
|
|
|
|
cogl_material_copy (_cogl_material_get_parent (material));
|
2010-05-18 19:36:31 -04:00
|
|
|
_cogl_material_set_static_breadcrumb (new_authority,
|
|
|
|
"pre_change_notify:copy-on-write");
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* We could explicitly walk the descendants, OR together the set
|
|
|
|
* of differences that we determine this material is the
|
|
|
|
* authority on and only copy those differences copied across.
|
|
|
|
*
|
|
|
|
* Or, if we don't explicitly walk the descendants we at least
|
|
|
|
* know that material->differences represents the largest set of
|
|
|
|
* differences that this material could possibly be an authority
|
|
|
|
* on.
|
|
|
|
*
|
|
|
|
* We do the later just because it's simplest, but we might need
|
|
|
|
* to come back to this later...
|
|
|
|
*/
|
|
|
|
_cogl_material_copy_differences (new_authority, material,
|
|
|
|
material->differences);
|
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
/* Reparent the dependants of material to be children of
|
2010-04-08 07:21:04 -04:00
|
|
|
* new_authority instead... */
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
|
2010-08-09 11:01:17 -04:00
|
|
|
reparent_children_cb,
|
2010-07-08 06:49:31 -04:00
|
|
|
new_authority);
|
2010-07-03 13:44:47 -04:00
|
|
|
|
|
|
|
/* The children will keep the new authority alive so drop the
|
|
|
|
* reference we got when copying... */
|
|
|
|
cogl_object_unref (new_authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
2010-05-27 15:04:49 -04:00
|
|
|
/* At this point we know we have a material with no strong
|
|
|
|
* dependants (though we may have some weak children) so we are now
|
|
|
|
* free to modify the material. */
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-05-27 10:19:15 -04:00
|
|
|
material->age++;
|
|
|
|
|
2010-08-08 08:41:15 -04:00
|
|
|
/* If changing a sparse property and if the material isn't already an
|
|
|
|
* authority for the state group being modified then we need to
|
|
|
|
* initialize the corresponding state. */
|
|
|
|
if (change & COGL_MATERIAL_STATE_ALL_SPARSE &&
|
|
|
|
!(material->differences & change))
|
|
|
|
{
|
|
|
|
authority = _cogl_material_get_authority (material, change);
|
|
|
|
_cogl_material_initialize_sparse_state (material, authority, change);
|
|
|
|
}
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Each material has a sorted cache of the layers it depends on
|
|
|
|
* which will need updating via _cogl_material_update_layers_cache
|
|
|
|
* if a material's layers are changed. */
|
|
|
|
if (change == COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
recursively_free_layer_caches (material);
|
|
|
|
|
|
|
|
/* If the material being changed is the same as the last material we
|
|
|
|
* flushed then we keep a track of the changes so we can try to
|
|
|
|
* minimize redundant OpenGL calls if the same material is flushed
|
|
|
|
* again.
|
|
|
|
*/
|
|
|
|
if (ctx->current_material == material)
|
|
|
|
ctx->current_material_changes_since_flush |= change;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_add_layer_difference (CoglMaterial *material,
|
|
|
|
CoglMaterialLayer *layer,
|
|
|
|
gboolean inc_n_layers)
|
|
|
|
{
|
|
|
|
g_return_if_fail (layer->owner == NULL);
|
|
|
|
|
|
|
|
layer->owner = material;
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_ref (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material,
|
|
|
|
COGL_MATERIAL_STATE_LAYERS,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
material->differences |= COGL_MATERIAL_STATE_LAYERS;
|
|
|
|
|
|
|
|
material->layer_differences =
|
|
|
|
g_list_prepend (material->layer_differences, layer);
|
|
|
|
|
|
|
|
if (inc_n_layers)
|
|
|
|
material->n_layers++;
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* NB: If you are calling this it's your responsibility to have
|
|
|
|
* already called:
|
|
|
|
* _cogl_material_pre_change_notify (m, _CHANGE_LAYERS, NULL);
|
|
|
|
*/
|
2010-04-26 05:01:43 -04:00
|
|
|
static void
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_remove_layer_difference (CoglMaterial *material,
|
|
|
|
CoglMaterialLayer *layer,
|
|
|
|
gboolean dec_n_layers)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
g_return_if_fail (layer->owner == material);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
2010-04-26 05:01:43 -04:00
|
|
|
*/
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_pre_change_notify (material,
|
|
|
|
COGL_MATERIAL_STATE_LAYERS,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
layer->owner = NULL;
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_unref (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
material->differences |= COGL_MATERIAL_STATE_LAYERS;
|
|
|
|
|
|
|
|
material->layer_differences =
|
|
|
|
g_list_remove (material->layer_differences, layer);
|
|
|
|
|
|
|
|
if (dec_n_layers)
|
|
|
|
material->n_layers--;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_try_reverting_layers_authority (CoglMaterial *authority,
|
|
|
|
CoglMaterial *old_authority)
|
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
if (authority->layer_differences == NULL &&
|
|
|
|
_cogl_material_get_parent (authority))
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
/* If the previous _STATE_LAYERS authority has the same
|
|
|
|
* ->n_layers then we can revert to that being the authority
|
|
|
|
* again. */
|
|
|
|
if (!old_authority)
|
|
|
|
{
|
|
|
|
old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_get_authority (_cogl_material_get_parent (authority),
|
2010-04-08 07:21:04 -04:00
|
|
|
COGL_MATERIAL_STATE_LAYERS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old_authority->n_layers == authority->n_layers)
|
|
|
|
authority->differences &= ~COGL_MATERIAL_STATE_LAYERS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_automatic_blend_enable (CoglMaterial *material,
|
|
|
|
CoglMaterialState change)
|
|
|
|
{
|
|
|
|
gboolean blend_enable =
|
|
|
|
_cogl_material_needs_blending_enabled (material, change, NULL);
|
|
|
|
|
|
|
|
if (blend_enable != material->real_blend_enable)
|
|
|
|
{
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be
|
|
|
|
* modified.
|
|
|
|
* - If the material isn't currently an authority for the state
|
|
|
|
* being changed, then initialize that state from the current
|
|
|
|
* authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material,
|
|
|
|
COGL_MATERIAL_STATE_REAL_BLEND_ENABLE,
|
|
|
|
NULL);
|
|
|
|
material->real_blend_enable = blend_enable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int keep_n;
|
|
|
|
int current_pos;
|
|
|
|
gboolean needs_pruning;
|
|
|
|
int first_index_to_prune;
|
|
|
|
} CoglMaterialPruneLayersInfo;
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
update_prune_layers_info_cb (CoglMaterialLayer *layer, void *user_data)
|
|
|
|
{
|
|
|
|
CoglMaterialPruneLayersInfo *state = user_data;
|
|
|
|
|
|
|
|
if (state->current_pos == state->keep_n)
|
|
|
|
{
|
|
|
|
state->needs_pruning = TRUE;
|
|
|
|
state->first_index_to_prune = layer->index;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
state->current_pos++;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_cogl_material_prune_to_n_layers (CoglMaterial *material, int n)
|
|
|
|
{
|
|
|
|
CoglMaterialPruneLayersInfo state;
|
|
|
|
gboolean notified_change = TRUE;
|
|
|
|
GList *l;
|
|
|
|
GList *next;
|
|
|
|
|
|
|
|
state.keep_n = n;
|
|
|
|
state.current_pos = 0;
|
|
|
|
state.needs_pruning = FALSE;
|
|
|
|
_cogl_material_foreach_layer (material,
|
|
|
|
update_prune_layers_info_cb,
|
|
|
|
&state);
|
|
|
|
|
|
|
|
material->n_layers = n;
|
|
|
|
|
|
|
|
if (!state.needs_pruning)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!(material->differences & COGL_MATERIAL_STATE_LAYERS))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* It's possible that this material owns some of the layers being
|
|
|
|
* discarded, so we'll need to unlink them... */
|
|
|
|
for (l = material->layer_differences; l; l = next)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *layer = l->data;
|
|
|
|
next = l->next; /* we're modifying the list we're iterating */
|
|
|
|
|
|
|
|
if (layer->index > state.first_index_to_prune)
|
|
|
|
{
|
|
|
|
if (!notified_change)
|
|
|
|
{
|
|
|
|
/* - Flush journal primitives referencing the current
|
|
|
|
* state.
|
|
|
|
* - Make sure the material has no dependants so it may
|
|
|
|
* be modified.
|
|
|
|
* - If the material isn't currently an authority for
|
|
|
|
* the state being changed, then initialize that state
|
|
|
|
* from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material,
|
|
|
|
COGL_MATERIAL_STATE_LAYERS,
|
|
|
|
NULL);
|
|
|
|
notified_change = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
material->layer_differences =
|
|
|
|
g_list_delete_link (material->layer_differences, l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_backend_layer_change_notify (CoglMaterialLayer *layer,
|
|
|
|
CoglMaterialLayerState change)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* NB: layers may be used by multiple materials which may be using
|
|
|
|
* different backends, therefore we determine which backends to
|
|
|
|
* notify based on the private state pointers for each backend...
|
|
|
|
*/
|
|
|
|
for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++)
|
|
|
|
{
|
2010-07-09 22:40:47 -04:00
|
|
|
if (layer->backend_priv[i] &&
|
|
|
|
_cogl_material_backends[i]->layer_pre_change_notify)
|
|
|
|
{
|
|
|
|
const CoglMaterialBackend *backend = _cogl_material_backends[i];
|
|
|
|
backend->layer_pre_change_notify (layer, change);
|
|
|
|
}
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
unsigned int
|
|
|
|
_cogl_get_n_args_for_combine_func (GLint func)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
switch (func)
|
|
|
|
{
|
|
|
|
case GL_REPLACE:
|
|
|
|
return 1;
|
|
|
|
case GL_MODULATE:
|
|
|
|
case GL_ADD:
|
|
|
|
case GL_ADD_SIGNED:
|
|
|
|
case GL_SUBTRACT:
|
|
|
|
case GL_DOT3_RGB:
|
|
|
|
case GL_DOT3_RGBA:
|
|
|
|
return 2;
|
|
|
|
case GL_INTERPOLATE:
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_layer_initialize_state (CoglMaterialLayer *dest,
|
|
|
|
CoglMaterialLayer *src,
|
|
|
|
unsigned long differences)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerBigState *big_state;
|
|
|
|
|
|
|
|
dest->differences |= differences;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_UNIT)
|
|
|
|
dest->unit_index = src->unit_index;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_TEXTURE)
|
|
|
|
dest->texture = src->texture;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_FILTERS)
|
|
|
|
{
|
|
|
|
dest->min_filter = src->min_filter;
|
|
|
|
dest->mag_filter = src->mag_filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_WRAP_MODES)
|
|
|
|
{
|
|
|
|
dest->wrap_mode_s = src->wrap_mode_s;
|
|
|
|
dest->wrap_mode_t = src->wrap_mode_t;
|
2010-07-12 12:01:32 -04:00
|
|
|
dest->wrap_mode_p = src->wrap_mode_p;
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_NEEDS_BIG_STATE)
|
|
|
|
{
|
|
|
|
if (!dest->has_big_state)
|
|
|
|
{
|
|
|
|
dest->big_state = g_slice_new (CoglMaterialLayerBigState);
|
|
|
|
dest->has_big_state = TRUE;
|
|
|
|
}
|
|
|
|
big_state = dest->big_state;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_COMBINE)
|
|
|
|
{
|
|
|
|
int n_args;
|
|
|
|
int i;
|
|
|
|
GLint func = src->big_state->texture_combine_rgb_func;
|
|
|
|
big_state->texture_combine_rgb_func = func;
|
2010-06-15 11:44:52 -04:00
|
|
|
n_args = _cogl_get_n_args_for_combine_func (func);
|
2010-04-08 07:21:04 -04:00
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
big_state->texture_combine_rgb_src[i] =
|
|
|
|
src->big_state->texture_combine_rgb_src[i];
|
|
|
|
big_state->texture_combine_rgb_op[i] =
|
|
|
|
src->big_state->texture_combine_rgb_op[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
func = src->big_state->texture_combine_alpha_func;
|
|
|
|
big_state->texture_combine_alpha_func = func;
|
2010-06-15 11:44:52 -04:00
|
|
|
n_args = _cogl_get_n_args_for_combine_func (func);
|
2010-04-08 07:21:04 -04:00
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
big_state->texture_combine_alpha_src[i] =
|
|
|
|
src->big_state->texture_combine_alpha_src[i];
|
|
|
|
big_state->texture_combine_alpha_op[i] =
|
|
|
|
src->big_state->texture_combine_alpha_op[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_COMBINE_CONSTANT)
|
|
|
|
memcpy (dest->big_state->texture_combine_constant,
|
|
|
|
src->big_state->texture_combine_constant,
|
|
|
|
sizeof (float) * 4);
|
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_USER_MATRIX)
|
|
|
|
dest->big_state->matrix = src->big_state->matrix;
|
2010-03-22 09:33:55 -04:00
|
|
|
|
|
|
|
if (differences & COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS)
|
|
|
|
dest->big_state->point_sprite_coords = src->big_state->point_sprite_coords;
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* NB: This function will allocate a new derived layer if you are
|
|
|
|
* trying to change the state of a layer with dependants so you must
|
|
|
|
* always check the return value.
|
|
|
|
*
|
|
|
|
* If a new layer is returned it will be owned by required_owner.
|
|
|
|
*
|
|
|
|
* required_owner can only by NULL for new, currently unowned layers
|
|
|
|
* with no dependants.
|
|
|
|
*/
|
|
|
|
static CoglMaterialLayer *
|
|
|
|
_cogl_material_layer_pre_change_notify (CoglMaterial *required_owner,
|
|
|
|
CoglMaterialLayer *layer,
|
|
|
|
CoglMaterialLayerState change)
|
|
|
|
{
|
|
|
|
CoglTextureUnit *unit;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
|
|
|
|
/* Identify the case where the layer is new with no owner or
|
|
|
|
* dependants and so we don't need to do anything. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (COGL_MATERIAL_NODE (layer)->has_children == FALSE &&
|
|
|
|
layer->owner == NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
goto init_layer_state;
|
|
|
|
|
|
|
|
/* We only allow a NULL required_owner for new layers */
|
|
|
|
g_return_val_if_fail (required_owner != NULL, layer);
|
|
|
|
|
2010-08-08 08:54:07 -04: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_material_pre_change_notify (required_owner,
|
|
|
|
COGL_MATERIAL_STATE_LAYERS,
|
|
|
|
NULL);
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Unlike materials; layers are simply considered immutable once
|
2010-08-08 08:54:07 -04:00
|
|
|
* they have dependants - either direct children, or another
|
|
|
|
* material as an owner.
|
2010-04-08 07:21:04 -04:00
|
|
|
*/
|
2010-07-08 06:49:31 -04:00
|
|
|
if (COGL_MATERIAL_NODE (layer)->has_children ||
|
|
|
|
layer->owner != required_owner)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayer *new = _cogl_material_layer_copy (layer);
|
2010-08-08 09:26:45 -04:00
|
|
|
if (layer->owner == required_owner)
|
|
|
|
_cogl_material_remove_layer_difference (required_owner, layer, FALSE);
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_add_layer_difference (required_owner, new, FALSE);
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_unref (new);
|
2010-04-08 07:21:04 -04:00
|
|
|
layer = new;
|
|
|
|
goto init_layer_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note: At this point we know there is only one material dependant on
|
|
|
|
* this layer (required_owner), and there are no other layers
|
|
|
|
* dependant on this layer so it's ok to modify it. */
|
|
|
|
|
|
|
|
_cogl_material_backend_layer_change_notify (layer, change);
|
|
|
|
|
|
|
|
/* 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_material_layer_get_unit_index (layer));
|
|
|
|
if (unit->layer == layer)
|
|
|
|
unit->layer_changes_since_flush |= change;
|
|
|
|
|
|
|
|
init_layer_state:
|
|
|
|
|
2010-05-27 10:19:15 -04:00
|
|
|
if (required_owner)
|
|
|
|
required_owner->age++;
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* If the material isn't already an authority for the state group
|
|
|
|
* being modified then we need to initialize the corresponding
|
|
|
|
* state. */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
_cogl_material_layer_initialize_state (layer, authority, change);
|
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
static void
|
|
|
|
_cogl_material_layer_unparent (CoglMaterialNode *layer)
|
|
|
|
{
|
|
|
|
/* Chain up */
|
|
|
|
_cogl_material_node_unparent_real (layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_layer_set_parent (CoglMaterialLayer *layer,
|
|
|
|
CoglMaterialLayer *parent)
|
|
|
|
{
|
|
|
|
/* Chain up */
|
|
|
|
_cogl_material_node_set_parent_real (COGL_MATERIAL_NODE (layer),
|
|
|
|
COGL_MATERIAL_NODE (parent),
|
2010-08-09 11:01:17 -04:00
|
|
|
_cogl_material_layer_unparent,
|
|
|
|
TRUE);
|
2010-07-08 06:49:31 -04:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* XXX: This is duplicated logic; the same as for
|
|
|
|
* _cogl_material_prune_redundant_ancestry it would be nice to find a
|
|
|
|
* way to consolidate these functions! */
|
|
|
|
static void
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (CoglMaterialLayer *layer)
|
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *new_parent = _cogl_material_layer_get_parent (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* walk up past ancestors that are now redundant and potentially
|
|
|
|
* reparent the layer. */
|
2010-07-08 06:49:31 -04:00
|
|
|
while (_cogl_material_layer_get_parent (new_parent) &&
|
2010-04-08 07:21:04 -04:00
|
|
|
(new_parent->differences | layer->differences) ==
|
2010-07-08 06:49:31 -04:00
|
|
|
layer->differences)
|
|
|
|
new_parent = _cogl_material_layer_get_parent (new_parent);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_set_parent (layer, new_parent);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: consider special casing layer->unit_index so it's not a sparse
|
|
|
|
* property so instead we can assume it's valid for all layer
|
|
|
|
* instances.
|
|
|
|
* - We would need to initialize ->unit_index in
|
|
|
|
* _cogl_material_layer_copy ().
|
|
|
|
*
|
|
|
|
* XXX: If you use this API you should consider that the given layer
|
|
|
|
* might not be writeable and so a new derived layer will be allocated
|
|
|
|
* and modified instead. The layer modified will be returned so you
|
|
|
|
* can identify when this happens.
|
|
|
|
*/
|
|
|
|
static CoglMaterialLayer *
|
|
|
|
_cogl_material_set_layer_unit (CoglMaterial *required_owner,
|
|
|
|
CoglMaterialLayer *layer,
|
|
|
|
int unit_index)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_UNIT;
|
|
|
|
CoglMaterialLayer *authority =
|
|
|
|
_cogl_material_layer_get_authority (layer, change);
|
|
|
|
CoglMaterialLayer *new;
|
|
|
|
|
|
|
|
if (authority->unit_index == unit_index)
|
|
|
|
return layer;
|
|
|
|
|
|
|
|
new =
|
|
|
|
_cogl_material_layer_pre_change_notify (required_owner,
|
|
|
|
layer,
|
|
|
|
change);
|
|
|
|
if (new != layer)
|
|
|
|
layer = new;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the layer we found is currently the authority on the state
|
|
|
|
* we are changing see if we can revert to one of our ancestors
|
|
|
|
* being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent =
|
|
|
|
_cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, change);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (old_authority->unit_index == unit_index)
|
|
|
|
{
|
|
|
|
layer->differences &= ~change;
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->unit_index = unit_index;
|
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
|
|
|
layer->differences |= change;
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* The layer we are trying to find */
|
|
|
|
int layer_index;
|
|
|
|
|
|
|
|
/* The layer we find or untouched if not found */
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
|
|
|
|
/* If the layer can't be found then a new layer should be
|
|
|
|
* inserted after this texture unit index... */
|
|
|
|
int insert_after;
|
|
|
|
|
|
|
|
/* When adding a layer we need the list of layers to shift up
|
|
|
|
* to a new texture unit. When removing we need the list of
|
|
|
|
* layers to shift down.
|
|
|
|
*
|
|
|
|
* Note: the list isn't sorted */
|
|
|
|
CoglMaterialLayer **layers_to_shift;
|
|
|
|
int n_layers_to_shift;
|
|
|
|
|
|
|
|
/* When adding a layer we don't need a complete list of
|
|
|
|
* layers_to_shift if we find a layer already corresponding to the
|
|
|
|
* layer_index. */
|
|
|
|
gboolean ignore_shift_layers_if_found;
|
|
|
|
|
|
|
|
} CoglMaterialLayerInfo;
|
|
|
|
|
|
|
|
/* Returns TRUE once we know there is nothing more to update */
|
|
|
|
static gboolean
|
|
|
|
update_layer_info (CoglMaterialLayer *layer,
|
|
|
|
CoglMaterialLayerInfo *layer_info)
|
|
|
|
{
|
|
|
|
if (layer->index == layer_info->layer_index)
|
|
|
|
{
|
|
|
|
layer_info->layer = layer;
|
|
|
|
if (layer_info->ignore_shift_layers_if_found)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (layer->index < layer_info->layer_index)
|
|
|
|
{
|
|
|
|
int unit_index = _cogl_material_layer_get_unit_index (layer);
|
|
|
|
layer_info->insert_after = unit_index;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
layer_info->layers_to_shift[layer_info->n_layers_to_shift++] =
|
|
|
|
layer;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns FALSE to break out of a _foreach_layer () iteration */
|
|
|
|
static gboolean
|
|
|
|
update_layer_info_cb (CoglMaterialLayer *layer,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerInfo *layer_info = user_data;
|
|
|
|
|
|
|
|
if (update_layer_info (layer, layer_info))
|
|
|
|
return FALSE; /* break */
|
|
|
|
else
|
|
|
|
return TRUE; /* continue */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_get_layer_info (CoglMaterial *material,
|
|
|
|
CoglMaterialLayerInfo *layer_info)
|
|
|
|
{
|
|
|
|
/* Note: we are assuming this material is a _STATE_LAYERS authority */
|
|
|
|
int n_layers = material->n_layers;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* FIXME: _cogl_material_foreach_layer now calls
|
|
|
|
* _cogl_material_update_layers_cache anyway so this codepath is
|
|
|
|
* pointless! */
|
|
|
|
if (layer_info->ignore_shift_layers_if_found &&
|
|
|
|
material->layers_cache_dirty)
|
|
|
|
{
|
|
|
|
/* The expectation is that callers of
|
|
|
|
* _cogl_material_get_layer_info are likely to be modifying the
|
|
|
|
* list of layers associated with a material so in this case
|
|
|
|
* where we don't have a cache of the layers and we don't
|
|
|
|
* necessarily have to iterate all the layers of the material we
|
|
|
|
* use a foreach_layer callback instead of updating the cache
|
|
|
|
* and iterating that as below. */
|
|
|
|
_cogl_material_foreach_layer (material,
|
|
|
|
update_layer_info_cb,
|
|
|
|
layer_info);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_cogl_material_update_layers_cache (material);
|
|
|
|
for (i = 0; i < n_layers; i++)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *layer = material->layers_cache[i];
|
|
|
|
|
|
|
|
if (update_layer_info (layer, layer_info))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static CoglMaterialLayer *
|
|
|
|
_cogl_material_get_layer (CoglMaterial *material,
|
|
|
|
int layer_index)
|
|
|
|
{
|
|
|
|
CoglMaterial *authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LAYERS);
|
|
|
|
CoglMaterialLayerInfo layer_info;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
int unit_index;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
_COGL_GET_CONTEXT (ctx, NULL);
|
|
|
|
|
|
|
|
/* The layer index of the layer we want info about */
|
|
|
|
layer_info.layer_index = layer_index;
|
|
|
|
|
|
|
|
/* If a layer already exists with the given index this will be
|
|
|
|
* updated. */
|
|
|
|
layer_info.layer = NULL;
|
|
|
|
|
|
|
|
/* If a layer isn't found for the given index we'll need to know
|
|
|
|
* where to insert a new layer. */
|
|
|
|
layer_info.insert_after = -1;
|
|
|
|
|
|
|
|
/* If a layer can't be found then we'll need to insert a new layer
|
|
|
|
* and bump up the texture unit for all layers with an index
|
|
|
|
* > layer_index. */
|
|
|
|
layer_info.layers_to_shift =
|
|
|
|
g_alloca (sizeof (CoglMaterialLayer *) * authority->n_layers);
|
|
|
|
layer_info.n_layers_to_shift = 0;
|
|
|
|
|
|
|
|
/* If an exact match is found though we don't need a complete
|
|
|
|
* list of layers with indices > layer_index... */
|
|
|
|
layer_info.ignore_shift_layers_if_found = TRUE;
|
|
|
|
|
|
|
|
_cogl_material_get_layer_info (authority, &layer_info);
|
|
|
|
|
|
|
|
if (layer_info.layer)
|
|
|
|
return layer_info.layer;
|
|
|
|
|
|
|
|
unit_index = layer_info.insert_after + 1;
|
|
|
|
if (unit_index == 0)
|
|
|
|
layer = _cogl_material_layer_copy (ctx->default_layer_0);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *new;
|
|
|
|
layer = _cogl_material_layer_copy (ctx->default_layer_n);
|
|
|
|
new = _cogl_material_set_layer_unit (NULL, layer, unit_index);
|
|
|
|
/* Since we passed a newly allocated layer we wouldn't expect
|
|
|
|
* _set_layer_unit() to have to allocate *another* layer. */
|
|
|
|
g_assert (new == layer);
|
|
|
|
}
|
2010-07-07 14:23:57 -04:00
|
|
|
layer->index = layer_index;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
for (i = 0; i < layer_info.n_layers_to_shift; i++)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *shift_layer = layer_info.layers_to_shift[i];
|
|
|
|
|
|
|
|
unit_index = _cogl_material_layer_get_unit_index (shift_layer);
|
|
|
|
_cogl_material_set_layer_unit (material, shift_layer, unit_index + 1);
|
|
|
|
/* NB: shift_layer may not be writeable so _set_layer_unit()
|
|
|
|
* will allocate a derived layer internally which will become
|
|
|
|
* owned by material. Check the return value if we need to do
|
|
|
|
* anything else with this layer. */
|
|
|
|
}
|
|
|
|
|
|
|
|
_cogl_material_add_layer_difference (material, layer, TRUE);
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_unref (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
2010-06-15 11:44:52 -04:00
|
|
|
CoglHandle
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_layer_get_texture (CoglMaterialLayer *layer)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_TEXTURE);
|
|
|
|
|
|
|
|
return authority->texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_prune_empty_layer_difference (CoglMaterial *layers_authority,
|
|
|
|
CoglMaterialLayer *layer)
|
|
|
|
{
|
|
|
|
/* Find the GList link that references the empty layer */
|
|
|
|
GList *link = g_list_find (layers_authority->layer_differences, layer);
|
|
|
|
/* No material directly owns the root node layer so this is safe... */
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *layer_parent = _cogl_material_layer_get_parent (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayerInfo layer_info;
|
|
|
|
CoglMaterial *old_layers_authority;
|
|
|
|
|
|
|
|
g_return_if_fail (link != NULL);
|
|
|
|
|
|
|
|
/* If the layer's parent doesn't have an owner then we can simply
|
|
|
|
* take ownership ourselves and drop our reference on the empty
|
|
|
|
* layer.
|
|
|
|
*/
|
|
|
|
if (layer_parent->index == layer->index && layer_parent->owner == NULL)
|
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_ref (layer_parent);
|
2010-07-08 06:49:31 -04:00
|
|
|
link->data = _cogl_material_layer_get_parent (layer);
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_unref (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
recursively_free_layer_caches (layers_authority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now we want to find the layer that would become the authority for
|
|
|
|
* layer->index if we were to remove layer from
|
|
|
|
* layers_authority->layer_differences
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* The layer index of the layer we want info about */
|
|
|
|
layer_info.layer_index = layer->index;
|
|
|
|
|
|
|
|
/* If a layer already exists with the given index this will be
|
|
|
|
* updated. */
|
|
|
|
layer_info.layer = NULL;
|
|
|
|
|
|
|
|
/* If a layer can't be found then we'll need to insert a new layer
|
|
|
|
* and bump up the texture unit for all layers with an index
|
|
|
|
* > layer_index. */
|
|
|
|
layer_info.layers_to_shift =
|
|
|
|
g_alloca (sizeof (CoglMaterialLayer *) * layers_authority->n_layers);
|
|
|
|
layer_info.n_layers_to_shift = 0;
|
|
|
|
|
|
|
|
/* If an exact match is found though we don't need a complete
|
|
|
|
* list of layers with indices > layer_index... */
|
|
|
|
layer_info.ignore_shift_layers_if_found = TRUE;
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
/* We know the default/root material isn't a LAYERS authority so it's
|
|
|
|
* safe to use the result of _cogl_material_get_parent (layers_authority)
|
|
|
|
* without checking it.
|
|
|
|
*/
|
2010-04-08 07:21:04 -04:00
|
|
|
old_layers_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_get_authority (_cogl_material_get_parent (layers_authority),
|
2010-04-08 07:21:04 -04:00
|
|
|
COGL_MATERIAL_STATE_LAYERS);
|
|
|
|
|
|
|
|
_cogl_material_get_layer_info (old_layers_authority, &layer_info);
|
|
|
|
|
|
|
|
/* If layer is the defining layer for the corresponding ->index then
|
|
|
|
* we can't get rid of it. */
|
|
|
|
if (!layer_info.layer)
|
|
|
|
return;
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
/* If the layer that would become the authority for layer->index is
|
|
|
|
* _cogl_material_layer_get_parent (layer) then we can simply remove the
|
|
|
|
* layer difference. */
|
|
|
|
if (layer_info.layer == _cogl_material_layer_get_parent (layer))
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
_cogl_material_remove_layer_difference (layers_authority, layer, FALSE);
|
|
|
|
_cogl_material_try_reverting_layers_authority (layers_authority,
|
|
|
|
old_layers_authority);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_set_layer_texture (CoglMaterial *material,
|
|
|
|
int layer_index,
|
|
|
|
CoglHandle texture,
|
|
|
|
gboolean overriden,
|
|
|
|
GLuint slice_gl_texture,
|
|
|
|
GLenum slice_gl_target)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_TEXTURE;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialLayer *new;
|
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
if (authority->texture_overridden == overriden &&
|
|
|
|
authority->texture == texture &&
|
|
|
|
(authority->texture_overridden == FALSE ||
|
|
|
|
(authority->slice_gl_texture == slice_gl_texture &&
|
|
|
|
authority->slice_gl_target == slice_gl_target)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
new = _cogl_material_layer_pre_change_notify (material, layer, change);
|
|
|
|
if (new != layer)
|
|
|
|
layer = new;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the original layer we found is currently the authority on
|
|
|
|
* the state we are changing see if we can revert to one of our
|
|
|
|
* ancestors being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent =
|
|
|
|
_cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, change);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (old_authority->texture_overridden == overriden &&
|
|
|
|
old_authority->texture == texture &&
|
|
|
|
(old_authority->texture_overridden == FALSE ||
|
|
|
|
(old_authority->slice_gl_texture == slice_gl_texture &&
|
|
|
|
old_authority->slice_gl_target == slice_gl_target)))
|
|
|
|
{
|
|
|
|
layer->differences &= ~change;
|
|
|
|
|
2010-08-06 11:41:41 -04:00
|
|
|
if (layer->texture != COGL_INVALID_HANDLE)
|
|
|
|
cogl_handle_unref (layer->texture);
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
g_assert (layer->owner == material);
|
|
|
|
if (layer->differences == 0)
|
|
|
|
_cogl_material_prune_empty_layer_difference (material,
|
|
|
|
layer);
|
|
|
|
goto changed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (texture != COGL_INVALID_HANDLE)
|
|
|
|
cogl_handle_ref (texture);
|
|
|
|
if (layer == authority &&
|
|
|
|
layer->texture != COGL_INVALID_HANDLE)
|
|
|
|
cogl_handle_unref (layer->texture);
|
|
|
|
layer->texture = texture;
|
2010-07-08 13:28:11 -04:00
|
|
|
layer->texture_overridden = overriden;
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->slice_gl_texture = slice_gl_texture;
|
|
|
|
layer->slice_gl_target = slice_gl_target;
|
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
|
|
|
layer->differences |= change;
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
changed:
|
|
|
|
|
|
|
|
handle_automatic_blend_enable (material, COGL_MATERIAL_STATE_LAYERS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_set_layer_gl_texture_slice (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
int layer_index,
|
|
|
|
CoglHandle texture,
|
|
|
|
GLuint slice_gl_texture,
|
|
|
|
GLenum slice_gl_target)
|
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-08 07:21:04 -04:00
|
|
|
/* GL texture overrides can only be set in association with a parent
|
|
|
|
* CoglTexture */
|
|
|
|
g_return_if_fail (cogl_is_texture (texture));
|
|
|
|
|
|
|
|
_cogl_material_set_layer_texture (material,
|
|
|
|
layer_index,
|
|
|
|
texture,
|
|
|
|
TRUE, /* slice override */
|
|
|
|
slice_gl_texture,
|
|
|
|
slice_gl_target);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: deprecate and replace with cogl_material_set_layer_texture?
|
|
|
|
*
|
|
|
|
* Originally I was planning on allowing users to set shaders somehow
|
|
|
|
* on layers (thus the ambiguous name), but now I wonder if we will do
|
|
|
|
* that with a more explicit "snippets" API and materials will have
|
|
|
|
* hooks defined to receive these snippets.
|
|
|
|
*/
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
int layer_index,
|
|
|
|
CoglHandle texture)
|
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-08 07:21:04 -04:00
|
|
|
g_return_if_fail (texture == COGL_INVALID_HANDLE ||
|
|
|
|
cogl_is_texture (texture));
|
|
|
|
|
|
|
|
_cogl_material_set_layer_texture (material,
|
|
|
|
layer_index,
|
|
|
|
texture,
|
|
|
|
FALSE, /* slice override */
|
|
|
|
0, /* slice_gl_texture */
|
|
|
|
0); /* slice_gl_target */
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
CoglMaterial *material;
|
|
|
|
unsigned long fallback_layers;
|
|
|
|
} CoglMaterialFallbackState;
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
fallback_layer_cb (CoglMaterialLayer *layer, void *user_data)
|
|
|
|
{
|
|
|
|
CoglMaterialFallbackState *state = user_data;
|
|
|
|
CoglMaterial *material = state->material;
|
|
|
|
CoglHandle texture = _cogl_material_layer_get_texture (layer);
|
|
|
|
GLenum gl_target;
|
|
|
|
COGL_STATIC_COUNTER (layer_fallback_counter,
|
|
|
|
"layer fallback counter",
|
|
|
|
"Increments each time a layer's texture is "
|
|
|
|
"forced to a fallback texture",
|
|
|
|
0 /* no application private data */);
|
|
|
|
|
|
|
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
|
|
|
|
|
|
|
if (!(state->fallback_layers & 1<<state->i))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
COGL_COUNTER_INC (_cogl_uprof_context, layer_fallback_counter);
|
|
|
|
|
|
|
|
if (G_LIKELY (texture != COGL_INVALID_HANDLE))
|
|
|
|
cogl_texture_get_gl_texture (texture, NULL, &gl_target);
|
|
|
|
else
|
|
|
|
gl_target = GL_TEXTURE_2D;
|
|
|
|
|
|
|
|
if (gl_target == GL_TEXTURE_2D)
|
|
|
|
texture = ctx->default_gl_texture_2d_tex;
|
|
|
|
#ifdef HAVE_COGL_GL
|
|
|
|
else if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
|
|
|
texture = ctx->default_gl_texture_rect_tex;
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_warning ("We don't have a fallback texture we can use to fill "
|
|
|
|
"in for an invalid material layer, since it was "
|
|
|
|
"using an unsupported texture target ");
|
|
|
|
/* might get away with this... */
|
|
|
|
texture = ctx->default_gl_texture_2d_tex;
|
|
|
|
}
|
|
|
|
|
|
|
|
cogl_material_set_layer (material, layer->index, texture);
|
|
|
|
|
|
|
|
state->i++;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_cogl_material_set_layer_wrap_modes (CoglMaterial *material,
|
|
|
|
CoglMaterialLayer *layer,
|
|
|
|
CoglMaterialLayer *authority,
|
|
|
|
CoglMaterialWrapModeInternal wrap_mode_s,
|
|
|
|
CoglMaterialWrapModeInternal wrap_mode_t,
|
2010-07-12 12:01:32 -04:00
|
|
|
CoglMaterialWrapModeInternal wrap_mode_p)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayer *new;
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
|
|
|
|
if (authority->wrap_mode_s == wrap_mode_s &&
|
|
|
|
authority->wrap_mode_t == wrap_mode_t &&
|
2010-07-12 12:01:32 -04:00
|
|
|
authority->wrap_mode_p == wrap_mode_p)
|
2010-04-08 07:21:04 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
new = _cogl_material_layer_pre_change_notify (material, layer, change);
|
|
|
|
if (new != layer)
|
|
|
|
layer = new;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the original layer we found is currently the authority on
|
|
|
|
* the state we are changing see if we can revert to one of our
|
|
|
|
* ancestors being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent =
|
|
|
|
_cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, change);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (old_authority->wrap_mode_s == wrap_mode_s &&
|
|
|
|
old_authority->wrap_mode_t == wrap_mode_t &&
|
2010-07-12 12:01:32 -04:00
|
|
|
old_authority->wrap_mode_p == wrap_mode_p)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
layer->differences &= ~change;
|
|
|
|
|
|
|
|
g_assert (layer->owner == material);
|
|
|
|
if (layer->differences == 0)
|
|
|
|
_cogl_material_prune_empty_layer_difference (material,
|
|
|
|
layer);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->wrap_mode_s = wrap_mode_s;
|
|
|
|
layer->wrap_mode_t = wrap_mode_t;
|
2010-07-12 12:01:32 -04:00
|
|
|
layer->wrap_mode_p = wrap_mode_p;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
|
|
|
layer->differences |= change;
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static CoglMaterialWrapModeInternal
|
|
|
|
public_to_internal_wrap_mode (CoglMaterialWrapMode mode)
|
|
|
|
{
|
|
|
|
return (CoglMaterialWrapModeInternal)mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CoglMaterialWrapMode
|
|
|
|
internal_to_public_wrap_mode (CoglMaterialWrapModeInternal internal_mode)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (internal_mode !=
|
|
|
|
COGL_MATERIAL_WRAP_MODE_INTERNAL_CLAMP_TO_BORDER,
|
|
|
|
COGL_MATERIAL_WRAP_MODE_AUTOMATIC);
|
|
|
|
return (CoglMaterialWrapMode)internal_mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer_wrap_mode_s (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
int layer_index,
|
|
|
|
CoglMaterialWrapMode mode)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialWrapModeInternal internal_mode =
|
|
|
|
public_to_internal_wrap_mode (mode);
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
_cogl_material_set_layer_wrap_modes (material, layer, authority,
|
|
|
|
internal_mode,
|
|
|
|
authority->wrap_mode_t,
|
2010-07-12 12:01:32 -04:00
|
|
|
authority->wrap_mode_p);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer_wrap_mode_t (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
int layer_index,
|
|
|
|
CoglMaterialWrapMode mode)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialWrapModeInternal internal_mode =
|
|
|
|
public_to_internal_wrap_mode (mode);
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
_cogl_material_set_layer_wrap_modes (material, layer, authority,
|
|
|
|
authority->wrap_mode_s,
|
|
|
|
internal_mode,
|
2010-07-12 12:01:32 -04:00
|
|
|
authority->wrap_mode_p);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
2010-07-12 12:01:32 -04:00
|
|
|
/* The rationale for naming the third texture coordinate 'p' instead
|
|
|
|
of OpenGL's usual 'r' is that 'r' conflicts with the usual naming
|
|
|
|
of the 'red' component when treating a vector as a color. Under
|
|
|
|
GLSL this is awkward because the texture swizzling for a vector
|
|
|
|
uses a single letter for each component and the names for colors,
|
|
|
|
textures and positions are synonymous. GLSL works around this by
|
|
|
|
naming the components of the texture s, t, p and q. Cogl already
|
|
|
|
effectively already exposes this naming because it exposes GLSL so
|
|
|
|
it makes sense to use that naming consistently. Another alternative
|
|
|
|
could be u, v and w. This is what Blender and Direct3D use. However
|
|
|
|
the w component conflicts with the w component of a position
|
|
|
|
vertex. */
|
2010-04-08 07:21:04 -04:00
|
|
|
void
|
2010-07-02 08:33:06 -04:00
|
|
|
cogl_material_set_layer_wrap_mode_p (CoglMaterial *material,
|
|
|
|
int layer_index,
|
|
|
|
CoglMaterialWrapMode mode)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialWrapModeInternal internal_mode =
|
|
|
|
public_to_internal_wrap_mode (mode);
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
_cogl_material_set_layer_wrap_modes (material, layer, authority,
|
|
|
|
authority->wrap_mode_s,
|
|
|
|
authority->wrap_mode_t,
|
|
|
|
internal_mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer_wrap_mode (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
int layer_index,
|
|
|
|
CoglMaterialWrapMode mode)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialWrapModeInternal internal_mode =
|
|
|
|
public_to_internal_wrap_mode (mode);
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
_cogl_material_set_layer_wrap_modes (material, layer, authority,
|
|
|
|
internal_mode,
|
|
|
|
internal_mode,
|
|
|
|
internal_mode);
|
|
|
|
/* XXX: I wonder if we should really be duplicating the mode into
|
|
|
|
* the 'r' wrap mode too? */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: deprecate this API */
|
|
|
|
CoglMaterialWrapMode
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_layer_get_wrap_mode_s (CoglMaterialLayer *layer)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
|
2010-07-09 13:46:31 -04:00
|
|
|
g_return_val_if_fail (_cogl_is_material_layer (layer), FALSE);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
return internal_to_public_wrap_mode (authority->wrap_mode_s);
|
|
|
|
}
|
|
|
|
|
|
|
|
CoglMaterialWrapMode
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_layer_wrap_mode_s (CoglMaterial *material, int layer_index)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
CoglMaterialLayer *layer;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
/* FIXME: we shouldn't ever construct a layer in a getter function */
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
return cogl_material_layer_get_wrap_mode_s (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: deprecate this API */
|
|
|
|
CoglMaterialWrapMode
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_layer_get_wrap_mode_t (CoglMaterialLayer *layer)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
|
2010-07-09 13:46:31 -04:00
|
|
|
g_return_val_if_fail (_cogl_is_material_layer (layer), FALSE);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
return internal_to_public_wrap_mode (authority->wrap_mode_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
CoglMaterialWrapMode
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_layer_wrap_mode_t (CoglMaterial *material, int layer_index)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
CoglMaterialLayer *layer;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
/* FIXME: we shouldn't ever construct a layer in a getter function */
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
return cogl_material_layer_get_wrap_mode_t (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
CoglMaterialWrapMode
|
2010-07-02 08:33:06 -04:00
|
|
|
cogl_material_layer_get_wrap_mode_p (CoglMaterialLayer *layer)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_WRAP_MODES;
|
|
|
|
CoglMaterialLayer *authority =
|
|
|
|
_cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
2010-07-12 12:01:32 -04:00
|
|
|
return internal_to_public_wrap_mode (authority->wrap_mode_p);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
CoglMaterialWrapMode
|
2010-07-02 08:33:06 -04:00
|
|
|
cogl_material_get_layer_wrap_mode_p (CoglMaterial *material, int layer_index)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
2010-07-02 08:33:06 -04:00
|
|
|
return cogl_material_layer_get_wrap_mode_p (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
2010-07-09 22:40:47 -04:00
|
|
|
void
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_layer_get_wrap_modes (CoglMaterialLayer *layer,
|
|
|
|
CoglMaterialWrapModeInternal *wrap_mode_s,
|
|
|
|
CoglMaterialWrapModeInternal *wrap_mode_t,
|
2010-07-12 12:01:32 -04:00
|
|
|
CoglMaterialWrapModeInternal *wrap_mode_p)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayer *authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_WRAP_MODES);
|
|
|
|
|
|
|
|
*wrap_mode_s = authority->wrap_mode_s;
|
|
|
|
*wrap_mode_t = authority->wrap_mode_t;
|
2010-07-12 12:01:32 -04:00
|
|
|
*wrap_mode_p = authority->wrap_mode_p;
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
2010-03-22 09:33:55 -04:00
|
|
|
gboolean
|
|
|
|
cogl_material_set_layer_point_sprite_coords_enabled (CoglMaterial *material,
|
|
|
|
int layer_index,
|
|
|
|
gboolean enable,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerState change =
|
|
|
|
COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *new;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
|
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
|
|
|
|
|
|
|
/* Don't allow point sprite coordinates to be enabled if the driver
|
|
|
|
doesn't support it */
|
|
|
|
if (enable && !cogl_features_available (COGL_FEATURE_POINT_SPRITE))
|
|
|
|
{
|
|
|
|
if (error)
|
|
|
|
{
|
2010-07-13 07:59:24 -04:00
|
|
|
g_set_error (error, COGL_ERROR, COGL_ERROR_UNSUPPORTED,
|
2010-03-22 09:33:55 -04:00
|
|
|
"Point sprite texture coordinates are enabled "
|
|
|
|
"for a layer but the GL driver does not support it.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
static gboolean warning_seen = FALSE;
|
|
|
|
if (!warning_seen)
|
|
|
|
g_warning ("Point sprite texture coordinates are enabled "
|
|
|
|
"for a layer but the GL driver does not support it.");
|
|
|
|
warning_seen = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
if (authority->big_state->point_sprite_coords == enable)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
new = _cogl_material_layer_pre_change_notify (material, layer, change);
|
|
|
|
if (new != layer)
|
|
|
|
layer = new;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the original layer we found is currently the authority on
|
|
|
|
* the state we are changing see if we can revert to one of our
|
|
|
|
* ancestors being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-03-22 09:33:55 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent =
|
|
|
|
_cogl_material_layer_get_parent (authority);
|
2010-03-22 09:33:55 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, change);
|
2010-03-22 09:33:55 -04:00
|
|
|
|
|
|
|
if (old_authority->big_state->point_sprite_coords == enable)
|
|
|
|
{
|
|
|
|
layer->differences &= ~change;
|
|
|
|
|
|
|
|
g_assert (layer->owner == material);
|
|
|
|
if (layer->differences == 0)
|
|
|
|
_cogl_material_prune_empty_layer_difference (material,
|
|
|
|
layer);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->big_state->point_sprite_coords = enable;
|
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
|
|
|
layer->differences |= change;
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
cogl_material_get_layer_point_sprite_coords_enabled (CoglMaterial *material,
|
|
|
|
int layer_index)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerState change =
|
|
|
|
COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
|
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
|
|
|
|
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
/* FIXME: we shouldn't ever construct a layer in a getter function */
|
|
|
|
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, change);
|
|
|
|
|
|
|
|
return authority->big_state->point_sprite_coords;
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CoglMaterial *material;
|
|
|
|
CoglMaterialWrapModeOverrides *wrap_mode_overrides;
|
|
|
|
int i;
|
|
|
|
} CoglMaterialWrapModeOverridesState;
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
apply_wrap_mode_overrides_cb (CoglMaterialLayer *layer,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
CoglMaterialWrapModeOverridesState *state = user_data;
|
|
|
|
CoglMaterialLayer *authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_WRAP_MODES);
|
|
|
|
CoglMaterialWrapModeInternal wrap_mode_s;
|
|
|
|
CoglMaterialWrapModeInternal wrap_mode_t;
|
2010-07-12 12:01:32 -04:00
|
|
|
CoglMaterialWrapModeInternal wrap_mode_p;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
g_return_val_if_fail (state->i < 32, FALSE);
|
|
|
|
|
|
|
|
wrap_mode_s = state->wrap_mode_overrides->values[state->i].s;
|
|
|
|
if (wrap_mode_s == COGL_MATERIAL_WRAP_MODE_OVERRIDE_NONE)
|
|
|
|
wrap_mode_s = (CoglMaterialWrapModeInternal)authority->wrap_mode_s;
|
|
|
|
wrap_mode_t = state->wrap_mode_overrides->values[state->i].t;
|
|
|
|
if (wrap_mode_t == COGL_MATERIAL_WRAP_MODE_OVERRIDE_NONE)
|
|
|
|
wrap_mode_t = (CoglMaterialWrapModeInternal)authority->wrap_mode_t;
|
2010-07-12 12:01:32 -04:00
|
|
|
wrap_mode_p = state->wrap_mode_overrides->values[state->i].p;
|
|
|
|
if (wrap_mode_p == COGL_MATERIAL_WRAP_MODE_OVERRIDE_NONE)
|
|
|
|
wrap_mode_p = (CoglMaterialWrapModeInternal)authority->wrap_mode_p;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
_cogl_material_set_layer_wrap_modes (state->material,
|
|
|
|
layer,
|
|
|
|
authority,
|
|
|
|
wrap_mode_s,
|
|
|
|
wrap_mode_t,
|
2010-07-12 12:01:32 -04:00
|
|
|
wrap_mode_p);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
state->i++;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CoglMaterial *material;
|
|
|
|
GLuint gl_texture;
|
|
|
|
} CoglMaterialOverrideLayerState;
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
override_layer_texture_cb (CoglMaterialLayer *layer, void *user_data)
|
|
|
|
{
|
|
|
|
CoglMaterialOverrideLayerState *state = user_data;
|
|
|
|
CoglHandle texture;
|
|
|
|
GLenum gl_target;
|
|
|
|
|
|
|
|
texture = _cogl_material_layer_get_texture (layer);
|
|
|
|
|
|
|
|
if (texture != COGL_INVALID_HANDLE)
|
2010-07-08 13:28:11 -04:00
|
|
|
cogl_texture_get_gl_texture (texture, NULL, &gl_target);
|
2010-04-08 07:21:04 -04:00
|
|
|
else
|
|
|
|
gl_target = GL_TEXTURE_2D;
|
|
|
|
|
|
|
|
_cogl_material_set_layer_gl_texture_slice (state->material,
|
|
|
|
layer->index,
|
|
|
|
texture,
|
|
|
|
state->gl_texture,
|
|
|
|
gl_target);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-05-18 17:42:49 -04:00
|
|
|
void
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_apply_overrides (CoglMaterial *material,
|
|
|
|
CoglMaterialFlushOptions *options)
|
|
|
|
{
|
|
|
|
COGL_STATIC_COUNTER (apply_overrides_counter,
|
|
|
|
"material overrides counter",
|
|
|
|
"Increments each time we have to apply "
|
|
|
|
"override options to a material",
|
|
|
|
0 /* no application private data */);
|
|
|
|
|
|
|
|
COGL_COUNTER_INC (_cogl_uprof_context, apply_overrides_counter);
|
|
|
|
|
|
|
|
if (options->flags & COGL_MATERIAL_FLUSH_DISABLE_MASK)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* NB: we can assume that once we see one bit to disable
|
|
|
|
* a layer, all subsequent layers are also disabled. */
|
|
|
|
for (i = 0; i < 32 && options->disable_layers & (1<<i); i++)
|
|
|
|
;
|
|
|
|
|
|
|
|
_cogl_material_prune_to_n_layers (material, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options->flags & COGL_MATERIAL_FLUSH_FALLBACK_MASK)
|
|
|
|
{
|
|
|
|
CoglMaterialFallbackState state;
|
|
|
|
|
|
|
|
state.i = 0;
|
|
|
|
state.material = material;
|
|
|
|
state.fallback_layers = options->fallback_layers;
|
|
|
|
|
|
|
|
_cogl_material_foreach_layer (material,
|
|
|
|
fallback_layer_cb,
|
|
|
|
&state);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options->flags & COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE)
|
|
|
|
{
|
|
|
|
CoglMaterialOverrideLayerState state;
|
|
|
|
|
|
|
|
_cogl_material_prune_to_n_layers (material, 1);
|
|
|
|
|
|
|
|
/* NB: we are overriding the first layer, but we don't know
|
|
|
|
* the user's given layer_index, which is why we use
|
|
|
|
* _cogl_material_foreach_layer() here even though we know
|
|
|
|
* there's only one layer. */
|
|
|
|
state.material = material;
|
|
|
|
state.gl_texture = options->layer0_override_texture;
|
|
|
|
_cogl_material_foreach_layer (material,
|
|
|
|
override_layer_texture_cb,
|
|
|
|
&state);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options->flags & COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES)
|
|
|
|
{
|
|
|
|
CoglMaterialWrapModeOverridesState state;
|
|
|
|
|
|
|
|
state.material = material;
|
|
|
|
state.wrap_mode_overrides = &options->wrap_mode_overrides;
|
|
|
|
state.i = 0;
|
|
|
|
_cogl_material_foreach_layer (material,
|
|
|
|
apply_wrap_mode_overrides_cb,
|
|
|
|
&state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_texture_equal (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1)
|
|
|
|
{
|
2010-08-12 04:11:28 -04:00
|
|
|
GLuint gl_handle0, gl_handle1;
|
|
|
|
GLenum gl_target0, gl_target1;
|
2010-07-08 13:28:11 -04:00
|
|
|
|
2010-08-12 04:11:28 -04:00
|
|
|
if (authority0->texture_overridden)
|
|
|
|
{
|
|
|
|
gl_handle0 = authority0->slice_gl_texture;
|
|
|
|
gl_target0 = authority0->slice_gl_target;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, &gl_target0);
|
2010-07-08 13:28:11 -04:00
|
|
|
|
2010-08-12 04:11:28 -04:00
|
|
|
if (authority1->texture_overridden)
|
|
|
|
{
|
|
|
|
gl_handle1 = authority1->slice_gl_texture;
|
|
|
|
gl_target1 = authority1->slice_gl_target;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, &gl_target1);
|
2010-07-08 13:28:11 -04:00
|
|
|
|
2010-08-12 04:11:28 -04:00
|
|
|
return gl_handle0 == gl_handle1 && gl_target0 == gl_target1;
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine the mask of differences between two layers.
|
|
|
|
*
|
|
|
|
* XXX: If layers and materials could both be cast to a common Tree
|
|
|
|
* type of some kind then we could have a unified
|
|
|
|
* compare_differences() function.
|
|
|
|
*/
|
2010-06-15 11:44:52 -04:00
|
|
|
unsigned long
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_layer_compare_differences (CoglMaterialLayer *layer0,
|
|
|
|
CoglMaterialLayer *layer1)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *node0;
|
|
|
|
CoglMaterialLayer *node1;
|
|
|
|
int len0;
|
|
|
|
int len1;
|
|
|
|
int len0_index;
|
|
|
|
int len1_index;
|
|
|
|
int count;
|
|
|
|
int i;
|
|
|
|
CoglMaterialLayer *common_ancestor = NULL;
|
|
|
|
unsigned long layers_difference = 0;
|
|
|
|
|
|
|
|
_COGL_GET_CONTEXT (ctx, 0);
|
|
|
|
|
|
|
|
/* Algorithm:
|
|
|
|
*
|
|
|
|
* 1) Walk the ancestors of each layer to the root node, adding a
|
|
|
|
* pointer to each ancester node to two GArrays:
|
|
|
|
* ctx->material0_nodes, and ctx->material1_nodes.
|
|
|
|
*
|
|
|
|
* 2) Compare the arrays to find the nodes where they stop to
|
|
|
|
* differ.
|
|
|
|
*
|
|
|
|
* 3) For each array now iterate from index 0 to the first node of
|
|
|
|
* difference ORing that nodes ->difference mask into the final
|
|
|
|
* material_differences mask.
|
|
|
|
*/
|
|
|
|
|
|
|
|
g_array_set_size (ctx->material0_nodes, 0);
|
|
|
|
g_array_set_size (ctx->material1_nodes, 0);
|
2010-07-08 06:49:31 -04:00
|
|
|
for (node0 = layer0; node0; node0 = _cogl_material_layer_get_parent (node0))
|
2010-04-08 07:21:04 -04:00
|
|
|
g_array_append_vals (ctx->material0_nodes, &node0, 1);
|
2010-07-08 06:49:31 -04:00
|
|
|
for (node1 = layer1; node1; node1 = _cogl_material_layer_get_parent (node1))
|
2010-04-08 07:21:04 -04:00
|
|
|
g_array_append_vals (ctx->material1_nodes, &node1, 1);
|
|
|
|
|
|
|
|
len0 = ctx->material0_nodes->len;
|
|
|
|
len1 = ctx->material1_nodes->len;
|
|
|
|
/* There's no point looking at the last entries since we know both
|
|
|
|
* layers must have the same default layer as their root node. */
|
|
|
|
len0_index = len0 - 2;
|
|
|
|
len1_index = len1 - 2;
|
|
|
|
count = MIN (len0, len1) - 1;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
node0 = g_array_index (ctx->material0_nodes,
|
|
|
|
CoglMaterialLayer *, len0_index--);
|
|
|
|
node1 = g_array_index (ctx->material1_nodes,
|
|
|
|
CoglMaterialLayer *, len1_index--);
|
|
|
|
if (node0 != node1)
|
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
common_ancestor = _cogl_material_layer_get_parent (node0);
|
2010-04-08 07:21:04 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we didn't already find the first the common_ancestor ancestor
|
|
|
|
* that's because one material is a direct descendant of the other
|
|
|
|
* and in this case the first common ancestor is the last node we
|
|
|
|
* looked at. */
|
|
|
|
if (!common_ancestor)
|
|
|
|
common_ancestor = node0;
|
|
|
|
|
|
|
|
count = len0 - 1;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
node0 = g_array_index (ctx->material0_nodes, CoglMaterialLayer *, i);
|
|
|
|
if (node0 == common_ancestor)
|
|
|
|
break;
|
|
|
|
layers_difference |= node0->differences;
|
|
|
|
}
|
|
|
|
|
|
|
|
count = len1 - 1;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
node1 = g_array_index (ctx->material1_nodes, CoglMaterialLayer *, i);
|
|
|
|
if (node1 == common_ancestor)
|
|
|
|
break;
|
|
|
|
layers_difference |= node1->differences;
|
|
|
|
}
|
|
|
|
|
|
|
|
return layers_difference;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_combine_state_equal (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerBigState *big_state0 = authority0->big_state;
|
|
|
|
CoglMaterialLayerBigState *big_state1 = authority1->big_state;
|
|
|
|
int n_args;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (big_state0->texture_combine_rgb_func !=
|
|
|
|
big_state1->texture_combine_rgb_func)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (big_state0->texture_combine_alpha_func !=
|
|
|
|
big_state1->texture_combine_alpha_func)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
n_args =
|
2010-06-15 11:44:52 -04:00
|
|
|
_cogl_get_n_args_for_combine_func (big_state0->texture_combine_rgb_func);
|
2010-04-08 07:21:04 -04:00
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
if ((big_state0->texture_combine_rgb_src[i] !=
|
|
|
|
big_state1->texture_combine_rgb_src[i]) ||
|
|
|
|
(big_state0->texture_combine_rgb_op[i] !=
|
|
|
|
big_state1->texture_combine_rgb_op[i]))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
n_args =
|
2010-06-15 11:44:52 -04:00
|
|
|
_cogl_get_n_args_for_combine_func (big_state0->texture_combine_alpha_func);
|
2010-04-08 07:21:04 -04:00
|
|
|
for (i = 0; i < n_args; i++)
|
|
|
|
{
|
|
|
|
if ((big_state0->texture_combine_alpha_src[i] !=
|
|
|
|
big_state1->texture_combine_alpha_src[i]) ||
|
|
|
|
(big_state0->texture_combine_alpha_op[i] !=
|
|
|
|
big_state1->texture_combine_alpha_op[i]))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_combine_constant_equal (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1)
|
|
|
|
{
|
|
|
|
return memcmp (authority0->big_state->texture_combine_constant,
|
|
|
|
authority1->big_state->texture_combine_constant,
|
|
|
|
sizeof (float) * 4) == 0 ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_filters_equal (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1)
|
|
|
|
{
|
|
|
|
if (authority0->mag_filter != authority1->mag_filter)
|
|
|
|
return FALSE;
|
|
|
|
if (authority0->min_filter != authority1->min_filter)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_wrap_modes_equal (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1)
|
|
|
|
{
|
|
|
|
if (authority0->wrap_mode_s != authority1->wrap_mode_s ||
|
|
|
|
authority0->wrap_mode_t != authority1->wrap_mode_t ||
|
2010-07-12 12:01:32 -04:00
|
|
|
authority0->wrap_mode_p != authority1->wrap_mode_p)
|
2010-04-08 07:21:04 -04:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_user_matrix_equal (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerBigState *big_state0 = authority0->big_state;
|
|
|
|
CoglMaterialLayerBigState *big_state1 = authority1->big_state;
|
|
|
|
|
|
|
|
if (!cogl_matrix_equal (&big_state0->matrix, &big_state1->matrix))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-03-22 09:33:55 -04:00
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_point_sprite_coords_equal (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1)
|
|
|
|
{
|
|
|
|
CoglMaterialLayerBigState *big_state0 = authority0->big_state;
|
|
|
|
CoglMaterialLayerBigState *big_state1 = authority1->big_state;
|
|
|
|
|
|
|
|
return big_state0->point_sprite_coords == big_state1->point_sprite_coords;
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
typedef gboolean
|
|
|
|
(*CoglMaterialLayerStateComparitor) (CoglMaterialLayer *authority0,
|
|
|
|
CoglMaterialLayer *authority1);
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
layer_state_equal (CoglMaterialLayerState state,
|
|
|
|
CoglMaterialLayer *layer0,
|
|
|
|
CoglMaterialLayer *layer1,
|
|
|
|
CoglMaterialLayerStateComparitor comparitor)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *authority0 =
|
|
|
|
_cogl_material_layer_get_authority (layer0, state);
|
|
|
|
CoglMaterialLayer *authority1 =
|
|
|
|
_cogl_material_layer_get_authority (layer1, state);
|
|
|
|
|
|
|
|
return comparitor (authority0, authority1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_layer_equal (CoglMaterialLayer *layer0,
|
|
|
|
CoglMaterialLayer *layer1)
|
|
|
|
{
|
|
|
|
unsigned long layers_difference;
|
|
|
|
|
|
|
|
if (layer0 == layer1)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
layers_difference =
|
|
|
|
_cogl_material_layer_compare_differences (layer0, layer1);
|
|
|
|
|
|
|
|
if (layers_difference & COGL_MATERIAL_LAYER_STATE_TEXTURE &&
|
|
|
|
!layer_state_equal (COGL_MATERIAL_LAYER_STATE_TEXTURE,
|
|
|
|
layer0, layer1,
|
|
|
|
_cogl_material_layer_texture_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_MATERIAL_LAYER_STATE_COMBINE &&
|
|
|
|
!layer_state_equal (COGL_MATERIAL_LAYER_STATE_COMBINE,
|
|
|
|
layer0, layer1,
|
|
|
|
_cogl_material_layer_combine_state_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_MATERIAL_LAYER_STATE_COMBINE_CONSTANT &&
|
|
|
|
!layer_state_equal (COGL_MATERIAL_LAYER_STATE_COMBINE_CONSTANT,
|
|
|
|
layer0, layer1,
|
|
|
|
_cogl_material_layer_combine_constant_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_MATERIAL_LAYER_STATE_FILTERS &&
|
|
|
|
!layer_state_equal (COGL_MATERIAL_LAYER_STATE_FILTERS,
|
|
|
|
layer0, layer1,
|
|
|
|
_cogl_material_layer_filters_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_MATERIAL_LAYER_STATE_WRAP_MODES &&
|
|
|
|
!layer_state_equal (COGL_MATERIAL_LAYER_STATE_WRAP_MODES,
|
|
|
|
layer0, layer1,
|
|
|
|
_cogl_material_layer_wrap_modes_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (layers_difference & COGL_MATERIAL_LAYER_STATE_USER_MATRIX &&
|
|
|
|
!layer_state_equal (COGL_MATERIAL_LAYER_STATE_USER_MATRIX,
|
|
|
|
layer0, layer1,
|
|
|
|
_cogl_material_layer_user_matrix_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-03-22 09:33:55 -04:00
|
|
|
if (layers_difference & COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS &&
|
|
|
|
!layer_state_equal (COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS,
|
|
|
|
layer0, layer1,
|
|
|
|
_cogl_material_layer_point_sprite_coords_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_color_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
return cogl_color_equal (&authority0->color, &authority1->color);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_lighting_state_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
CoglMaterialLightingState *state0 = &authority0->big_state->lighting_state;
|
|
|
|
CoglMaterialLightingState *state1 = &authority1->big_state->lighting_state;
|
|
|
|
|
|
|
|
if (memcmp (state0->ambient, state1->ambient, sizeof (float) * 4) != 0)
|
|
|
|
return FALSE;
|
|
|
|
if (memcmp (state0->diffuse, state1->diffuse, sizeof (float) * 4) != 0)
|
|
|
|
return FALSE;
|
|
|
|
if (memcmp (state0->specular, state1->specular, sizeof (float) * 4) != 0)
|
|
|
|
return FALSE;
|
|
|
|
if (memcmp (state0->emission, state1->emission, sizeof (float) * 4) != 0)
|
|
|
|
return FALSE;
|
|
|
|
if (state0->shininess != state1->shininess)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_alpha_state_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
CoglMaterialAlphaFuncState *alpha_state0 =
|
|
|
|
&authority0->big_state->alpha_state;
|
|
|
|
CoglMaterialAlphaFuncState *alpha_state1 =
|
|
|
|
&authority1->big_state->alpha_state;
|
|
|
|
|
|
|
|
if (alpha_state0->alpha_func != alpha_state1->alpha_func ||
|
|
|
|
alpha_state0->alpha_func_reference != alpha_state1->alpha_func_reference)
|
|
|
|
return FALSE;
|
|
|
|
else
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_blend_state_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
CoglMaterialBlendState *blend_state0 = &authority0->big_state->blend_state;
|
|
|
|
CoglMaterialBlendState *blend_state1 = &authority1->big_state->blend_state;
|
|
|
|
|
|
|
|
#ifndef HAVE_COGL_GLES
|
|
|
|
if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb)
|
|
|
|
return FALSE;
|
|
|
|
if (blend_state0->blend_equation_alpha !=
|
|
|
|
blend_state1->blend_equation_alpha)
|
|
|
|
return FALSE;
|
|
|
|
if (blend_state0->blend_src_factor_alpha !=
|
|
|
|
blend_state1->blend_src_factor_alpha)
|
|
|
|
return FALSE;
|
|
|
|
if (blend_state0->blend_dst_factor_alpha !=
|
|
|
|
blend_state1->blend_dst_factor_alpha)
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
if (blend_state0->blend_src_factor_rgb !=
|
|
|
|
blend_state1->blend_src_factor_rgb)
|
|
|
|
return FALSE;
|
|
|
|
if (blend_state0->blend_dst_factor_rgb !=
|
|
|
|
blend_state1->blend_dst_factor_rgb)
|
|
|
|
return FALSE;
|
|
|
|
#ifndef HAVE_COGL_GLES
|
|
|
|
if (!cogl_color_equal (&blend_state0->blend_constant,
|
|
|
|
&blend_state1->blend_constant))
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-05-26 06:33:32 -04:00
|
|
|
static gboolean
|
|
|
|
_cogl_material_depth_state_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
2010-05-26 09:13:37 -04:00
|
|
|
if (authority0->big_state->depth_state.depth_test_enabled == FALSE &&
|
|
|
|
authority1->big_state->depth_state.depth_test_enabled == FALSE)
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return memcmp (&authority0->big_state->depth_state,
|
|
|
|
&authority1->big_state->depth_state,
|
|
|
|
sizeof (CoglMaterialDepthState)) == 0;
|
2010-05-26 06:33:32 -04:00
|
|
|
}
|
|
|
|
|
2010-07-06 15:18:26 -04:00
|
|
|
static gboolean
|
|
|
|
_cogl_material_fog_state_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
CoglMaterialFogState *fog_state0 = &authority0->big_state->fog_state;
|
|
|
|
CoglMaterialFogState *fog_state1 = &authority1->big_state->fog_state;
|
|
|
|
|
|
|
|
if (fog_state0->enabled == fog_state1->enabled &&
|
|
|
|
cogl_color_equal (&fog_state0->color, &fog_state1->color) &&
|
|
|
|
fog_state0->mode == fog_state1->mode &&
|
|
|
|
fog_state0->density == fog_state1->density &&
|
|
|
|
fog_state0->z_near == fog_state1->z_near &&
|
|
|
|
fog_state0->z_far == fog_state1->z_far)
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-03-22 05:32:17 -04:00
|
|
|
static gboolean
|
|
|
|
_cogl_material_point_size_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
return authority0->big_state->point_size == authority1->big_state->point_size;
|
|
|
|
}
|
|
|
|
|
2010-07-17 09:08:28 -04:00
|
|
|
static gboolean
|
|
|
|
_cogl_material_user_shader_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
return (authority0->big_state->user_program ==
|
|
|
|
authority1->big_state->user_program);
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
static gboolean
|
|
|
|
_cogl_material_layers_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (authority0->n_layers != authority1->n_layers)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
_cogl_material_update_layers_cache (authority0);
|
|
|
|
_cogl_material_update_layers_cache (authority1);
|
|
|
|
|
|
|
|
for (i = 0; i < authority0->n_layers; i++)
|
|
|
|
{
|
|
|
|
if (!_cogl_material_layer_equal (authority0->layers_cache[i],
|
|
|
|
authority1->layers_cache[i]))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine the mask of differences between two materials */
|
2010-07-09 22:40:47 -04:00
|
|
|
unsigned long
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_compare_differences (CoglMaterial *material0,
|
|
|
|
CoglMaterial *material1)
|
|
|
|
{
|
|
|
|
CoglMaterial *node0;
|
|
|
|
CoglMaterial *node1;
|
|
|
|
int len0;
|
|
|
|
int len1;
|
|
|
|
int len0_index;
|
|
|
|
int len1_index;
|
|
|
|
int count;
|
|
|
|
int i;
|
|
|
|
CoglMaterial *common_ancestor = NULL;
|
|
|
|
unsigned long materials_difference = 0;
|
|
|
|
|
|
|
|
_COGL_GET_CONTEXT (ctx, 0);
|
|
|
|
|
|
|
|
/* Algorithm:
|
|
|
|
*
|
|
|
|
* 1) Walk the ancestors of each layer to the root node, adding a
|
|
|
|
* pointer to each ancester node to two GArrays:
|
|
|
|
* ctx->material0_nodes, and ctx->material1_nodes.
|
|
|
|
*
|
|
|
|
* 2) Compare the arrays to find the nodes where they stop to
|
|
|
|
* differ.
|
|
|
|
*
|
|
|
|
* 3) For each array now iterate from index 0 to the first node of
|
|
|
|
* difference ORing that nodes ->difference mask into the final
|
|
|
|
* material_differences mask.
|
|
|
|
*/
|
|
|
|
|
|
|
|
g_array_set_size (ctx->material0_nodes, 0);
|
|
|
|
g_array_set_size (ctx->material1_nodes, 0);
|
2010-07-08 06:49:31 -04:00
|
|
|
for (node0 = material0; node0; node0 = _cogl_material_get_parent (node0))
|
2010-04-08 07:21:04 -04:00
|
|
|
g_array_append_vals (ctx->material0_nodes, &node0, 1);
|
2010-07-08 06:49:31 -04:00
|
|
|
for (node1 = material1; node1; node1 = _cogl_material_get_parent (node1))
|
2010-04-08 07:21:04 -04:00
|
|
|
g_array_append_vals (ctx->material1_nodes, &node1, 1);
|
|
|
|
|
|
|
|
len0 = ctx->material0_nodes->len;
|
|
|
|
len1 = ctx->material1_nodes->len;
|
|
|
|
/* There's no point looking at the last entries since we know both
|
|
|
|
* layers must have the same default layer as their root node. */
|
|
|
|
len0_index = len0 - 2;
|
|
|
|
len1_index = len1 - 2;
|
|
|
|
count = MIN (len0, len1) - 1;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
node0 = g_array_index (ctx->material0_nodes,
|
|
|
|
CoglMaterial *, len0_index--);
|
|
|
|
node1 = g_array_index (ctx->material1_nodes,
|
|
|
|
CoglMaterial *, len1_index--);
|
|
|
|
if (node0 != node1)
|
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
common_ancestor = _cogl_material_get_parent (node0);
|
2010-04-08 07:21:04 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we didn't already find the first the common_ancestor ancestor
|
|
|
|
* that's because one material is a direct descendant of the other
|
|
|
|
* and in this case the first common ancestor is the last node we
|
|
|
|
* looked at. */
|
|
|
|
if (!common_ancestor)
|
|
|
|
common_ancestor = node0;
|
|
|
|
|
|
|
|
count = len0 - 1;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
node0 = g_array_index (ctx->material0_nodes, CoglMaterial *, i);
|
|
|
|
if (node0 == common_ancestor)
|
|
|
|
break;
|
|
|
|
materials_difference |= node0->differences;
|
|
|
|
}
|
|
|
|
|
|
|
|
count = len1 - 1;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
node1 = g_array_index (ctx->material1_nodes, CoglMaterial *, i);
|
|
|
|
if (node1 == common_ancestor)
|
|
|
|
break;
|
|
|
|
materials_difference |= node1->differences;
|
|
|
|
}
|
|
|
|
|
|
|
|
return materials_difference;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-05-26 09:13:37 -04:00
|
|
|
static gboolean
|
|
|
|
simple_property_equal (CoglMaterial *material0,
|
|
|
|
CoglMaterial *material1,
|
|
|
|
unsigned long materials_difference,
|
|
|
|
CoglMaterialState state,
|
|
|
|
CoglMaterialStateComparitor comparitor)
|
|
|
|
{
|
|
|
|
if (materials_difference & state)
|
|
|
|
{
|
|
|
|
if (!comparitor (_cogl_material_get_authority (material0, state),
|
|
|
|
_cogl_material_get_authority (material1, state)))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Comparison of two arbitrary materials is done by:
|
|
|
|
* 1) walking up the parents of each material until a common
|
|
|
|
* ancestor is found, and at each step ORing together the
|
|
|
|
* difference masks.
|
|
|
|
*
|
|
|
|
* 2) using the final difference mask to determine which state
|
|
|
|
* groups to compare.
|
|
|
|
*
|
|
|
|
* This is used by the Cogl journal to compare materials so that it
|
|
|
|
* can split up geometry that needs different OpenGL state.
|
|
|
|
*
|
|
|
|
* It is acceptable to have false negatives - although they will result
|
|
|
|
* in redundant OpenGL calls that try and update the state.
|
|
|
|
*
|
2010-08-12 04:11:28 -04:00
|
|
|
* When comparing texture layers, _cogl_material_equal will actually
|
|
|
|
* compare the underlying GL texture handle that the Cogl texture uses
|
|
|
|
* so that atlas textures and sub textures will be considered equal if
|
|
|
|
* they point to the same texture. This is useful for comparing
|
|
|
|
* materials in the journal but it means that _cogl_material_equal
|
|
|
|
* doesn't strictly compare whether the materials are the same. If we
|
|
|
|
* needed those semantics we could perhaps add another function or
|
|
|
|
* some flags to control the behaviour.
|
|
|
|
*
|
2010-04-08 07:21:04 -04:00
|
|
|
* False positives aren't allowed.
|
|
|
|
*/
|
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_equal (CoglMaterial *material0,
|
|
|
|
CoglMaterial *material1,
|
2010-04-08 07:21:04 -04:00
|
|
|
gboolean skip_gl_color)
|
|
|
|
{
|
|
|
|
unsigned long materials_difference;
|
|
|
|
|
|
|
|
if (material0 == material1)
|
2010-05-18 18:38:33 -04:00
|
|
|
return TRUE;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* First check non-sparse properties */
|
|
|
|
|
|
|
|
if (material0->real_blend_enable != material1->real_blend_enable)
|
2010-05-18 18:38:33 -04:00
|
|
|
return FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* Then check sparse properties */
|
|
|
|
|
|
|
|
materials_difference =
|
|
|
|
_cogl_material_compare_differences (material0, material1);
|
|
|
|
|
|
|
|
if (materials_difference & COGL_MATERIAL_STATE_COLOR &&
|
|
|
|
!skip_gl_color)
|
|
|
|
{
|
2010-05-26 09:13:37 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_COLOR;
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority0 =
|
2010-05-26 09:13:37 -04:00
|
|
|
_cogl_material_get_authority (material0, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority1 =
|
2010-05-26 09:13:37 -04:00
|
|
|
_cogl_material_get_authority (material1, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (!cogl_color_equal (&authority0->color, &authority1->color))
|
2010-05-18 18:38:33 -04:00
|
|
|
return FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
2010-05-26 09:13:37 -04:00
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_LIGHTING,
|
|
|
|
_cogl_material_lighting_state_equal))
|
|
|
|
return FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-05-26 09:13:37 -04:00
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_ALPHA_FUNC,
|
|
|
|
_cogl_material_alpha_state_equal))
|
|
|
|
return FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-05-26 09:13:37 -04:00
|
|
|
/* We don't need to compare the detailed blending state if we know
|
|
|
|
* blending is disabled for both materials. */
|
|
|
|
if (material0->real_blend_enable &&
|
|
|
|
materials_difference & COGL_MATERIAL_STATE_BLEND)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-05-26 09:13:37 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_BLEND;
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority0 =
|
2010-05-26 09:13:37 -04:00
|
|
|
_cogl_material_get_authority (material0, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority1 =
|
2010-05-26 09:13:37 -04:00
|
|
|
_cogl_material_get_authority (material1, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (!_cogl_material_blend_state_equal (authority0, authority1))
|
2010-05-18 18:38:33 -04:00
|
|
|
return FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
2010-05-26 09:13:37 -04:00
|
|
|
/* XXX: we don't need to compare the BLEND_ENABLE state because it's
|
|
|
|
* already reflected in ->real_blend_enable */
|
|
|
|
#if 0
|
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_BLEND,
|
|
|
|
_cogl_material_blend_enable_equal))
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
2010-05-26 06:33:32 -04:00
|
|
|
|
2010-05-26 09:13:37 -04:00
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_DEPTH,
|
|
|
|
_cogl_material_depth_state_equal))
|
|
|
|
return FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-07-06 15:18:26 -04:00
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_FOG,
|
|
|
|
_cogl_material_fog_state_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-03-22 05:32:17 -04:00
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_POINT_SIZE,
|
|
|
|
_cogl_material_point_size_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-07-17 09:08:28 -04:00
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_USER_SHADER,
|
|
|
|
_cogl_material_user_shader_equal))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-05-26 09:13:37 -04:00
|
|
|
if (!simple_property_equal (material0, material1,
|
|
|
|
materials_difference,
|
|
|
|
COGL_MATERIAL_STATE_LAYERS,
|
|
|
|
_cogl_material_layers_equal))
|
|
|
|
return FALSE;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-05-18 18:38:33 -04:00
|
|
|
return TRUE;
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
}
|
|
|
|
|
2008-12-23 18:35:49 -05:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_color (CoglMaterial *material,
|
|
|
|
CoglColor *color)
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_COLOR);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
*color = authority->color;
|
2009-06-04 09:23:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This is used heavily by the cogl journal when logging quads */
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_get_colorubv (CoglMaterial *material,
|
|
|
|
guint8 *color)
|
2009-06-04 09:23:16 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_COLOR);
|
|
|
|
|
|
|
|
_cogl_color_get_rgba_4ubv (&authority->color, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_prune_redundant_ancestry (CoglMaterial *material)
|
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *new_parent = _cogl_material_get_parent (material);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* walk up past ancestors that are now redundant and potentially
|
|
|
|
* reparent the material. */
|
2010-07-08 06:49:31 -04:00
|
|
|
while (_cogl_material_get_parent (new_parent) &&
|
2010-04-08 07:21:04 -04:00
|
|
|
(new_parent->differences | material->differences) ==
|
|
|
|
material->differences)
|
2010-07-08 06:49:31 -04:00
|
|
|
new_parent = _cogl_material_get_parent (new_parent);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-08-09 11:01:17 -04:00
|
|
|
if (new_parent != _cogl_material_get_parent (material))
|
|
|
|
{
|
|
|
|
gboolean is_weak = _cogl_material_is_weak (material);
|
|
|
|
_cogl_material_set_parent (material, new_parent, is_weak ? FALSE : TRUE);
|
|
|
|
}
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_material_update_authority (CoglMaterial *material,
|
|
|
|
CoglMaterial *authority,
|
|
|
|
CoglMaterialState state,
|
|
|
|
CoglMaterialStateComparitor comparitor)
|
|
|
|
{
|
|
|
|
/* If we are the current authority see if we can revert to one of
|
|
|
|
* our ancestors being the authority */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (material == authority &&
|
|
|
|
_cogl_material_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *parent = _cogl_material_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_get_authority (parent, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (comparitor (authority, old_authority))
|
|
|
|
material->differences &= ~state;
|
|
|
|
}
|
|
|
|
else if (material != authority)
|
|
|
|
{
|
|
|
|
/* If we weren't previously the authority on this state then we
|
|
|
|
* need to extended our differences mask and so it's possible
|
|
|
|
* that some of our ancestry will now become redundant, so we
|
|
|
|
* aim to reparent ourselves if that's true... */
|
|
|
|
material->differences |= state;
|
|
|
|
_cogl_material_prune_redundant_ancestry (material);
|
|
|
|
}
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_color (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
const CoglColor *color)
|
2008-12-23 18:35:49 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_COLOR;
|
|
|
|
CoglMaterial *authority;
|
2008-12-23 18:35:49 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2008-12-23 18:35:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
2008-12-23 18:35:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (cogl_color_equal (color, &authority->color))
|
2008-12-23 18:35:49 -05:00
|
|
|
return;
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, color);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
material->color = *color;
|
2008-12-23 18:35:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_color_equal);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
handle_automatic_blend_enable (material, state);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_color4ub (CoglMaterial *material,
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
guint8 red,
|
|
|
|
guint8 green,
|
|
|
|
guint8 blue,
|
|
|
|
guint8 alpha)
|
|
|
|
{
|
|
|
|
CoglColor color;
|
|
|
|
cogl_color_set_from_4ub (&color, red, green, blue, alpha);
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_color (material, &color);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
}
|
|
|
|
|
2009-05-01 04:53:20 -04:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_color4f (CoglMaterial *material,
|
2009-05-01 04:53:20 -04:00
|
|
|
float red,
|
|
|
|
float green,
|
|
|
|
float blue,
|
|
|
|
float alpha)
|
|
|
|
{
|
|
|
|
CoglColor color;
|
|
|
|
cogl_color_set_from_4f (&color, red, green, blue, alpha);
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_color (material, &color);
|
2009-05-01 04:53:20 -04:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialBlendEnable
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_get_blend_enabled (CoglMaterial *material)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_BLEND_ENABLE);
|
|
|
|
return authority->blend_enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_cogl_material_blend_enable_equal (CoglMaterial *authority0,
|
|
|
|
CoglMaterial *authority1)
|
|
|
|
{
|
|
|
|
return authority0->blend_enable == authority1->blend_enable ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_set_blend_enabled (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialBlendEnable enable)
|
|
|
|
{
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_BLEND_ENABLE;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-08 07:21:04 -04:00
|
|
|
g_return_if_fail (enable > 1 &&
|
|
|
|
"don't pass TRUE or FALSE to _set_blend_enabled!");
|
|
|
|
|
|
|
|
authority = _cogl_material_get_authority (material, state);
|
|
|
|
|
|
|
|
if (authority->blend_enable == enable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
material->blend_enable = enable;
|
|
|
|
|
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_blend_enable_equal);
|
|
|
|
|
|
|
|
handle_automatic_blend_enable (material, state);
|
|
|
|
}
|
|
|
|
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_ambient (CoglMaterial *material,
|
|
|
|
CoglColor *ambient)
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LIGHTING);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
cogl_color_init_from_4fv (ambient,
|
|
|
|
authority->big_state->lighting_state.ambient);
|
2008-12-23 18:35:49 -05:00
|
|
|
}
|
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_ambient (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
const CoglColor *ambient)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_LIGHTING;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialLightingState *lighting_state;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &authority->big_state->lighting_state;
|
|
|
|
if (cogl_color_equal (ambient, &lighting_state->ambient))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &material->big_state->lighting_state;
|
|
|
|
lighting_state->ambient[0] = cogl_color_get_red_float (ambient);
|
|
|
|
lighting_state->ambient[1] = cogl_color_get_green_float (ambient);
|
|
|
|
lighting_state->ambient[2] = cogl_color_get_blue_float (ambient);
|
|
|
|
lighting_state->ambient[3] = cogl_color_get_alpha_float (ambient);
|
2008-12-23 18:22:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_lighting_state_equal);
|
2009-11-29 15:06:36 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
handle_automatic_blend_enable (material, state);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_diffuse (CoglMaterial *material,
|
|
|
|
CoglColor *diffuse)
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LIGHTING);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
cogl_color_init_from_4fv (diffuse,
|
|
|
|
authority->big_state->lighting_state.diffuse);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_diffuse (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
const CoglColor *diffuse)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_LIGHTING;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialLightingState *lighting_state;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &authority->big_state->lighting_state;
|
|
|
|
if (cogl_color_equal (diffuse, &lighting_state->diffuse))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &material->big_state->lighting_state;
|
|
|
|
lighting_state->diffuse[0] = cogl_color_get_red_float (diffuse);
|
|
|
|
lighting_state->diffuse[1] = cogl_color_get_green_float (diffuse);
|
|
|
|
lighting_state->diffuse[2] = cogl_color_get_blue_float (diffuse);
|
|
|
|
lighting_state->diffuse[3] = cogl_color_get_alpha_float (diffuse);
|
2008-12-23 18:22:40 -05:00
|
|
|
|
2009-11-29 15:06:36 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_lighting_state_equal);
|
|
|
|
|
|
|
|
handle_automatic_blend_enable (material, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_ambient_and_diffuse (CoglMaterial *material,
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
const CoglColor *color)
|
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_ambient (material, color);
|
|
|
|
cogl_material_set_diffuse (material, color);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_specular (CoglMaterial *material,
|
|
|
|
CoglColor *specular)
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *authority;
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LIGHTING);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
cogl_color_init_from_4fv (specular,
|
|
|
|
authority->big_state->lighting_state.specular);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
}
|
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_specular (CoglMaterial *material, const CoglColor *specular)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_LIGHTING;
|
|
|
|
CoglMaterialLightingState *lighting_state;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &authority->big_state->lighting_state;
|
|
|
|
if (cogl_color_equal (specular, &lighting_state->specular))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &material->big_state->lighting_state;
|
|
|
|
lighting_state->specular[0] = cogl_color_get_red_float (specular);
|
|
|
|
lighting_state->specular[1] = cogl_color_get_green_float (specular);
|
|
|
|
lighting_state->specular[2] = cogl_color_get_blue_float (specular);
|
|
|
|
lighting_state->specular[3] = cogl_color_get_alpha_float (specular);
|
2008-12-23 18:22:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_lighting_state_equal);
|
2009-11-29 15:06:36 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
handle_automatic_blend_enable (material, state);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
float
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_shininess (CoglMaterial *material)
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), 0);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LIGHTING);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
return authority->big_state->lighting_state.shininess;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_shininess (CoglMaterial *material,
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
float shininess)
|
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_LIGHTING;
|
|
|
|
CoglMaterialLightingState *lighting_state;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-07-20 12:34:04 -04:00
|
|
|
if (shininess < 0.0)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
g_warning ("Out of range shininess %f supplied for material\n",
|
|
|
|
shininess);
|
|
|
|
return;
|
|
|
|
}
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &authority->big_state->lighting_state;
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (lighting_state->shininess == shininess)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
lighting_state = &material->big_state->lighting_state;
|
|
|
|
lighting_state->shininess = shininess;
|
2008-12-23 18:22:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_lighting_state_equal);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_emission (CoglMaterial *material,
|
|
|
|
CoglColor *emission)
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LIGHTING);
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
cogl_color_init_from_4fv (emission,
|
|
|
|
authority->big_state->lighting_state.emission);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_emission (CoglMaterial *material, const CoglColor *emission)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_LIGHTING;
|
|
|
|
CoglMaterialLightingState *lighting_state;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &authority->big_state->lighting_state;
|
|
|
|
if (cogl_color_equal (emission, &lighting_state->emission))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
lighting_state = &material->big_state->lighting_state;
|
|
|
|
lighting_state->emission[0] = cogl_color_get_red_float (emission);
|
|
|
|
lighting_state->emission[1] = cogl_color_get_green_float (emission);
|
|
|
|
lighting_state->emission[2] = cogl_color_get_blue_float (emission);
|
|
|
|
lighting_state->emission[3] = cogl_color_get_alpha_float (emission);
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_lighting_state_equal);
|
2009-11-29 15:06:36 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
handle_automatic_blend_enable (material, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_alpha_test_function (CoglMaterial *material,
|
2008-12-22 11:19:49 -05:00
|
|
|
CoglMaterialAlphaFunc alpha_func,
|
|
|
|
float alpha_reference)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_ALPHA_FUNC;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialAlphaFuncState *alpha_state;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
alpha_state = &authority->big_state->alpha_state;
|
|
|
|
if (alpha_state->alpha_func == alpha_func &&
|
|
|
|
alpha_state->alpha_func_reference == alpha_reference)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
alpha_state = &material->big_state->alpha_state;
|
|
|
|
alpha_state->alpha_func = alpha_func;
|
|
|
|
alpha_state->alpha_func_reference = alpha_reference;
|
2008-12-23 18:22:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_alpha_state_equal);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2009-05-10 19:40:41 -04:00
|
|
|
GLenum
|
|
|
|
arg_to_gl_blend_factor (CoglBlendStringArgument *arg)
|
|
|
|
{
|
|
|
|
if (arg->source.is_zero)
|
|
|
|
return GL_ZERO;
|
|
|
|
if (arg->factor.is_one)
|
|
|
|
return GL_ONE;
|
|
|
|
else if (arg->factor.is_src_alpha_saturate)
|
|
|
|
return GL_SRC_ALPHA_SATURATE;
|
|
|
|
else if (arg->factor.source.info->type ==
|
|
|
|
COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR)
|
|
|
|
{
|
2010-05-12 12:56:25 -04:00
|
|
|
if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
|
2009-05-10 19:40:41 -04:00
|
|
|
{
|
|
|
|
if (arg->factor.source.one_minus)
|
|
|
|
return GL_ONE_MINUS_SRC_COLOR;
|
|
|
|
else
|
|
|
|
return GL_SRC_COLOR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (arg->factor.source.one_minus)
|
|
|
|
return GL_ONE_MINUS_SRC_ALPHA;
|
|
|
|
else
|
|
|
|
return GL_SRC_ALPHA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (arg->factor.source.info->type ==
|
|
|
|
COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR)
|
|
|
|
{
|
2010-05-12 12:56:25 -04:00
|
|
|
if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
|
2009-05-10 19:40:41 -04:00
|
|
|
{
|
|
|
|
if (arg->factor.source.one_minus)
|
|
|
|
return GL_ONE_MINUS_DST_COLOR;
|
|
|
|
else
|
|
|
|
return GL_DST_COLOR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (arg->factor.source.one_minus)
|
|
|
|
return GL_ONE_MINUS_DST_ALPHA;
|
|
|
|
else
|
|
|
|
return GL_DST_ALPHA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifndef HAVE_COGL_GLES
|
|
|
|
else if (arg->factor.source.info->type ==
|
|
|
|
COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
|
|
|
|
{
|
2010-05-12 12:56:25 -04:00
|
|
|
if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
|
2009-05-10 19:40:41 -04:00
|
|
|
{
|
|
|
|
if (arg->factor.source.one_minus)
|
|
|
|
return GL_ONE_MINUS_CONSTANT_COLOR;
|
|
|
|
else
|
|
|
|
return GL_CONSTANT_COLOR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (arg->factor.source.one_minus)
|
|
|
|
return GL_ONE_MINUS_CONSTANT_ALPHA;
|
|
|
|
else
|
|
|
|
return GL_CONSTANT_ALPHA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
g_warning ("Unable to determine valid blend factor from blend string\n");
|
|
|
|
return GL_ONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setup_blend_state (CoglBlendStringStatement *statement,
|
|
|
|
GLenum *blend_equation,
|
2009-05-23 11:23:00 -04:00
|
|
|
GLint *blend_src_factor,
|
|
|
|
GLint *blend_dst_factor)
|
2009-05-10 19:40:41 -04:00
|
|
|
{
|
|
|
|
#ifndef HAVE_COGL_GLES
|
|
|
|
switch (statement->function->type)
|
|
|
|
{
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_ADD:
|
|
|
|
*blend_equation = GL_FUNC_ADD;
|
|
|
|
break;
|
|
|
|
/* TODO - add more */
|
|
|
|
default:
|
|
|
|
g_warning ("Unsupported blend function given");
|
|
|
|
*blend_equation = GL_FUNC_ADD;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
*blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]);
|
|
|
|
*blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_blend (CoglMaterial *material,
|
2009-05-10 19:40:41 -04:00
|
|
|
const char *blend_description,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_BLEND;
|
|
|
|
CoglMaterial *authority;
|
2009-05-10 19:40:41 -04:00
|
|
|
CoglBlendStringStatement statements[2];
|
|
|
|
CoglBlendStringStatement *rgb;
|
|
|
|
CoglBlendStringStatement *a;
|
2009-06-08 09:26:57 -04:00
|
|
|
GError *internal_error = NULL;
|
2009-05-10 19:40:41 -04:00
|
|
|
int count;
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialBlendState *blend_state;
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2009-05-10 19:40:41 -04:00
|
|
|
|
|
|
|
count =
|
|
|
|
_cogl_blend_string_compile (blend_description,
|
|
|
|
COGL_BLEND_STRING_CONTEXT_BLENDING,
|
|
|
|
statements,
|
2009-06-08 09:26:57 -04:00
|
|
|
&internal_error);
|
2009-05-10 19:40:41 -04:00
|
|
|
if (!count)
|
2009-06-08 09:26:57 -04:00
|
|
|
{
|
|
|
|
if (error)
|
|
|
|
g_propagate_error (error, internal_error);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_warning ("Cannot compile blend description: %s\n",
|
|
|
|
internal_error->message);
|
|
|
|
g_error_free (internal_error);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-05-12 12:56:25 -04:00
|
|
|
if (count == 1)
|
|
|
|
rgb = a = statements;
|
2009-05-10 19:40:41 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
rgb = &statements[0];
|
|
|
|
a = &statements[1];
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, state);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
blend_state = &material->big_state->blend_state;
|
2009-05-10 19:40:41 -04:00
|
|
|
#ifndef HAVE_COGL_GLES
|
|
|
|
setup_blend_state (rgb,
|
2010-04-08 07:21:04 -04:00
|
|
|
&blend_state->blend_equation_rgb,
|
|
|
|
&blend_state->blend_src_factor_rgb,
|
|
|
|
&blend_state->blend_dst_factor_rgb);
|
2009-05-10 19:40:41 -04:00
|
|
|
setup_blend_state (a,
|
2010-04-08 07:21:04 -04:00
|
|
|
&blend_state->blend_equation_alpha,
|
|
|
|
&blend_state->blend_src_factor_alpha,
|
|
|
|
&blend_state->blend_dst_factor_alpha);
|
2009-05-10 19:40:41 -04:00
|
|
|
#else
|
|
|
|
setup_blend_state (rgb,
|
|
|
|
NULL,
|
2010-04-08 07:21:04 -04:00
|
|
|
&blend_state->blend_src_factor_rgb,
|
|
|
|
&blend_state->blend_dst_factor_rgb);
|
2009-05-10 19:40:41 -04:00
|
|
|
#endif
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* If we are the current authority see if we can revert to one of our
|
|
|
|
* ancestors being the authority */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (material == authority &&
|
|
|
|
_cogl_material_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *parent = _cogl_material_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_get_authority (parent, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (_cogl_material_blend_state_equal (authority, old_authority))
|
|
|
|
material->differences &= ~state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (material != authority)
|
|
|
|
{
|
|
|
|
material->differences |= state;
|
|
|
|
_cogl_material_prune_redundant_ancestry (material);
|
|
|
|
}
|
|
|
|
|
|
|
|
handle_automatic_blend_enable (material, state);
|
2009-05-10 19:40:41 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_blend_constant (CoglMaterial *material,
|
2010-06-28 10:25:19 -04:00
|
|
|
const CoglColor *constant_color)
|
2009-05-10 19:40:41 -04:00
|
|
|
{
|
|
|
|
#ifndef HAVE_COGL_GLES
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_BLEND;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialBlendState *blend_state;
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
blend_state = &authority->big_state->blend_state;
|
|
|
|
if (cogl_color_equal (constant_color, &blend_state->blend_constant))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
blend_state = &material->big_state->blend_state;
|
|
|
|
blend_state->blend_constant = *constant_color;
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_blend_state_equal);
|
|
|
|
|
|
|
|
handle_automatic_blend_enable (material, state);
|
2009-05-10 19:40:41 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-08-05 05:46:54 -04:00
|
|
|
CoglHandle
|
|
|
|
cogl_material_get_user_program (CoglMaterial *material)
|
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
|
|
|
g_return_val_if_fail (cogl_is_material (material), COGL_INVALID_HANDLE);
|
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_USER_SHADER);
|
|
|
|
|
|
|
|
return authority->big_state->user_program;
|
|
|
|
}
|
|
|
|
|
2010-04-26 05:01:43 -04:00
|
|
|
/* XXX: for now we don't mind if the program has vertex shaders
|
|
|
|
* attached but if we ever make a similar API public we should only
|
|
|
|
* allow attaching of programs containing fragment shaders. Eventually
|
|
|
|
* we will have a CoglPipeline abstraction to also cover vertex
|
|
|
|
* processing.
|
|
|
|
*/
|
|
|
|
void
|
2010-08-05 05:46:54 -04:00
|
|
|
cogl_material_set_user_program (CoglMaterial *material,
|
|
|
|
CoglHandle program)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_USER_SHADER;
|
|
|
|
CoglMaterial *authority;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority = _cogl_material_get_authority (material, state);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (authority->big_state->user_program == program)
|
2010-04-26 05:01:43 -04:00
|
|
|
return;
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
|
|
|
if (program != COGL_INVALID_HANDLE)
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_set_backend (material, COGL_MATERIAL_BACKEND_DEFAULT);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* If we are the current authority see if we can revert to one of our
|
|
|
|
* ancestors being the authority */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (material == authority &&
|
|
|
|
_cogl_material_get_parent (authority) != NULL)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *parent = _cogl_material_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_get_authority (parent, state);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (old_authority->big_state->user_program == program)
|
|
|
|
material->differences &= ~state;
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
2010-04-08 07:21:04 -04:00
|
|
|
else if (material != authority)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
/* If we weren't previously the authority on this state then we
|
|
|
|
* need to extended our differences mask and so it's possible
|
|
|
|
* that some of our ancestry will now become redundant, so we
|
|
|
|
* aim to reparent ourselves if that's true... */
|
|
|
|
material->differences |= state;
|
|
|
|
_cogl_material_prune_redundant_ancestry (material);
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (program != COGL_INVALID_HANDLE)
|
|
|
|
cogl_handle_ref (program);
|
|
|
|
if (authority == material &&
|
|
|
|
material->big_state->user_program != COGL_INVALID_HANDLE)
|
|
|
|
cogl_handle_unref (material->big_state->user_program);
|
|
|
|
material->big_state->user_program = program;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
handle_automatic_blend_enable (material, state);
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
2010-05-26 06:33:32 -04:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_depth_test_enabled (CoglMaterial *material,
|
2010-05-26 06:33:32 -04:00
|
|
|
gboolean enable)
|
|
|
|
{
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialDepthState *depth_state;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
authority = _cogl_material_get_authority (material, state);
|
|
|
|
|
|
|
|
depth_state = &authority->big_state->depth_state;
|
|
|
|
if (depth_state->depth_test_enabled == enable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
material->big_state->depth_state.depth_test_enabled = enable;
|
|
|
|
|
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_depth_state_equal);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_depth_test_enabled (CoglMaterial *material)
|
2010-05-26 06:33:32 -04:00
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH);
|
|
|
|
|
|
|
|
return authority->big_state->depth_state.depth_test_enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_depth_writing_enabled (CoglMaterial *material,
|
2010-05-26 06:33:32 -04:00
|
|
|
gboolean enable)
|
|
|
|
{
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialDepthState *depth_state;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
authority = _cogl_material_get_authority (material, state);
|
|
|
|
|
|
|
|
depth_state = &authority->big_state->depth_state;
|
|
|
|
if (depth_state->depth_writing_enabled == enable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
material->big_state->depth_state.depth_writing_enabled = enable;
|
|
|
|
|
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_depth_state_equal);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_depth_writing_enabled (CoglMaterial *material)
|
2010-05-26 06:33:32 -04:00
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), TRUE);
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH);
|
|
|
|
|
|
|
|
return authority->big_state->depth_state.depth_writing_enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_depth_test_function (CoglMaterial *material,
|
2010-05-26 06:33:32 -04:00
|
|
|
CoglDepthTestFunction function)
|
|
|
|
{
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialDepthState *depth_state;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
authority = _cogl_material_get_authority (material, state);
|
|
|
|
|
|
|
|
depth_state = &authority->big_state->depth_state;
|
|
|
|
if (depth_state->depth_test_function == function)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
material->big_state->depth_state.depth_test_function = function;
|
|
|
|
|
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_depth_state_equal);
|
|
|
|
}
|
|
|
|
|
|
|
|
CoglDepthTestFunction
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_depth_test_function (CoglMaterial *material)
|
2010-05-26 06:33:32 -04:00
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material),
|
2010-05-26 06:33:32 -04:00
|
|
|
COGL_DEPTH_TEST_FUNCTION_LESS);
|
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH);
|
|
|
|
|
|
|
|
return authority->big_state->depth_state.depth_test_function;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_depth_range (CoglMaterial *material,
|
2010-06-18 10:33:03 -04:00
|
|
|
float near_val,
|
|
|
|
float far_val,
|
2010-05-26 06:33:32 -04:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
#ifndef COGL_HAS_GLES
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialDepthState *depth_state;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
authority = _cogl_material_get_authority (material, state);
|
|
|
|
|
|
|
|
depth_state = &authority->big_state->depth_state;
|
2010-06-18 10:33:03 -04:00
|
|
|
if (depth_state->depth_range_near == near_val &&
|
|
|
|
depth_state->depth_range_far == far_val)
|
2010-05-26 06:33:32 -04:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
2010-06-18 10:33:03 -04:00
|
|
|
material->big_state->depth_state.depth_range_near = near_val;
|
|
|
|
material->big_state->depth_state.depth_range_far = far_val;
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_depth_state_equal);
|
|
|
|
return TRUE;
|
|
|
|
#else
|
|
|
|
g_set_error (error,
|
|
|
|
COGL_ERROR,
|
2010-07-13 07:59:24 -04:00
|
|
|
COGL_ERROR_UNSUPPORTED,
|
2010-05-26 06:33:32 -04:00
|
|
|
"glDepthRange not available on GLES 1");
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_depth_range (CoglMaterial *material,
|
2010-06-18 10:33:03 -04:00
|
|
|
float *near_val,
|
|
|
|
float *far_val)
|
2010-05-26 06:33:32 -04:00
|
|
|
{
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH);
|
|
|
|
|
2010-06-18 10:33:03 -04:00
|
|
|
*near_val = authority->big_state->depth_state.depth_range_near;
|
|
|
|
*far_val = authority->big_state->depth_state.depth_range_far;
|
2010-05-26 06:33:32 -04:00
|
|
|
}
|
|
|
|
|
2010-07-06 15:18:26 -04:00
|
|
|
static void
|
|
|
|
_cogl_material_set_fog_state (CoglMaterial *material,
|
|
|
|
const CoglMaterialFogState *fog_state)
|
|
|
|
{
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_FOG;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialFogState *current_fog_state;
|
|
|
|
|
|
|
|
g_return_if_fail (cogl_is_material (material));
|
|
|
|
|
|
|
|
authority = _cogl_material_get_authority (material, state);
|
|
|
|
|
|
|
|
current_fog_state = &authority->big_state->fog_state;
|
|
|
|
|
|
|
|
if (current_fog_state->enabled == fog_state->enabled &&
|
|
|
|
cogl_color_equal (¤t_fog_state->color, &fog_state->color) &&
|
|
|
|
current_fog_state->mode == fog_state->mode &&
|
|
|
|
current_fog_state->density == fog_state->density &&
|
|
|
|
current_fog_state->z_near == fog_state->z_near &&
|
|
|
|
current_fog_state->z_far == fog_state->z_far)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
material->big_state->fog_state = *fog_state;
|
|
|
|
|
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_fog_state_equal);
|
|
|
|
}
|
|
|
|
|
2010-05-27 10:19:15 -04:00
|
|
|
unsigned long
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_get_age (CoglMaterial *material)
|
2010-05-27 10:19:15 -04:00
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), 0);
|
2010-05-27 10:19:15 -04:00
|
|
|
|
|
|
|
return material->age;
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
static CoglMaterialLayer *
|
|
|
|
_cogl_material_layer_copy (CoglMaterialLayer *src)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *layer = g_slice_new (CoglMaterialLayer);
|
2010-04-26 05:01:43 -04:00
|
|
|
int i;
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_init (COGL_MATERIAL_NODE (layer));
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->owner = NULL;
|
|
|
|
layer->index = src->index;
|
|
|
|
layer->differences = 0;
|
|
|
|
layer->has_big_state = FALSE;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++)
|
|
|
|
layer->backend_priv[i] = NULL;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_set_parent (layer, src);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
return _cogl_material_layer_object_new (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
static void
|
|
|
|
_cogl_material_layer_free (CoglMaterialLayer *layer)
|
|
|
|
{
|
|
|
|
int i;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_unparent (COGL_MATERIAL_NODE (layer));
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* NB: layers may be used by multiple materials which may be using
|
|
|
|
* different backends, therefore we determine which backends to
|
|
|
|
* notify based on the private state pointers for each backend...
|
|
|
|
*/
|
|
|
|
for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++)
|
|
|
|
{
|
2010-07-09 22:40:47 -04:00
|
|
|
if (layer->backend_priv[i] &&
|
|
|
|
_cogl_material_backends[i]->free_layer_priv)
|
|
|
|
{
|
|
|
|
const CoglMaterialBackend *backend = _cogl_material_backends[i];
|
|
|
|
backend->free_layer_priv (layer);
|
|
|
|
}
|
2010-04-08 07:21:04 -04:00
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (layer->differences & COGL_MATERIAL_LAYER_STATE_TEXTURE)
|
|
|
|
cogl_handle_unref (layer->texture);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (layer->differences & COGL_MATERIAL_LAYER_STATE_NEEDS_BIG_STATE)
|
|
|
|
g_slice_free (CoglMaterialLayerBigState, layer->big_state);
|
2010-05-19 19:40:24 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
g_slice_free (CoglMaterialLayer, layer);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* If a layer has descendants we can't modify it freely
|
|
|
|
*
|
|
|
|
* If the layer is owned and the owner has descendants we can't
|
|
|
|
* modify it freely.
|
|
|
|
*
|
|
|
|
* In both cases when we can't freely modify a layer we can either:
|
|
|
|
* - create a new layer; splice it in to replace the layer so it can
|
|
|
|
* be directly modified.
|
|
|
|
* XXX: disadvantage is that we have to invalidate the layers_cache
|
|
|
|
* for the owner and its descendants.
|
|
|
|
* - create a new derived layer and modify that.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* XXX: how is the caller expected to deal with ref-counting?
|
|
|
|
*
|
|
|
|
* If the layer can't be freely modified and we return a new layer
|
|
|
|
* then that will effectively make the caller own a new reference
|
|
|
|
* which doesn't happen if we simply modify the given layer.
|
|
|
|
*
|
|
|
|
* We could make it consistent by taking a reference on the layer if
|
|
|
|
* we don't create a new one. At least this way the caller could
|
|
|
|
* deal with it consistently, though the semantics are a bit
|
|
|
|
* strange.
|
|
|
|
*
|
|
|
|
* Alternatively we could leave it to the caller to check
|
|
|
|
* ...?
|
|
|
|
*/
|
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
void
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_init_default_layers (void)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *layer = g_slice_new0 (CoglMaterialLayer);
|
|
|
|
CoglMaterialLayerBigState *big_state =
|
|
|
|
g_slice_new0 (CoglMaterialLayerBigState);
|
|
|
|
CoglMaterialLayer *new;
|
|
|
|
int i;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_init (COGL_MATERIAL_NODE (layer));
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->index = 0;
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++)
|
|
|
|
layer->backend_priv[i] = NULL;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->differences = COGL_MATERIAL_LAYER_STATE_ALL_SPARSE;
|
2009-04-04 14:21:22 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->unit_index = 0;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->texture = COGL_INVALID_HANDLE;
|
|
|
|
layer->texture_overridden = FALSE;
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->mag_filter = COGL_MATERIAL_FILTER_LINEAR;
|
|
|
|
layer->min_filter = COGL_MATERIAL_FILTER_LINEAR;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->wrap_mode_s = COGL_MATERIAL_WRAP_MODE_AUTOMATIC;
|
|
|
|
layer->wrap_mode_t = COGL_MATERIAL_WRAP_MODE_AUTOMATIC;
|
2010-07-12 12:01:32 -04:00
|
|
|
layer->wrap_mode_p = COGL_MATERIAL_WRAP_MODE_AUTOMATIC;
|
2009-02-19 04:01:18 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->big_state = big_state;
|
|
|
|
layer->has_big_state = TRUE;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Choose the same default combine mode as OpenGL:
|
|
|
|
* RGBA = MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */
|
|
|
|
big_state->texture_combine_rgb_func = GL_MODULATE;
|
|
|
|
big_state->texture_combine_rgb_src[0] = GL_PREVIOUS;
|
|
|
|
big_state->texture_combine_rgb_src[1] = GL_TEXTURE;
|
|
|
|
big_state->texture_combine_rgb_op[0] = GL_SRC_COLOR;
|
|
|
|
big_state->texture_combine_rgb_op[1] = GL_SRC_COLOR;
|
|
|
|
big_state->texture_combine_alpha_func = GL_MODULATE;
|
|
|
|
big_state->texture_combine_alpha_src[0] = GL_PREVIOUS;
|
|
|
|
big_state->texture_combine_alpha_src[1] = GL_TEXTURE;
|
|
|
|
big_state->texture_combine_alpha_op[0] = GL_SRC_ALPHA;
|
|
|
|
big_state->texture_combine_alpha_op[1] = GL_SRC_ALPHA;
|
|
|
|
|
2010-03-22 09:33:55 -04:00
|
|
|
big_state->point_sprite_coords = FALSE;
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
cogl_matrix_init_identity (&big_state->matrix);
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
ctx->default_layer_0 = _cogl_material_layer_object_new (layer);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
/* 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_material_layer_copy (layer);
|
|
|
|
new = _cogl_material_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_material_layer_copy (ctx->default_layer_n);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2009-05-10 19:40:41 -04:00
|
|
|
static void
|
|
|
|
setup_texture_combine_state (CoglBlendStringStatement *statement,
|
2009-05-23 11:23:00 -04:00
|
|
|
GLint *texture_combine_func,
|
|
|
|
GLint *texture_combine_src,
|
|
|
|
GLint *texture_combine_op)
|
2009-05-10 19:40:41 -04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
switch (statement->function->type)
|
|
|
|
{
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_REPLACE:
|
|
|
|
*texture_combine_func = GL_REPLACE;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_MODULATE:
|
|
|
|
*texture_combine_func = GL_MODULATE;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_ADD:
|
|
|
|
*texture_combine_func = GL_ADD;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_ADD_SIGNED:
|
|
|
|
*texture_combine_func = GL_ADD_SIGNED;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_INTERPOLATE:
|
|
|
|
*texture_combine_func = GL_INTERPOLATE;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_SUBTRACT:
|
|
|
|
*texture_combine_func = GL_SUBTRACT;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_DOT3_RGB:
|
|
|
|
*texture_combine_func = GL_DOT3_RGB;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_FUNCTION_DOT3_RGBA:
|
|
|
|
*texture_combine_func = GL_DOT3_RGBA;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < statement->function->argc; i++)
|
|
|
|
{
|
|
|
|
CoglBlendStringArgument *arg = &statement->args[i];
|
|
|
|
|
|
|
|
switch (arg->source.info->type)
|
|
|
|
{
|
|
|
|
case COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT:
|
|
|
|
texture_combine_src[i] = GL_CONSTANT;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE:
|
|
|
|
texture_combine_src[i] = GL_TEXTURE;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N:
|
|
|
|
texture_combine_src[i] =
|
|
|
|
GL_TEXTURE0 + arg->source.texture;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY:
|
|
|
|
texture_combine_src[i] = GL_PRIMARY_COLOR;
|
|
|
|
break;
|
|
|
|
case COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS:
|
|
|
|
texture_combine_src[i] = GL_PREVIOUS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_warning ("Unexpected texture combine source");
|
|
|
|
texture_combine_src[i] = GL_TEXTURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
|
|
|
|
{
|
|
|
|
if (statement->args[i].source.one_minus)
|
|
|
|
texture_combine_op[i] = GL_ONE_MINUS_SRC_COLOR;
|
|
|
|
else
|
|
|
|
texture_combine_op[i] = GL_SRC_COLOR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (statement->args[i].source.one_minus)
|
|
|
|
texture_combine_op[i] = GL_ONE_MINUS_SRC_ALPHA;
|
|
|
|
else
|
|
|
|
texture_combine_op[i] = GL_SRC_ALPHA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer_combine (CoglMaterial *material,
|
cogl: improves header and coding style consistency
We've had complaints that our Cogl code/headers are a bit "special" so
this is a first pass at tidying things up by giving them some
consistency. These changes are all consistent with how new code in Cogl
is being written, but the style isn't consistently applied across all
code yet.
There are two parts to this patch; but since each one required a large
amount of effort to maintain tidy indenting it made sense to combine the
changes to reduce the time spent re indenting the same lines.
The first change is to use a consistent style for declaring function
prototypes in headers. Cogl headers now consistently use this style for
prototypes:
return_type
cogl_function_name (CoglType arg0,
CoglType arg1);
Not everyone likes this style, but it seems that most of the currently
active Cogl developers agree on it.
The second change is to constrain the use of redundant glib data types
in Cogl. Uses of gint, guint, gfloat, glong, gulong and gchar have all
been replaced with int, unsigned int, float, long, unsigned long and char
respectively. When talking about pixel data; use of guchar has been
replaced with guint8, otherwise unsigned char can be used.
The glib types that we continue to use for portability are gboolean,
gint{8,16,32,64}, guint{8,16,32,64} and gsize.
The general intention is that Cogl should look palatable to the widest
range of C programmers including those outside the Gnome community so
- especially for the public API - we want to minimize the number of
foreign looking typedefs.
2010-02-09 20:57:32 -05:00
|
|
|
int layer_index,
|
2009-05-10 19:40:41 -04:00
|
|
|
const char *combine_description,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayerState state = COGL_MATERIAL_LAYER_STATE_COMBINE;
|
|
|
|
CoglMaterialLayer *authority;
|
2009-05-10 19:40:41 -04:00
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglBlendStringStatement statements[2];
|
|
|
|
CoglBlendStringStatement split[2];
|
|
|
|
CoglBlendStringStatement *rgb;
|
|
|
|
CoglBlendStringStatement *a;
|
2009-06-08 09:26:57 -04:00
|
|
|
GError *internal_error = NULL;
|
2009-05-10 19:40:41 -04:00
|
|
|
int count;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), FALSE);
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, state);
|
2009-05-10 19:40:41 -04:00
|
|
|
|
|
|
|
count =
|
|
|
|
_cogl_blend_string_compile (combine_description,
|
|
|
|
COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE,
|
|
|
|
statements,
|
2009-06-08 09:26:57 -04:00
|
|
|
&internal_error);
|
2009-05-10 19:40:41 -04:00
|
|
|
if (!count)
|
2009-06-08 09:26:57 -04:00
|
|
|
{
|
|
|
|
if (error)
|
|
|
|
g_propagate_error (error, internal_error);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_warning ("Cannot compile combine description: %s\n",
|
|
|
|
internal_error->message);
|
|
|
|
g_error_free (internal_error);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-05-10 19:40:41 -04:00
|
|
|
|
|
|
|
if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
|
|
|
|
{
|
|
|
|
_cogl_blend_string_split_rgba_statement (statements,
|
|
|
|
&split[0], &split[1]);
|
|
|
|
rgb = &split[0];
|
|
|
|
a = &split[1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rgb = &statements[0];
|
|
|
|
a = &statements[1];
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* FIXME: compare the new state with the current state! */
|
|
|
|
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
/* possibly flush primitives referencing the current state... */
|
2010-04-08 07:21:04 -04:00
|
|
|
layer = _cogl_material_layer_pre_change_notify (material, layer, state);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2009-05-10 19:40:41 -04:00
|
|
|
setup_texture_combine_state (rgb,
|
2010-04-08 07:21:04 -04:00
|
|
|
&layer->big_state->texture_combine_rgb_func,
|
|
|
|
layer->big_state->texture_combine_rgb_src,
|
|
|
|
layer->big_state->texture_combine_rgb_op);
|
2009-05-10 19:40:41 -04:00
|
|
|
|
|
|
|
setup_texture_combine_state (a,
|
2010-04-08 07:21:04 -04:00
|
|
|
&layer->big_state->texture_combine_alpha_func,
|
|
|
|
layer->big_state->texture_combine_alpha_src,
|
|
|
|
layer->big_state->texture_combine_alpha_op);
|
|
|
|
|
|
|
|
/* If the original layer we found is currently the authority on
|
|
|
|
* the state we are changing see if we can revert to one of our
|
|
|
|
* ancestors being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent = _cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (_cogl_material_layer_combine_state_equal (authority,
|
|
|
|
old_authority))
|
|
|
|
{
|
|
|
|
layer->differences &= ~state;
|
|
|
|
|
|
|
|
g_assert (layer->owner == material);
|
|
|
|
if (layer->differences == 0)
|
|
|
|
_cogl_material_prune_empty_layer_difference (material,
|
|
|
|
layer);
|
|
|
|
goto changed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
|
|
|
layer->differences |= state;
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
changed:
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
handle_automatic_blend_enable (material, COGL_MATERIAL_STATE_LAYERS);
|
2009-05-10 19:40:41 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer_combine_constant (CoglMaterial *material,
|
cogl: improves header and coding style consistency
We've had complaints that our Cogl code/headers are a bit "special" so
this is a first pass at tidying things up by giving them some
consistency. These changes are all consistent with how new code in Cogl
is being written, but the style isn't consistently applied across all
code yet.
There are two parts to this patch; but since each one required a large
amount of effort to maintain tidy indenting it made sense to combine the
changes to reduce the time spent re indenting the same lines.
The first change is to use a consistent style for declaring function
prototypes in headers. Cogl headers now consistently use this style for
prototypes:
return_type
cogl_function_name (CoglType arg0,
CoglType arg1);
Not everyone likes this style, but it seems that most of the currently
active Cogl developers agree on it.
The second change is to constrain the use of redundant glib data types
in Cogl. Uses of gint, guint, gfloat, glong, gulong and gchar have all
been replaced with int, unsigned int, float, long, unsigned long and char
respectively. When talking about pixel data; use of guchar has been
replaced with guint8, otherwise unsigned char can be used.
The glib types that we continue to use for portability are gboolean,
gint{8,16,32,64}, guint{8,16,32,64} and gsize.
The general intention is that Cogl should look palatable to the widest
range of C programmers including those outside the Gnome community so
- especially for the public API - we want to minimize the number of
foreign looking typedefs.
2010-02-09 20:57:32 -05:00
|
|
|
int layer_index,
|
2010-06-28 10:25:19 -04:00
|
|
|
const CoglColor *constant_color)
|
2009-05-10 19:40:41 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayerState state = COGL_MATERIAL_LAYER_STATE_COMBINE_CONSTANT;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialLayer *new;
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, state);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (memcmp (authority->big_state->texture_combine_constant,
|
|
|
|
constant_color, sizeof (float) * 4) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
new = _cogl_material_layer_pre_change_notify (material, layer, state);
|
|
|
|
if (new != layer)
|
|
|
|
layer = new;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the original layer we found is currently the authority on
|
|
|
|
* the state we are changing see if we can revert to one of our
|
|
|
|
* ancestors being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent =
|
|
|
|
_cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayerBigState *old_big_state = old_authority->big_state;
|
|
|
|
|
|
|
|
if (memcmp (old_big_state->texture_combine_constant,
|
|
|
|
constant_color, sizeof (float) * 4) == 0)
|
|
|
|
{
|
|
|
|
layer->differences &= ~state;
|
|
|
|
|
|
|
|
g_assert (layer->owner == material);
|
|
|
|
if (layer->differences == 0)
|
|
|
|
_cogl_material_prune_empty_layer_difference (material,
|
|
|
|
layer);
|
|
|
|
goto changed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->big_state->texture_combine_constant[0] =
|
|
|
|
cogl_color_get_red_float (constant_color);
|
|
|
|
layer->big_state->texture_combine_constant[1] =
|
|
|
|
cogl_color_get_green_float (constant_color);
|
|
|
|
layer->big_state->texture_combine_constant[2] =
|
|
|
|
cogl_color_get_blue_float (constant_color);
|
|
|
|
layer->big_state->texture_combine_constant[3] =
|
|
|
|
cogl_color_get_alpha_float (constant_color);
|
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
|
|
|
layer->differences |= state;
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
2009-05-10 19:40:41 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
changed:
|
|
|
|
|
|
|
|
handle_automatic_blend_enable (material, COGL_MATERIAL_STATE_LAYERS);
|
2009-05-10 19:40:41 -04:00
|
|
|
}
|
|
|
|
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer_matrix (CoglMaterial *material,
|
cogl: improves header and coding style consistency
We've had complaints that our Cogl code/headers are a bit "special" so
this is a first pass at tidying things up by giving them some
consistency. These changes are all consistent with how new code in Cogl
is being written, but the style isn't consistently applied across all
code yet.
There are two parts to this patch; but since each one required a large
amount of effort to maintain tidy indenting it made sense to combine the
changes to reduce the time spent re indenting the same lines.
The first change is to use a consistent style for declaring function
prototypes in headers. Cogl headers now consistently use this style for
prototypes:
return_type
cogl_function_name (CoglType arg0,
CoglType arg1);
Not everyone likes this style, but it seems that most of the currently
active Cogl developers agree on it.
The second change is to constrain the use of redundant glib data types
in Cogl. Uses of gint, guint, gfloat, glong, gulong and gchar have all
been replaced with int, unsigned int, float, long, unsigned long and char
respectively. When talking about pixel data; use of guchar has been
replaced with guint8, otherwise unsigned char can be used.
The glib types that we continue to use for portability are gboolean,
gint{8,16,32,64}, guint{8,16,32,64} and gsize.
The general intention is that Cogl should look palatable to the widest
range of C programmers including those outside the Gnome community so
- especially for the public API - we want to minimize the number of
foreign looking typedefs.
2010-02-09 20:57:32 -05:00
|
|
|
int layer_index,
|
2010-06-28 10:25:19 -04:00
|
|
|
const CoglMatrix *matrix)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayerState state = COGL_MATERIAL_LAYER_STATE_USER_MATRIX;
|
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialLayer *new;
|
2008-12-22 11:19:49 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
|
|
|
authority = _cogl_material_layer_get_authority (layer, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (cogl_matrix_equal (matrix, &authority->big_state->matrix))
|
2010-04-26 05:01:43 -04:00
|
|
|
return;
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
new = _cogl_material_layer_pre_change_notify (material, layer, state);
|
|
|
|
if (new != layer)
|
|
|
|
layer = new;
|
2010-04-26 05:01:43 -04:00
|
|
|
else
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
/* If the original layer we found is currently the authority on
|
|
|
|
* the state we are changing see if we can revert to one of our
|
|
|
|
* ancestors being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent =
|
|
|
|
_cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, state);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (cogl_matrix_equal (matrix, &old_authority->big_state->matrix))
|
|
|
|
{
|
|
|
|
layer->differences &= ~state;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
g_assert (layer->owner == material);
|
|
|
|
if (layer->differences == 0)
|
|
|
|
_cogl_material_prune_empty_layer_difference (material,
|
|
|
|
layer);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
layer->big_state->matrix = *matrix;
|
|
|
|
|
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
|
|
|
layer->differences |= state;
|
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_remove_layer (CoglMaterial *material, int layer_index)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
|
|
|
CoglMaterialLayerInfo layer_info;
|
|
|
|
int i;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LAYERS);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* The layer index of the layer we want info about */
|
|
|
|
layer_info.layer_index = layer_index;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* This will be updated with a reference to the layer being removed
|
|
|
|
* if it can be found. */
|
|
|
|
layer_info.layer = NULL;
|
2009-06-24 13:34:06 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* This will be filled in with a list of layers that need to be
|
|
|
|
* dropped down to a lower texture unit to fill the gap of the
|
|
|
|
* removed layer. */
|
|
|
|
layer_info.layers_to_shift =
|
|
|
|
g_alloca (sizeof (CoglMaterialLayer *) * authority->n_layers);
|
|
|
|
layer_info.n_layers_to_shift = 0;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Unlike when we query layer info when adding a layer we must
|
|
|
|
* always have a complete layers_to_shift list... */
|
|
|
|
layer_info.ignore_shift_layers_if_found = FALSE;
|
2009-06-24 13:34:06 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_get_layer_info (authority, &layer_info);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (layer_info.layer == NULL)
|
|
|
|
return;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
for (i = 0; i < layer_info.n_layers_to_shift; i++)
|
|
|
|
{
|
|
|
|
CoglMaterialLayer *shift_layer = layer_info.layers_to_shift[i];
|
|
|
|
int unit_index = _cogl_material_layer_get_unit_index (shift_layer);
|
|
|
|
_cogl_material_set_layer_unit (material, shift_layer, unit_index - 1);
|
|
|
|
/* NB: shift_layer may not be writeable so _set_layer_unit()
|
|
|
|
* will allocate a derived layer internally which will become
|
|
|
|
* owned by material. Check the return value if we need to do
|
|
|
|
* anything else with this layer. */
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
Fully integrates CoglMaterial throughout the rest of Cogl
This glues CoglMaterial in as the fundamental way that Cogl describes how to
fill in geometry.
It adds cogl_set_source (), which is used to set the material which will be
used by all subsequent drawing functions
It adds cogl_set_source_texture as a convenience for setting up a default
material with a single texture layer, and cogl_set_source_color is now also
a convenience for setting up a material with a solid fill.
"drawing functions" include, cogl_rectangle, cogl_texture_rectangle,
cogl_texture_multiple_rectangles, cogl_texture_polygon (though the
cogl_texture_* funcs have been renamed; see below for details),
cogl_path_fill/stroke and cogl_vertex_buffer_draw*.
cogl_texture_rectangle, cogl_texture_multiple_rectangles and
cogl_texture_polygon no longer take a texture handle; instead the current
source material is referenced. The functions have also been renamed to:
cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords
and cogl_polygon respectivly.
Most code that previously did:
cogl_texture_rectangle (tex_handle, x, y,...);
needs to be changed to now do:
cogl_set_source_texture (tex_handle);
cogl_rectangle_with_texture_coords (x, y,....);
In the less likely case where you were blending your source texture with a color
like:
cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */
cogl_texture_rectangle (tex_handle, x, y,...);
you will need your own material to do that:
mat = cogl_material_new ();
cogl_material_set_color4ub (r,g,b,a);
cogl_material_set_layer (mat, 0, tex_handle));
cogl_set_source_material (mat);
Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use
cog_rectangle_with_texure_coords since these are the coordinates that
cogl_rectangle will use.
For cogl_texture_polygon; as well as dropping the texture handle, the
n_vertices and vertices arguments were transposed for consistency. So
code previously written as:
cogl_texture_polygon (tex_handle, 3, verts, TRUE);
need to be written as:
cogl_set_source_texture (tex_handle);
cogl_polygon (verts, 3, TRUE);
All of the unit tests have been updated to now use the material API and
test-cogl-material has been renamed to test-cogl-multitexture since any
textured quad is now technically a test of CoglMaterial but this test
specifically creates a material with multiple texture layers.
Note: The GLES backend has not been updated yet; that will be done in a
following commit.
2009-01-23 11:15:40 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_remove_layer_difference (material, layer_info.layer, TRUE);
|
|
|
|
_cogl_material_try_reverting_layers_authority (material, NULL);
|
|
|
|
|
|
|
|
handle_automatic_blend_enable (material, COGL_MATERIAL_STATE_LAYERS);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
static gboolean
|
|
|
|
prepend_layer_to_list_cb (CoglMaterialLayer *layer,
|
|
|
|
void *user_data)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
GList **layers = user_data;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
*layers = g_list_prepend (*layers, layer);
|
|
|
|
return TRUE;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* TODO: deprecate this API and replace it with
|
|
|
|
* cogl_material_foreach_layer
|
|
|
|
* TODO: update the docs to note that if the user modifies any layers
|
|
|
|
* then the list may become invalid.
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
*/
|
|
|
|
const GList *
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_layers (CoglMaterial *material)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), NULL);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
if (!material->deprecated_get_layers_list_dirty)
|
|
|
|
g_list_free (material->deprecated_get_layers_list);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
material->deprecated_get_layers_list = NULL;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_foreach_layer (material,
|
|
|
|
prepend_layer_to_list_cb,
|
|
|
|
&material->deprecated_get_layers_list);
|
|
|
|
material->deprecated_get_layers_list =
|
|
|
|
g_list_reverse (material->deprecated_get_layers_list);
|
|
|
|
|
|
|
|
material->deprecated_get_layers_list_dirty = 0;
|
|
|
|
|
|
|
|
return material->deprecated_get_layers_list;
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
int
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_get_n_layers (CoglMaterial *material)
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterial *authority;
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_val_if_fail (cogl_is_material (material), 0);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_LAYERS);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
return authority->n_layers;
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* FIXME: deprecate and replace with
|
|
|
|
* cogl_material_get_layer_type() instead. */
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
CoglMaterialLayerType
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_layer_get_type (CoglMaterialLayer *layer)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
|
|
|
return COGL_MATERIAL_LAYER_TYPE_TEXTURE;
|
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* FIXME: deprecate and replace with
|
|
|
|
* cogl_material_get_layer_texture() instead. */
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
CoglHandle
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_layer_get_texture (CoglMaterialLayer *layer)
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
{
|
2010-07-09 13:46:31 -04:00
|
|
|
g_return_val_if_fail (_cogl_is_material_layer (layer),
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
COGL_INVALID_HANDLE);
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
return _cogl_material_layer_get_texture (layer);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2010-04-26 05:01:43 -04:00
|
|
|
gboolean
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_layer_has_user_matrix (CoglMaterialLayer *layer)
|
2009-11-11 07:50:48 -05:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *authority;
|
2009-11-11 07:50:48 -05:00
|
|
|
|
2010-07-09 13:46:31 -04:00
|
|
|
g_return_val_if_fail (_cogl_is_material_layer (layer), FALSE);
|
2009-11-11 07:50:48 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_USER_MATRIX);
|
2009-11-11 07:50:48 -05:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* If the authority is the default material then no, otherwise yes */
|
2010-07-08 06:49:31 -04:00
|
|
|
return _cogl_material_layer_get_parent (authority) ? TRUE : FALSE;
|
2009-11-11 07:50:48 -05:00
|
|
|
}
|
|
|
|
|
2010-07-09 22:40:47 -04:00
|
|
|
void
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_layer_get_filters (CoglMaterialLayer *layer,
|
|
|
|
CoglMaterialFilter *min_filter,
|
|
|
|
CoglMaterialFilter *mag_filter)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_FILTERS);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
*min_filter = authority->min_filter;
|
|
|
|
*mag_filter = authority->mag_filter;
|
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_layer_pre_paint (CoglMaterialLayer *layer)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayer *texture_authority;
|
|
|
|
|
|
|
|
texture_authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_TEXTURE);
|
|
|
|
|
2010-06-09 12:39:59 -04:00
|
|
|
if (texture_authority->texture != COGL_INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
CoglTexturePrePaintFlags flags = 0;
|
|
|
|
CoglMaterialFilter min_filter;
|
|
|
|
CoglMaterialFilter mag_filter;
|
|
|
|
|
|
|
|
_cogl_material_layer_get_filters (layer, &min_filter, &mag_filter);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
2010-06-09 12:39:59 -04:00
|
|
|
if (min_filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST
|
|
|
|
|| min_filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST
|
|
|
|
|| min_filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR
|
|
|
|
|| min_filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR)
|
|
|
|
flags |= COGL_TEXTURE_NEEDS_MIPMAP;
|
|
|
|
|
2010-08-06 09:12:22 -04:00
|
|
|
_cogl_texture_pre_paint (texture_authority->texture, flags);
|
2010-06-09 12:39:59 -04:00
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialFilter
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_layer_get_min_filter (CoglMaterialLayer *layer)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *authority;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-07-09 13:46:31 -04:00
|
|
|
g_return_val_if_fail (_cogl_is_material_layer (layer), 0);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_FILTERS);
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
return authority->min_filter;
|
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialFilter
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_layer_get_mag_filter (CoglMaterialLayer *layer)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
|
2010-07-09 13:46:31 -04:00
|
|
|
g_return_val_if_fail (_cogl_is_material_layer (layer), 0);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_layer_get_authority (layer,
|
|
|
|
COGL_MATERIAL_LAYER_STATE_FILTERS);
|
|
|
|
|
|
|
|
return authority->mag_filter;
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_layer_filters (CoglMaterial *material,
|
2010-04-08 07:21:04 -04:00
|
|
|
int layer_index,
|
|
|
|
CoglMaterialFilter min_filter,
|
|
|
|
CoglMaterialFilter mag_filter)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayerState state = COGL_MATERIAL_LAYER_STATE_FILTERS;
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *layer;
|
|
|
|
CoglMaterialLayer *authority;
|
|
|
|
CoglMaterialLayer *new;
|
|
|
|
|
2010-06-22 09:02:17 -04:00
|
|
|
g_return_if_fail (cogl_is_material (material));
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* Note: this will ensure that the layer exists, creating one if it
|
|
|
|
* doesn't already.
|
|
|
|
*
|
|
|
|
* Note: If the layer already existed it's possibly owned by another
|
|
|
|
* material. If the layer is created then it will be owned by
|
|
|
|
* material. */
|
|
|
|
layer = _cogl_material_get_layer (material, layer_index);
|
|
|
|
|
|
|
|
/* Now find the ancestor of the layer that is the authority for the
|
|
|
|
* state we want to change */
|
2010-07-08 06:49:31 -04:00
|
|
|
authority = _cogl_material_layer_get_authority (layer, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (authority->min_filter == min_filter &&
|
|
|
|
authority->mag_filter == mag_filter)
|
|
|
|
return;
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
new = _cogl_material_layer_pre_change_notify (material, layer, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
if (new != layer)
|
|
|
|
layer = new;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the original layer we found is currently the authority on
|
|
|
|
* the state we are changing see if we can revert to one of our
|
|
|
|
* ancestors being the authority. */
|
2010-07-08 06:49:31 -04:00
|
|
|
if (layer == authority &&
|
|
|
|
_cogl_material_layer_get_parent (authority) != NULL)
|
2010-04-08 07:21:04 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *parent =
|
|
|
|
_cogl_material_layer_get_parent (authority);
|
2010-04-08 07:21:04 -04:00
|
|
|
CoglMaterialLayer *old_authority =
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_layer_get_authority (parent, state);
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
if (old_authority->min_filter == min_filter &&
|
|
|
|
old_authority->mag_filter == mag_filter)
|
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
layer->differences &= ~state;
|
2010-04-08 07:21:04 -04:00
|
|
|
|
|
|
|
g_assert (layer->owner == material);
|
|
|
|
if (layer->differences == 0)
|
|
|
|
_cogl_material_prune_empty_layer_difference (material,
|
|
|
|
layer);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->min_filter = min_filter;
|
|
|
|
layer->mag_filter = mag_filter;
|
2010-04-26 05:01:43 -04:00
|
|
|
|
2010-04-08 07:21:04 -04:00
|
|
|
/* If we weren't previously the authority on this state then we need
|
|
|
|
* to extended our differences mask and so it's possible that some
|
|
|
|
* of our ancestry will now become redundant, so we aim to reparent
|
|
|
|
* ourselves if that's true... */
|
|
|
|
if (layer != authority)
|
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
layer->differences |= state;
|
2010-04-08 07:21:04 -04:00
|
|
|
_cogl_material_layer_prune_redundant_ancestry (layer);
|
|
|
|
}
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
2010-03-22 05:32:17 -04:00
|
|
|
float
|
|
|
|
cogl_material_get_point_size (CoglHandle handle)
|
|
|
|
{
|
|
|
|
CoglMaterial *material = COGL_MATERIAL (handle);
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
|
|
|
g_return_val_if_fail (cogl_is_material (handle), FALSE);
|
|
|
|
|
|
|
|
authority =
|
|
|
|
_cogl_material_get_authority (material, COGL_MATERIAL_STATE_POINT_SIZE);
|
|
|
|
|
|
|
|
return authority->big_state->point_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cogl_material_set_point_size (CoglHandle handle,
|
|
|
|
float point_size)
|
|
|
|
{
|
|
|
|
CoglMaterial *material = COGL_MATERIAL (handle);
|
|
|
|
CoglMaterialState state = COGL_MATERIAL_STATE_POINT_SIZE;
|
|
|
|
CoglMaterial *authority;
|
|
|
|
|
|
|
|
g_return_if_fail (cogl_is_material (handle));
|
|
|
|
|
|
|
|
authority = _cogl_material_get_authority (material, state);
|
|
|
|
|
|
|
|
if (authority->big_state->point_size == point_size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* - Flush journal primitives referencing the current state.
|
|
|
|
* - Make sure the material has no dependants so it may be modified.
|
|
|
|
* - If the material isn't currently an authority for the state being
|
|
|
|
* changed, then initialize that state from the current authority.
|
|
|
|
*/
|
|
|
|
_cogl_material_pre_change_notify (material, state, NULL);
|
|
|
|
|
|
|
|
material->big_state->point_size = point_size;
|
|
|
|
|
|
|
|
_cogl_material_update_authority (material, authority, state,
|
|
|
|
_cogl_material_point_size_equal);
|
|
|
|
}
|
|
|
|
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
/* While a material is referenced by the Cogl journal we can not allow
|
|
|
|
* modifications, so this gives us a mechanism to track journal
|
|
|
|
* references separately */
|
2010-06-22 09:02:17 -04:00
|
|
|
CoglMaterial *
|
|
|
|
_cogl_material_journal_ref (CoglMaterial *material)
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
{
|
|
|
|
material->journal_ref_count++;
|
2010-06-22 09:02:17 -04:00
|
|
|
return cogl_object_ref (material);
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_journal_unref (CoglMaterial *material)
|
[cogl] Improving Cogl journal to minimize driver overheads + GPU state changes
Previously the journal was always flushed at the end of
_cogl_rectangles_with_multitexture_coords, (i.e. the end of any
cogl_rectangle* calls) but now we have broadened the potential for batching
geometry. In ideal circumstances we will only flush once per scene.
In summary the journal works like this:
When you use any of the cogl_rectangle* APIs then nothing is emitted to the
GPU at this point, we just log one or more quads into the journal. A
journal entry consists of the quad coordinates, an associated material
reference, and a modelview matrix. Ideally the journal only gets flushed
once at the end of a scene, but in fact there are things to consider that
may cause unwanted flushing, including:
- modifying materials mid-scene
This is because each quad in the journal has an associated material
reference (i.e. not copy), so if you try and modify a material that is
already referenced in the journal we force a flush first)
NOTE: For now this means you should avoid using cogl_set_source_color()
since that currently uses a single shared material. Later we
should change it to use a pool of materials that is recycled
when the journal is flushed.
- modifying any state that isn't currently logged, such as depth, fog and
backface culling enables.
The first thing that happens when flushing, is to upload all the vertex data
associated with the journal into a single VBO.
We then go through a process of splitting up the journal into batches that
have compatible state so they can be emitted to the GPU together. This is
currently broken up into 3 levels so we can stagger the state changes:
1) we break the journal up according to changes in the number of material layers
associated with logged quads. The number of layers in a material determines
the stride of the associated vertices, so we have to update our vertex
array offsets at this level. (i.e. calling gl{Vertex,Color},Pointer etc)
2) we further split batches up according to material compatability. (e.g.
materials with different textures) We flush material state at this level.
3) Finally we split batches up according to modelview changes. At this level
we update the modelview matrix and actually emit the actual draw command.
This commit is largely about putting the initial design in-place; this will be
followed by other changes that take advantage of the extended batching.
2009-06-17 13:46:42 -04:00
|
|
|
{
|
|
|
|
material->journal_ref_count--;
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_object_unref (material);
|
Adds a CoglMaterial abstraction, which includes support for multi-texturing
My previous work to provide muti-texturing support has been extended into
a CoglMaterial abstraction that adds control over the texture combine
functions (controlling how multiple texture layers are blended together),
the gl blend function (used for blending the final primitive with the
framebuffer), the alpha function (used to discard fragments based on
their alpha channel), describing attributes such as a diffuse, ambient and
specular color (for use with the standard OpenGL lighting model), and
per layer rotations. (utilizing the new CoglMatrix utility API)
For now the only way this abstraction is exposed is via a new
cogl_material_rectangle function, that is similar to cogl_texture_rectangle
but doesn't take a texture handle (the source material is pulled from
the context), and the array of texture coordinates is extended to be able
to supply coordinates for each layer.
Note: this function doesn't support sliced textures; supporting sliced
textures is a non trivial problem, considering the ability to rotate layers.
Note: cogl_material_rectangle, has quite a few workarounds, for a number of
other limitations within Cogl a.t.m.
Note: The GLES1/2 multi-texturing support has yet to be updated to use
the material abstraction.
2008-12-11 15:11:30 -05:00
|
|
|
}
|
|
|
|
|
2010-04-26 05:01:43 -04:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_apply_legacy_state (CoglMaterial *material)
|
2010-04-26 05:01:43 -04:00
|
|
|
{
|
|
|
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
|
|
|
|
2010-05-26 06:33:32 -04:00
|
|
|
/* It was a mistake that we ever copied the OpenGL style API for
|
|
|
|
* associating these things directly with the context when we
|
|
|
|
* originally wrote Cogl. Until the corresponding deprecated APIs
|
|
|
|
* can be removed though we now shoehorn the state changes through
|
|
|
|
* the cogl_material API instead.
|
|
|
|
*/
|
|
|
|
|
2010-08-05 05:46:54 -04:00
|
|
|
/* A program explicitly set on the material has higher precedence than
|
|
|
|
* one associated with the context using cogl_program_use() */
|
|
|
|
if (ctx->current_program &&
|
|
|
|
cogl_material_get_user_program (material) == COGL_INVALID_HANDLE)
|
|
|
|
cogl_material_set_user_program (material, ctx->current_program);
|
2010-05-26 06:33:32 -04:00
|
|
|
|
|
|
|
if (ctx->legacy_depth_test_enabled)
|
2010-06-22 09:02:17 -04:00
|
|
|
cogl_material_set_depth_test_enabled (material, TRUE);
|
2010-07-06 15:18:26 -04:00
|
|
|
|
|
|
|
if (ctx->legacy_fog_state.enabled)
|
|
|
|
_cogl_material_set_fog_state (material, &ctx->legacy_fog_state);
|
2010-04-26 05:01:43 -04:00
|
|
|
}
|
|
|
|
|
2010-05-18 19:36:31 -04:00
|
|
|
void
|
2010-06-22 09:02:17 -04:00
|
|
|
_cogl_material_set_static_breadcrumb (CoglMaterial *material,
|
2010-05-18 19:36:31 -04:00
|
|
|
const char *breadcrumb)
|
|
|
|
{
|
|
|
|
material->has_static_breadcrumb = TRUE;
|
|
|
|
material->static_breadcrumb = breadcrumb;
|
|
|
|
}
|
|
|
|
|
2010-07-02 13:04:45 -04:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int parent_id;
|
2010-07-07 15:43:54 -04:00
|
|
|
int *node_id_ptr;
|
2010-07-02 13:04:45 -04:00
|
|
|
GString *graph;
|
|
|
|
int indent;
|
|
|
|
} PrintDebugState;
|
|
|
|
|
|
|
|
static gboolean
|
2010-07-08 06:49:31 -04:00
|
|
|
dump_layer_cb (CoglMaterialNode *node, void *user_data)
|
2010-07-07 15:43:54 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterialLayer *layer = COGL_MATERIAL_LAYER (node);
|
2010-07-07 15:43:54 -04:00
|
|
|
PrintDebugState *state = user_data;
|
|
|
|
int layer_id = *state->node_id_ptr;
|
|
|
|
PrintDebugState state_out;
|
|
|
|
GString *changes_label;
|
|
|
|
gboolean changes = FALSE;
|
|
|
|
|
|
|
|
if (state->parent_id >= 0)
|
2010-08-08 09:09:26 -04:00
|
|
|
g_string_append_printf (state->graph, "%*slayer%p -> layer%p;\n",
|
2010-07-07 15:43:54 -04:00
|
|
|
state->indent, "",
|
2010-08-08 09:09:26 -04:00
|
|
|
layer->_parent.parent,
|
|
|
|
layer);
|
2010-07-07 15:43:54 -04:00
|
|
|
|
|
|
|
g_string_append_printf (state->graph,
|
2010-08-08 09:09:26 -04:00
|
|
|
"%*slayer%p [label=\"layer=0x%p\\n"
|
2010-07-07 15:43:54 -04:00
|
|
|
"ref count=%d\" "
|
|
|
|
"color=\"blue\"];\n",
|
|
|
|
state->indent, "",
|
2010-08-08 09:09:26 -04:00
|
|
|
layer,
|
2010-07-07 15:43:54 -04:00
|
|
|
layer,
|
|
|
|
COGL_OBJECT (layer)->ref_count);
|
|
|
|
|
|
|
|
changes_label = g_string_new ("");
|
|
|
|
g_string_append_printf (changes_label,
|
2010-08-08 09:09:26 -04:00
|
|
|
"%*slayer%p -> layer_state%d [weight=100];\n"
|
2010-07-07 15:43:54 -04:00
|
|
|
"%*slayer_state%d [shape=box label=\"",
|
|
|
|
state->indent, "",
|
2010-08-08 09:09:26 -04:00
|
|
|
layer,
|
2010-07-07 15:43:54 -04:00
|
|
|
layer_id,
|
|
|
|
state->indent, "",
|
|
|
|
layer_id);
|
|
|
|
|
2010-08-08 09:09:26 -04:00
|
|
|
if (layer->differences & COGL_MATERIAL_LAYER_STATE_UNIT)
|
|
|
|
{
|
|
|
|
changes = TRUE;
|
|
|
|
g_string_append_printf (changes_label,
|
|
|
|
"\\lunit=%u\\n",
|
|
|
|
layer->unit_index);
|
|
|
|
}
|
|
|
|
|
2010-07-07 15:43:54 -04:00
|
|
|
if (layer->differences & COGL_MATERIAL_LAYER_STATE_TEXTURE)
|
|
|
|
{
|
|
|
|
changes = TRUE;
|
|
|
|
g_string_append_printf (changes_label,
|
|
|
|
"\\ltexture=%p\\n",
|
|
|
|
layer->texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changes)
|
|
|
|
{
|
|
|
|
g_string_append_printf (changes_label, "\"];\n");
|
|
|
|
g_string_append (state->graph, changes_label->str);
|
|
|
|
g_string_free (changes_label, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
state_out.parent_id = layer_id;
|
|
|
|
|
|
|
|
state_out.node_id_ptr = state->node_id_ptr;
|
|
|
|
(*state_out.node_id_ptr)++;
|
|
|
|
|
|
|
|
state_out.graph = state->graph;
|
|
|
|
state_out.indent = state->indent + 2;
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (layer),
|
|
|
|
dump_layer_cb,
|
|
|
|
&state_out);
|
2010-07-07 15:43:54 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
dump_layer_ref_cb (CoglMaterialLayer *layer, void *data)
|
2010-07-02 13:04:45 -04:00
|
|
|
{
|
|
|
|
PrintDebugState *state = data;
|
2010-07-07 15:43:54 -04:00
|
|
|
int material_id = *state->node_id_ptr;
|
2010-07-02 13:04:45 -04:00
|
|
|
|
|
|
|
g_string_append_printf (state->graph,
|
2010-08-08 09:09:26 -04:00
|
|
|
"%*smaterial_state%d -> layer%p;\n",
|
2010-07-02 13:04:45 -04:00
|
|
|
state->indent, "",
|
|
|
|
material_id,
|
|
|
|
layer);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2010-07-08 06:49:31 -04:00
|
|
|
dump_material_cb (CoglMaterialNode *node, void *user_data)
|
2010-07-02 13:04:45 -04:00
|
|
|
{
|
2010-07-08 06:49:31 -04:00
|
|
|
CoglMaterial *material = COGL_MATERIAL (node);
|
2010-07-02 13:04:45 -04:00
|
|
|
PrintDebugState *state = user_data;
|
2010-07-07 15:43:54 -04:00
|
|
|
int material_id = *state->node_id_ptr;
|
2010-07-02 13:04:45 -04:00
|
|
|
PrintDebugState state_out;
|
|
|
|
GString *changes_label;
|
|
|
|
gboolean changes = FALSE;
|
|
|
|
gboolean layers = FALSE;
|
|
|
|
|
|
|
|
if (state->parent_id >= 0)
|
|
|
|
g_string_append_printf (state->graph, "%*smaterial%d -> material%d;\n",
|
|
|
|
state->indent, "",
|
|
|
|
state->parent_id,
|
|
|
|
material_id);
|
|
|
|
|
|
|
|
g_string_append_printf (state->graph,
|
2010-07-07 15:43:54 -04:00
|
|
|
"%*smaterial%d [label=\"material=0x%p\\n"
|
2010-07-02 13:04:45 -04:00
|
|
|
"ref count=%d\\n"
|
|
|
|
"breadcrumb=\\\"%s\\\"\" color=\"red\"];\n",
|
|
|
|
state->indent, "",
|
|
|
|
material_id,
|
|
|
|
material,
|
|
|
|
COGL_OBJECT (material)->ref_count,
|
|
|
|
material->has_static_breadcrumb ?
|
|
|
|
material->static_breadcrumb : "NULL");
|
|
|
|
|
|
|
|
changes_label = g_string_new ("");
|
|
|
|
g_string_append_printf (changes_label,
|
2010-07-07 15:43:54 -04:00
|
|
|
"%*smaterial%d -> material_state%d [weight=100];\n"
|
|
|
|
"%*smaterial_state%d [shape=box label=\"",
|
2010-07-02 13:04:45 -04:00
|
|
|
state->indent, "",
|
|
|
|
material_id,
|
|
|
|
material_id,
|
|
|
|
state->indent, "",
|
|
|
|
material_id);
|
|
|
|
|
|
|
|
|
|
|
|
if (material->differences & COGL_MATERIAL_STATE_COLOR)
|
|
|
|
{
|
|
|
|
changes = TRUE;
|
|
|
|
g_string_append_printf (changes_label,
|
|
|
|
"\\lcolor=0x%02X%02X%02X%02X\\n",
|
|
|
|
cogl_color_get_red_byte (&material->color),
|
|
|
|
cogl_color_get_green_byte (&material->color),
|
|
|
|
cogl_color_get_blue_byte (&material->color),
|
|
|
|
cogl_color_get_alpha_byte (&material->color));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (material->differences & COGL_MATERIAL_STATE_BLEND)
|
|
|
|
{
|
|
|
|
changes = TRUE;
|
|
|
|
const char *blend_enable_name;
|
|
|
|
switch (material->blend_enable)
|
|
|
|
{
|
|
|
|
case COGL_MATERIAL_BLEND_ENABLE_AUTOMATIC:
|
|
|
|
blend_enable_name = "AUTO";
|
|
|
|
break;
|
|
|
|
case COGL_MATERIAL_BLEND_ENABLE_ENABLED:
|
|
|
|
blend_enable_name = "ENABLED";
|
|
|
|
break;
|
|
|
|
case COGL_MATERIAL_BLEND_ENABLE_DISABLED:
|
|
|
|
blend_enable_name = "DISABLED";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
blend_enable_name = "UNKNOWN";
|
|
|
|
}
|
|
|
|
g_string_append_printf (changes_label,
|
|
|
|
"\\lblend=%s\\n",
|
|
|
|
blend_enable_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (material->differences & COGL_MATERIAL_STATE_LAYERS)
|
|
|
|
{
|
|
|
|
changes = TRUE;
|
|
|
|
layers = TRUE;
|
|
|
|
g_string_append_printf (changes_label, "\\ln_layers=%d\\n",
|
|
|
|
material->n_layers);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changes)
|
|
|
|
{
|
|
|
|
g_string_append_printf (changes_label, "\"];\n");
|
|
|
|
g_string_append (state->graph, changes_label->str);
|
|
|
|
g_string_free (changes_label, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (layers)
|
2010-07-07 15:43:54 -04:00
|
|
|
_cogl_material_foreach_layer (material, dump_layer_ref_cb, state);
|
2010-07-02 13:04:45 -04:00
|
|
|
|
|
|
|
state_out.parent_id = material_id;
|
|
|
|
|
2010-07-07 15:43:54 -04:00
|
|
|
state_out.node_id_ptr = state->node_id_ptr;
|
|
|
|
(*state_out.node_id_ptr)++;
|
2010-07-02 13:04:45 -04:00
|
|
|
|
|
|
|
state_out.graph = state->graph;
|
|
|
|
state_out.indent = state->indent + 2;
|
|
|
|
|
2010-07-08 06:49:31 -04:00
|
|
|
_cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
|
|
|
|
dump_material_cb,
|
|
|
|
&state_out);
|
2010-07-02 13:04:45 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_cogl_debug_dump_materials_dot_file (const char *filename)
|
|
|
|
{
|
2010-07-07 15:43:54 -04:00
|
|
|
GString *graph;
|
|
|
|
PrintDebugState layer_state;
|
|
|
|
PrintDebugState material_state;
|
|
|
|
int layer_id = 0;
|
2010-07-02 13:04:45 -04:00
|
|
|
int material_id = 0;
|
|
|
|
|
|
|
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
|
|
|
|
|
|
|
if (!ctx->default_material)
|
|
|
|
return;
|
|
|
|
|
2010-07-07 15:43:54 -04:00
|
|
|
graph = g_string_new ("");
|
|
|
|
g_string_append_printf (graph, "digraph {\n");
|
2010-07-02 13:04:45 -04:00
|
|
|
|
2010-07-07 15:43:54 -04:00
|
|
|
layer_state.graph = graph;
|
|
|
|
layer_state.parent_id = -1;
|
|
|
|
layer_state.node_id_ptr = &layer_id;
|
|
|
|
layer_state.indent = 0;
|
|
|
|
dump_layer_cb (ctx->default_layer_0, &layer_state);
|
2010-07-02 13:04:45 -04:00
|
|
|
|
2010-07-07 15:43:54 -04:00
|
|
|
material_state.graph = graph;
|
|
|
|
material_state.parent_id = -1;
|
|
|
|
material_state.node_id_ptr = &material_id;
|
|
|
|
material_state.indent = 0;
|
|
|
|
dump_material_cb (ctx->default_material, &material_state);
|
2010-07-02 13:04:45 -04:00
|
|
|
|
2010-07-07 15:43:54 -04:00
|
|
|
g_string_append_printf (graph, "}\n");
|
2010-07-02 13:04:45 -04:00
|
|
|
|
|
|
|
if (filename)
|
2010-07-07 15:43:54 -04:00
|
|
|
g_file_set_contents (filename, graph->str, -1, NULL);
|
2010-07-02 13:04:45 -04:00
|
|
|
else
|
2010-07-07 15:43:54 -04:00
|
|
|
g_print ("%s", graph->str);
|
2010-07-02 13:04:45 -04:00
|
|
|
|
2010-07-07 15:43:54 -04:00
|
|
|
g_string_free (graph, TRUE);
|
2010-07-02 13:04:45 -04:00
|
|
|
}
|
|
|
|
|