Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
    }
}
Ejemplo n.º 4
0
/* 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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
gboolean
_cogl_matrix_stack_has_identity_flag (CoglMatrixStack *stack)
{
  return _cogl_matrix_stack_top (stack)->is_identity;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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
}