[current-matrix] Adds texture matrix stacks + removes GL matrix API usage

This relates back to an earlier commitment to stop using the OpenGL matrix
API which is considered deprecated. (ref 54159f5a1d)

The new texture matrix stacks are hung from a list of (internal only)
CoglTextureUnit structures which the CoglMaterial code internally references
via _cogl_get_texure_unit ().

So we would be left with only the cogl-matrix-stack code being responsible
for glMatrixMode, glLoadMatrix and glLoadIdentity this commit updates the
journal code so it now uses the matrix-stack API instead of GL directly.
This commit is contained in:
Robert Bragg 2009-09-29 02:58:27 +01:00
parent 473f7ee31e
commit 2656b569b9
8 changed files with 174 additions and 212 deletions

View File

@ -65,6 +65,8 @@ cogl_create_context (void)
_context->indirect = gl_is_indirect; _context->indirect = gl_is_indirect;
_context->texture_units = NULL;
_context->default_material = cogl_material_new (); _context->default_material = cogl_material_new ();
_context->source_material = NULL; _context->source_material = NULL;
@ -151,6 +153,8 @@ _cogl_destroy_context ()
_cogl_current_matrix_state_destroy (); _cogl_current_matrix_state_destroy ();
_cogl_destroy_texture_units ();
if (_context->path_nodes) if (_context->path_nodes)
g_array_free (_context->path_nodes, TRUE); g_array_free (_context->path_nodes, TRUE);

View File

@ -58,10 +58,11 @@ typedef struct
gboolean indirect; gboolean indirect;
/* Client-side matrix stack or NULL if none */
CoglMatrixMode matrix_mode; CoglMatrixMode matrix_mode;
CoglMatrixStack *modelview_stack;
CoglMatrixStack *projection_stack; CoglMatrixStack *projection_stack;
CoglMatrixStack *modelview_stack;
GList *texture_units;
/* Cache of inverse projection matrix */ /* Cache of inverse projection matrix */
float inverse_projection[16]; float inverse_projection[16];

View File

