[cogl-material] Adds cogl_material_copy() API
cogl_material_copy can be used to create a new CoglHandle referencing a copy of some given material. From now on we will advise that developers always aim to use this function instead of cogl_material_new() when creating a material that is in any way derived from another. By using cogl_material_copy, Cogl can maintain an ancestry for each material and keep track of "similar" materials. The plan is that Cogl will use this information to minimize the cost of GPU state transitions.
This commit is contained in:
parent
78fb882a4b
commit
16a09763ef
@ -64,6 +64,8 @@ cogl_create_context (void)
|
|||||||
_cogl_create_context_driver (_context);
|
_cogl_create_context_driver (_context);
|
||||||
_cogl_features_init ();
|
_cogl_features_init ();
|
||||||
|
|
||||||
|
_cogl_material_init_default_material ();
|
||||||
|
|
||||||
_context->enable_flags = 0;
|
_context->enable_flags = 0;
|
||||||
_context->color_alpha = 0;
|
_context->color_alpha = 0;
|
||||||
|
|
||||||
@ -79,7 +81,7 @@ cogl_create_context (void)
|
|||||||
_context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW;
|
_context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW;
|
||||||
_context->texture_units = NULL;
|
_context->texture_units = NULL;
|
||||||
|
|
||||||
_context->default_material = cogl_material_new ();
|
_context->simple_material = cogl_material_new ();
|
||||||
_context->source_material = NULL;
|
_context->source_material = NULL;
|
||||||
|
|
||||||
_context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
|
_context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
|
||||||
@ -137,7 +139,7 @@ cogl_create_context (void)
|
|||||||
0, /* auto calc row stride */
|
0, /* auto calc row stride */
|
||||||
default_texture_data);
|
default_texture_data);
|
||||||
|
|
||||||
cogl_set_source (_context->default_material);
|
cogl_set_source (_context->simple_material);
|
||||||
_cogl_material_flush_gl_state (_context->source_material, NULL);
|
_cogl_material_flush_gl_state (_context->source_material, NULL);
|
||||||
enable_flags =
|
enable_flags =
|
||||||
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||||
@ -166,8 +168,8 @@ _cogl_destroy_context ()
|
|||||||
if (_context->default_gl_texture_rect_tex)
|
if (_context->default_gl_texture_rect_tex)
|
||||||
cogl_handle_unref (_context->default_gl_texture_rect_tex);
|
cogl_handle_unref (_context->default_gl_texture_rect_tex);
|
||||||
|
|
||||||
if (_context->default_material)
|
if (_context->simple_material)
|
||||||
cogl_handle_unref (_context->default_material);
|
cogl_handle_unref (_context->simple_material);
|
||||||
|
|
||||||
if (_context->journal)
|
if (_context->journal)
|
||||||
g_array_free (_context->journal, TRUE);
|
g_array_free (_context->journal, TRUE);
|
||||||
@ -182,6 +184,9 @@ _cogl_destroy_context ()
|
|||||||
if (_context->quad_indices_short)
|
if (_context->quad_indices_short)
|
||||||
cogl_handle_unref (_context->quad_indices_short);
|
cogl_handle_unref (_context->quad_indices_short);
|
||||||
|
|
||||||
|
if (_context->default_material)
|
||||||
|
cogl_handle_unref (_context->default_material);
|
||||||
|
|
||||||
g_free (_context);
|
g_free (_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ typedef struct
|
|||||||
CoglFeatureFlags feature_flags;
|
CoglFeatureFlags feature_flags;
|
||||||
gboolean features_cached;
|
gboolean features_cached;
|
||||||
|
|
||||||
|
CoglHandle default_material;
|
||||||
|
|
||||||
/* Enable cache */
|
/* Enable cache */
|
||||||
gulong enable_flags;
|
gulong enable_flags;
|
||||||
guint8 color_alpha;
|
guint8 color_alpha;
|
||||||
@ -62,7 +64,7 @@ typedef struct
|
|||||||
GList *texture_units;
|
GList *texture_units;
|
||||||
|
|
||||||
/* Materials */
|
/* Materials */
|
||||||
CoglHandle default_material;
|
CoglHandle simple_material;
|
||||||
CoglHandle source_material;
|
CoglHandle source_material;
|
||||||
|
|
||||||
/* Textures */
|
/* Textures */
|
||||||
|
@ -156,6 +156,15 @@ struct _CoglMaterial
|
|||||||
* able to fill your geometry according to a given Cogl material.
|
* able to fill your geometry according to a given Cogl material.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _cogl_material_init_default_material:
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_cogl_material_init_default_material (void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cogl_material_get_cogl_enable_flags:
|
* cogl_material_get_cogl_enable_flags:
|
||||||
|
@ -57,6 +57,8 @@
|
|||||||
#define glBlendEquationSeparate ctx->drv.pf_glBlendEquationSeparate
|
#define glBlendEquationSeparate ctx->drv.pf_glBlendEquationSeparate
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static CoglHandle _cogl_material_layer_copy (CoglHandle layer_handle);
|
||||||
|
|
||||||
static void _cogl_material_free (CoglMaterial *tex);
|
static void _cogl_material_free (CoglMaterial *tex);
|
||||||
static void _cogl_material_layer_free (CoglMaterialLayer *layer);
|
static void _cogl_material_layer_free (CoglMaterialLayer *layer);
|
||||||
|
|
||||||
@ -71,17 +73,19 @@ _cogl_material_error_quark (void)
|
|||||||
return g_quark_from_static_string ("cogl-material-error-quark");
|
return g_quark_from_static_string ("cogl-material-error-quark");
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
void
|
||||||
cogl_material_new (void)
|
_cogl_material_init_default_material (void)
|
||||||
{
|
{
|
||||||
/* Create new - blank - material */
|
/* Create new - blank - material */
|
||||||
CoglMaterial *material = g_new0 (CoglMaterial, 1);
|
CoglMaterial *material = g_slice_new0 (CoglMaterial);
|
||||||
GLubyte *unlit = material->unlit;
|
GLubyte *unlit = material->unlit;
|
||||||
GLfloat *ambient = material->ambient;
|
GLfloat *ambient = material->ambient;
|
||||||
GLfloat *diffuse = material->diffuse;
|
GLfloat *diffuse = material->diffuse;
|
||||||
GLfloat *specular = material->specular;
|
GLfloat *specular = material->specular;
|
||||||
GLfloat *emission = material->emission;
|
GLfloat *emission = material->emission;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
/* Use the same defaults as the GL spec... */
|
/* Use the same defaults as the GL spec... */
|
||||||
unlit[0] = 0xff; unlit[1] = 0xff; unlit[2] = 0xff; unlit[3] = 0xff;
|
unlit[0] = 0xff; unlit[1] = 0xff; unlit[2] = 0xff; unlit[3] = 0xff;
|
||||||
material->flags |= COGL_MATERIAL_FLAG_DEFAULT_COLOR;
|
material->flags |= COGL_MATERIAL_FLAG_DEFAULT_COLOR;
|
||||||
@ -116,9 +120,34 @@ cogl_material_new (void)
|
|||||||
material->layers = NULL;
|
material->layers = NULL;
|
||||||
material->n_layers = 0;
|
material->n_layers = 0;
|
||||||
|
|
||||||
|
ctx->default_material = _cogl_material_handle_new (material);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglHandle
|
||||||
|
cogl_material_copy (CoglHandle handle)
|
||||||
|
{
|
||||||
|
CoglMaterial *material = g_slice_new (CoglMaterial);
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
|
memcpy (material, handle, sizeof (CoglMaterial));
|
||||||
|
|
||||||
|
material->layers = g_list_copy (material->layers);
|
||||||
|
for (l = material->layers; l; l = l->next)
|
||||||
|
l->data = _cogl_material_layer_copy (l->data);
|
||||||
|
|
||||||
return _cogl_material_handle_new (material);
|
return _cogl_material_handle_new (material);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoglHandle
|
||||||
|
cogl_material_new (void)
|
||||||
|
{
|
||||||
|
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
|
return cogl_material_copy (ctx->default_material);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_material_free (CoglMaterial *material)
|
_cogl_material_free (CoglMaterial *material)
|
||||||
{
|
{
|
||||||
@ -128,7 +157,7 @@ _cogl_material_free (CoglMaterial *material)
|
|||||||
g_list_foreach (material->layers,
|
g_list_foreach (material->layers,
|
||||||
(GFunc)cogl_handle_unref, NULL);
|
(GFunc)cogl_handle_unref, NULL);
|
||||||
g_list_free (material->layers);
|
g_list_free (material->layers);
|
||||||
g_free (material);
|
g_slice_free (CoglMaterial, material);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -727,7 +756,7 @@ _cogl_material_get_layer (CoglMaterial *material,
|
|||||||
/* possibly flush primitives referencing the current state... */
|
/* possibly flush primitives referencing the current state... */
|
||||||
_cogl_material_pre_change_notify (material, FALSE, NULL);
|
_cogl_material_pre_change_notify (material, FALSE, NULL);
|
||||||
|
|
||||||
layer = g_new0 (CoglMaterialLayer, 1);
|
layer = g_slice_new0 (CoglMaterialLayer);
|
||||||
|
|
||||||
layer_handle = _cogl_material_layer_handle_new (layer);
|
layer_handle = _cogl_material_layer_handle_new (layer);
|
||||||
layer->index = index_;
|
layer->index = index_;
|
||||||
@ -1016,7 +1045,7 @@ _cogl_material_layer_free (CoglMaterialLayer *layer)
|
|||||||
{
|
{
|
||||||
if (layer->texture != COGL_INVALID_HANDLE)
|
if (layer->texture != COGL_INVALID_HANDLE)
|
||||||
cogl_handle_unref (layer->texture);
|
cogl_handle_unref (layer->texture);
|
||||||
g_free (layer);
|
g_slice_free (CoglMaterialLayer, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1140,6 +1169,21 @@ _cogl_material_layer_get_flags (CoglHandle layer_handle)
|
|||||||
return layer->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX;
|
return layer->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglHandle
|
||||||
|
_cogl_material_layer_copy (CoglHandle layer_handle)
|
||||||
|
{
|
||||||
|
CoglMaterialLayer *layer =
|
||||||
|
_cogl_material_layer_pointer_from_handle (layer_handle);
|
||||||
|
CoglMaterialLayer *layer_copy = g_slice_new (CoglMaterialLayer);
|
||||||
|
|
||||||
|
memcpy (layer_copy, layer, sizeof (CoglMaterialLayer));
|
||||||
|
|
||||||
|
if (layer_copy->texture != COGL_INVALID_HANDLE)
|
||||||
|
cogl_handle_ref (layer_copy->texture);
|
||||||
|
|
||||||
|
return _cogl_material_layer_handle_new (layer_copy);
|
||||||
|
}
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
get_n_args_for_combine_func (GLint func)
|
get_n_args_for_combine_func (GLint func)
|
||||||
{
|
{
|
||||||
@ -1926,10 +1970,10 @@ cogl_set_source_texture (CoglHandle texture_handle)
|
|||||||
|
|
||||||
g_return_if_fail (texture_handle != COGL_INVALID_HANDLE);
|
g_return_if_fail (texture_handle != COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
cogl_material_set_layer (ctx->default_material, 0, texture_handle);
|
cogl_material_set_layer (ctx->simple_material, 0, texture_handle);
|
||||||
cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff);
|
cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff);
|
||||||
cogl_material_set_color (ctx->default_material, &white);
|
cogl_material_set_color (ctx->simple_material, &white);
|
||||||
cogl_set_source (ctx->default_material);
|
cogl_set_source (ctx->simple_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglMaterialFilter
|
CoglMaterialFilter
|
||||||
|
@ -90,6 +90,24 @@ CoglHandle cogl_material_new (void);
|
|||||||
|
|
||||||
#ifndef COGL_DISABLE_DEPRECATED
|
#ifndef COGL_DISABLE_DEPRECATED
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_material_copy:
|
||||||
|
*
|
||||||
|
* Creates a new material handle with the configuration copied from the
|
||||||
|
* source material.
|
||||||
|
*
|
||||||
|
* We would strongly advise developers to always aim to use
|
||||||
|
* cogl_material_copy() instead of cogl_material_new() whenever there will
|
||||||
|
* be any similarity between two materials. Copying a material helps Cogl
|
||||||
|
* keep track of a materials ancestry which we may use to help minimize GPU
|
||||||
|
* state changes.
|
||||||
|
*
|
||||||
|
* Returns: a handle to the new material
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
CoglHandle cogl_material_copy (CoglHandle source);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cogl_material_ref:
|
* cogl_material_ref:
|
||||||
* @handle: a @CoglHandle.
|
* @handle: a @CoglHandle.
|
||||||
|
@ -328,13 +328,13 @@ cogl_set_source_color (const CoglColor *color)
|
|||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
/* In case cogl_set_source_texture was previously used... */
|
/* In case cogl_set_source_texture was previously used... */
|
||||||
cogl_material_remove_layer (ctx->default_material, 0);
|
cogl_material_remove_layer (ctx->simple_material, 0);
|
||||||
|
|
||||||
premultiplied = *color;
|
premultiplied = *color;
|
||||||
cogl_color_premultiply (&premultiplied);
|
cogl_color_premultiply (&premultiplied);
|
||||||
cogl_material_set_color (ctx->default_material, &premultiplied);
|
cogl_material_set_color (ctx->simple_material, &premultiplied);
|
||||||
|
|
||||||
cogl_set_source (ctx->default_material);
|
cogl_set_source (ctx->simple_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user