matrix-stack: more optimization for load_identity case
This goes a bit further than the previous patch, and as a special case we now simply represent identity matrices using a boolean, and only lazily initialize them when they need to be modified.
This commit is contained in:
parent
460025d603
commit
b1f9f0a97d
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CoglMatrix matrix;
|
CoglMatrix matrix;
|
||||||
|
gboolean is_identity;
|
||||||
/* count of pushes with no changes; when a change is
|
/* count of pushes with no changes; when a change is
|
||||||
* requested, we create a new state and decrement this
|
* requested, we create a new state and decrement this
|
||||||
*/
|
*/
|
||||||
@ -54,6 +55,7 @@ struct _CoglMatrixStack
|
|||||||
|
|
||||||
/* which state does GL have, NULL if unknown */
|
/* which state does GL have, NULL if unknown */
|
||||||
CoglMatrixState *flushed_state;
|
CoglMatrixState *flushed_state;
|
||||||
|
gboolean flushed_identity;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XXX: this doesn't initialize the matrix! */
|
/* XXX: this doesn't initialize the matrix! */
|
||||||
@ -64,6 +66,7 @@ _cogl_matrix_state_new (void)
|
|||||||
|
|
||||||
state = g_slice_new (CoglMatrixState);
|
state = g_slice_new (CoglMatrixState);
|
||||||
state->push_count = 0;
|
state->push_count = 0;
|
||||||
|
state->is_identity = FALSE;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -71,7 +74,6 @@ _cogl_matrix_state_new (void)
|
|||||||
static void
|
static void
|
||||||
_cogl_matrix_state_destroy (CoglMatrixState *state)
|
_cogl_matrix_state_destroy (CoglMatrixState *state)
|
||||||
{
|
{
|
||||||
|
|
||||||
g_slice_free (CoglMatrixState, state);
|
g_slice_free (CoglMatrixState, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +83,18 @@ _cogl_matrix_stack_top (CoglMatrixStack *stack)
|
|||||||
return stack->stack->data;
|
return stack->stack->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX:
|
||||||
|
* Operations like scale, translate, rotate etc need to have an
|
||||||
|
* initialized state->matrix to work with, so they will pass
|
||||||
|
* initialize = TRUE.
|
||||||
|
*
|
||||||
|
* _cogl_matrix_stack_load_identity and _cogl_matrix_stack_set on the
|
||||||
|
* other hand don't so they will pass initialize = FALSE
|
||||||
|
*
|
||||||
|
* NB: Identity matrices are represented by setting
|
||||||
|
* state->is_identity=TRUE in which case state->matrix will be
|
||||||
|
* uninitialized.
|
||||||
|
*/
|
||||||
static CoglMatrixState *
|
static CoglMatrixState *
|
||||||
_cogl_matrix_stack_top_mutable (CoglMatrixStack *stack,
|
_cogl_matrix_stack_top_mutable (CoglMatrixStack *stack,
|
||||||
gboolean initialize)
|
gboolean initialize)
|
||||||
@ -91,7 +105,11 @@ _cogl_matrix_stack_top_mutable (CoglMatrixStack *stack,
|
|||||||
state = _cogl_matrix_stack_top (stack);
|
state = _cogl_matrix_stack_top (stack);
|
||||||
|
|
||||||
if (state->push_count == 0)
|
if (state->push_count == 0)
|
||||||
return state;
|
{
|
||||||
|
if (state->is_identity && initialize)
|
||||||
|
cogl_matrix_init_identity (&state->matrix);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
state->push_count -= 1;
|
state->push_count -= 1;
|
||||||
|
|
||||||
@ -99,7 +117,10 @@ _cogl_matrix_stack_top_mutable (CoglMatrixStack *stack,
|
|||||||
|
|
||||||
if (initialize)
|
if (initialize)
|
||||||
{
|
{
|
||||||
new_top->matrix = state->matrix;
|
if (state->is_identity)
|
||||||
|
cogl_matrix_init_identity (&new_top->matrix);
|
||||||
|
else
|
||||||
|
new_top->matrix = state->matrix;
|
||||||
|
|
||||||
if (stack->flushed_state == state)
|
if (stack->flushed_state == state)
|
||||||
stack->flushed_state = new_top;
|
stack->flushed_state = new_top;
|
||||||
@ -119,7 +140,7 @@ _cogl_matrix_stack_new (void)
|
|||||||
stack = g_slice_new0 (CoglMatrixStack);
|
stack = g_slice_new0 (CoglMatrixStack);
|
||||||
|
|
||||||
state = _cogl_matrix_state_new ();
|
state = _cogl_matrix_state_new ();
|
||||||
cogl_matrix_init_identity (&state->matrix);
|
state->is_identity = TRUE;
|
||||||
|
|
||||||
stack->stack = g_slist_prepend (stack->stack, state);
|
stack->stack = g_slist_prepend (stack->stack, state);
|
||||||
|
|
||||||
@ -192,12 +213,22 @@ _cogl_matrix_stack_load_identity (CoglMatrixStack *stack)
|
|||||||
{
|
{
|
||||||
CoglMatrixState *state;
|
CoglMatrixState *state;
|
||||||
|
|
||||||
/* XXX: In this case an uninitialized top is acceptable */
|
|
||||||
state = _cogl_matrix_stack_top_mutable (stack, FALSE);
|
state = _cogl_matrix_stack_top_mutable (stack, FALSE);
|
||||||
cogl_matrix_init_identity (&state->matrix);
|
|
||||||
|
|
||||||
/* mark dirty */
|
/* NB: Identity matrices are represented by setting
|
||||||
stack->flushed_state = NULL;
|
* state->is_identity = TRUE and leaving state->matrix
|
||||||
|
* uninitialized.
|
||||||
|
*
|
||||||
|
* This is done to optimize the heavy usage of
|
||||||
|
* _cogl_matrix_stack_load_identity by the Cogl Journal.
|
||||||
|
*/
|
||||||
|
if (!state->is_identity)
|
||||||
|
{
|
||||||
|
state->is_identity = TRUE;
|
||||||
|
|
||||||
|
/* mark dirty */
|
||||||
|
stack->flushed_state = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -212,6 +243,7 @@ _cogl_matrix_stack_scale (CoglMatrixStack *stack,
|
|||||||
cogl_matrix_scale (&state->matrix, x, y, z);
|
cogl_matrix_scale (&state->matrix, x, y, z);
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -226,6 +258,7 @@ _cogl_matrix_stack_translate (CoglMatrixStack *stack,
|
|||||||
cogl_matrix_translate (&state->matrix, x, y, z);
|
cogl_matrix_translate (&state->matrix, x, y, z);
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -241,6 +274,7 @@ _cogl_matrix_stack_rotate (CoglMatrixStack *stack,
|
|||||||
cogl_matrix_rotate (&state->matrix, angle, x, y, z);
|
cogl_matrix_rotate (&state->matrix, angle, x, y, z);
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -253,6 +287,7 @@ _cogl_matrix_stack_multiply (CoglMatrixStack *stack,
|
|||||||
cogl_matrix_multiply (&state->matrix, &state->matrix, matrix);
|
cogl_matrix_multiply (&state->matrix, &state->matrix, matrix);
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -272,6 +307,7 @@ _cogl_matrix_stack_frustum (CoglMatrixStack *stack,
|
|||||||
z_near, z_far);
|
z_near, z_far);
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -288,6 +324,7 @@ _cogl_matrix_stack_perspective (CoglMatrixStack *stack,
|
|||||||
fov_y, aspect, z_near, z_far);
|
fov_y, aspect, z_near, z_far);
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -306,6 +343,7 @@ _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
|
|||||||
left, right, bottom, top, z_near, z_far);
|
left, right, bottom, top, z_near, z_far);
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -316,7 +354,17 @@ _cogl_matrix_stack_get (CoglMatrixStack *stack,
|
|||||||
|
|
||||||
state = _cogl_matrix_stack_top (stack);
|
state = _cogl_matrix_stack_top (stack);
|
||||||
|
|
||||||
*matrix = state->matrix;
|
/* NB: identity matrices are lazily initialized because we can often avoid
|
||||||
|
* initializing them at all if nothing is pushed on top of them since we
|
||||||
|
* load them using glLoadIdentity()
|
||||||
|
*
|
||||||
|
* The Cogl journal typically loads an identiy matrix because it performs
|
||||||
|
* software transformations, which is why we have optimized this case.
|
||||||
|
*/
|
||||||
|
if (state->is_identity)
|
||||||
|
cogl_matrix_init_identity (matrix);
|
||||||
|
else
|
||||||
|
*matrix = state->matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -325,10 +373,11 @@ _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
|||||||
{
|
{
|
||||||
CoglMatrixState *state;
|
CoglMatrixState *state;
|
||||||
|
|
||||||
state = _cogl_matrix_stack_top_mutable (stack, TRUE);
|
state = _cogl_matrix_stack_top_mutable (stack, FALSE);
|
||||||
state->matrix = *matrix;
|
state->matrix = *matrix;
|
||||||
/* mark dirty */
|
/* mark dirty */
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -362,7 +411,17 @@ _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
|
|||||||
* than LoadMatrix to send a 2D matrix
|
* than LoadMatrix to send a 2D matrix
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GE (glLoadMatrixf (cogl_matrix_get_array (&state->matrix)));
|
if (state->is_identity)
|
||||||
|
{
|
||||||
|
if (!stack->flushed_identity)
|
||||||
|
GE (glLoadIdentity ());
|
||||||
|
stack->flushed_identity = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GE (glLoadMatrixf (cogl_matrix_get_array (&state->matrix)));
|
||||||
|
stack->flushed_identity = FALSE;
|
||||||
|
}
|
||||||
stack->flushed_state = state;
|
stack->flushed_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,5 +429,6 @@ void
|
|||||||
_cogl_matrix_stack_dirty (CoglMatrixStack *stack)
|
_cogl_matrix_stack_dirty (CoglMatrixStack *stack)
|
||||||
{
|
{
|
||||||
stack->flushed_state = NULL;
|
stack->flushed_state = NULL;
|
||||||
|
stack->flushed_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user