@ -59,14 +59,21 @@ _cogl_get_client_stack (CoglContext *ctx,
CoglMatrixMode mode, CoglMatrixMode mode,
CoglMatrixStack **current_stack_p) CoglMatrixStack **current_stack_p)
{ {
if (ctx->modelview_stack && switch (mode)
mode == COGL_MATRIX_MODELVIEW) {
*current_stack_p = ctx->modelview_stack; case COGL_MATRIX_MODELVIEW:
else if (ctx->projection_stack && *current_stack_p = ctx->modelview_stack;
mode == COGL_MATRIX_PROJECTION) break;
*current_stack_p = ctx->projection_stack; case COGL_MATRIX_PROJECTION:
else *current_stack_p = ctx->projection_stack;
*current_stack_p = NULL; break;
case COGL_MATRIX_TEXTURE:
g_critical ("The current-matrix API doesn't support the texture matrix "
"you must deal with the CoglMatrixStack directly");
*current_stack_p = NULL;
break;
}
g_assert (*current_stack_p);
} }
#define _COGL_GET_CONTEXT_AND_STACK(contextvar, stackvar, rval) \ #define _COGL_GET_CONTEXT_AND_STACK(contextvar, stackvar, rval) \
@ -77,90 +84,46 @@ _cogl_get_client_stack (CoglContext *ctx,
void void
_cogl_set_current_matrix (CoglMatrixMode mode) _cogl_set_current_matrix (CoglMatrixMode mode)
{ {
GLenum gl_mode;
CoglMatrixStack *current_stack; \
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (mode == ctx->matrix_mode) if (mode == ctx->matrix_mode)
return; return;
ctx->matrix_mode = mode; ctx->matrix_mode = mode;
/* If we have a client side stack then then the GL matrix mode only needs
* changing when we come to flush it to OpenGL */
_cogl_get_client_stack (ctx, mode, &current_stack);
if (current_stack)
return;
gl_mode = 0; /* silence compiler warning */
switch (mode)
{
case COGL_MATRIX_MODELVIEW:
gl_mode = GL_MODELVIEW;
break;
case COGL_MATRIX_PROJECTION:
gl_mode = GL_PROJECTION;
break;
case COGL_MATRIX_TEXTURE:
gl_mode = GL_TEXTURE;
break;
}
GE (glMatrixMode (gl_mode));
} }
void void
_cogl_current_matrix_push (void) _cogl_current_matrix_push (void)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_push (current_stack);
if (current_stack != NULL)
_cogl_matrix_stack_push (current_stack);
else
GE (glPushMatrix ());
} }
void void
_cogl_current_matrix_pop (void) _cogl_current_matrix_pop (void)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_pop (current_stack);
if (current_stack != NULL)
_cogl_matrix_stack_pop (current_stack);
else
GE (glPopMatrix ());
} }
void void
_cogl_current_matrix_identity (void) _cogl_current_matrix_identity (void)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_load_identity (current_stack);
if (current_stack != NULL)
_cogl_matrix_stack_load_identity (current_stack);
else
GE (glLoadIdentity ());
} }
void void
_cogl_current_matrix_load (const CoglMatrix *matrix) _cogl_current_matrix_load (const CoglMatrix *matrix)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_set (current_stack, matrix);
if (current_stack != NULL)
_cogl_matrix_stack_set (current_stack, matrix);
else
GE (glLoadMatrixf (cogl_matrix_get_array (matrix)));
} }
void void
_cogl_current_matrix_multiply (const CoglMatrix *matrix) _cogl_current_matrix_multiply (const CoglMatrix *matrix)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_multiply (current_stack, matrix);
if (current_stack != NULL)
_cogl_matrix_stack_multiply (current_stack, matrix);
else
GE (glMultMatrixf (cogl_matrix_get_array (matrix)));
} }
void void
@ -170,11 +133,7 @@ _cogl_current_matrix_rotate (float angle,
float z) float z)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_rotate (current_stack, angle, x, y, z);
if (current_stack != NULL)
_cogl_matrix_stack_rotate (current_stack, angle, x, y, z);
else
GE (glRotatef (angle, x, y, z));
} }
void void
@ -183,11 +142,7 @@ _cogl_current_matrix_scale (float x,
float z) float z)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_scale (current_stack, x, y, z);
if (current_stack != NULL)
_cogl_matrix_stack_scale (current_stack, x, y, z);
else
GE (glScalef (x, y, z));
} }
void void
@ -196,11 +151,7 @@ _cogl_current_matrix_translate (float x,
float z) float z)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_translate (current_stack, x, y, z);
if (current_stack != NULL)
_cogl_matrix_stack_translate (current_stack, x, y, z);
else
GE (glTranslatef (x, y, z));
} }
void void
@ -212,15 +163,11 @@ _cogl_current_matrix_frustum (float left,
float far_val) float far_val)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_frustum (current_stack,
if (current_stack != NULL) left, right,
_cogl_matrix_stack_frustum (current_stack, bottom, top,
left, right, near_val,
bottom, top, far_val);
near_val,
far_val);
else
GE (glFrustum (left, right, bottom, top, near_val, far_val));
} }
void void
@ -230,20 +177,8 @@ _cogl_current_matrix_perspective (float fov_y,
float z_far) float z_far)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_perspective (current_stack,
if (current_stack != NULL) fov_y, aspect, z_near, z_far);
_cogl_matrix_stack_perspective (current_stack,
fov_y, aspect, z_near, z_far);
else
{
/* NB: There is no glPerspective() (only gluPerspective()) so we use
* cogl_matrix_perspective: */
CoglMatrix matrix;
_cogl_get_matrix (ctx->matrix_mode, &matrix);
cogl_matrix_perspective (&matrix,
fov_y, aspect, z_near, z_far);
_cogl_current_matrix_load (&matrix);
}
} }
void void
@ -255,26 +190,11 @@ _cogl_current_matrix_ortho (float left,
float far_val) float far_val)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_ortho (current_stack,
if (current_stack != NULL) left, right,
_cogl_matrix_stack_ortho (current_stack, bottom, top,
left, right, near_val,
bottom, top, far_val);
near_val,
far_val);
else
{
#ifdef HAVE_COGL_GLES2
/* NB: GLES 2 has no glOrtho(): */
CoglMatrix matrix;
_cogl_get_matrix (ctx->matrix_mode, &matrix);
cogl_matrix_ortho (&matrix,
left, right, bottom, top, near_val, far_val);
_cogl_current_matrix_load (&matrix);
#else
GE (glOrtho (left, right, bottom, top, near_val, far_val));
#endif
}
} }
void void
@ -286,36 +206,7 @@ _cogl_get_matrix (CoglMatrixMode mode,
_cogl_get_client_stack (ctx, mode, &current_stack); _cogl_get_client_stack (ctx, mode, &current_stack);
if (current_stack) _cogl_matrix_stack_get (current_stack, matrix);
_cogl_matrix_stack_get (current_stack, matrix);
else
{
GLenum gl_mode;
GLfloat gl_matrix[16];
gl_mode = 0; /* silence compiler warning */
switch (mode)
{
case COGL_MATRIX_MODELVIEW:
gl_mode = GL_MODELVIEW_MATRIX;
break;
case COGL_MATRIX_PROJECTION:
gl_mode = GL_PROJECTION_MATRIX;
break;
case COGL_MATRIX_TEXTURE:
gl_mode = GL_TEXTURE_MATRIX;
break;
}
/* Note: we have a redundant copy happening here. If that turns out to be
* a problem then, since this is internal to Cogl, we could pass the
* CoglMatrix pointer directly to glGetFloatv; the only problem with that
* is that if we later add internal flags to CoglMatrix they will need to
* be initialized seperatly.
*/
GE (glGetFloatv (gl_mode, gl_matrix));
cogl_matrix_init_from_array (matrix, gl_matrix);
}
} }
void void
@ -330,62 +221,31 @@ _cogl_current_matrix_state_init (void)
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
ctx->matrix_mode = COGL_MATRIX_MODELVIEW; ctx->matrix_mode = COGL_MATRIX_MODELVIEW;
ctx->modelview_stack = NULL; ctx->projection_stack = _cogl_matrix_stack_new ();
ctx->projection_stack = NULL; ctx->modelview_stack = _cogl_matrix_stack_new ();
#if 0
if (ctx->indirect ||
cogl_debug_flags & COGL_DEBUG_FORCE_CLIENT_SIDE_MATRICES)
#endif
{
ctx->modelview_stack = _cogl_matrix_stack_new ();
ctx->projection_stack = _cogl_matrix_stack_new ();
}
} }
void void
_cogl_current_matrix_state_destroy (void) _cogl_current_matrix_state_destroy (void)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (current_stack) _cogl_matrix_stack_destroy (ctx->projection_stack);
_cogl_matrix_stack_destroy (current_stack); _cogl_matrix_stack_destroy (ctx->modelview_stack);
} }
void void
_cogl_current_matrix_state_flush (void) _cogl_current_matrix_state_flush (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_flush_to_gl (current_stack, ctx->matrix_mode);
if (ctx->matrix_mode != COGL_MATRIX_MODELVIEW &&
ctx->matrix_mode != COGL_MATRIX_PROJECTION)
{
g_warning ("matrix state must be flushed in "
"MODELVIEW or PROJECTION mode");
return;
}
if (ctx->modelview_stack &&
ctx->matrix_mode == COGL_MATRIX_MODELVIEW)
{
_cogl_matrix_stack_flush_to_gl (ctx->modelview_stack,
GL_MODELVIEW);
}
else if (ctx->projection_stack &&
ctx->matrix_mode == COGL_MATRIX_PROJECTION)
{
_cogl_matrix_stack_flush_to_gl (ctx->projection_stack,
GL_PROJECTION);
}
} }
void void
_cogl_current_matrix_state_dirty (void) _cogl_current_matrix_state_dirty (void)
{ {
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
_cogl_matrix_stack_dirty (current_stack);
if (current_stack)
_cogl_matrix_stack_dirty (current_stack);
} }
void void
@ -541,9 +401,9 @@ cogl_set_projection_matrix (CoglMatrix *matrix)
void void
_cogl_flush_matrix_stacks (void) _cogl_flush_matrix_stacks (void)
{ {
_cogl_set_current_matrix (COGL_MATRIX_PROJECTION); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
_cogl_current_matrix_state_flush ();
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); _cogl_matrix_stack_flush_to_gl (ctx->projection_stack, COGL_MATRIX_PROJECTION);
_cogl_current_matrix_state_flush (); _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack, COGL_MATRIX_MODELVIEW);
} }

