diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index ee39f766f..330cba9d0 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -115,6 +115,7 @@ cogl_experimental_h = \
$(srcdir)/cogl-vector.h \
$(srcdir)/cogl-euler.h \
$(srcdir)/cogl-quaternion.h \
+ $(srcdir)/cogl-matrix-stack.h \
$(srcdir)/cogl-poll.h \
$(srcdir)/cogl-texture-3d.h \
$(srcdir)/cogl-texture-2d.h \
@@ -326,7 +327,7 @@ cogl_sources_c = \
$(srcdir)/cogl-quaternion.c \
$(srcdir)/cogl-matrix-private.h \
$(srcdir)/cogl-matrix-stack.c \
- $(srcdir)/cogl-matrix-stack.h \
+ $(srcdir)/cogl-matrix-stack-private.h \
$(srcdir)/cogl-depth-state.c \
$(srcdir)/cogl-depth-state-private.h \
$(srcdir)/cogl-node.c \
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index 7ecf83fd4..a6b0d04b0 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -190,10 +190,10 @@ _cogl_clip_stack_push_rectangle (CoglClipStack *stack,
entry->x1 = x_2;
entry->y1 = y_2;
- entry->matrix_entry = _cogl_matrix_entry_ref (modelview_entry);
+ entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);
- _cogl_matrix_entry_get (modelview_entry, &modelview);
- _cogl_matrix_entry_get (projection_entry, &projection);
+ cogl_matrix_entry_get (modelview_entry, &modelview);
+ cogl_matrix_entry_get (projection_entry, &projection);
cogl_matrix_multiply (&modelview_projection,
&projection,
@@ -284,10 +284,10 @@ _cogl_clip_stack_push_from_path (CoglClipStack *stack,
entry->path = cogl_path_copy (path);
- entry->matrix_entry = _cogl_matrix_entry_ref (modelview_entry);
+ entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);
- _cogl_matrix_entry_get (modelview_entry, &modelview);
- _cogl_matrix_entry_get (projection_entry, &projection);
+ cogl_matrix_entry_get (modelview_entry, &modelview);
+ cogl_matrix_entry_get (projection_entry, &projection);
get_transformed_corners (x_1, y_1, x_2, y_2,
&modelview,
@@ -323,15 +323,15 @@ _cogl_clip_stack_push_primitive (CoglClipStack *stack,
entry->primitive = cogl_object_ref (primitive);
- entry->matrix_entry = _cogl_matrix_entry_ref (modelview_entry);
+ entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);
entry->bounds_x1 = bounds_x1;
entry->bounds_y1 = bounds_y1;
entry->bounds_x2 = bounds_x2;
entry->bounds_y2 = bounds_y2;
- _cogl_matrix_entry_get (modelview_entry, &modelview);
- _cogl_matrix_entry_get (modelview_entry, &projection);
+ cogl_matrix_entry_get (modelview_entry, &modelview);
+ cogl_matrix_entry_get (modelview_entry, &projection);
get_transformed_corners (bounds_x1, bounds_y1, bounds_x2, bounds_y2,
&modelview,
@@ -372,7 +372,7 @@ _cogl_clip_stack_unref (CoglClipStack *entry)
case COGL_CLIP_STACK_RECT:
{
CoglClipStackRect *rect = (CoglClipStackRect *) entry;
- _cogl_matrix_entry_unref (rect->matrix_entry);
+ cogl_matrix_entry_unref (rect->matrix_entry);
g_slice_free1 (sizeof (CoglClipStackRect), entry);
break;
}
@@ -383,7 +383,7 @@ _cogl_clip_stack_unref (CoglClipStack *entry)
case COGL_CLIP_STACK_PATH:
{
CoglClipStackPath *path_entry = (CoglClipStackPath *) entry;
- _cogl_matrix_entry_unref (path_entry->matrix_entry);
+ cogl_matrix_entry_unref (path_entry->matrix_entry);
cogl_object_unref (path_entry->path);
g_slice_free1 (sizeof (CoglClipStackPath), entry);
break;
@@ -392,7 +392,7 @@ _cogl_clip_stack_unref (CoglClipStack *entry)
{
CoglClipStackPrimitive *primitive_entry =
(CoglClipStackPrimitive *) entry;
- _cogl_matrix_entry_unref (primitive_entry->matrix_entry);
+ cogl_matrix_entry_unref (primitive_entry->matrix_entry);
cogl_object_unref (primitive_entry->primitive);
g_slice_free1 (sizeof (CoglClipStackPrimitive), entry);
break;
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 86965e26f..f0a3ade50 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -551,9 +551,9 @@ _cogl_context_free (CoglContext *context)
g_slist_free (context->buffer_types);
if (context->current_modelview_entry)
- _cogl_matrix_entry_unref (context->current_modelview_entry);
+ cogl_matrix_entry_unref (context->current_modelview_entry);
if (context->current_projection_entry)
- _cogl_matrix_entry_unref (context->current_projection_entry);
+ cogl_matrix_entry_unref (context->current_projection_entry);
_cogl_matrix_entry_cache_destroy (&context->builtin_flushed_projection);
_cogl_matrix_entry_cache_destroy (&context->builtin_flushed_modelview);
@@ -625,9 +625,9 @@ void
_cogl_context_set_current_projection_entry (CoglContext *context,
CoglMatrixEntry *entry)
{
- _cogl_matrix_entry_ref (entry);
+ cogl_matrix_entry_ref (entry);
if (context->current_projection_entry)
- _cogl_matrix_entry_unref (context->current_projection_entry);
+ cogl_matrix_entry_unref (context->current_projection_entry);
context->current_projection_entry = entry;
}
@@ -635,9 +635,9 @@ void
_cogl_context_set_current_modelview_entry (CoglContext *context,
CoglMatrixEntry *entry)
{
- _cogl_matrix_entry_ref (entry);
+ cogl_matrix_entry_ref (entry);
if (context->current_modelview_entry)
- _cogl_matrix_entry_unref (context->current_modelview_entry);
+ cogl_matrix_entry_unref (context->current_modelview_entry);
context->current_modelview_entry = entry;
}
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 12e68d350..7664f7c08 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -25,7 +25,7 @@
#define __COGL_FRAMEBUFFER_PRIVATE_H
#include "cogl-object-private.h"
-#include "cogl-matrix-stack.h"
+#include "cogl-matrix-stack-private.h"
#include "cogl-clip-state-private.h"
#include "cogl-journal-private.h"
#include "cogl-winsys-private.h"
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 0af2e4fe2..704410ec8 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -116,8 +116,8 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
framebuffer->viewport_age_for_scissor_workaround = -1;
framebuffer->dither_enabled = TRUE;
- framebuffer->modelview_stack = _cogl_matrix_stack_new ();
- framebuffer->projection_stack = _cogl_matrix_stack_new ();
+ framebuffer->modelview_stack = cogl_matrix_stack_new (ctx);
+ framebuffer->projection_stack = cogl_matrix_stack_new (ctx);
framebuffer->dirty_bitmasks = TRUE;
@@ -1894,7 +1894,7 @@ cogl_framebuffer_push_matrix (CoglFramebuffer *framebuffer)
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_push (modelview_stack);
+ cogl_matrix_stack_push (modelview_stack);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -1906,7 +1906,7 @@ cogl_framebuffer_pop_matrix (CoglFramebuffer *framebuffer)
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_pop (modelview_stack);
+ cogl_matrix_stack_pop (modelview_stack);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -1918,7 +1918,7 @@ cogl_framebuffer_identity_matrix (CoglFramebuffer *framebuffer)
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_load_identity (modelview_stack);
+ cogl_matrix_stack_load_identity (modelview_stack);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -1933,7 +1933,7 @@ cogl_framebuffer_scale (CoglFramebuffer *framebuffer,
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_scale (modelview_stack, x, y, z);
+ cogl_matrix_stack_scale (modelview_stack, x, y, z);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -1948,7 +1948,7 @@ cogl_framebuffer_translate (CoglFramebuffer *framebuffer,
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_translate (modelview_stack, x, y, z);
+ cogl_matrix_stack_translate (modelview_stack, x, y, z);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -1964,7 +1964,7 @@ cogl_framebuffer_rotate (CoglFramebuffer *framebuffer,
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_rotate (modelview_stack, angle, x, y, z);
+ cogl_matrix_stack_rotate (modelview_stack, angle, x, y, z);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -1977,7 +1977,7 @@ cogl_framebuffer_rotate_quaternion (CoglFramebuffer *framebuffer,
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_rotate_quaternion (modelview_stack, quaternion);
+ cogl_matrix_stack_rotate_quaternion (modelview_stack, quaternion);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -1990,7 +1990,7 @@ cogl_framebuffer_rotate_euler (CoglFramebuffer *framebuffer,
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_rotate_euler (modelview_stack, euler);
+ cogl_matrix_stack_rotate_euler (modelview_stack, euler);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -2003,7 +2003,7 @@ cogl_framebuffer_transform (CoglFramebuffer *framebuffer,
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_multiply (modelview_stack, matrix);
+ cogl_matrix_stack_multiply (modelview_stack, matrix);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -2048,15 +2048,15 @@ cogl_framebuffer_frustum (CoglFramebuffer *framebuffer,
* so we need to flush all journaled primitives first... */
_cogl_framebuffer_flush_journal (framebuffer);
- _cogl_matrix_stack_load_identity (projection_stack);
+ cogl_matrix_stack_load_identity (projection_stack);
- _cogl_matrix_stack_frustum (projection_stack,
- left,
- right,
- bottom,
- top,
- z_near,
- z_far);
+ cogl_matrix_stack_frustum (projection_stack,
+ left,
+ right,
+ bottom,
+ top,
+ z_near,
+ z_far);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -2082,7 +2082,7 @@ cogl_framebuffer_orthographic (CoglFramebuffer *framebuffer,
cogl_matrix_init_identity (&ortho);
cogl_matrix_orthographic (&ortho, x_1, y_1, x_2, y_2, near, far);
- _cogl_matrix_stack_set (projection_stack, &ortho);
+ cogl_matrix_stack_set (projection_stack, &ortho);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -2094,7 +2094,7 @@ _cogl_framebuffer_push_projection (CoglFramebuffer *framebuffer)
{
CoglMatrixStack *projection_stack =
_cogl_framebuffer_get_projection_stack (framebuffer);
- _cogl_matrix_stack_push (projection_stack);
+ cogl_matrix_stack_push (projection_stack);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -2106,7 +2106,7 @@ _cogl_framebuffer_pop_projection (CoglFramebuffer *framebuffer)
{
CoglMatrixStack *projection_stack =
_cogl_framebuffer_get_projection_stack (framebuffer);
- _cogl_matrix_stack_pop (projection_stack);
+ cogl_matrix_stack_pop (projection_stack);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -2119,7 +2119,7 @@ cogl_framebuffer_get_modelview_matrix (CoglFramebuffer *framebuffer,
{
CoglMatrixEntry *modelview_entry =
_cogl_framebuffer_get_modelview_entry (framebuffer);
- _cogl_matrix_entry_get (modelview_entry, matrix);
+ cogl_matrix_entry_get (modelview_entry, matrix);
_COGL_MATRIX_DEBUG_PRINT (matrix);
}
@@ -2129,7 +2129,7 @@ cogl_framebuffer_set_modelview_matrix (CoglFramebuffer *framebuffer,
{
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_set (modelview_stack, matrix);
+ cogl_matrix_stack_set (modelview_stack, matrix);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
@@ -2144,7 +2144,7 @@ cogl_framebuffer_get_projection_matrix (CoglFramebuffer *framebuffer,
{
CoglMatrixEntry *projection_entry =
_cogl_framebuffer_get_projection_entry (framebuffer);
- _cogl_matrix_entry_get (projection_entry, matrix);
+ cogl_matrix_entry_get (projection_entry, matrix);
_COGL_MATRIX_DEBUG_PRINT (matrix);
}
@@ -2159,7 +2159,7 @@ cogl_framebuffer_set_projection_matrix (CoglFramebuffer *framebuffer,
* so we need to flush all journaled primitives first... */
_cogl_framebuffer_flush_journal (framebuffer);
- _cogl_matrix_stack_set (projection_stack, matrix);
+ cogl_matrix_stack_set (projection_stack, matrix);
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h
index 8c31147f8..e0fc99fba 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -336,10 +336,10 @@ cogl_framebuffer_translate (CoglFramebuffer *framebuffer,
* @z: Z-component of vertex to rotate around.
*
* Multiplies the current model-view matrix by one that rotates the
- * model around the vertex specified by @x, @y and @z. The rotation
- * follows the right-hand thumb rule so for example rotating by 10
- * degrees about the vertex (0, 0, 1) causes a small counter-clockwise
- * rotation.
+ * model around the axis-vector specified by @x, @y and @z. The
+ * rotation follows the right-hand thumb rule so for example rotating
+ * by 10 degrees about the axis-vector (0, 0, 1) causes a small
+ * counter-clockwise rotation.
*
* Since: 1.10
* Stability: unstable
diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
index 18c4c4783..fef4383ee 100644
--- a/cogl/cogl-journal.c
+++ b/cogl/cogl-journal.c
@@ -803,7 +803,7 @@ can_software_clip_entry (CoglJournalEntry *journal_entry,
clip_rect = (CoglClipStackRect *) clip_entry;
modelview_entry = journal_entry->modelview_entry;
- if (!_cogl_matrix_entry_calculate_translation (clip_rect->matrix_entry,
+ if (!cogl_matrix_entry_calculate_translation (clip_rect->matrix_entry,
modelview_entry,
&tx, &ty, &tz))
return FALSE;
@@ -1138,7 +1138,7 @@ upload_vertices (CoglJournal *journal,
v[7] = vin[1];
if (entry->modelview_entry != last_modelview_entry)
- _cogl_matrix_entry_get (entry->modelview_entry, &modelview);
+ cogl_matrix_entry_get (entry->modelview_entry, &modelview);
cogl_matrix_transform_points (&modelview,
2, /* n_components */
sizeof (float) * 2, /* stride_in */
@@ -1186,7 +1186,7 @@ _cogl_journal_discard (CoglJournal *journal)
CoglJournalEntry *entry =
&g_array_index (journal->entries, CoglJournalEntry, i);
_cogl_pipeline_journal_unref (entry->pipeline);
- _cogl_matrix_entry_unref (entry->modelview_entry);
+ cogl_matrix_entry_unref (entry->modelview_entry);
_cogl_clip_stack_unref (entry->clip_stack);
}
@@ -1524,7 +1524,7 @@ _cogl_journal_log_quad (CoglJournal *journal,
modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
- entry->modelview_entry = _cogl_matrix_entry_ref (modelview_stack->last_entry);
+ entry->modelview_entry = cogl_matrix_entry_ref (modelview_stack->last_entry);
_cogl_pipeline_foreach_layer_internal (pipeline,
add_framebuffer_deps_cb,
@@ -1574,7 +1574,7 @@ entry_to_screen_polygon (CoglFramebuffer *framebuffer,
* _cogl_transform_points utility...
*/
- _cogl_matrix_entry_get (entry->modelview_entry, &modelview);
+ cogl_matrix_entry_get (entry->modelview_entry, &modelview);
cogl_matrix_transform_points (&modelview,
2, /* n_components */
sizeof (float) * 4, /* stride_in */
@@ -1586,7 +1586,7 @@ entry_to_screen_polygon (CoglFramebuffer *framebuffer,
projection_stack =
_cogl_framebuffer_get_projection_stack (framebuffer);
- _cogl_matrix_stack_get (projection_stack, &projection);
+ cogl_matrix_stack_get (projection_stack, &projection);
cogl_matrix_project_points (&projection,
3, /* n_components */
diff --git a/cogl/cogl-matrix-stack-private.h b/cogl/cogl-matrix-stack-private.h
new file mode 100644
index 000000000..5d0e911bc
--- /dev/null
+++ b/cogl/cogl-matrix-stack-private.h
@@ -0,0 +1,194 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2009,2010,2012 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
+ * .
+ *
+ *
+ *
+ * Authors:
+ * Havoc Pennington for litl
+ * Robert Bragg
+ */
+
+#ifndef _COGL_MATRIX_STACK_PRIVATE_H_
+#define _COGL_MATRIX_STACK_PRIVATE_H_
+
+#include "cogl-object-private.h"
+#include "cogl-matrix-stack.h"
+#include "cogl-context.h"
+#include "cogl-framebuffer.h"
+
+typedef enum _CoglMatrixOp
+{
+ COGL_MATRIX_OP_LOAD_IDENTITY,
+ COGL_MATRIX_OP_TRANSLATE,
+ COGL_MATRIX_OP_ROTATE,
+ COGL_MATRIX_OP_ROTATE_QUATERNION,
+ COGL_MATRIX_OP_ROTATE_EULER,
+ COGL_MATRIX_OP_SCALE,
+ COGL_MATRIX_OP_MULTIPLY,
+ COGL_MATRIX_OP_LOAD,
+ COGL_MATRIX_OP_SAVE,
+} CoglMatrixOp;
+
+struct _CoglMatrixEntry
+{
+ CoglMatrixEntry *parent;
+ CoglMatrixOp op;
+ unsigned int ref_count;
+
+#ifdef COGL_DEBUG_ENABLED
+ /* used for performance tracing */
+ int composite_gets;
+#endif
+};
+
+typedef struct _CoglMatrixEntryTranslate
+{
+ CoglMatrixEntry _parent_data;
+
+ float x;
+ float y;
+ float z;
+
+} CoglMatrixEntryTranslate;
+
+typedef struct _CoglMatrixEntryRotate
+{
+ CoglMatrixEntry _parent_data;
+
+ float angle;
+ float x;
+ float y;
+ float z;
+
+} CoglMatrixEntryRotate;
+
+typedef struct _CoglMatrixEntryRotateEuler
+{
+ CoglMatrixEntry _parent_data;
+
+ /* This doesn't store an actual CoglEuler in order to avoid the
+ * padding */
+ float heading;
+ float pitch;
+ float roll;
+} CoglMatrixEntryRotateEuler;
+
+typedef struct _CoglMatrixEntryRotateQuaternion
+{
+ CoglMatrixEntry _parent_data;
+
+ /* This doesn't store an actual CoglQuaternion in order to avoid the
+ * padding */
+ float values[4];
+} CoglMatrixEntryRotateQuaternion;
+
+typedef struct _CoglMatrixEntryScale
+{
+ CoglMatrixEntry _parent_data;
+
+ float x;
+ float y;
+ float z;
+
+} CoglMatrixEntryScale;
+
+typedef struct _CoglMatrixEntryMultiply
+{
+ CoglMatrixEntry _parent_data;
+
+ CoglMatrix *matrix;
+
+} CoglMatrixEntryMultiply;
+
+typedef struct _CoglMatrixEntryLoad
+{
+ CoglMatrixEntry _parent_data;
+
+ CoglMatrix *matrix;
+
+} CoglMatrixEntryLoad;
+
+typedef struct _CoglMatrixEntrySave
+{
+ CoglMatrixEntry _parent_data;
+
+ CoglBool cache_valid;
+ CoglMatrix *cache;
+
+} CoglMatrixEntrySave;
+
+typedef union _CoglMatrixEntryFull
+{
+ CoglMatrixEntry any;
+ CoglMatrixEntryTranslate translate;
+ CoglMatrixEntryRotate rotate;
+ CoglMatrixEntryRotateEuler rotate_euler;
+ CoglMatrixEntryRotateQuaternion rotate_quaternion;
+ CoglMatrixEntryScale scale;
+ CoglMatrixEntryMultiply multiply;
+ CoglMatrixEntryLoad load;
+ CoglMatrixEntrySave save;
+} CoglMatrixEntryFull;
+
+struct _CoglMatrixStack
+{
+ CoglObject _parent;
+
+ CoglContext *context;
+
+ CoglMatrixEntry *last_entry;
+};
+
+typedef struct _CoglMatrixEntryCache
+{
+ CoglMatrixEntry *entry;
+ CoglBool flushed_identity;
+ CoglBool flipped;
+} CoglMatrixEntryCache;
+
+void
+_cogl_matrix_entry_identity_init (CoglMatrixEntry *entry);
+
+typedef enum {
+ COGL_MATRIX_MODELVIEW,
+ COGL_MATRIX_PROJECTION,
+ COGL_MATRIX_TEXTURE
+} CoglMatrixMode;
+
+void
+_cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx,
+ CoglMatrixEntry *entry,
+ CoglMatrixMode mode,
+ CoglFramebuffer *framebuffer,
+ CoglBool disable_flip);
+
+void
+_cogl_matrix_entry_cache_init (CoglMatrixEntryCache *cache);
+
+CoglBool
+_cogl_matrix_entry_cache_maybe_update (CoglMatrixEntryCache *cache,
+ CoglMatrixEntry *entry,
+ CoglBool flip);
+
+void
+_cogl_matrix_entry_cache_destroy (CoglMatrixEntryCache *cache);
+
+#endif /* _COGL_MATRIX_STACK_PRIVATE_H_ */
diff --git a/cogl/cogl-matrix-stack.c b/cogl/cogl-matrix-stack.c
index 36b1dfd80..15933cd94 100644
--- a/cogl/cogl-matrix-stack.c
+++ b/cogl/cogl-matrix-stack.c
@@ -40,40 +40,62 @@
static void _cogl_matrix_stack_free (CoglMatrixStack *stack);
-COGL_OBJECT_INTERNAL_DEFINE (MatrixStack, matrix_stack);
+COGL_OBJECT_DEFINE (MatrixStack, matrix_stack);
-static CoglMagazine *_cogl_matrix_stack_magazine;
-static CoglMagazine *_cogl_matrix_stack_matrices_magazine;
+static CoglMagazine *cogl_matrix_stack_magazine;
+static CoglMagazine *cogl_matrix_stack_matrices_magazine;
-static void *
-_cogl_matrix_stack_push_entry (CoglMatrixStack *stack,
- size_t size,
- CoglMatrixOp operation)
+/* XXX: Note: this leaves entry->parent uninitialized! */
+static CoglMatrixEntry *
+_cogl_matrix_entry_new (CoglMatrixOp operation)
{
CoglMatrixEntry *entry =
- _cogl_magazine_chunk_alloc (_cogl_matrix_stack_magazine);
+ _cogl_magazine_chunk_alloc (cogl_matrix_stack_magazine);
- /* The new entry starts with a ref count of 1 because the stack
- holds a reference to it as it is the top entry */
entry->ref_count = 1;
entry->op = operation;
- entry->parent = stack->last_entry;
#ifdef COGL_DEBUG_ENABLED
entry->composite_gets = 0;
#endif
+ return entry;
+}
+
+static void *
+_cogl_matrix_stack_push_entry (CoglMatrixStack *stack,
+ CoglMatrixEntry *entry)
+{
+ /* NB: The initial reference of the entry is transferred to the
+ * stack here.
+ *
+ * The stack only maintains a reference to the top of the stack (the
+ * last entry pushed) and each entry in-turn maintains a reference
+ * to its parent.
+ *
+ * We don't need to take a reference to the parent from the entry
+ * here because the we are stealing the reference that was held by
+ * the stack while that parent was previously the top of the stack.
+ */
+ entry->parent = stack->last_entry;
stack->last_entry = entry;
- /* We don't need to take a reference to the parent from the entry
- because the we are stealing the ref in the new stack top */
+ return entry;
+}
+
+static void *
+_cogl_matrix_stack_push_operation (CoglMatrixStack *stack,
+ CoglMatrixOp operation)
+{
+ CoglMatrixEntry *entry = _cogl_matrix_entry_new (operation);
+
+ _cogl_matrix_stack_push_entry (stack, entry);
return entry;
}
static void *
_cogl_matrix_stack_push_replacement_entry (CoglMatrixStack *stack,
- size_t size,
CoglMatrixOp operation)
{
CoglMatrixEntry *old_top = stack->last_entry;
@@ -86,17 +108,17 @@ _cogl_matrix_stack_push_replacement_entry (CoglMatrixStack *stack,
* instead just perform their own matrix manipulations and load a
* new stack every frame. If this optimisation isn't done then the
* stack would just grow endlessly. See the comments
- * _cogl_matrix_stack_pop for a description of how popping works. */
+ * cogl_matrix_stack_pop for a description of how popping works. */
for (new_top = old_top;
new_top->op != COGL_MATRIX_OP_SAVE && new_top->parent;
new_top = new_top->parent)
;
- _cogl_matrix_entry_ref (new_top);
- _cogl_matrix_entry_unref (old_top);
+ cogl_matrix_entry_ref (new_top);
+ cogl_matrix_entry_unref (old_top);
stack->last_entry = new_top;
- return _cogl_matrix_stack_push_entry (stack, size, operation);
+ return _cogl_matrix_stack_push_operation (stack, operation);
}
void
@@ -111,24 +133,21 @@ _cogl_matrix_entry_identity_init (CoglMatrixEntry *entry)
}
void
-_cogl_matrix_stack_load_identity (CoglMatrixStack *stack)
+cogl_matrix_stack_load_identity (CoglMatrixStack *stack)
{
_cogl_matrix_stack_push_replacement_entry (stack,
- sizeof (CoglMatrixEntry),
COGL_MATRIX_OP_LOAD_IDENTITY);
}
void
-_cogl_matrix_stack_translate (CoglMatrixStack *stack,
+cogl_matrix_stack_translate (CoglMatrixStack *stack,
float x,
float y,
float z)
{
CoglMatrixEntryTranslate *entry;
- entry = _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntryTranslate),
- COGL_MATRIX_OP_TRANSLATE);
+ entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_TRANSLATE);
entry->x = x;
entry->y = y;
@@ -136,7 +155,7 @@ _cogl_matrix_stack_translate (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_rotate (CoglMatrixStack *stack,
+cogl_matrix_stack_rotate (CoglMatrixStack *stack,
float angle,
float x,
float y,
@@ -144,9 +163,7 @@ _cogl_matrix_stack_rotate (CoglMatrixStack *stack,
{
CoglMatrixEntryRotate *entry;
- entry = _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntryRotate),
- COGL_MATRIX_OP_ROTATE);
+ entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_ROTATE);
entry->angle = angle;
entry->x = x;
@@ -155,14 +172,13 @@ _cogl_matrix_stack_rotate (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack,
- const CoglQuaternion *quaternion)
+cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack,
+ const CoglQuaternion *quaternion)
{
CoglMatrixEntryRotateQuaternion *entry;
- entry = _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntryRotate),
- COGL_MATRIX_OP_ROTATE_QUATERNION);
+ entry = _cogl_matrix_stack_push_operation (stack,
+ COGL_MATRIX_OP_ROTATE_QUATERNION);
entry->values[0] = quaternion->w;
entry->values[1] = quaternion->x;
@@ -171,14 +187,13 @@ _cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack,
+cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack,
const CoglEuler *euler)
{
CoglMatrixEntryRotateEuler *entry;
- entry = _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntryRotate),
- COGL_MATRIX_OP_ROTATE_EULER);
+ entry = _cogl_matrix_stack_push_operation (stack,
+ COGL_MATRIX_OP_ROTATE_EULER);
entry->heading = euler->heading;
entry->pitch = euler->pitch;
@@ -186,16 +201,14 @@ _cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_scale (CoglMatrixStack *stack,
+cogl_matrix_stack_scale (CoglMatrixStack *stack,
float x,
float y,
float z)
{
CoglMatrixEntryScale *entry;
- entry = _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntryScale),
- COGL_MATRIX_OP_SCALE);
+ entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_SCALE);
entry->x = x;
entry->y = y;
@@ -203,40 +216,37 @@ _cogl_matrix_stack_scale (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_multiply (CoglMatrixStack *stack,
- const CoglMatrix *matrix)
+cogl_matrix_stack_multiply (CoglMatrixStack *stack,
+ const CoglMatrix *matrix)
{
CoglMatrixEntryMultiply *entry;
- entry = _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntryMultiply),
- COGL_MATRIX_OP_MULTIPLY);
+ entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_MULTIPLY);
entry->matrix =
- _cogl_magazine_chunk_alloc (_cogl_matrix_stack_matrices_magazine);
+ _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);
cogl_matrix_init_from_array (entry->matrix, (float *)matrix);
}
void
-_cogl_matrix_stack_set (CoglMatrixStack *stack,
- const CoglMatrix *matrix)
+cogl_matrix_stack_set (CoglMatrixStack *stack,
+ const CoglMatrix *matrix)
{
CoglMatrixEntryLoad *entry;
entry =
_cogl_matrix_stack_push_replacement_entry (stack,
- sizeof (CoglMatrixEntryLoad),
COGL_MATRIX_OP_LOAD);
entry->matrix =
- _cogl_magazine_chunk_alloc (_cogl_matrix_stack_matrices_magazine);
+ _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);
cogl_matrix_init_from_array (entry->matrix, (float *)matrix);
}
void
-_cogl_matrix_stack_frustum (CoglMatrixStack *stack,
+cogl_matrix_stack_frustum (CoglMatrixStack *stack,
float left,
float right,
float bottom,
@@ -248,11 +258,10 @@ _cogl_matrix_stack_frustum (CoglMatrixStack *stack,
entry =
_cogl_matrix_stack_push_replacement_entry (stack,
- sizeof (CoglMatrixEntryLoad),
COGL_MATRIX_OP_LOAD);
entry->matrix =
- _cogl_magazine_chunk_alloc (_cogl_matrix_stack_matrices_magazine);
+ _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);
cogl_matrix_init_identity (entry->matrix);
cogl_matrix_frustum (entry->matrix,
@@ -261,7 +270,7 @@ _cogl_matrix_stack_frustum (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_perspective (CoglMatrixStack *stack,
+cogl_matrix_stack_perspective (CoglMatrixStack *stack,
float fov_y,
float aspect,
float z_near,
@@ -271,11 +280,10 @@ _cogl_matrix_stack_perspective (CoglMatrixStack *stack,
entry =
_cogl_matrix_stack_push_replacement_entry (stack,
- sizeof (CoglMatrixEntryLoad),
COGL_MATRIX_OP_LOAD);
entry->matrix =
- _cogl_magazine_chunk_alloc (_cogl_matrix_stack_matrices_magazine);
+ _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);
cogl_matrix_init_identity (entry->matrix);
cogl_matrix_perspective (entry->matrix,
@@ -283,7 +291,7 @@ _cogl_matrix_stack_perspective (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_orthographic (CoglMatrixStack *stack,
+cogl_matrix_stack_orthographic (CoglMatrixStack *stack,
float x_1,
float y_1,
float x_2,
@@ -295,11 +303,10 @@ _cogl_matrix_stack_orthographic (CoglMatrixStack *stack,
entry =
_cogl_matrix_stack_push_replacement_entry (stack,
- sizeof (CoglMatrixEntryLoad),
COGL_MATRIX_OP_LOAD);
entry->matrix =
- _cogl_magazine_chunk_alloc (_cogl_matrix_stack_matrices_magazine);
+ _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);
cogl_matrix_init_identity (entry->matrix);
cogl_matrix_orthographic (entry->matrix,
@@ -307,19 +314,17 @@ _cogl_matrix_stack_orthographic (CoglMatrixStack *stack,
}
void
-_cogl_matrix_stack_push (CoglMatrixStack *stack)
+cogl_matrix_stack_push (CoglMatrixStack *stack)
{
CoglMatrixEntrySave *entry;
- entry = _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntrySave),
- COGL_MATRIX_OP_SAVE);
+ entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_SAVE);
entry->cache_valid = FALSE;
}
CoglMatrixEntry *
-_cogl_matrix_entry_ref (CoglMatrixEntry *entry)
+cogl_matrix_entry_ref (CoglMatrixEntry *entry)
{
/* A NULL pointer is considered a valid stack so we should accept
that as an argument */
@@ -330,7 +335,7 @@ _cogl_matrix_entry_ref (CoglMatrixEntry *entry)
}
void
-_cogl_matrix_entry_unref (CoglMatrixEntry *entry)
+cogl_matrix_entry_unref (CoglMatrixEntry *entry)
{
CoglMatrixEntry *parent;
@@ -351,14 +356,14 @@ _cogl_matrix_entry_unref (CoglMatrixEntry *entry)
{
CoglMatrixEntryMultiply *multiply =
(CoglMatrixEntryMultiply *)entry;
- _cogl_magazine_chunk_free (_cogl_matrix_stack_matrices_magazine,
+ _cogl_magazine_chunk_free (cogl_matrix_stack_matrices_magazine,
multiply->matrix);
break;
}
case COGL_MATRIX_OP_LOAD:
{
CoglMatrixEntryLoad *load = (CoglMatrixEntryLoad *)entry;
- _cogl_magazine_chunk_free (_cogl_matrix_stack_matrices_magazine,
+ _cogl_magazine_chunk_free (cogl_matrix_stack_matrices_magazine,
load->matrix);
break;
}
@@ -366,18 +371,18 @@ _cogl_matrix_entry_unref (CoglMatrixEntry *entry)
{
CoglMatrixEntrySave *save = (CoglMatrixEntrySave *)entry;
if (save->cache_valid)
- _cogl_magazine_chunk_free (_cogl_matrix_stack_matrices_magazine,
+ _cogl_magazine_chunk_free (cogl_matrix_stack_matrices_magazine,
save->cache);
break;
}
}
- _cogl_magazine_chunk_free (_cogl_matrix_stack_magazine, entry);
+ _cogl_magazine_chunk_free (cogl_matrix_stack_magazine, entry);
}
}
void
-_cogl_matrix_stack_pop (CoglMatrixStack *stack)
+cogl_matrix_stack_pop (CoglMatrixStack *stack)
{
CoglMatrixEntry *old_top;
CoglMatrixEntry *new_top;
@@ -393,7 +398,7 @@ _cogl_matrix_stack_pop (CoglMatrixStack *stack)
* previously had a reference to the old top so we need to decrease
* the ref count on that. We need to ref the new head first in case
* this stack was the only thing referencing the old top. In that
- * case the call to _cogl_matrix_entry_unref will unref the parent.
+ * case the call to cogl_matrix_entry_unref will unref the parent.
*/
/* Find the last save operation and remove it */
@@ -406,19 +411,19 @@ _cogl_matrix_stack_pop (CoglMatrixStack *stack)
;
new_top = new_top->parent;
- _cogl_matrix_entry_ref (new_top);
+ cogl_matrix_entry_ref (new_top);
- _cogl_matrix_entry_unref (old_top);
+ cogl_matrix_entry_unref (old_top);
stack->last_entry = new_top;
}
CoglBool
-_cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
+cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
CoglMatrix *inverse)
{
CoglMatrix matrix;
- CoglMatrix *internal = _cogl_matrix_stack_get (stack, &matrix);
+ CoglMatrix *internal = cogl_matrix_stack_get (stack, &matrix);
if (internal)
return cogl_matrix_get_inverse (internal, inverse);
@@ -432,7 +437,7 @@ _cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
* should query from the return matrix so that the result can
* be cached within the stack. */
CoglMatrix *
-_cogl_matrix_entry_get (CoglMatrixEntry *entry,
+cogl_matrix_entry_get (CoglMatrixEntry *entry,
CoglMatrix *matrix)
{
int depth;
@@ -462,9 +467,9 @@ _cogl_matrix_entry_get (CoglMatrixEntry *entry,
if (!save->cache_valid)
{
CoglMagazine *matrices_magazine =
- _cogl_matrix_stack_matrices_magazine;
+ cogl_matrix_stack_matrices_magazine;
save->cache = _cogl_magazine_chunk_alloc (matrices_magazine);
- _cogl_matrix_entry_get (current->parent, save->cache);
+ cogl_matrix_entry_get (current->parent, save->cache);
save->cache_valid = TRUE;
}
_cogl_matrix_init_from_matrix_without_inverse (matrix, save->cache);
@@ -613,43 +618,49 @@ initialized:
return NULL;
}
+CoglMatrixEntry *
+cogl_matrix_stack_get_entry (CoglMatrixStack *stack)
+{
+ return stack->last_entry;
+}
+
/* In addition to writing the stack matrix into the give @matrix
* argument this function *may* sometimes also return a pointer
* to a matrix too so if we are querying the inverse matrix we
* should query from the return matrix so that the result can
* be cached within the stack. */
CoglMatrix *
-_cogl_matrix_stack_get (CoglMatrixStack *stack,
- CoglMatrix *matrix)
+cogl_matrix_stack_get (CoglMatrixStack *stack,
+ CoglMatrix *matrix)
{
- return _cogl_matrix_entry_get (stack->last_entry, matrix);
+ return cogl_matrix_entry_get (stack->last_entry, matrix);
}
static void
_cogl_matrix_stack_free (CoglMatrixStack *stack)
{
- _cogl_matrix_entry_unref (stack->last_entry);
+ cogl_matrix_entry_unref (stack->last_entry);
g_slice_free (CoglMatrixStack, stack);
}
CoglMatrixStack *
-_cogl_matrix_stack_new (void)
+cogl_matrix_stack_new (CoglContext *ctx)
{
CoglMatrixStack *stack = g_slice_new (CoglMatrixStack);
- if (G_UNLIKELY (_cogl_matrix_stack_magazine == NULL))
+ if (G_UNLIKELY (cogl_matrix_stack_magazine == NULL))
{
- _cogl_matrix_stack_magazine =
+ cogl_matrix_stack_magazine =
_cogl_magazine_new (sizeof (CoglMatrixEntryFull), 20);
- _cogl_matrix_stack_matrices_magazine =
+ cogl_matrix_stack_matrices_magazine =
_cogl_magazine_new (sizeof (CoglMatrix), 20);
}
+ stack->context = ctx;
stack->last_entry = NULL;
- _cogl_matrix_stack_push_entry (stack,
- sizeof (CoglMatrixEntry),
- COGL_MATRIX_OP_LOAD_IDENTITY);
+ cogl_matrix_entry_ref (&ctx->identity_entry);
+ _cogl_matrix_stack_push_entry (stack, &ctx->identity_entry);
return _cogl_matrix_stack_object_new (stack);
}
@@ -667,11 +678,11 @@ _cogl_matrix_entry_skip_saves (CoglMatrixEntry *entry)
}
CoglBool
-_cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0,
- CoglMatrixEntry *entry1,
- float *x,
- float *y,
- float *z)
+cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0,
+ CoglMatrixEntry *entry1,
+ float *x,
+ float *y,
+ float *z)
{
GSList *head0 = NULL;
GSList *head1 = NULL;
@@ -794,7 +805,7 @@ _cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0,
}
CoglBool
-_cogl_matrix_entry_has_identity_flag (CoglMatrixEntry *entry)
+cogl_matrix_entry_is_identity (CoglMatrixEntry *entry)
{
return entry ? entry->op == COGL_MATRIX_OP_LOAD_IDENTITY : FALSE;
}
@@ -889,7 +900,7 @@ _cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx,
else
{
is_identity = FALSE;
- _cogl_matrix_entry_get (entry, &matrix);
+ cogl_matrix_entry_get (entry, &matrix);
}
if (needs_flip)
@@ -921,15 +932,8 @@ _cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx,
}
CoglBool
-_cogl_matrix_entry_fast_equal (CoglMatrixEntry *entry0,
- CoglMatrixEntry *entry1)
-{
- return entry0 == entry1;
-}
-
-CoglBool
-_cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
- CoglMatrixEntry *entry1)
+cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
+ CoglMatrixEntry *entry1)
{
for (;
entry0 && entry1;
@@ -1038,7 +1042,7 @@ _cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
}
void
-_cogl_matrix_entry_print (CoglMatrixEntry *entry)
+cogl_debug_matrix_entry_print (CoglMatrixEntry *entry)
{
int depth;
CoglMatrixEntry *e;
@@ -1172,9 +1176,9 @@ _cogl_matrix_entry_cache_maybe_update (CoglMatrixEntryCache *cache,
if (cache->entry != entry)
{
- _cogl_matrix_entry_ref (entry);
+ cogl_matrix_entry_ref (entry);
if (cache->entry)
- _cogl_matrix_entry_unref (cache->entry);
+ cogl_matrix_entry_unref (cache->entry);
cache->entry = entry;
/* We want to make sure here that if the cache->entry and the
@@ -1192,5 +1196,5 @@ void
_cogl_matrix_entry_cache_destroy (CoglMatrixEntryCache *cache)
{
if (cache->entry)
- _cogl_matrix_entry_unref (cache->entry);
+ cogl_matrix_entry_unref (cache->entry);
}
diff --git a/cogl/cogl-matrix-stack.h b/cogl/cogl-matrix-stack.h
index 52e80de32..8a06cb2e4 100644
--- a/cogl/cogl-matrix-stack.h
+++ b/cogl/cogl-matrix-stack.h
@@ -26,284 +26,594 @@
* Robert Bragg
*/
-#ifndef __COGL_MATRIX_STACK_H
-#define __COGL_MATRIX_STACK_H
+#ifndef _COGL_MATRIX_STACK_H_
+#define _COGL_MATRIX_STACK_H_
+
+#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION)
+#error "Only can be included directly."
+#endif
-#include "cogl-object-private.h"
#include "cogl-matrix.h"
#include "cogl-context.h"
-#include "cogl-framebuffer.h"
-typedef enum _CoglMatrixOp
-{
- COGL_MATRIX_OP_LOAD_IDENTITY,
- COGL_MATRIX_OP_TRANSLATE,
- COGL_MATRIX_OP_ROTATE,
- COGL_MATRIX_OP_ROTATE_QUATERNION,
- COGL_MATRIX_OP_ROTATE_EULER,
- COGL_MATRIX_OP_SCALE,
- COGL_MATRIX_OP_MULTIPLY,
- COGL_MATRIX_OP_LOAD,
- COGL_MATRIX_OP_SAVE,
-} CoglMatrixOp;
+/**
+ * SECTION:cogl-matrix-stack
+ * @short_description: Functions for efficiently tracking many
+ * related transformations
+ *
+ * Matrices can be used (for example) to describe the model-view
+ * transforms of objects, texture transforms, and projective
+ * transforms.
+ *
+ * The #CoglMatrix api provides a good way to manipulate individual
+ * matrices representing a single transformation but if you need to
+ * track many-many such transformations for many objects that are
+ * organized in a scenegraph for example then using a separate
+ * #CoglMatrix for each object may not be the most efficient way.
+ *
+ * A #CoglMatrixStack enables applications to track lots of
+ * transformations that are related to each other in some kind of
+ * hierarchy. In a scenegraph for example if you want to know how to
+ * transform a particular node then you usually have to walk up
+ * through the ancestors and accumulate their transforms before
+ * finally applying the transform of the node itself. In this model
+ * things are grouped together spatially according to their ancestry
+ * and all siblings with the same parent share the same initial
+ * transformation. The #CoglMatrixStack API is suited to tracking lots
+ * of transformations that fit this kind of model.
+ *
+ * Compared to using the #CoglMatrix api directly to track many
+ * related transforms, these can be some advantages to using a
+ * #CoglMatrixStack:
+ *
+ * - Faster equality comparisons of transformations
+ * - Efficient comparisons of the differences between arbitrary
+ * transformations
+ * - Avoid redundant arithmetic related to common transforms
+ * - Can be more space efficient (not always though)
+ *
+ *
+ * For reference (to give an idea of when a #CoglMatrixStack can
+ * provide a space saving) a #CoglMatrix can be expected to take 72
+ * bytes whereas a single #CoglMatrixEntry in a #CoglMatrixStack is
+ * currently around 32 bytes on a 32bit CPU or 36 bytes on a 64bit
+ * CPU. An entry is needed for each individual operation applied to
+ * the stack (such as rotate, scale, translate) so if most of your
+ * leaf node transformations only need one or two simple operations
+ * relative to their parent then a matrix stack will likely take less
+ * space than having a #CoglMatrix for each node.
+ *
+ * Even without any space saving though the ability to perform fast
+ * comparisons and avoid redundant arithmetic (especially sine and
+ * cosine calculations for rotations) can make using a matrix stack
+ * worthwhile.
+ */
+
+/**
+ * CoglMatrixStack:
+ *
+ * Tracks your current position within a hierarchy and lets you build
+ * up a graph of transformations as you traverse through a hierarchy
+ * such as a scenegraph.
+ *
+ * A #CoglMatrixStack always maintains a reference to a single
+ * transformation at any point in time, representing the
+ * transformation at the current position in the hierarchy. You can
+ * get a reference to the current transformation by calling
+ * cogl_matrix_stack_get_entry().
+ *
+ * When a #CoglMatrixStack is first created with
+ * cogl_matrix_stack_new() then it is conceptually positioned at the
+ * root of your hierarchy and the current transformation simply
+ * represents an identity transformation.
+ *
+ * As you traverse your object hierarchy (your scenegraph) then you
+ * should call cogl_matrix_stack_push() whenever you move down one
+ * level and call cogl_matrix_stack_pop() whenever you move back up
+ * one level towards the root.
+ *
+ * At any time you can apply a set of operations, such as "rotate",
+ * "scale", "translate" on top of the current transformation of a
+ * #CoglMatrixStack using functions such as
+ * cogl_matrix_stack_rotate(), cogl_matrix_stack_scale() and
+ * cogl_matrix_stack_translate(). These operations will derive a new
+ * current transformation and will never affect a transformation
+ * that you have referenced using cogl_matrix_stack_get_entry().
+ *
+ * Internally applying operations to a #CoglMatrixStack builds up a
+ * graph of #CoglMatrixEntry structures which each represent a single
+ * immutable transform.
+ */
+typedef struct _CoglMatrixStack CoglMatrixStack;
+
+/**
+ * CoglMatrixEntry:
+ *
+ * Represents a single immutable transformation that was retrieved
+ * from a #CoglMatrixStack using cogl_matrix_stack_get_entry().
+ *
+ * Internally a #CoglMatrixEntry represents a single matrix
+ * operation (such as "rotate", "scale", "translate") which is applied
+ * to the transform of a single parent entry.
+ *
+ * Using the #CoglMatrixStack api effectively builds up a graph of
+ * these immutable #CoglMatrixEntry structures whereby operations
+ * that can be shared between multiple transformations will result
+ * in shared #CoglMatrixEntry nodes in the graph.
+ *
+ * When a #CoglMatrixStack is first created it references one
+ * #CoglMatrixEntry that represents a single "load identity"
+ * operation. This serves as the root entry and all operations
+ * that are then applied to the stack will extend the graph
+ * starting from this root "load identity" entry.
+ *
+ * Given the typical usage model for a #CoglMatrixStack and the way
+ * the entries are built up while traversing a scenegraph then in most
+ * cases where an application is interested in comparing two
+ * transformations for equality then it is enough to simply compare
+ * two #CoglMatrixEntry pointers directly. Technically this can lead
+ * to false negatives that could be identified with a deeper
+ * comparison but often these false negatives are unlikely and
+ * don't matter anyway so this enables extremely cheap comparisons.
+ *
+ * #CoglMatrixEntrys are reference counted using
+ * cogl_matrix_entry_ref() and cogl_matrix_entry_unref() not with
+ * cogl_object_ref() and cogl_object_unref().
+ */
typedef struct _CoglMatrixEntry CoglMatrixEntry;
-struct _CoglMatrixEntry
-{
- CoglMatrixEntry *parent;
- CoglMatrixOp op;
- unsigned int ref_count;
-
-#ifdef COGL_ENABLE_DEBUG
- /* used for performance tracing */
- int composite_gets;
-#endif
-};
-
-typedef struct _CoglMatrixEntryTranslate
-{
- CoglMatrixEntry _parent_data;
-
- float x;
- float y;
- float z;
-
-} CoglMatrixEntryTranslate;
-
-typedef struct _CoglMatrixEntryRotate
-{
- CoglMatrixEntry _parent_data;
-
- float angle;
- float x;
- float y;
- float z;
-
-} CoglMatrixEntryRotate;
-
-typedef struct _CoglMatrixEntryRotateEuler
-{
- CoglMatrixEntry _parent_data;
-
- /* This doesn't store an actual CoglEuler in order to avoid the
- * padding */
- float heading;
- float pitch;
- float roll;
-} CoglMatrixEntryRotateEuler;
-
-typedef struct _CoglMatrixEntryRotateQuaternion
-{
- CoglMatrixEntry _parent_data;
-
- /* This doesn't store an actual CoglQuaternion in order to avoid the
- * padding */
- float values[4];
-} CoglMatrixEntryRotateQuaternion;
-
-typedef struct _CoglMatrixEntryScale
-{
- CoglMatrixEntry _parent_data;
-
- float x;
- float y;
- float z;
-
-} CoglMatrixEntryScale;
-
-typedef struct _CoglMatrixEntryMultiply
-{
- CoglMatrixEntry _parent_data;
-
- CoglMatrix *matrix;
-
-} CoglMatrixEntryMultiply;
-
-typedef struct _CoglMatrixEntryLoad
-{
- CoglMatrixEntry _parent_data;
-
- CoglMatrix *matrix;
-
-} CoglMatrixEntryLoad;
-
-typedef struct _CoglMatrixEntrySave
-{
- CoglMatrixEntry _parent_data;
-
- CoglBool cache_valid;
- CoglMatrix *cache;
-
-} CoglMatrixEntrySave;
-
-typedef union _CoglMatrixEntryFull
-{
- CoglMatrixEntry any;
- CoglMatrixEntryTranslate translate;
- CoglMatrixEntryRotate rotate;
- CoglMatrixEntryRotateEuler rotate_euler;
- CoglMatrixEntryRotateQuaternion rotate_quaternion;
- CoglMatrixEntryScale scale;
- CoglMatrixEntryMultiply multiply;
- CoglMatrixEntryLoad load;
- CoglMatrixEntrySave save;
-} CoglMatrixEntryFull;
-
-typedef struct _CoglMatrixStack
-{
- CoglObject _parent;
-
- CoglMatrixEntry *last_entry;
-} CoglMatrixStack;
-
-typedef struct _CoglMatrixEntryCache
-{
- CoglMatrixEntry *entry;
- CoglBool flushed_identity;
- CoglBool flipped;
-} CoglMatrixEntryCache;
-
+/**
+ * cogl_matrix_stack_new:
+ * @context: A #CoglContext
+ *
+ * Allocates a new #CoglMatrixStack that can be used to build up
+ * transformations relating to objects in a scenegraph like hierarchy.
+ * (See the description of #CoglMatrixStack and #CoglMatrixEntry for
+ * more details of what a matrix stack is best suited for)
+ *
+ * When a #CoglMatrixStack is first allocated it is conceptually
+ * positioned at the root of your scenegraph hierarchy. As you
+ * traverse your scenegraph then you should call
+ * cogl_matrix_stack_push() whenever you move down a level and
+ * cogl_matrix_stack_pop() whenever you move back up a level towards
+ * the root.
+ *
+ * Once you have allocated a #CoglMatrixStack you can get a reference
+ * to the current transformation for the current position in the
+ * hierarchy by calling cogl_matrix_stack_get_entry().
+ *
+ * Once you have allocated a #CoglMatrixStack you can apply operations
+ * such as rotate, scale and translate to modify the current transform
+ * for the current position in the hierarchy by calling
+ * cogl_matrix_stack_rotate(), cogl_matrix_stack_scale() and
+ * cogl_matrix_stack_translate().
+ *
+ * Return value: A newly allocated #CoglMatrixStack
+ */
CoglMatrixStack *
-_cogl_matrix_stack_new (void);
+cogl_matrix_stack_new (CoglContext *ctx);
+/**
+ * cogl_matrix_stack_push:
+ * @stack: A #CoglMatrixStack
+ *
+ * Saves the current transform and starts a new transform that derives
+ * from the current transform.
+ *
+ * This is usually called while traversing a scenegraph whenever you
+ * traverse one level deeper. cogl_matrix_stack_pop() can then be
+ * called when going back up one layer to restore the previous
+ * transform of an ancestor.
+ */
void
-_cogl_matrix_stack_push (CoglMatrixStack *stack);
+cogl_matrix_stack_push (CoglMatrixStack *stack);
+/**
+ * cogl_matrix_stack_pop:
+ * @stack: A #CoglMatrixStack
+ *
+ * Restores the previous transform that was last saved by calling
+ * cogl_matrix_stack_push().
+ *
+ * This is usually called while traversing a scenegraph whenever you
+ * return up one level in the graph towards the root node.
+ */
void
-_cogl_matrix_stack_pop (CoglMatrixStack *stack);
+cogl_matrix_stack_pop (CoglMatrixStack *stack);
+/**
+ * cogl_matrix_stack_load_identity:
+ * @stack: A #CoglMatrixStack
+ *
+ * Resets the current matrix to the identity matrix.
+ */
void
-_cogl_matrix_entry_identity_init (CoglMatrixEntry *entry);
+cogl_matrix_stack_load_identity (CoglMatrixStack *stack);
+/**
+ * cogl_matrix_stack_scale:
+ * @stack: A #CoglMatrixStack
+ * @x: Amount to scale along the x-axis
+ * @y: Amount to scale along the y-axis
+ * @z: Amount to scale along the z-axis
+ *
+ * Multiplies the current matrix by one that scales the x, y and z
+ * axes by the given values.
+ */
void
-_cogl_matrix_stack_load_identity (CoglMatrixStack *stack);
+cogl_matrix_stack_scale (CoglMatrixStack *stack,
+ float x,
+ float y,
+ float z);
+/**
+ * cogl_matrix_stack_translate:
+ * @stack: A #CoglMatrixStack
+ * @x: Distance to translate along the x-axis
+ * @y: Distance to translate along the y-axis
+ * @z: Distance to translate along the z-axis
+ *
+ * Multiplies the current matrix by one that translates along all
+ * three axes according to the given values.
+ */
void
-_cogl_matrix_stack_scale (CoglMatrixStack *stack,
+cogl_matrix_stack_translate (CoglMatrixStack *stack,
+ float x,
+ float y,
+ float z);
+
+/**
+ * cogl_matrix_stack_rotate:
+ * @stack: A #CoglMatrixStack
+ * @angle: Angle in degrees to rotate.
+ * @x: X-component of vertex to rotate around.
+ * @y: Y-component of vertex to rotate around.
+ * @z: Z-component of vertex to rotate around.
+ *
+ * Multiplies the current matrix by one that rotates the around the
+ * axis-vector specified by @x, @y and @z. The rotation follows the
+ * right-hand thumb rule so for example rotating by 10 degrees about
+ * the axis-vector (0, 0, 1) causes a small counter-clockwise
+ * rotation.
+ */
+void
+cogl_matrix_stack_rotate (CoglMatrixStack *stack,
+ float angle,
float x,
float y,
float z);
-void
-_cogl_matrix_stack_translate (CoglMatrixStack *stack,
- float x,
- float y,
- float z);
-void
-_cogl_matrix_stack_rotate (CoglMatrixStack *stack,
- float angle,
- float x,
- float y,
- float z);
-void
-_cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack,
- const CoglQuaternion *quaternion);
-void
-_cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack,
- const CoglEuler *euler);
-void
-_cogl_matrix_stack_multiply (CoglMatrixStack *stack,
- const CoglMatrix *matrix);
-void
-_cogl_matrix_stack_frustum (CoglMatrixStack *stack,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far);
-void
-_cogl_matrix_stack_perspective (CoglMatrixStack *stack,
- float fov_y,
- float aspect,
- float z_near,
- float z_far);
-void
-_cogl_matrix_stack_orthographic (CoglMatrixStack *stack,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- float near,
- float far);
+/**
+ * cogl_matrix_stack_rotate_quaternion:
+ * @stack: A #CoglMatrixStack
+ * @quaternion: A #CoglQuaternion
+ *
+ * Multiplies the current matrix by one that rotates according to the
+ * rotation described by @quaternion.
+ */
+void
+cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack,
+ const CoglQuaternion *quaternion);
+
+/**
+ * cogl_matrix_stack_rotate_euler:
+ * @stack: A #CoglMatrixStack
+ * @euler: A #CoglEuler
+ *
+ * Multiplies the current matrix by one that rotates according to the
+ * rotation described by @euler.
+ */
+void
+cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack,
+ const CoglEuler *euler);
+
+/**
+ * cogl_matrix_stack_multiply:
+ * @stack: A #CoglMatrixStack
+ * @matrix: the matrix to multiply with the current model-view
+ *
+ * Multiplies the current matrix by the given matrix.
+ */
+void
+cogl_matrix_stack_multiply (CoglMatrixStack *stack,
+ const CoglMatrix *matrix);
+
+/**
+ * cogl_matrix_stack_frustum:
+ * @stack: A #CoglMatrixStack
+ * @left: X position of the left clipping plane where it
+ * intersects the near clipping plane
+ * @right: X position of the right clipping plane where it
+ * intersects the near clipping plane
+ * @bottom: Y position of the bottom clipping plane where it
+ * intersects the near clipping plane
+ * @top: Y position of the top clipping plane where it intersects
+ * the near clipping plane
+ * @z_near: The distance to the near clipping plane (Must be positive)
+ * @z_far: The distance to the far clipping plane (Must be positive)
+ *
+ * Replaces the current matrix with a perspective matrix for a given
+ * viewing frustum defined by 4 side clip planes that all cross
+ * through the origin and 2 near and far clip planes.
+ */
+void
+cogl_matrix_stack_frustum (CoglMatrixStack *stack,
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float z_near,
+ float z_far);
+
+/**
+ * cogl_matrix_stack_perspective:
+ * @stack: A #CoglMatrixStack
+ * @fov_y: Vertical field of view angle in degrees.
+ * @aspect: The (width over height) aspect ratio for display
+ * @z_near: The distance to the near clipping plane (Must be positive,
+ * and must not be 0)
+ * @z_far: The distance to the far clipping plane (Must be positive)
+ *
+ * Replaces the current matrix with a perspective matrix based on the
+ * provided values.
+ *
+ * You should be careful not to have too great a @z_far / @z_near
+ * ratio since that will reduce the effectiveness of depth testing
+ * since there wont be enough precision to identify the depth of
+ * objects near to each other.
+ */
+void
+cogl_matrix_stack_perspective (CoglMatrixStack *stack,
+ float fov_y,
+ float aspect,
+ float z_near,
+ float z_far);
+
+/**
+ * cogl_matrix_stack_orthographic:
+ * @stack: A #CoglMatrixStack
+ * @x_1: The x coordinate for the first vertical clipping plane
+ * @y_1: The y coordinate for the first horizontal clipping plane
+ * @x_2: The x coordinate for the second vertical clipping plane
+ * @y_2: The y coordinate for the second horizontal clipping plane
+ * @near: The distance to the near clipping
+ * plane (will be negative if the plane is
+ * behind the viewer)
+ * @far: The distance to the far clipping
+ * plane (will be negative if the plane is
+ * behind the viewer)
+ *
+ * Replaces the current matrix with an orthographic projection matrix.
+ */
+void
+cogl_matrix_stack_orthographic (CoglMatrixStack *stack,
+ float x_1,
+ float y_1,
+ float x_2,
+ float y_2,
+ float near,
+ float far);
+
+/**
+ * cogl_matrix_stack_get_inverse:
+ * @stack: A #CoglMatrixStack
+ * @inverse: (out): The destination for a 4x4 inverse transformation matrix
+ *
+ * Gets the inverse transform of the current matrix and uses it to
+ * initialize a new #CoglMatrix.
+ *
+ * Return value: %TRUE if the inverse was successfully calculated or %FALSE
+ * for degenerate transformations that can't be inverted (in this case the
+ * @inverse matrix will simply be initialized with the identity matrix)
+ */
CoglBool
-_cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
- CoglMatrix *inverse);
-
-/* NB: This function only *sometimes* returns a pointer to a matrix if
- * the matrix returned didn't need to be composed of multiple
- * operations */
-CoglMatrix *
-_cogl_matrix_stack_get (CoglMatrixStack *stack,
- CoglMatrix *matrix);
-
-/* NB: This function only *sometimes* returns a pointer to a matrix if
- * the matrix returned didn't need to be composed of multiple
- * operations */
-CoglMatrix *
-_cogl_matrix_entry_get (CoglMatrixEntry *entry,
- CoglMatrix *matrix);
-
-void
-_cogl_matrix_stack_set (CoglMatrixStack *stack,
- const CoglMatrix *matrix);
-
-CoglBool
-_cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0,
- CoglMatrixEntry *entry1,
- float *x,
- float *y,
- float *z);
-
-/* If this returns TRUE then the entry is definitely the identity
- * matrix. If it returns FALSE it may or may not be the identity
- * matrix but no expensive comparison is performed to verify it. */
-CoglBool
-_cogl_matrix_entry_has_identity_flag (CoglMatrixEntry *entry);
-
-CoglBool
-_cogl_matrix_entry_fast_equal (CoglMatrixEntry *entry0,
- CoglMatrixEntry *entry1);
-
-CoglBool
-_cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
- CoglMatrixEntry *entry1);
-
-void
-_cogl_matrix_entry_print (CoglMatrixEntry *entry);
+cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
+ CoglMatrix *inverse);
+/**
+ * cogl_matrix_stack_get_entry:
+ * @stack: A #CoglMatrixStack
+ *
+ * Gets a reference to the current transform represented by a
+ * #CoglMatrixEntry pointer.
+ *
+ * The transform represented by a #CoglMatrixEntry is
+ * immutable.
+ *
+ * #CoglMatrixEntrys are reference counted using
+ * cogl_matrix_entry_ref() and cogl_matrix_entry_unref() and you
+ * should call cogl_matrix_entry_unref() when you are finished with
+ * and entry you get via cogl_matrix_stack_get_entry().
+ *
+ * Return value: (transfer none): A pointer to the #CoglMatrixEntry
+ * representing the current matrix stack transform.
+ */
CoglMatrixEntry *
-_cogl_matrix_entry_ref (CoglMatrixEntry *entry);
+cogl_matrix_stack_get_entry (CoglMatrixStack *stack);
+/**
+ * cogl_matrix_stack_get:
+ * @stack: A #CoglMatrixStack
+ * @matrix: (out): The potential destination for the current matrix
+ *
+ * Resolves the current @stack transform into a #CoglMatrix by
+ * combining the operations that have been applied to build up the
+ * current transform.
+ *
+ * There are two possible ways that this function may return its
+ * result depending on whether the stack is able to directly point
+ * to an internal #CoglMatrix or whether the result needs to be
+ * composed of multiple operations.
+ *
+ * If an internal matrix contains the required result then this
+ * function will directly return a pointer to that matrix, otherwise
+ * if the function returns %NULL then @matrix will be initialized
+ * to match the current transform of @stack.
+ *
+ * @matrix will be left untouched if a direct pointer is
+ * returned.
+ *
+ * Return value: A direct pointer to the current transform or %NULL
+ * and in that case @matrix will be initialized with
+ * the value of the current transform.
+ */
+CoglMatrix *
+cogl_matrix_stack_get (CoglMatrixStack *stack,
+ CoglMatrix *matrix);
+
+/**
+ * cogl_matrix_entry_get:
+ * @entry: A #CoglMatrixEntry
+ * @matrix: (out): The potential destination for the transform as
+ * a matrix
+ *
+ * Resolves the current @entry transform into a #CoglMatrix by
+ * combining the sequence of operations that have been applied to
+ * build up the current transform.
+ *
+ * There are two possible ways that this function may return its
+ * result depending on whether it's possible to directly point
+ * to an internal #CoglMatrix or whether the result needs to be
+ * composed of multiple operations.
+ *
+ * If an internal matrix contains the required result then this
+ * function will directly return a pointer to that matrix, otherwise
+ * if the function returns %NULL then @matrix will be initialized
+ * to match the transform of @entry.
+ *
+ * @matrix will be left untouched if a direct pointer is
+ * returned.
+ *
+ * Return value: A direct pointer to a #CoglMatrix transform or %NULL
+ * and in that case @matrix will be initialized with
+ * the effective transform represented by @entry.
+ */
+CoglMatrix *
+cogl_matrix_entry_get (CoglMatrixEntry *entry,
+ CoglMatrix *matrix);
+
+/**
+ * cogl_matrix_stack_set:
+ * @stack: A #CoglMatrixStack
+ * @matrix: A #CoglMatrix replace the current matrix value with
+ *
+ * Replaces the current @stack matrix value with the value of @matrix.
+ * This effectively discards any other operations that were applied
+ * since the last time cogl_matrix_stack_push() was called or since
+ * the stack was initialized.
+ */
void
-_cogl_matrix_entry_unref (CoglMatrixEntry *entry);
-
-typedef enum {
- COGL_MATRIX_MODELVIEW,
- COGL_MATRIX_PROJECTION,
- COGL_MATRIX_TEXTURE
-} CoglMatrixMode;
-
-void
-_cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx,
- CoglMatrixEntry *entry,
- CoglMatrixMode mode,
- CoglFramebuffer *framebuffer,
- CoglBool disable_flip);
-
-void
-_cogl_matrix_entry_cache_init (CoglMatrixEntryCache *cache);
+cogl_matrix_stack_set (CoglMatrixStack *stack,
+ const CoglMatrix *matrix);
+/**
+ * cogl_is_matrix_stack:
+ * @object: a #CoglObject
+ *
+ * Determines if the given #CoglObject refers to a #CoglMatrixStack.
+ *
+ * Return value: %TRUE if @object is a #CoglMatrixStack, otherwise
+ * %FALSE.
+ */
CoglBool
-_cogl_matrix_entry_cache_maybe_update (CoglMatrixEntryCache *cache,
- CoglMatrixEntry *entry,
- CoglBool flip);
-
-void
-_cogl_matrix_entry_cache_destroy (CoglMatrixEntryCache *cache);
+cogl_is_matrix_stack (void *object);
+/**
+ * cogl_matrix_entry_calculate_translation:
+ * @entry0: The first reference transform
+ * @entry1: A second reference transform
+ * @x: (out): The destination for the x-component of the translation
+ * @y: (out): The destination for the y-component of the translation
+ * @z: (out): The destination for the z-component of the translation
+ *
+ * Determines if the only difference between two transforms is a
+ * translation and if so returns what the @x, @y, and @z components of
+ * the translation are.
+ *
+ * If the difference between the two translations involves anything
+ * other than a translation then the function returns %FALSE.
+ *
+ * Return value: %TRUE if the only difference between the transform of
+ * @entry0 and the transform of @entry1 is a translation,
+ * otherwise %FALSE.
+ */
CoglBool
-_cogl_is_matrix_stack (void *object);
+cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0,
+ CoglMatrixEntry *entry1,
+ float *x,
+ float *y,
+ float *z);
-#endif /* __COGL_MATRIX_STACK_H */
+/**
+ * cogl_matrix_entry_is_identity:
+ * @entry: A #CoglMatrixEntry
+ *
+ * Determines whether @entry is known to represent an identity
+ * transform.
+ *
+ * If this returns %TRUE then the entry is definitely the identity
+ * matrix. If it returns %FALSE it may or may not be the identity
+ * matrix but no expensive comparison is performed to verify it.
+ *
+ * Return value: %TRUE if @entry is definitely an identity transform,
+ * otherwise %FALSE.
+ */
+CoglBool
+cogl_matrix_entry_is_identity (CoglMatrixEntry *entry);
+
+/**
+ * cogl_matrix_entry_equal:
+ * @entry0: The first #CoglMatrixEntry to compare
+ * @entry1: A second #CoglMatrixEntry to compare
+ *
+ * Compares two arbitrary #CoglMatrixEntry transforms for equality
+ * returning %TRUE if they are equal or %FALSE otherwise.
+ *
+ * In many cases it is unnecessary to use this api and instead
+ * direct pointer comparisons of entries are good enough and much
+ * cheaper too.
+ *
+ * Return value: %TRUE if @entry0 represents the same transform as
+ * @entry1, otherwise %FALSE.
+ */
+CoglBool
+cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
+ CoglMatrixEntry *entry1);
+
+/**
+ * cogl_debug_matrix_entry_print:
+ * @entry: A #CoglMatrixEntry
+ *
+ * Allows visualizing the operations that build up the given @entry
+ * for debugging purposes by printing to stdout.
+ */
+void
+cogl_debug_matrix_entry_print (CoglMatrixEntry *entry);
+
+/**
+ * cogl_matrix_entry_ref:
+ * @entry: A #CoglMatrixEntry
+ *
+ * Takes a reference on the given @entry to ensure the @entry stays
+ * alive and remains valid. When you are finished with the @entry then
+ * you should call cogl_matrix_entry_unref().
+ *
+ * It is an error to pass an @entry pointer to cogl_object_ref() and
+ * cogl_object_unref()
+ */
+CoglMatrixEntry *
+cogl_matrix_entry_ref (CoglMatrixEntry *entry);
+
+/**
+ * cogl_matrix_entry_unref:
+ * @entry: A #CoglMatrixEntry
+ *
+ * Releases a reference on @entry either taken by calling
+ * cogl_matrix_entry_unref() or to release the reference given when
+ * calling cogl_matrix_stack_get_entry().
+ */
+void
+cogl_matrix_entry_unref (CoglMatrixEntry *entry);
+
+#endif /* _COGL_MATRIX_STACK_H_ */
diff --git a/cogl/cogl-matrix.h b/cogl/cogl-matrix.h
index 926f4c8b4..7525f8fed 100644
--- a/cogl/cogl-matrix.h
+++ b/cogl/cogl-matrix.h
@@ -41,7 +41,7 @@ COGL_BEGIN_DECLS
/**
* SECTION:cogl-matrix
- * @short_description: Fuctions for initializing and manipulating 4x4 matrices
+ * @short_description: Functions for initializing and manipulating 4x4 matrices
*
* Matrices are used in Cogl to describe affine model-view transforms, texture
* transforms, and projective transforms. This exposes a utility API that can
diff --git a/cogl/cogl.h b/cogl/cogl.h
index b5e87b65e..075345adf 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -51,6 +51,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/cogl/driver/gl/cogl-clip-stack-gl.c b/cogl/driver/gl/cogl-clip-stack-gl.c
index a9034782e..6a336db20 100644
--- a/cogl/driver/gl/cogl-clip-stack-gl.c
+++ b/cogl/driver/gl/cogl-clip-stack-gl.c
@@ -75,27 +75,27 @@ set_clip_plane (CoglFramebuffer *framebuffer,
_cogl_framebuffer_get_projection_stack (framebuffer);
CoglMatrix inverse_projection;
- _cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection);
+ cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection);
/* Calculate the angle between the axes and the line crossing the
two points */
angle = atan2f (vertex_b[1] - vertex_a[1],
vertex_b[0] - vertex_a[0]) * (180.0/G_PI);
- _cogl_matrix_stack_push (modelview_stack);
+ cogl_matrix_stack_push (modelview_stack);
/* Load the inverse of the projection matrix so we can specify the plane
* in screen coordinates */
- _cogl_matrix_stack_set (modelview_stack, &inverse_projection);
+ cogl_matrix_stack_set (modelview_stack, &inverse_projection);
/* Rotate about point a */
- _cogl_matrix_stack_translate (modelview_stack,
- vertex_a[0], vertex_a[1], vertex_a[2]);
+ cogl_matrix_stack_translate (modelview_stack,
+ vertex_a[0], vertex_a[1], vertex_a[2]);
/* Rotate the plane by the calculated angle so that it will connect
the two points */
- _cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f);
- _cogl_matrix_stack_translate (modelview_stack,
- -vertex_a[0], -vertex_a[1], -vertex_a[2]);
+ cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f);
+ cogl_matrix_stack_translate (modelview_stack,
+ -vertex_a[0], -vertex_a[1], -vertex_a[2]);
/* Clip planes can only be used when a fixed function backend is in
use so we know we can directly push this matrix to the builtin
@@ -131,7 +131,7 @@ set_clip_plane (CoglFramebuffer *framebuffer,
break;
}
- _cogl_matrix_stack_pop (modelview_stack);
+ cogl_matrix_stack_pop (modelview_stack);
}
static void
@@ -154,8 +154,8 @@ set_clip_planes (CoglFramebuffer *framebuffer,
float vertex_bl[4] = { x_1, y_2, 0, 1.0 };
float vertex_br[4] = { x_2, y_2, 0, 1.0 };
- _cogl_matrix_stack_get (projection_stack, &projection_matrix);
- _cogl_matrix_entry_get (modelview_entry, &modelview_matrix);
+ cogl_matrix_stack_get (projection_stack, &projection_matrix);
+ cogl_matrix_entry_get (modelview_entry, &modelview_matrix);
cogl_matrix_multiply (&modelview_projection,
&projection_matrix,
diff --git a/cogl/driver/gl/cogl-pipeline-opengl.c b/cogl/driver/gl/cogl-pipeline-opengl.c
index b354944a4..fa78a7c5f 100644
--- a/cogl/driver/gl/cogl-pipeline-opengl.c
+++ b/cogl/driver/gl/cogl-pipeline-opengl.c
@@ -60,7 +60,9 @@
static void
-texture_unit_init (CoglTextureUnit *unit, int index_)
+texture_unit_init (CoglContext *ctx,
+ CoglTextureUnit *unit,
+ int index_)
{
unit->index = index_;
unit->enabled_gl_target = 0;
@@ -68,7 +70,7 @@ texture_unit_init (CoglTextureUnit *unit, int index_)
unit->gl_target = 0;
unit->is_foreign = FALSE;
unit->dirty_gl_texture = FALSE;
- unit->matrix_stack = _cogl_matrix_stack_new ();
+ unit->matrix_stack = cogl_matrix_stack_new (ctx);
unit->layer = NULL;
unit->layer_changes_since_flush = 0;
@@ -98,7 +100,7 @@ _cogl_get_texture_unit (int index_)
CoglTextureUnit *unit =
&g_array_index (ctx->texture_units, CoglTextureUnit, i);
- texture_unit_init (unit, i);
+ texture_unit_init (ctx, unit, i);
}
}
diff --git a/cogl/driver/gl/cogl-pipeline-progend-glsl.c b/cogl/driver/gl/cogl-pipeline-progend-glsl.c
index 29fbe3063..54e7293f9 100644
--- a/cogl/driver/gl/cogl-pipeline-progend-glsl.c
+++ b/cogl/driver/gl/cogl-pipeline-progend-glsl.c
@@ -949,19 +949,19 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline,
}
if (need_modelview)
- _cogl_matrix_entry_get (modelview_entry, &modelview);
+ cogl_matrix_entry_get (modelview_entry, &modelview);
if (need_projection)
{
if (needs_flip && program_state->flip_uniform == -1)
{
CoglMatrix tmp_matrix;
- _cogl_matrix_entry_get (projection_entry, &tmp_matrix);
+ cogl_matrix_entry_get (projection_entry, &tmp_matrix);
cogl_matrix_multiply (&projection,
&ctx->y_flip_matrix,
&tmp_matrix);
}
else
- _cogl_matrix_entry_get (projection_entry, &projection);
+ cogl_matrix_entry_get (projection_entry, &projection);
}
if (projection_changed && program_state->projection_uniform != -1)
@@ -981,7 +981,7 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline,
/* The journal usually uses an identity matrix for the
modelview so we can optimise this common case by
avoiding the matrix multiplication */
- if (_cogl_matrix_entry_has_identity_flag (modelview_entry))
+ if (cogl_matrix_entry_is_identity (modelview_entry))
{
GE (ctx,
glUniformMatrix4fv (program_state->mvp_uniform,
diff --git a/cogl/driver/gl/cogl-pipeline-vertend-fixed.c b/cogl/driver/gl/cogl-pipeline-vertend-fixed.c
index 487bb28bb..8ebbec430 100644
--- a/cogl/driver/gl/cogl-pipeline-vertend-fixed.c
+++ b/cogl/driver/gl/cogl-pipeline-vertend-fixed.c
@@ -69,8 +69,8 @@ _cogl_pipeline_vertend_fixed_add_layer (CoglPipeline *pipeline,
_cogl_pipeline_layer_get_authority (layer, state);
CoglMatrixEntry *matrix_entry;
- _cogl_matrix_stack_set (unit->matrix_stack,
- &authority->big_state->matrix);
+ cogl_matrix_stack_set (unit->matrix_stack,
+ &authority->big_state->matrix);
_cogl_set_active_texture_unit (unit_index);
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in
index ddfc92601..624021418 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in
@@ -124,6 +124,7 @@
Utilities
+
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
index fc7821bd4..43dc63626 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
@@ -582,6 +582,36 @@ cogl_matrix_project_points
cogl_matrix_is_identity
+
+cogl-matrix-stack
+Matrix Stacks
+CoglMatrixStack
+CoglMatrixEntry
+cogl_matrix_stack_new
+cogl_matrix_stack_push
+cogl_matrix_stack_pop
+cogl_matrix_stack_load_identity
+cogl_matrix_stack_scale
+cogl_matrix_stack_translate
+cogl_matrix_stack_rotate
+cogl_matrix_stack_rotate_quaternion
+cogl_matrix_stack_rotate_euler
+cogl_matrix_stack_multiply
+cogl_matrix_stack_frustum
+cogl_matrix_stack_perspective
+cogl_matrix_stack_orthographic
+cogl_matrix_stack_get_inverse
+cogl_matrix_stack_get_entry
+cogl_matrix_stack_get
+cogl_matrix_entry_get
+cogl_matrix_stack_set
+cogl_matrix_entry_calculate_translation
+cogl_matrix_entry_is_identity
+cogl_matrix_entry_equal
+cogl_matrix_entry_ref
+cogl_matrix_entry_unref
+
+
cogl-euler
Eulers (Rotations)