diff --git a/common/cogl-current-matrix.c b/common/cogl-current-matrix.c index 6f70be880..217eb2df4 100644 --- a/common/cogl-current-matrix.c +++ b/common/cogl-current-matrix.c @@ -22,6 +22,7 @@ * * Authors: * Havoc Pennington for litl + * Robert Bragg */ #ifdef HAVE_CONFIG_H @@ -53,16 +54,43 @@ #include #include +static void +_cogl_get_client_stack (CoglContext *ctx, + CoglMatrixMode mode, + CoglMatrixStack **current_stack_p) +{ + if (ctx->modelview_stack && + mode == COGL_MATRIX_MODELVIEW) + *current_stack_p = ctx->modelview_stack; + else if (ctx->projection_stack && + mode == COGL_MATRIX_PROJECTION) + *current_stack_p = ctx->projection_stack; + else + *current_stack_p = NULL; +} + +#define _COGL_GET_CONTEXT_AND_STACK(contextvar, stackvar, rval) \ + CoglMatrixStack *stackvar; \ + _COGL_GET_CONTEXT (contextvar, rval); \ + _cogl_get_client_stack (contextvar, ctx->matrix_mode, &stackvar) + void _cogl_set_current_matrix (CoglMatrixMode mode) { GLenum gl_mode; + CoglMatrixStack *current_stack; \ _COGL_GET_CONTEXT (ctx, NO_RETVAL); if (mode == ctx->matrix_mode) return; ctx->matrix_mode = mode; + /* If we have a client side stack then then the GL matrix mode only needs + * changing when we come to flush it to OpenGL */ + _cogl_get_client_stack (ctx, mode, ¤t_stack); + if (current_stack) + return; + gl_mode = 0; /* silence compiler warning */ switch (mode) { @@ -80,22 +108,6 @@ _cogl_set_current_matrix (CoglMatrixMode mode) GE (glMatrixMode (gl_mode)); } -static void -_cogl_get_client_stack (CoglContext *ctx, - CoglMatrixStack **current_stack_p) -{ - if (ctx->modelview_stack && - ctx->matrix_mode == COGL_MATRIX_MODELVIEW) - *current_stack_p = ctx->modelview_stack; - else - *current_stack_p = NULL; -} - -#define _COGL_GET_CONTEXT_AND_STACK(contextvar, stackvar, rval) \ - CoglMatrixStack *stackvar; \ - _COGL_GET_CONTEXT (contextvar, rval); \ - _cogl_get_client_stack (contextvar, &stackvar) - void _cogl_current_matrix_push (void) { @@ -204,7 +216,7 @@ _cogl_current_matrix_frustum (float left, if (current_stack != NULL) _cogl_matrix_stack_frustum (current_stack, left, right, - top, bottom, + bottom, top, near_val, far_val); else @@ -269,13 +281,13 @@ void _cogl_get_matrix (CoglMatrixMode mode, CoglMatrix *matrix) { + CoglMatrixStack *current_stack; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (ctx->modelview_stack != NULL && - mode == COGL_MATRIX_MODELVIEW) - { - _cogl_matrix_stack_get (ctx->modelview_stack, matrix); - } + _cogl_get_client_stack (ctx, mode, ¤t_stack); + + if (current_stack) + _cogl_matrix_stack_get (current_stack, matrix); else { GLenum gl_mode; @@ -319,24 +331,25 @@ _cogl_current_matrix_state_init (void) ctx->matrix_mode = COGL_MATRIX_MODELVIEW; ctx->modelview_stack = NULL; + ctx->projection_stack = NULL; #if 0 if (ctx->indirect || cogl_debug_flags & COGL_DEBUG_FORCE_CLIENT_SIDE_MATRICES) #endif { - ctx->modelview_stack = - _cogl_matrix_stack_new (); + ctx->modelview_stack = _cogl_matrix_stack_new (); + ctx->projection_stack = _cogl_matrix_stack_new (); } } void _cogl_current_matrix_state_destroy (void) { - _COGL_GET_CONTEXT (ctx, NO_RETVAL); + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); - if (ctx->modelview_stack) - _cogl_matrix_stack_destroy (ctx->modelview_stack); + if (current_stack) + _cogl_matrix_stack_destroy (current_stack); } void @@ -344,32 +357,35 @@ _cogl_current_matrix_state_flush (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (ctx->matrix_mode != COGL_MATRIX_MODELVIEW) + if (ctx->matrix_mode != COGL_MATRIX_MODELVIEW && + ctx->matrix_mode != COGL_MATRIX_PROJECTION) { - g_warning ("matrix state must be flushed in MODELVIEW mode"); + g_warning ("matrix state must be flushed in " + "MODELVIEW or PROJECTION mode"); return; } - if (ctx->modelview_stack) + if (ctx->modelview_stack && + ctx->matrix_mode == COGL_MATRIX_MODELVIEW) { _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack, GL_MODELVIEW); } + else if (ctx->projection_stack && + ctx->matrix_mode == COGL_MATRIX_PROJECTION) + { + _cogl_matrix_stack_flush_to_gl (ctx->projection_stack, + GL_PROJECTION); + } } void _cogl_current_matrix_state_dirty (void) { - _COGL_GET_CONTEXT (ctx, NO_RETVAL); + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); - if (ctx->matrix_mode != COGL_MATRIX_MODELVIEW) - { - g_warning ("matrix state must be dirtied in MODELVIEW mode"); - return; - } - - if (ctx->modelview_stack) - _cogl_matrix_stack_dirty (ctx->modelview_stack); + if (current_stack) + _cogl_matrix_stack_dirty (current_stack); } void @@ -445,8 +461,6 @@ cogl_frustum (float left, z_near, z_far); - _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); - /* Calculate and store the inverse of the matrix */ memset (ctx->inverse_projection, 0, sizeof (float) * 16); @@ -524,3 +538,12 @@ cogl_set_projection_matrix (CoglMatrix *matrix) _cogl_current_matrix_load (matrix); } +void +_cogl_flush_matrix_stacks (void) +{ + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_state_flush (); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_state_flush (); +} + diff --git a/common/cogl-current-matrix.h b/common/cogl-current-matrix.h index 876c72bbb..eb2464888 100644 --- a/common/cogl-current-matrix.h +++ b/common/cogl-current-matrix.h @@ -90,4 +90,6 @@ void _cogl_current_matrix_state_destroy (void); void _cogl_current_matrix_state_flush (void); void _cogl_current_matrix_state_dirty (void); +void _cogl_flush_matrix_stacks (void); + #endif /* __COGL_CURRENT_MATRIX_H */ diff --git a/common/cogl-matrix-stack.c b/common/cogl-matrix-stack.c index e395ee1c6..ceda0576f 100644 --- a/common/cogl-matrix-stack.c +++ b/common/cogl-matrix-stack.c @@ -344,10 +344,7 @@ _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, if (stack->flushed_state == state) return; - /* NOTE we assume caller was in MODELVIEW mode */ - - if (gl_mode != GL_MODELVIEW) - GE (glMatrixMode (gl_mode)); + GE (glMatrixMode (gl_mode)); /* In theory it might help the GL implementation if we used our * local analysis of the matrix and called Translate/Scale rather @@ -356,9 +353,6 @@ _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, GE (glLoadMatrixf (cogl_matrix_get_array (&state->matrix))); stack->flushed_state = state; - - if (gl_mode != GL_MODELVIEW) - GE (glMatrixMode (GL_MODELVIEW)); } void diff --git a/common/cogl-matrix.c b/common/cogl-matrix.c index 45f367d73..d4cacaedd 100644 --- a/common/cogl-matrix.c +++ b/common/cogl-matrix.c @@ -24,6 +24,7 @@ * Robert Bragg */ +#include #include #include diff --git a/common/cogl-primitives.c b/common/cogl-primitives.c index 81f00f5c2..e2d9a2487 100644 --- a/common/cogl-primitives.c +++ b/common/cogl-primitives.c @@ -546,9 +546,13 @@ _cogl_journal_flush (void) state.vbo_offset = (char *)ctx->logged_vertices->data; /* Since the journal deals with emitting the modelview matrices manually - * we need to dirty our client side matrix stack cache... */ + * we need to dirty our client side modelview matrix stack cache... */ _cogl_current_matrix_state_dirty (); + /* And explicitly flush other matrix stacks... */ + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_state_flush (); + /* If we have transformed all our quads at log time then the whole journal * then we ensure no further model transform is applied by loading the * identity matrix here...*/ @@ -1460,7 +1464,7 @@ _cogl_texture_sliced_polygon (CoglTextureVertex *vertices, options.layer0_override_texture = gl_handle; _cogl_material_flush_gl_state (ctx->source_material, &options); - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) ); } @@ -1564,7 +1568,7 @@ _cogl_multitexture_unsliced_polygon (CoglTextureVertex *vertices, options.flags |= COGL_MATERIAL_FLUSH_SKIP_GL_COLOR; options.fallback_layers = fallback_layers; _cogl_material_flush_gl_state (ctx->source_material, &options); - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices)); } diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c index 4f3a51413..2dda3198f 100644 --- a/common/cogl-vertex-buffer.c +++ b/common/cogl-vertex-buffer.c @@ -1751,7 +1751,7 @@ cogl_vertex_buffer_draw (CoglHandle handle, buffer = _cogl_vertex_buffer_pointer_from_handle (handle); cogl_clip_ensure (); - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); enable_state_for_drawing_buffer (buffer); /* FIXME: flush cogl cache */ @@ -1888,7 +1888,7 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle, indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle); cogl_clip_ensure (); - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); enable_state_for_drawing_buffer (buffer); byte_offset = indices_offset * get_indices_type_size (indices->type); diff --git a/common/cogl.c b/common/cogl.c index a4d8feaec..e1796fb5d 100644 --- a/common/cogl.c +++ b/common/cogl.c @@ -324,7 +324,7 @@ set_clip_plane (GLint plane_num, _cogl_current_matrix_rotate (angle, 0.0f, 0.0f, 1.0f); _cogl_current_matrix_translate (-vertex_a[0], -vertex_a[1], -vertex_a[2]); - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); plane[0] = 0; plane[1] = -1.0; @@ -568,6 +568,7 @@ _cogl_setup_viewport (guint width, cogl_get_projection_matrix (&projection_matrix); z_camera = 0.5 * projection_matrix.xx; + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); _cogl_current_matrix_identity (); _cogl_current_matrix_translate (-0.5f, -0.5f, -z_camera); _cogl_current_matrix_scale (1.0f / width, -1.0f / height, 1.0f / width); @@ -706,7 +707,7 @@ cogl_disable_fog (void) void cogl_flush_gl_state (int flags) { - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); } #endif @@ -800,7 +801,7 @@ cogl_begin_gl (void) cogl_clip_ensure (); /* Flush any client side matrix state */ - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); /* Setup the state for the current material */ diff --git a/gl/cogl-context.h b/gl/cogl-context.h index 57facfa2f..b0a72eaf4 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -60,6 +60,7 @@ typedef struct /* Client-side matrix stack or NULL if none */ CoglMatrixMode matrix_mode; CoglMatrixStack *modelview_stack; + CoglMatrixStack *projection_stack; /* Cache of inverse projection matrix */ float inverse_projection[16]; diff --git a/gl/cogl-primitives.c b/gl/cogl-primitives.c index cb6671c08..bdc24f709 100644 --- a/gl/cogl-primitives.c +++ b/gl/cogl-primitives.c @@ -88,7 +88,7 @@ _cogl_path_stroke_nodes () options.disable_layers = (guint32)~0; _cogl_material_flush_gl_state (ctx->source_material, &options); - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); while (path_start < ctx->path_nodes->len) { @@ -177,7 +177,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, } ctx->n_texcoord_arrays_enabled = 0; - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); while (path_start < path_size) { @@ -226,7 +226,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, _cogl_current_matrix_push (); _cogl_current_matrix_identity (); - _cogl_current_matrix_state_flush (); + _cogl_flush_matrix_stacks (); glRectf (-1.0, -1.0, 1.0, 1.0); glRectf (-1.0, -1.0, 1.0, 1.0);