View File

@ -26,6 +26,7 @@
#include "cogl-debug.h" #include "cogl-debug.h"
#include "cogl-types.h" #include "cogl-types.h"
#include "cogl-context.h"
#ifdef HAVE_COGL_GLES2 #ifdef HAVE_COGL_GLES2
typedef enum { typedef enum {
@ -85,4 +86,15 @@ gint _cogl_get_format_bpp (CoglPixelFormat format);
void cogl_enable (gulong flags); void cogl_enable (gulong flags);
gulong cogl_get_enable (void); gulong cogl_get_enable (void);
typedef struct _CoglTextureUnit
{
int index;
CoglMatrixStack *matrix_stack;
} CoglTextureUnit;
CoglTextureUnit *
_cogl_get_texture_unit (int index_);
void
_cogl_destroy_texture_units (void);
#endif /* __COGL_INTERNAL_H */ #endif /* __COGL_INTERNAL_H */

View File

@ -96,6 +96,7 @@ typedef struct _CoglJournalFlushState
CoglJournalIndices *indices; CoglJournalIndices *indices;
size_t indices_type_size; size_t indices_type_size;
#endif #endif
CoglMatrixStack *modelview_stack;
} CoglJournalFlushState; } CoglJournalFlushState;
typedef void (*CoglJournalBatchCallback) (CoglJournalEntry *start, typedef void (*CoglJournalBatchCallback) (CoglJournalEntry *start,
@ -193,7 +194,12 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
g_print ("BATCHING: modelview batch len = %d\n", batch_len); g_print ("BATCHING: modelview batch len = %d\n", batch_len);
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)) if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
GE (glLoadMatrixf ((GLfloat *)&batch_start->model_view)); {
_cogl_matrix_stack_set (state->modelview_stack,
&batch_start->model_view);
_cogl_matrix_stack_flush_to_gl (state->modelview_stack,
COGL_MATRIX_MODELVIEW);
}
#ifdef HAVE_COGL_GL #ifdef HAVE_COGL_GL
@ -541,21 +547,20 @@ _cogl_journal_flush (void)
else else
state.vbo_offset = (char *)ctx->logged_vertices->data; state.vbo_offset = (char *)ctx->logged_vertices->data;
/* Since the journal deals with emitting the modelview matrices manually _cogl_matrix_stack_flush_to_gl (ctx->projection_stack,
* we need to dirty our client side modelview matrix stack cache... */ COGL_MATRIX_PROJECTION);
_cogl_current_matrix_state_dirty ();
/* And explicitly flush other matrix stacks... */ state.modelview_stack = ctx->modelview_stack;
_cogl_set_current_matrix (COGL_MATRIX_PROJECTION); _cogl_matrix_stack_push (ctx->modelview_stack);
_cogl_current_matrix_state_flush ();
/* If we have transformed all our quads at log time then the whole journal /* If we have transformed all our quads at log time then we ensure no
* then we ensure no further model transform is applied by loading the * further model transform is applied by loading the identity matrix
* identity matrix here...*/ * here... */
if (!(cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)) if (G_LIKELY (!(cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
{ {
GE (glMatrixMode (GL_MODELVIEW)); _cogl_matrix_stack_load_identity (ctx->modelview_stack);
glLoadIdentity (); _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack,
COGL_MATRIX_MODELVIEW);
} }
/* batch_and_call() batches a list of journal entries according to some /* batch_and_call() batches a list of journal entries according to some
@ -586,6 +591,8 @@ _cogl_journal_flush (void)
_cogl_journal_flush_vbo_offsets_and_entries, /* callback */ _cogl_journal_flush_vbo_offsets_and_entries, /* callback */
&state); /* data */ &state); /* data */
_cogl_matrix_stack_pop (ctx->modelview_stack);
for (i = 0; i < ctx->journal->len; i++) for (i = 0; i < ctx->journal->len; i++)
{ {
CoglJournalEntry *entry = CoglJournalEntry *entry =

View File

@ -1169,8 +1169,11 @@ is_mipmap_filter (CoglMaterialFilter filter)
|| filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR); || filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR);
} }
/* FIXME: All direct manipulation of GL texture unit state should be dealt with
* by extending the CoglTextureUnit abstraction */
static void static void
_cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer, _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer,
CoglTextureUnit *unit,
CoglLayerInfo *gl_layer_info) CoglLayerInfo *gl_layer_info)
{ {
int n_rgb_func_args; int n_rgb_func_args;
@ -1246,16 +1249,17 @@ _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer,
layer->texture_combine_constant)); layer->texture_combine_constant));
} }
#ifndef DISABLE_MATERIAL_CACHE
if ((gl_layer_info && if ((gl_layer_info &&
gl_layer_info->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX) || gl_layer_info->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX) ||
(layer->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX)) (layer->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX))
#endif _cogl_matrix_stack_set (unit->matrix_stack, &layer->matrix);
{ else
_cogl_set_current_matrix (COGL_MATRIX_TEXTURE); _cogl_matrix_stack_load_identity (unit->matrix_stack);
_cogl_current_matrix_load (&layer->matrix);
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); /* TODO: Eventually we should just have something like
} * _cogl_flush_texture_units() that we can call in
* _cogl_material_flush_layers_gl_state */
_cogl_matrix_stack_flush_to_gl (unit->matrix_stack, COGL_MATRIX_TEXTURE);
} }
/* /*
@ -1327,6 +1331,7 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material,
#ifdef HAVE_COGL_GLES2 #ifdef HAVE_COGL_GLES2
GLenum gl_internal_format; GLenum gl_internal_format;
#endif #endif
CoglTextureUnit *unit;
new_gl_layer_info.layer0_overridden = new_gl_layer_info.layer0_overridden =
layer0_override_texture ? TRUE : FALSE; layer0_override_texture ? TRUE : FALSE;
@ -1366,6 +1371,7 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material,
} }
GE (glActiveTexture (GL_TEXTURE0 + i)); GE (glActiveTexture (GL_TEXTURE0 + i));
unit = _cogl_get_texture_unit (i);
_cogl_texture_set_filters (layer->texture, _cogl_texture_set_filters (layer->texture,
layer->min_filter, layer->min_filter,
@ -1453,7 +1459,7 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material,
} }
} }
_cogl_material_layer_flush_gl_sampler_state (layer, gl_layer_info); _cogl_material_layer_flush_gl_sampler_state (layer, unit, gl_layer_info);
new_gl_layer_info.handle = layer_handle; new_gl_layer_info.handle = layer_handle;
new_gl_layer_info.flags = layer->flags; new_gl_layer_info.flags = layer->flags;

View File

@ -335,15 +335,28 @@ _cogl_matrix_stack_set (CoglMatrixStack *stack,
void void
_cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
GLenum gl_mode) CoglMatrixMode mode)
{ {
CoglMatrixState *state; CoglMatrixState *state;
GLenum gl_mode;
state = _cogl_matrix_stack_top (stack); state = _cogl_matrix_stack_top (stack);
if (stack->flushed_state == state) if (stack->flushed_state == state)
return; return;
switch (mode)
{
case COGL_MATRIX_MODELVIEW:
gl_mode = GL_MODELVIEW;
break;
case COGL_MATRIX_PROJECTION:
gl_mode = GL_PROJECTION;
break;
case COGL_MATRIX_TEXTURE:
gl_mode = GL_TEXTURE;
break;
}
GE (glMatrixMode (gl_mode)); GE (glMatrixMode (gl_mode));
/* In theory it might help the GL implementation if we used our /* In theory it might help the GL implementation if we used our

View File

@ -877,3 +877,62 @@ cogl_end_gl (void)
ctx->in_begin_gl_block = FALSE; ctx->in_begin_gl_block = FALSE;
} }
static CoglTextureUnit *
_cogl_texture_unit_new (void)
{
CoglTextureUnit *unit = g_new0 (CoglTextureUnit, 1);
unit->matrix_stack = _cogl_matrix_stack_new ();
return unit;
}
static void
_cogl_texture_unit_free (CoglTextureUnit *unit)
{
_cogl_matrix_stack_destroy (unit->matrix_stack);
g_free (unit);
}
CoglTextureUnit *
_cogl_get_texture_unit (int index_)
{
GList *l;
CoglTextureUnit *unit;
_COGL_GET_CONTEXT (ctx, NULL);
for (l = ctx->texture_units; l; l = l->next)
{
unit = l->data;
if (unit->index == index_)
return unit;
/* The units are always sorted, so at this point we know this unit
* doesn't exist */
if (unit->index > index_)
break;
}
/* NB: if we now insert a new layer before l, that will maintain order.
*/
unit = _cogl_texture_unit_new ();
/* Note: see comment after for() loop above */
ctx->texture_units =
g_list_insert_before (ctx->texture_units, l, unit);
return unit;
}
void
_cogl_destroy_texture_units (void)
{
GList *l;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
for (l = ctx->texture_units; l; l = l->next)
_cogl_texture_unit_free (l->data);
g_list_free (ctx->texture_units);
}