mutter/cogl/cogl-material-private.h
Robert Bragg 0e99fa7a1e material: pass material owner for layer pre changes
When notifying a backend about a layer being modified we now pass the
layers current owner for reference. NB: Although a layer can indirectly
be referenced by multiple layers, a layer is considered immutable once
it has dependants, so there is only ever one material associated with a
layer being modified. Passing the material pointer to the backends
layer_pre_change callback can be useful for backends that associate
their private state with materials and may need to update that state in
response to layer changes.
2010-09-15 14:07:49 +01:00

924 lines
31 KiB
C

/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2008,2009,2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef __COGL_MATERIAL_PRIVATE_H
#define __COGL_MATERIAL_PRIVATE_H
#include "cogl.h"
#include "cogl-material.h"
#include "cogl-matrix.h"
#include "cogl-handle.h"
#include "cogl-profile.h"
#include <glib.h>
#if defined (HAVE_COGL_GL)
/* NB: material->backend is currently a 3bit unsigned int bitfield */
#define COGL_MATERIAL_BACKEND_GLSL 0
#define COGL_MATERIAL_BACKEND_GLSL_MASK (1L<<0)
#define COGL_MATERIAL_BACKEND_ARBFP 1
#define COGL_MATERIAL_BACKEND_ARBFP_MASK (1L<<1)
#define COGL_MATERIAL_BACKEND_FIXED 2
#define COGL_MATERIAL_BACKEND_FIXED_MASK (1L<<2)
#define COGL_MATERIAL_N_BACKENDS 3
#elif defined (HAVE_COGL_GLES2)
#define COGL_MATERIAL_BACKEND_GLSL 0
#define COGL_MATERIAL_BACKEND_GLSL_MASK (1L<<0)
#define COGL_MATERIAL_BACKEND_FIXED 1
#define COGL_MATERIAL_BACKEND_FIXED_MASK (1L<<1)
#define COGL_MATERIAL_N_BACKENDS 2
#else /* HAVE_COGL_GLES */
#define COGL_MATERIAL_BACKEND_FIXED 0
#define COGL_MATERIAL_BACKEND_FIXED_MASK (1L<<0)
#define COGL_MATERIAL_N_BACKENDS 1
#endif
#define COGL_MATERIAL_BACKEND_DEFAULT 0
#define COGL_MATERIAL_BACKEND_UNDEFINED 3
typedef enum
{
COGL_MATERIAL_LAYER_STATE_UNIT = 1L<<0,
COGL_MATERIAL_LAYER_STATE_TEXTURE = 1L<<1,
COGL_MATERIAL_LAYER_STATE_FILTERS = 1L<<2,
COGL_MATERIAL_LAYER_STATE_WRAP_MODES = 1L<<3,
COGL_MATERIAL_LAYER_STATE_COMBINE = 1L<<4,
COGL_MATERIAL_LAYER_STATE_COMBINE_CONSTANT = 1L<<5,
COGL_MATERIAL_LAYER_STATE_USER_MATRIX = 1L<<6,
COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS = 1L<<7,
/* COGL_MATERIAL_LAYER_STATE_TEXTURE_INTERN = 1L<<8, */
COGL_MATERIAL_LAYER_STATE_ALL_SPARSE =
COGL_MATERIAL_LAYER_STATE_UNIT |
COGL_MATERIAL_LAYER_STATE_TEXTURE |
COGL_MATERIAL_LAYER_STATE_FILTERS |
COGL_MATERIAL_LAYER_STATE_WRAP_MODES |
COGL_MATERIAL_LAYER_STATE_COMBINE |
COGL_MATERIAL_LAYER_STATE_COMBINE_CONSTANT |
COGL_MATERIAL_LAYER_STATE_USER_MATRIX |
COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS,
COGL_MATERIAL_LAYER_STATE_NEEDS_BIG_STATE =
COGL_MATERIAL_LAYER_STATE_COMBINE |
COGL_MATERIAL_LAYER_STATE_COMBINE_CONSTANT |
COGL_MATERIAL_LAYER_STATE_USER_MATRIX |
COGL_MATERIAL_LAYER_STATE_POINT_SPRITE_COORDS,
} CoglMaterialLayerState;
typedef struct
{
/* The texture combine state determines how the color of individual
* texture fragments are calculated. */
GLint texture_combine_rgb_func;
GLint texture_combine_rgb_src[3];
GLint texture_combine_rgb_op[3];
GLint texture_combine_alpha_func;
GLint texture_combine_alpha_src[3];
GLint texture_combine_alpha_op[3];
float texture_combine_constant[4];
/* The texture matrix dscribes how to transform texture coordinates */
CoglMatrix matrix;
gboolean point_sprite_coords;
} CoglMaterialLayerBigState;
/* Materials and layers represent their state in a tree structure where
* some of the state relating to a given material or layer may actually
* be owned by one if is ancestors in the tree. We have a common data
* type to track the tree heirachy so we can share code... */
typedef struct _CoglMaterialNode CoglMaterialNode;
struct _CoglMaterialNode
{
/* the parent in terms of class hierarchy, so anything inheriting
* from CoglMaterialNode also inherits from CoglObject. */
CoglObject _parent;
/* The parent material/layer */
CoglMaterialNode *parent;
/* As an optimization for creating leaf node materials/layers (the
* most common) we don't require any list node allocations to link
* to a single descendant. */
CoglMaterialNode *first_child;
/* Determines if node->first_child and node->children are
* initialized pointers. */
gboolean has_children;
/* Materials and layers are sparse structures defined as a diff
* against their parent and may have multiple children which depend
* on them to define the values of properties which they don't
* change. */
GList *children;
};
#define COGL_MATERIAL_NODE(X) ((CoglMaterialNode *)(X))
typedef void (*CoglMaterialNodeUnparentVFunc) (CoglMaterialNode *node);
typedef gboolean (*CoglMaterialNodeChildCallback) (CoglMaterialNode *child,
void *user_data);
void
_cogl_material_node_foreach_child (CoglMaterialNode *node,
CoglMaterialNodeChildCallback callback,
void *user_data);
struct _CoglMaterialLayer
{
/* XXX: Please think twice about adding members that *have* be
* initialized during a _cogl_material_layer_copy. We are aiming
* to have copies be as cheap as possible and copies may be
* done by the primitives APIs which means they may happen
* in performance critical code paths.
*
* XXX: If you are extending the state we track please consider if
* the state is expected to vary frequently across many materials or
* if the state can be shared among many derived materials instead.
* This will determine if the state should be added directly to this
* structure which will increase the memory overhead for *all*
* layers or if instead it can go under ->big_state.
*/
/* Layers represent their state in a tree structure where some of
* the state relating to a given material or layer may actually be
* owned by one if is ancestors in the tree. We have a common data
* type to track the tree heirachy so we can share code... */
CoglMaterialNode _parent;
/* Some layers have a material owner, which is to say that the layer
* is referenced in that materials->layer_differences list. A layer
* doesn't always have an owner and may simply be an ancestor for
* other layers that keeps track of some shared state. */
CoglMaterial *owner;
/* The lowest index is blended first then others on top */
int index;
/* Different material backends (GLSL/ARBfp/Fixed Function) may
* want to associate private data with a layer...
*
* NB: we have per backend pointers because a layer may be
* associated with multiple materials with different backends.
*/
void *backend_priv[COGL_MATERIAL_N_BACKENDS];
/* A mask of which state groups are different in this layer
* in comparison to its parent. */
unsigned long differences;
/* Common differences
*
* As a basic way to reduce memory usage we divide the layer
* state into two groups; the minimal state modified in 90% of
* all layers and the rest, so that the second group can
* be allocated dynamically when required.
*/
/* Each layer is directly associated with a single texture unit */
int unit_index;
/* The texture for this layer, or COGL_INVALID_HANDLE for an empty
* layer */
CoglHandle texture;
gboolean texture_overridden;
/* If ->texture_overridden == TRUE then the texture is instead
* defined by these... */
GLuint slice_gl_texture;
GLenum slice_gl_target;
CoglMaterialFilter mag_filter;
CoglMaterialFilter min_filter;
CoglMaterialWrapMode wrap_mode_s;
CoglMaterialWrapMode wrap_mode_t;
CoglMaterialWrapMode wrap_mode_p;
/* Infrequent differences aren't currently tracked in
* a separate, dynamically allocated structure as they are
* for materials... */
CoglMaterialLayerBigState *big_state;
/* bitfields */
/* Determines if layer->big_state is valid */
unsigned int has_big_state:1;
};
/* Used in material->differences masks and for notifying material
* state changes... */
typedef enum _CoglMaterialState
{
COGL_MATERIAL_STATE_COLOR = 1L<<0,
COGL_MATERIAL_STATE_BLEND_ENABLE = 1L<<1,
COGL_MATERIAL_STATE_LAYERS = 1L<<2,
COGL_MATERIAL_STATE_LIGHTING = 1L<<3,
COGL_MATERIAL_STATE_ALPHA_FUNC = 1L<<4,
COGL_MATERIAL_STATE_BLEND = 1L<<5,
COGL_MATERIAL_STATE_USER_SHADER = 1L<<6,
COGL_MATERIAL_STATE_DEPTH = 1L<<7,
COGL_MATERIAL_STATE_FOG = 1L<<8,
COGL_MATERIAL_STATE_POINT_SIZE = 1L<<9,
COGL_MATERIAL_STATE_REAL_BLEND_ENABLE = 1L<<10,
COGL_MATERIAL_STATE_ALL_SPARSE =
COGL_MATERIAL_STATE_COLOR |
COGL_MATERIAL_STATE_BLEND_ENABLE |
COGL_MATERIAL_STATE_LAYERS |
COGL_MATERIAL_STATE_LIGHTING |
COGL_MATERIAL_STATE_ALPHA_FUNC |
COGL_MATERIAL_STATE_BLEND |
COGL_MATERIAL_STATE_USER_SHADER |
COGL_MATERIAL_STATE_DEPTH |
COGL_MATERIAL_STATE_FOG |
COGL_MATERIAL_STATE_POINT_SIZE,
COGL_MATERIAL_STATE_AFFECTS_BLENDING =
COGL_MATERIAL_STATE_COLOR |
COGL_MATERIAL_STATE_BLEND_ENABLE |
COGL_MATERIAL_STATE_LAYERS |
COGL_MATERIAL_STATE_LIGHTING |
COGL_MATERIAL_STATE_BLEND |
COGL_MATERIAL_STATE_USER_SHADER,
COGL_MATERIAL_STATE_NEEDS_BIG_STATE =
COGL_MATERIAL_STATE_LIGHTING |
COGL_MATERIAL_STATE_ALPHA_FUNC |
COGL_MATERIAL_STATE_BLEND |
COGL_MATERIAL_STATE_USER_SHADER |
COGL_MATERIAL_STATE_DEPTH |
COGL_MATERIAL_STATE_FOG |
COGL_MATERIAL_STATE_POINT_SIZE
} CoglMaterialState;
typedef enum
{
COGL_MATERIAL_LIGHTING_STATE_PROPERTY_AMBIENT = 1,
COGL_MATERIAL_LIGHTING_STATE_PROPERTY_DIFFUSE,
COGL_MATERIAL_LIGHTING_STATE_PROPERTY_SPECULAR,
COGL_MATERIAL_LIGHTING_STATE_PROPERTY_EMISSION,
COGL_MATERIAL_LIGHTING_STATE_PROPERTY_SHININESS
} CoglMaterialLightingStateProperty;
typedef struct
{
/* Standard OpenGL lighting model attributes */
float ambient[4];
float diffuse[4];
float specular[4];
float emission[4];
float shininess;
} CoglMaterialLightingState;
typedef struct
{
/* Determines what fragments are discarded based on their alpha */
CoglMaterialAlphaFunc alpha_func;
GLfloat alpha_func_reference;
} CoglMaterialAlphaFuncState;
typedef enum _CoglMaterialBlendEnable
{
/* XXX: we want to detect users mistakenly using TRUE or FALSE
* so start the enum at 2. */
COGL_MATERIAL_BLEND_ENABLE_ENABLED = 2,
COGL_MATERIAL_BLEND_ENABLE_DISABLED,
COGL_MATERIAL_BLEND_ENABLE_AUTOMATIC
} CoglMaterialBlendEnable;
typedef struct
{
/* Determines how this material is blended with other primitives */
#ifndef HAVE_COGL_GLES
GLenum blend_equation_rgb;
GLenum blend_equation_alpha;
GLint blend_src_factor_alpha;
GLint blend_dst_factor_alpha;
CoglColor blend_constant;
#endif
GLint blend_src_factor_rgb;
GLint blend_dst_factor_rgb;
} CoglMaterialBlendState;
typedef struct
{
gboolean depth_test_enabled;
CoglDepthTestFunction depth_test_function;
gboolean depth_writing_enabled;
float depth_range_near;
float depth_range_far;
} CoglMaterialDepthState;
typedef struct
{
gboolean enabled;
CoglColor color;
CoglFogMode mode;
float density;
float z_near;
float z_far;
} CoglMaterialFogState;
typedef struct
{
CoglMaterialLightingState lighting_state;
CoglMaterialAlphaFuncState alpha_state;
CoglMaterialBlendState blend_state;
CoglHandle user_program;
CoglMaterialDepthState depth_state;
CoglMaterialFogState fog_state;
float point_size;
} CoglMaterialBigState;
typedef enum
{
COGL_MATERIAL_FLAG_DIRTY_LAYERS_CACHE = 1L<<0,
COGL_MATERIAL_FLAG_DIRTY_GET_LAYERS_LIST = 1L<<1
} CoglMaterialFlag;
typedef struct
{
CoglMaterial *owner;
CoglMaterialLayer *layer;
} CoglMaterialLayerCacheEntry;
/*
* CoglMaterialDestroyCallback
* @material: The #CoglMaterial that has been destroyed
* @user_data: The private data associated with the callback
*
* Notifies when a weak material has been destroyed because one
* of its ancestors has been freed or modified.
*/
typedef void (*CoglMaterialDestroyCallback)(CoglMaterial *material,
void *user_data);
struct _CoglMaterial
{
/* XXX: Please think twice about adding members that *have* be
* initialized during a cogl_material_copy. We are aiming to have
* copies be as cheap as possible and copies may be done by the
* primitives APIs which means they may happen in performance
* critical code paths.
*
* XXX: If you are extending the state we track please consider if
* the state is expected to vary frequently across many materials or
* if the state can be shared among many derived materials instead.
* This will determine if the state should be added directly to this
* structure which will increase the memory overhead for *all*
* materials or if instead it can go under ->big_state.
*/
/* Layers represent their state in a tree structure where some of
* the state relating to a given material or layer may actually be
* owned by one if is ancestors in the tree. We have a common data
* type to track the tree heirachy so we can share code... */
CoglMaterialNode _parent;
/* We need to track if a material is referenced in the journal
* because we can't allow modification to these materials without
* flushing the journal first */
unsigned long journal_ref_count;
/* When weak materials are destroyed the user is notified via this
* callback */
CoglMaterialDestroyCallback destroy_callback;
/* When notifying that a weak material has been destroyed this
* private data is passed to the above callback */
void *destroy_data;
/* A mask of which sparse state groups are different in this
* material in comparison to its parent. */
unsigned long differences;
/* The fragment processing backends can associate private data with a
* material. */
void *backend_privs[COGL_MATERIAL_N_BACKENDS];
/* Whenever a material is modified we increment the age. There's no
* guarantee that it won't wrap but it can nevertheless be a
* convenient mechanism to determine when a material has been
* changed to you can invalidate some some associated cache that
* depends on the old state. */
unsigned long age;
/* This is the primary color of the material.
*
* This is a sparse property, ref COGL_MATERIAL_STATE_COLOR */
CoglColor color;
/* A material may be made up with multiple layers used to combine
* textures together.
*
* This is sparse state, ref COGL_MATERIAL_STATE_LAYERS */
GList *layer_differences;
unsigned int n_layers;
/* As a basic way to reduce memory usage we divide the material
* state into two groups; the minimal state modified in 90% of
* all materials and the rest, so that the second group can
* be allocated dynamically when required... */
CoglMaterialBigState *big_state;
/* For debugging purposes it's possible to associate a static const
* string with a material which can be an aid when trying to trace
* where the material originates from */
const char *static_breadcrumb;
/* Cached state... */
/* A cached, complete list of the layers this material depends
* on sorted by layer->unit_index. */
CoglMaterialLayer **layers_cache;
/* To avoid a separate ->layers_cache allocation for common
* materials with only a few layers... */
CoglMaterialLayer *short_layers_cache[3];
/* The deprecated cogl_material_get_layers() API returns a
* const GList of layers, which we track here... */
GList *deprecated_get_layers_list;
/* XXX: consider adding an authorities cache to speed up sparse
* property value lookups:
* CoglMaterial *authorities_cache[COGL_MATERIAL_N_SPARSE_PROPERTIES];
* and corresponding authorities_cache_dirty:1 bitfield
*/
/* bitfields */
/* A material can have private data associated with it for multiple
* fragment processing backends. Although only one backend is
* associated with a material the backends may want to cache private
* state with the ancestors of other materials and those ancestors
* could currently be associated with different backends.
*
* Each set bit indicates if the correspondong ->backend_privs[]
* entry is valid.
*/
unsigned int backend_priv_set_mask:COGL_MATERIAL_N_BACKENDS;
/* Weak materials don't count as dependants on their parents which
* means that the parent material can be modified without
* considering how the modifications may affect the weak material.
*/
unsigned int is_weak:1;
/* Determines if material->big_state is valid */
unsigned int has_big_state:1;
/* By default blending is enabled automatically depending on the
* unlit color, the lighting colors or the texture format. The user
* can override this to explicitly enable or disable blending.
*
* This is a sparse property */
unsigned int blend_enable:3;
/* There are many factors that can determine if we need to enable
* blending, this holds our final decision */
unsigned int real_blend_enable:1;
unsigned int layers_cache_dirty:1;
unsigned int deprecated_get_layers_list_dirty:1;
/* For debugging purposes it's possible to associate a static const
* string with a material which can be an aid when trying to trace
* where the material originates from */
unsigned int has_static_breadcrumb:1;
/* There are multiple fragment processing backends for CoglMaterial,
* glsl, arbfp and fixed. This identifies the backend being used for
* the material and any private state the backend has associated
* with the material. */
unsigned int backend:3;
};
typedef struct _CoglMaterialBackend
{
int (*get_max_texture_units) (void);
gboolean (*start) (CoglMaterial *material,
int n_layers,
unsigned long materials_difference);
gboolean (*add_layer) (CoglMaterial *material,
CoglMaterialLayer *layer,
unsigned long layers_difference);
gboolean (*passthrough) (CoglMaterial *material);
gboolean (*end) (CoglMaterial *material,
unsigned long materials_difference);
void (*material_pre_change_notify) (CoglMaterial *material,
CoglMaterialState change,
const CoglColor *new_color);
void (*material_set_parent_notify) (CoglMaterial *material);
void (*layer_pre_change_notify) (CoglMaterial *owner,
CoglMaterialLayer *layer,
CoglMaterialLayerState change);
void (*free_priv) (CoglMaterial *material);
void (*free_layer_priv) (CoglMaterialLayer *layer);
} CoglMaterialBackend;
typedef enum
{
COGL_MATERIAL_PROGRAM_TYPE_GLSL = 1,
COGL_MATERIAL_PROGRAM_TYPE_ARBFP,
COGL_MATERIAL_PROGRAM_TYPE_FIXED
} CoglMaterialProgramType;
extern const CoglMaterialBackend *
_cogl_material_backends[COGL_MATERIAL_N_BACKENDS];
void
_cogl_material_init_default_material (void);
void
_cogl_material_init_default_layers (void);
/*
* SECTION:cogl-material-internals
* @short_description: Functions for creating custom primitives that make use
* of Cogl materials for filling.
*
* Normally you shouldn't need to use this API directly, but if you need to
* developing a custom/specialised primitive - probably using raw OpenGL - then
* this API aims to expose enough of the material internals to support being
* able to fill your geometry according to a given Cogl material.
*/
gboolean
_cogl_material_get_real_blend_enabled (CoglMaterial *material);
gboolean
_cogl_material_layer_has_user_matrix (CoglMaterialLayer *layer);
/*
* Calls the pre_paint method on the layer texture if there is
* one. This will determine whether mipmaps are needed based on the
* filter settings.
*/
void
_cogl_material_layer_pre_paint (CoglMaterialLayer *layerr);
/*
* CoglMaterialFlushFlag:
* @COGL_MATERIAL_FLUSH_FALLBACK_MASK: The fallback_layers member is set to
* a guint32 mask of the layers that can't be supported with the user
* supplied texture and need to be replaced with fallback textures. (1 =
* fallback, and the least significant bit = layer 0)
* @COGL_MATERIAL_FLUSH_DISABLE_MASK: The disable_layers member is set to
* a guint32 mask of the layers that you want to completly disable
* texturing for (1 = fallback, and the least significant bit = layer 0)
* @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: The layer0_override_texture member is
* set to a GLuint OpenGL texture name to override the texture used for
* layer 0 of the material. This is intended for dealing with sliced
* textures where you will need to point to each of the texture slices in
* turn when drawing your geometry. Passing a value of 0 is the same as
* not passing the option at all.
* @COGL_MATERIAL_FLUSH_SKIP_GL_COLOR: When flushing the GL state for the
* material don't call glColor.
* @COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES: Specifies that a bitmask
* of overrides for the wrap modes for some or all layers is
* given.
*/
typedef enum _CoglMaterialFlushFlag
{
COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1L<<0,
COGL_MATERIAL_FLUSH_DISABLE_MASK = 1L<<1,
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE = 1L<<2,
COGL_MATERIAL_FLUSH_SKIP_GL_COLOR = 1L<<3,
COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES = 1L<<4
} CoglMaterialFlushFlag;
/* This isn't defined in the GLES headers */
#ifndef GL_CLAMP_TO_BORDER
#define GL_CLAMP_TO_BORDER 0x812d
#endif
/* GL_ALWAYS is just used here as a value that is known not to clash
* with any valid GL wrap modes.
*
* XXX: keep the values in sync with the CoglMaterialWrapMode enum
* so no conversion is actually needed.
*/
typedef enum _CoglMaterialWrapModeInternal
{
COGL_MATERIAL_WRAP_MODE_INTERNAL_REPEAT = GL_REPEAT,
COGL_MATERIAL_WRAP_MODE_INTERNAL_CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE,
COGL_MATERIAL_WRAP_MODE_INTERNAL_CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER,
COGL_MATERIAL_WRAP_MODE_INTERNAL_AUTOMATIC = GL_ALWAYS
} CoglMaterialWrapModeInternal;
typedef enum _CoglMaterialWrapModeOverride
{
COGL_MATERIAL_WRAP_MODE_OVERRIDE_NONE = 0,
COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT =
COGL_MATERIAL_WRAP_MODE_INTERNAL_REPEAT,
COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_EDGE =
COGL_MATERIAL_WRAP_MODE_INTERNAL_CLAMP_TO_EDGE,
COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_BORDER =
COGL_MATERIAL_WRAP_MODE_INTERNAL_CLAMP_TO_BORDER,
} CoglMaterialWrapModeOverride;
/* There can't be more than 32 layers because we need to fit a bitmask
of the layers into a guint32 */
#define COGL_MATERIAL_MAX_LAYERS 32
typedef struct _CoglMaterialWrapModeOverrides
{
struct
{
CoglMaterialWrapModeOverride s;
CoglMaterialWrapModeOverride t;
CoglMaterialWrapModeOverride p;
} values[COGL_MATERIAL_MAX_LAYERS];
} CoglMaterialWrapModeOverrides;
/*
* CoglMaterialFlushOptions:
*
*/
typedef struct _CoglMaterialFlushOptions
{
CoglMaterialFlushFlag flags;
guint32 fallback_layers;
guint32 disable_layers;
GLuint layer0_override_texture;
CoglMaterialWrapModeOverrides wrap_mode_overrides;
} CoglMaterialFlushOptions;
int
_cogl_get_max_texture_image_units (void);
void
_cogl_use_program (CoglHandle program_handle, CoglMaterialProgramType type);
unsigned int
_cogl_get_n_args_for_combine_func (GLint func);
/*
* _cogl_material_weak_copy:
* @material: A #CoglMaterial object
* @callback: A callback to notify when your weak material is destroyed
* @user_data: Private data to pass to your given callback.
*
* Returns a weak copy of the given source @material. Unlike a normal
* copy no internal reference is taken on the source @material and you
* can expect that later modifications of the source material (or in
* fact any other material) can result in the weak material being
* destroyed.
*
* To understand this better its good to know a bit about the internal
* design of #CoglMaterial...
*
* Internally #CoglMaterial<!-- -->s are represented as a graph of
* property diff's, where each node is a diff of properties that gets
* applied on top of its parent. Copying a material creates an empty
* diff and a child->parent relationship between the empty diff and
* the source @material, parent.
*
* Because of this internal graph design a single #CoglMaterial may
* indirectly depend on a chain of ancestors to fully define all of
* its properties. Because a node depends on its ancestors it normally
* owns a reference to its parent to stop it from being freed. Also if
* you try to modify a material with children we internally use a
* copy-on-write mechanism to ensure that you don't indirectly change
* the properties those children.
*
* Weak materials avoid the use of copy-on-write to preserve the
* integrity of weak dependants and instead weak dependants are
* simply destroyed allowing the parent to be modified directly. Also
* because weak materials don't own a reference to their parent they
* won't stop the source @material from being freed when the user
* releases their reference on it.
*
* Because weak materials don't own a reference on their parent they
* are the recommended mechanism for creating derived materials that you
* want to cache as a private property of the original material
* because they won't result in a circular dependency.
*
* An example use case:
*
* Consider for example you are implementing a custom primitive that is
* not compatible with certain source materials. To handle this you
* implement a validation stage that given an arbitrary material as
* input will create a derived material that is suitable for drawing
* your primitive.
*
* Because you don't want to have to repeat this validation every time
* the same incompatible material is given as input you want to cache
* the result as a private property of the original material. If the
* derived material were created using cogl_material_copy that would
* create a circular dependency so the original material can never be
* freed.
*
* If you instead create a weak copy you won't stop the original material
* from being freed if it's no longer needed, and you will instead simply
* be notified that your weak material has been destroyed.
*
* This is the recommended coding pattern for validating an input
* material and caching a derived result:
* |[
* static CoglUserDataKey _cogl_my_cache_key;
*
* typedef struct {
* CoglMaterial *validated_source;
* } MyValidatedMaterialCache;
*
* static void
* destroy_cache_cb (CoglObject *object, void *user_data)
* {
* g_slice_free (MyValidatedMaterialCache, user_data);
* }
*
* static void
* invalidate_cache_cb (CoglMaterial *destroyed, void *user_data)
* {
* MyValidatedMaterialCache *cache = user_data;
* cogl_object_unref (cache->validated_source);
* cache->validated_source = NULL;
* }
*
* static CoglMaterial *
* get_validated_material (CoglMaterial *source)
* {
* MyValidatedMaterialCache *cache =
* cogl_object_get_user_data (COGL_OBJECT (source),
* &_cogl_my_cache_key);
* if (G_UNLIKELY (cache == NULL))
* {
* cache = g_slice_new (MyValidatedMaterialCache);
* cogl_object_set_user_data (COGL_OBJECT (source),
* &_cogl_my_cache_key,
* cache, destroy_cache_cb);
* cache->validated_source = source;
* }
*
* if (G_UNLIKELY (cache->validated_source == NULL))
* {
* cache->validated_source = source;
*
* /&nbsp;* Start validating source... *&nbsp;/
*
* /&nbsp;* If you find you need to change something... *&nbsp;/
* if (cache->validated_source == source)
* cache->validated_source =
* cogl_material_weak_copy (source,
* invalidate_cache_cb,
* cache);
*
* /&nbsp;* Modify cache->validated_source *&nbsp;/
* }
*
* return cache->validated_source;
* }
* ]|
*/
CoglMaterial *
_cogl_material_weak_copy (CoglMaterial *material,
CoglMaterialDestroyCallback callback,
void *user_data);
void
_cogl_material_set_backend (CoglMaterial *material, int backend);
CoglMaterial *
_cogl_material_get_parent (CoglMaterial *material);
void
_cogl_material_get_colorubv (CoglMaterial *material,
guint8 *color);
unsigned long
_cogl_material_compare_differences (CoglMaterial *material0,
CoglMaterial *material1);
gboolean
_cogl_material_equal (CoglMaterial *material0,
CoglMaterial *material1,
gboolean skip_gl_color);
CoglMaterial *
_cogl_material_journal_ref (CoglMaterial *material);
void
_cogl_material_journal_unref (CoglMaterial *material);
void
_cogl_material_layer_get_wrap_modes (CoglMaterialLayer *layer,
CoglMaterialWrapModeInternal *wrap_mode_s,
CoglMaterialWrapModeInternal *wrap_mode_t,
CoglMaterialWrapModeInternal *wrap_mode_r);
void
_cogl_material_layer_get_filters (CoglMaterialLayer *layer,
CoglMaterialFilter *min_filter,
CoglMaterialFilter *mag_filter);
void
_cogl_material_texture_storage_change_notify (CoglHandle texture);
void
_cogl_material_apply_legacy_state (CoglMaterial *material);
void
_cogl_material_apply_overrides (CoglMaterial *material,
CoglMaterialFlushOptions *options);
CoglMaterialBlendEnable
_cogl_material_get_blend_enabled (CoglMaterial *material);
void
_cogl_material_set_blend_enabled (CoglMaterial *material,
CoglMaterialBlendEnable enable);
void
_cogl_material_set_static_breadcrumb (CoglMaterial *material,
const char *breadcrumb);
unsigned long
_cogl_material_get_age (CoglMaterial *material);
CoglMaterial *
_cogl_material_get_authority (CoglMaterial *material,
unsigned long difference);
unsigned long
_cogl_material_layer_compare_differences (CoglMaterialLayer *layer0,
CoglMaterialLayer *layer1);
CoglMaterialLayer *
_cogl_material_layer_get_authority (CoglMaterialLayer *layer,
unsigned long difference);
CoglHandle
_cogl_material_layer_get_texture (CoglMaterialLayer *layer);
typedef gboolean (*CoglMaterialLayerCallback) (CoglMaterialLayer *layer,
void *user_data);
void
_cogl_material_foreach_layer (CoglMaterial *material,
CoglMaterialLayerCallback callback,
void *user_data);
int
_cogl_material_layer_get_unit_index (CoglMaterialLayer *layer);
void
_cogl_material_get_layer_combine_constant (CoglMaterial *material,
int layer_index,
float *constant);
#endif /* __COGL_MATERIAL_PRIVATE_H */