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)