gboolean _cogl_matrix_stack_equal (CoglMatrixStack *stack0, CoglMatrixStack *stack1) { CoglMatrixState *state0 = _cogl_matrix_stack_top (stack0); CoglMatrixState *state1 = _cogl_matrix_stack_top (stack1); if (state0->is_identity != state1->is_identity) return FALSE; if (state0->is_identity) return TRUE; else return cogl_matrix_equal (&state0->matrix, &state1->matrix); }
void _cogl_matrix_stack_prepare_for_flush (CoglMatrixStack *stack, CoglMatrixMode mode, CoglMatrixStackFlushFunc callback, void *user_data) { CoglMatrixState *state; _COGL_GET_CONTEXT (ctx, NO_RETVAL); state = _cogl_matrix_stack_top (stack); /* Because Cogl defines texture coordinates to have a top left origin and * because offscreen framebuffers may be used for rendering to textures we * always render upside down to offscreen buffers. */ if (mode == COGL_MATRIX_PROJECTION && cogl_is_offscreen (_cogl_get_draw_buffer ())) { CoglMatrix flipped_projection; CoglMatrix *projection = state->is_identity ? &ctx->identity_matrix : &state->matrix; cogl_matrix_multiply (&flipped_projection, &ctx->y_flip_matrix, projection); callback (FALSE, &flipped_projection, user_data); } else callback (state->is_identity, state->is_identity ? &ctx->identity_matrix : &state->matrix, user_data); }
void _cogl_matrix_stack_pop (CoglMatrixStack *stack) { CoglMatrixState *state; state = _cogl_matrix_stack_top (stack); if (state->push_count > 0) { state->push_count -= 1; } else { if (stack->stack->len == 1) { g_warning ("Too many matrix pops"); return; } if (stack->flushed_state == state) { stack->flushed_state = NULL; } stack->age++; g_array_set_size (stack->stack, stack->stack->len - 1); } }
/* 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 * _cogl_matrix_stack_top_mutable (CoglMatrixStack *stack, gboolean initialize) { CoglMatrixState *state; CoglMatrixState *new_top; state = _cogl_matrix_stack_top (stack); if (state->push_count == 0) { if (state->is_identity && initialize) cogl_matrix_init_identity (&state->matrix); return state; } state->push_count -= 1; g_array_set_size (stack->stack, stack->stack->len + 1); new_top = &g_array_index (stack->stack, CoglMatrixState, stack->stack->len - 1); _cogl_matrix_state_init (new_top); if (initialize) { if (state->is_identity) cogl_matrix_init_identity (&new_top->matrix); else new_top->matrix = state->matrix; } return new_top; }
void _cogl_matrix_stack_push (CoglMatrixStack *stack) { CoglMatrixState *state; state = _cogl_matrix_stack_top (stack); /* we lazily create a new stack top if someone changes the matrix * while push_count > 0 */ state->push_count += 1; }
void _cogl_matrix_stack_get (CoglMatrixStack *stack, CoglMatrix *matrix) { CoglMatrixState *state; state = _cogl_matrix_stack_top (stack); /* 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; }
gboolean _cogl_matrix_stack_has_identity_flag (CoglMatrixStack *stack) { return _cogl_matrix_stack_top (stack)->is_identity; }
void _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, CoglMatrixMode mode) { CoglMatrixState *state; _COGL_GET_CONTEXT (ctx, NO_RETVAL); state = _cogl_matrix_stack_top (stack); #ifdef HAVE_COGL_GLES2 /* Under GLES2 we need to flush the matrices differently because they are stored in uniforms attached to the program instead of the global GL context state. At this point we can't be sure that the right program will be generated so instead we'll just store a reference to the matrix stack that is intended to be flushed and update the uniform once the program is ready. */ switch (mode) { case COGL_MATRIX_MODELVIEW: cogl_object_ref (stack); if (ctx->flushed_modelview_stack) cogl_object_unref (ctx->flushed_modelview_stack); ctx->flushed_modelview_stack = stack; break; case COGL_MATRIX_PROJECTION: cogl_object_ref (stack); if (ctx->flushed_projection_stack) cogl_object_unref (ctx->flushed_projection_stack); ctx->flushed_projection_stack = stack; break; case COGL_MATRIX_TEXTURE: /* This shouldn't happen because the texture matrices are handled by the GLSL pipeline backend */ g_assert_not_reached (); break; } #else /* HAVE_COGL_GLES2 */ if (stack->flushed_state == state) return; if (ctx->flushed_matrix_mode != mode) { GLenum gl_mode = 0; switch (mode) { case COGL_MATRIX_MODELVIEW: gl_mode = GL_MODELVIEW; break; case COGL_MATRIX_PROJECTION: gl_mode = GL_PROJECTION; break; case COGL_MATRIX_TEXTURE: gl_mode = GL_TEXTURE; break; } GE (glMatrixMode (gl_mode)); ctx->flushed_matrix_mode = mode; } _cogl_matrix_stack_prepare_for_flush (stack, mode, flush_to_fixed_api_gl, stack); #endif /* HAVE_COGL_GLES2 */ stack->flushed_state = state; }
void _cogl_matrix_stack_flush_to_gl_builtins (CoglContext *ctx, CoglMatrixStack *stack, CoglMatrixMode mode, gboolean disable_flip) { g_assert (ctx->driver == COGL_DRIVER_GL || ctx->driver == COGL_DRIVER_GLES1); #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) { gboolean needs_flip; CoglMatrixState *state; CoglMatrixStackCache *cache; state = _cogl_matrix_stack_top (stack); if (mode == COGL_MATRIX_PROJECTION) { /* Because Cogl defines texture coordinates to have a top left * origin and because offscreen framebuffers may be used for * rendering to textures we always render upside down to * offscreen buffers. Also for some backends we need to render * onscreen buffers upside-down too. */ if (disable_flip) needs_flip = FALSE; else needs_flip = cogl_is_offscreen (cogl_get_draw_framebuffer ()); cache = &ctx->builtin_flushed_projection; } else { needs_flip = FALSE; if (mode == COGL_MATRIX_MODELVIEW) cache = &ctx->builtin_flushed_modelview; else cache = NULL; } /* We don't need to do anything if the state is the same */ if (!cache || _cogl_matrix_stack_check_and_update_cache (stack, cache, needs_flip)) { gboolean is_identity = state->is_identity && !needs_flip; if (needs_flip) { CoglMatrix flipped_matrix; cogl_matrix_multiply (&flipped_matrix, &ctx->y_flip_matrix, state->is_identity ? &ctx->identity_matrix : &state->matrix); _cogl_matrix_stack_flush_matrix_to_gl_builtin (ctx, /* not identity */ FALSE, &flipped_matrix, mode); } else _cogl_matrix_stack_flush_matrix_to_gl_builtin (ctx, is_identity, &state->matrix, mode); } } #endif }