diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index ac934394a..058551d77 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -103,6 +103,8 @@ cogl_sources_c = \
$(srcdir)/cogl-bitmap-pixbuf.c \
$(srcdir)/cogl-clip-stack.h \
$(srcdir)/cogl-clip-stack.c \
+ $(srcdir)/cogl-clip-state.h \
+ $(srcdir)/cogl-clip-state.c \
$(srcdir)/cogl-feature-private.h \
$(srcdir)/cogl-feature-private.c \
$(srcdir)/cogl-fixed.c \
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index 37c9d022f..83e95afe4 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -3,7 +3,7 @@
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
- * Copyright (C) 2007,2008,2009 Intel Corporation.
+ * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -40,8 +40,6 @@
#include "cogl-util.h"
#include "cogl-path-private.h"
-typedef struct _CoglClipStack CoglClipStack;
-
typedef struct _CoglClipStackEntry CoglClipStackEntry;
typedef struct _CoglClipStackEntryRect CoglClipStackEntryRect;
typedef struct _CoglClipStackEntryWindowRect CoglClipStackEntryWindowRect;
@@ -402,27 +400,16 @@ _cogl_clip_stack_push_entry (CoglClipStack *clip_stack,
}
void
-cogl_clip_push_window_rectangle (int x_offset,
- int y_offset,
- int width,
- int height)
+_cogl_clip_stack_push_window_rectangle (CoglClipStack *stack,
+ int x_offset,
+ int y_offset,
+ int width,
+ int height)
{
- CoglHandle framebuffer;
- CoglClipStackState *clip_state;
- CoglClipStack *stack;
CoglClipStackEntryWindowRect *entry;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- /* We don't log clip stack changes in the journal so we must flush
- * it before making modifications */
- _cogl_journal_flush ();
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- stack = clip_state->stacks->data;
-
entry = _cogl_clip_stack_push_entry (stack,
sizeof (CoglClipStackEntryWindowRect),
COGL_CLIP_STACK_WINDOW_RECT);
@@ -431,137 +418,18 @@ cogl_clip_push_window_rectangle (int x_offset,
entry->x1 = x_offset + width;
entry->y0 = y_offset;
entry->y1 = y_offset + height;
-
- clip_state->stack_dirty = TRUE;
}
-/* XXX: This is deprecated API */
void
-cogl_clip_push_window_rect (float x_offset,
- float y_offset,
- float width,
- float height)
-{
- cogl_clip_push_window_rectangle (x_offset, y_offset, width, height);
-}
-
-/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
- * to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with
- * (0,0) being top left. */
-#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \
- ( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) )
-/* Note: for Y we first flip all coordinates around the X axis while in
- * normalized device coodinates */
-#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \
- ( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) )
-
-/* Transform a homogeneous vertex position from model space to Cogl
- * window coordinates (with 0,0 being top left) */
-static void
-transform_point (CoglMatrix *matrix_mv,
- CoglMatrix *matrix_p,
- float *viewport,
- float *x,
- float *y)
-{
- float z = 0;
- float w = 1;
-
- /* Apply the modelview matrix transform */
- cogl_matrix_transform_point (matrix_mv, x, y, &z, &w);
-
- /* Apply the projection matrix transform */
- cogl_matrix_transform_point (matrix_p, x, y, &z, &w);
-
- /* Perform perspective division */
- *x /= w;
- *y /= w;
-
- /* Apply viewport transform */
- *x = VIEWPORT_TRANSFORM_X (*x, viewport[0], viewport[2]);
- *y = VIEWPORT_TRANSFORM_Y (*y, viewport[1], viewport[3]);
-}
-
-#undef VIEWPORT_SCALE_X
-#undef VIEWPORT_SCALE_Y
-
-/* Try to push a rectangle given in object coordinates as a rectangle in window
- * coordinates instead of object coordinates */
-gboolean
-try_pushing_rect_as_window_rect (float x_1,
- float y_1,
+_cogl_clip_stack_push_rectangle (CoglClipStack *stack,
+ float x_1,
+ float y_1,
float x_2,
- float y_2)
+ float y_2,
+ const CoglMatrix *modelview_matrix)
{
- CoglMatrix matrix;
- CoglMatrix matrix_p;
- float v[4];
-
- cogl_get_modelview_matrix (&matrix);
-
- /* If the modelview meets these constraints then a transformed rectangle
- * should still be a rectangle when it reaches screen coordinates.
- *
- * FIXME: we are are making certain assumptions about the projection
- * matrix a.t.m and should really be looking at the combined modelview
- * and projection matrix.
- * FIXME: we don't consider rotations that are a multiple of 90 degrees
- * which could be quite common.
- */
- if (matrix.xy != 0 || matrix.xz != 0 ||
- matrix.yx != 0 || matrix.yz != 0 ||
- matrix.zx != 0 || matrix.zy != 0)
- return FALSE;
-
- cogl_get_projection_matrix (&matrix_p);
- cogl_get_viewport (v);
-
- transform_point (&matrix, &matrix_p, v, &x_1, &y_1);
- transform_point (&matrix, &matrix_p, v, &x_2, &y_2);
-
- /* Consider that the modelview matrix may flip the rectangle
- * along the x or y axis... */
-#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
- if (x_1 > x_2)
- SWAP (x_1, x_2);
- if (y_1 > y_2)
- SWAP (y_1, y_2);
-#undef SWAP
-
- cogl_clip_push_window_rectangle (COGL_UTIL_NEARBYINT (x_1),
- COGL_UTIL_NEARBYINT (y_1),
- COGL_UTIL_NEARBYINT (x_2 - x_1),
- COGL_UTIL_NEARBYINT (y_2 - y_1));
- return TRUE;
-}
-
-void
-cogl_clip_push_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- CoglHandle framebuffer;
- CoglClipStackState *clip_state;
- CoglClipStack *stack;
CoglClipStackEntryRect *entry;
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* We don't log clip stack changes in the journal so we must flush
- * it before making modifications */
- _cogl_journal_flush ();
-
- /* Try and catch window space rectangles so we can redirect to
- * cogl_clip_push_window_rect which will use scissoring. */
- if (try_pushing_rect_as_window_rect (x_1, y_1, x_2, y_2))
- return;
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- stack = clip_state->stacks->data;
-
/* Make a new entry */
entry = _cogl_clip_stack_push_entry (stack,
sizeof (CoglClipStackEntryRect),
@@ -572,60 +440,23 @@ cogl_clip_push_rectangle (float x_1,
entry->x1 = x_2;
entry->y1 = y_2;
- cogl_get_modelview_matrix (&entry->matrix);
-
- clip_state->stack_dirty = TRUE;
-}
-
-/* XXX: Deprecated API */
-void
-cogl_clip_push (float x_offset,
- float y_offset,
- float width,
- float height)
-{
- cogl_clip_push_rectangle (x_offset,
- y_offset,
- x_offset + width,
- y_offset + height);
+ entry->matrix = *modelview_matrix;
}
void
-cogl_clip_push_from_path_preserve (void)
+_cogl_clip_stack_push_from_path (CoglClipStack *stack,
+ CoglHandle path,
+ const CoglMatrix *modelview_matrix)
{
- CoglHandle framebuffer;
- CoglClipStackState *clip_state;
- CoglClipStack *stack;
CoglClipStackEntryPath *entry;
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* We don't log clip stack changes in the journal so we must flush
- * it before making modifications */
- _cogl_journal_flush ();
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- stack = clip_state->stacks->data;
-
entry = _cogl_clip_stack_push_entry (stack,
sizeof (CoglClipStackEntryPath),
COGL_CLIP_STACK_PATH);
- entry->path = cogl_path_copy (cogl_path_get ());
+ entry->path = cogl_path_copy (path);
- cogl_get_modelview_matrix (&entry->matrix);
-
- clip_state->stack_dirty = TRUE;
-}
-
-void
-cogl_clip_push_from_path (void)
-{
- cogl_clip_push_from_path_preserve ();
-
- cogl_path_new ();
+ entry->matrix = *modelview_matrix;
}
static void
@@ -660,18 +491,11 @@ _cogl_clip_stack_entry_unref (CoglClipStackEntry *entry)
}
}
-static void
-_cogl_clip_pop_real (CoglClipStackState *clip_state)
+void
+_cogl_clip_stack_pop (CoglClipStack *stack)
{
- CoglClipStack *stack;
CoglClipStackEntry *entry;
- /* We don't log clip stack changes in the journal so we must flush
- * it before making modifications */
- _cogl_journal_flush ();
-
- stack = clip_state->stacks->data;
-
g_return_if_fail (stack->stack_top != NULL);
/* To pop we are moving the top of the stack to the old top's parent
@@ -687,28 +511,12 @@ _cogl_clip_pop_real (CoglClipStackState *clip_state)
if (stack->stack_top)
stack->stack_top->ref_count++;
_cogl_clip_stack_entry_unref (entry);
-
- clip_state->stack_dirty = TRUE;
}
void
-cogl_clip_pop (void)
+_cogl_clip_stack_flush (CoglClipStack *stack,
+ gboolean *stencil_used_p)
{
- CoglHandle framebuffer;
- CoglClipStackState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- _cogl_clip_pop_real (clip_state);
-}
-
-void
-_cogl_flush_clip_state (CoglClipStackState *clip_state)
-{
- CoglClipStack *stack;
int has_clip_planes;
gboolean using_clip_planes = FALSE;
gboolean using_stencil_buffer = FALSE;
@@ -720,26 +528,8 @@ _cogl_flush_clip_state (CoglClipStackState *clip_state)
_cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ());
CoglClipStackEntry *entry;
- if (!clip_state->stack_dirty)
- return;
-
- /* The current primitive journal does not support tracking changes to the
- * clip stack... */
- _cogl_journal_flush ();
-
- /* XXX: the handling of clipping is quite complex. It may involve use of
- * the Cogl Journal or other Cogl APIs which may end up recursively
- * wanting to ensure the clip state is flushed. We need to ensure we
- * don't recurse infinitely...
- */
- clip_state->stack_dirty = FALSE;
-
has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
- stack = clip_state->stacks->data;
-
- clip_state->stencil_used = FALSE;
-
disable_clip_planes ();
disable_stencil_buffer ();
GE (glDisable (GL_SCISSOR_TEST));
@@ -854,112 +644,27 @@ _cogl_flush_clip_state (CoglClipStackState *clip_state)
scissor_y1 - scissor_y0));
}
- clip_state->stencil_used = using_stencil_buffer;
+ *stencil_used_p = using_stencil_buffer;
}
-/* XXX: This should never have been made public API! */
-void
-cogl_clip_ensure (void)
-{
- CoglClipStackState *clip_state;
-
- clip_state = _cogl_framebuffer_get_clip_state (_cogl_get_framebuffer ());
- _cogl_flush_clip_state (clip_state);
-}
-
-static void
-_cogl_clip_stack_save_real (CoglClipStackState *clip_state)
+CoglClipStack *
+_cogl_clip_stack_new (void)
{
CoglClipStack *stack;
- /* We don't log clip stack changes in the journal so we must flush
- * it before making modifications */
- _cogl_journal_flush ();
-
stack = g_slice_new (CoglClipStack);
stack->stack_top = NULL;
- clip_state->stacks = g_slist_prepend (clip_state->stacks, stack);
- clip_state->stack_dirty = TRUE;
+ return stack;
}
void
-cogl_clip_stack_save (void)
+_cogl_clip_stack_free (CoglClipStack *stack)
{
- CoglHandle framebuffer;
- CoglClipStackState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- _cogl_clip_stack_save_real (clip_state);
-}
-
-static void
-_cogl_clip_stack_restore_real (CoglClipStackState *clip_state)
-{
- CoglClipStack *stack;
-
- g_return_if_fail (clip_state->stacks != NULL);
-
- /* We don't log clip stack changes in the journal so we must flush
- * it before making modifications */
- _cogl_journal_flush ();
-
- stack = clip_state->stacks->data;
-
- /* Free the stack. We only need to unref the top node and this
+ /* We only need to unref the top node and this
should end up freeing all of the parents if need be */
if (stack->stack_top)
_cogl_clip_stack_entry_unref (stack->stack_top);
- /* Revert to an old stack */
g_slice_free (CoglClipStack, stack);
- clip_state->stacks = g_slist_delete_link (clip_state->stacks,
- clip_state->stacks);
-
- clip_state->stack_dirty = TRUE;
}
-
-void
-cogl_clip_stack_restore (void)
-{
- CoglHandle framebuffer;
- CoglClipStackState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- _cogl_clip_stack_restore_real (clip_state);
-}
-
-void
-_cogl_clip_stack_state_init (CoglClipStackState *clip_state)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- clip_state->stacks = NULL;
- clip_state->stack_dirty = TRUE;
-
- /* Add an intial stack */
- _cogl_clip_stack_save_real (clip_state);
-}
-
-void
-_cogl_clip_stack_state_destroy (CoglClipStackState *clip_state)
-{
- /* Destroy all of the stacks */
- while (clip_state->stacks)
- _cogl_clip_stack_restore_real (clip_state);
-}
-
-void
-_cogl_clip_stack_state_dirty (CoglClipStackState *clip_state)
-{
- clip_state->stack_dirty = TRUE;
-}
-
diff --git a/cogl/cogl-clip-stack.h b/cogl/cogl-clip-stack.h
index 43a4105c9..508cea9db 100644
--- a/cogl/cogl-clip-stack.h
+++ b/cogl/cogl-clip-stack.h
@@ -3,7 +3,7 @@
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
- * Copyright (C) 2007,2008,2009 Intel Corporation.
+ * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,27 +24,38 @@
#ifndef __COGL_CLIP_STACK_H
#define __COGL_CLIP_STACK_H
-typedef struct _CoglClipStackState CoglClipStackState;
+typedef struct _CoglClipStack CoglClipStack;
-struct _CoglClipStackState
-{
- /* Stack of stacks */
- GSList *stacks;
-
- gboolean stack_dirty;
- gboolean stencil_used;
-};
+CoglClipStack *
+_cogl_clip_stack_new (void);
void
-_cogl_clip_stack_state_init (CoglClipStackState *state);
+_cogl_clip_stack_free (CoglClipStack *stack);
void
-_cogl_clip_stack_state_destroy (CoglClipStackState *state);
+_cogl_clip_stack_push_window_rectangle (CoglClipStack *stack,
+ int x_offset,
+ int y_offset,
+ int width,
+ int height);
void
-_cogl_clip_stack_state_dirty (CoglClipStackState *state);
+_cogl_clip_stack_push_rectangle (CoglClipStack *stack,
+ float x_1,
+ float y_1,
+ float x_2,
+ float y_2,
+ const CoglMatrix *modelview_matrix);
void
-_cogl_flush_clip_state (CoglClipStackState *clip_state);
+_cogl_clip_stack_push_from_path (CoglClipStack *stack,
+ CoglHandle path,
+ const CoglMatrix *modelview_matrix);
+void
+_cogl_clip_stack_pop (CoglClipStack *stack);
+
+void
+_cogl_clip_stack_flush (CoglClipStack *stack,
+ gboolean *stencil_used_p);
#endif /* __COGL_CLIP_STACK_H */
diff --git a/cogl/cogl-clip-state.c b/cogl/cogl-clip-state.c
new file mode 100644
index 000000000..c5b7442a6
--- /dev/null
+++ b/cogl/cogl-clip-state.c
@@ -0,0 +1,405 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009,2010 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 .
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+
+#include
+
+#include "cogl.h"
+#include "cogl-clip-stack.h"
+#include "cogl-clip-state.h"
+#include "cogl-context.h"
+#include "cogl-internal.h"
+#include "cogl-framebuffer-private.h"
+#include "cogl-journal-private.h"
+#include "cogl-util.h"
+
+void
+cogl_clip_push_window_rectangle (int x_offset,
+ int y_offset,
+ int width,
+ int height)
+{
+ CoglHandle framebuffer;
+ CoglClipState *clip_state;
+ CoglClipStack *stack;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ framebuffer = _cogl_get_framebuffer ();
+ clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ stack = clip_state->stacks->data;
+
+ _cogl_clip_stack_push_window_rectangle (stack, x_offset, y_offset,
+ width, height);
+
+ clip_state->stack_dirty = TRUE;
+}
+
+/* XXX: This is deprecated API */
+void
+cogl_clip_push_window_rect (float x_offset,
+ float y_offset,
+ float width,
+ float height)
+{
+ cogl_clip_push_window_rectangle (x_offset, y_offset, width, height);
+}
+
+/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
+ * to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with
+ * (0,0) being top left. */
+#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \
+ ( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) )
+/* Note: for Y we first flip all coordinates around the X axis while in
+ * normalized device coodinates */
+#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \
+ ( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) )
+
+/* Transform a homogeneous vertex position from model space to Cogl
+ * window coordinates (with 0,0 being top left) */
+static void
+transform_point (CoglMatrix *matrix_mv,
+ CoglMatrix *matrix_p,
+ float *viewport,
+ float *x,
+ float *y)
+{
+ float z = 0;
+ float w = 1;
+
+ /* Apply the modelview matrix transform */
+ cogl_matrix_transform_point (matrix_mv, x, y, &z, &w);
+
+ /* Apply the projection matrix transform */
+ cogl_matrix_transform_point (matrix_p, x, y, &z, &w);
+
+ /* Perform perspective division */
+ *x /= w;
+ *y /= w;
+
+ /* Apply viewport transform */
+ *x = VIEWPORT_TRANSFORM_X (*x, viewport[0], viewport[2]);
+ *y = VIEWPORT_TRANSFORM_Y (*y, viewport[1], viewport[3]);
+}
+
+#undef VIEWPORT_SCALE_X
+#undef VIEWPORT_SCALE_Y
+
+/* Try to push a rectangle given in object coordinates as a rectangle in window
+ * coordinates instead of object coordinates */
+gboolean
+try_pushing_rect_as_window_rect (float x_1,
+ float y_1,
+ float x_2,
+ float y_2)
+{
+ CoglMatrix matrix;
+ CoglMatrix matrix_p;
+ float v[4];
+
+ cogl_get_modelview_matrix (&matrix);
+
+ /* If the modelview meets these constraints then a transformed rectangle
+ * should still be a rectangle when it reaches screen coordinates.
+ *
+ * FIXME: we are are making certain assumptions about the projection
+ * matrix a.t.m and should really be looking at the combined modelview
+ * and projection matrix.
+ * FIXME: we don't consider rotations that are a multiple of 90 degrees
+ * which could be quite common.
+ */
+ if (matrix.xy != 0 || matrix.xz != 0 ||
+ matrix.yx != 0 || matrix.yz != 0 ||
+ matrix.zx != 0 || matrix.zy != 0)
+ return FALSE;
+
+ cogl_get_projection_matrix (&matrix_p);
+ cogl_get_viewport (v);
+
+ transform_point (&matrix, &matrix_p, v, &x_1, &y_1);
+ transform_point (&matrix, &matrix_p, v, &x_2, &y_2);
+
+ /* Consider that the modelview matrix may flip the rectangle
+ * along the x or y axis... */
+#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
+ if (x_1 > x_2)
+ SWAP (x_1, x_2);
+ if (y_1 > y_2)
+ SWAP (y_1, y_2);
+#undef SWAP
+
+ cogl_clip_push_window_rectangle (COGL_UTIL_NEARBYINT (x_1),
+ COGL_UTIL_NEARBYINT (y_1),
+ COGL_UTIL_NEARBYINT (x_2 - x_1),
+ COGL_UTIL_NEARBYINT (y_2 - y_1));
+ return TRUE;
+}
+
+void
+cogl_clip_push_rectangle (float x_1,
+ float y_1,
+ float x_2,
+ float y_2)
+{
+ CoglHandle framebuffer;
+ CoglClipState *clip_state;
+ CoglClipStack *stack;
+ CoglMatrix modelview_matrix;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ /* Try and catch window space rectangles so we can redirect to
+ * cogl_clip_push_window_rect which will use scissoring. */
+ if (try_pushing_rect_as_window_rect (x_1, y_1, x_2, y_2))
+ return;
+
+ framebuffer = _cogl_get_framebuffer ();
+ clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ stack = clip_state->stacks->data;
+
+ cogl_get_modelview_matrix (&modelview_matrix);
+
+ _cogl_clip_stack_push_rectangle (stack, x_1, y_1, x_2, y_2,
+ &modelview_matrix);
+
+ clip_state->stack_dirty = TRUE;
+}
+
+/* XXX: Deprecated API */
+void
+cogl_clip_push (float x_offset,
+ float y_offset,
+ float width,
+ float height)
+{
+ cogl_clip_push_rectangle (x_offset,
+ y_offset,
+ x_offset + width,
+ y_offset + height);
+}
+
+void
+cogl_clip_push_from_path_preserve (void)
+{
+ CoglHandle framebuffer;
+ CoglClipState *clip_state;
+ CoglClipStack *stack;
+ CoglMatrix modelview_matrix;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ framebuffer = _cogl_get_framebuffer ();
+ clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ stack = clip_state->stacks->data;
+
+ cogl_get_modelview_matrix (&modelview_matrix);
+
+ _cogl_clip_stack_push_from_path (stack, cogl_path_get (),
+ &modelview_matrix);
+
+ clip_state->stack_dirty = TRUE;
+}
+
+void
+cogl_clip_push_from_path (void)
+{
+ cogl_clip_push_from_path_preserve ();
+
+ cogl_path_new ();
+}
+
+static void
+_cogl_clip_pop_real (CoglClipState *clip_state)
+{
+ CoglClipStack *stack;
+
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ stack = clip_state->stacks->data;
+
+ _cogl_clip_stack_pop (stack);
+
+ clip_state->stack_dirty = TRUE;
+}
+
+void
+cogl_clip_pop (void)
+{
+ CoglHandle framebuffer;
+ CoglClipState *clip_state;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ framebuffer = _cogl_get_framebuffer ();
+ clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ _cogl_clip_pop_real (clip_state);
+}
+
+void
+_cogl_clip_state_flush (CoglClipState *clip_state)
+{
+ CoglClipStack *stack;
+
+ if (!clip_state->stack_dirty)
+ return;
+
+ /* The current primitive journal does not support tracking changes to the
+ * clip stack... */
+ _cogl_journal_flush ();
+
+ /* XXX: the handling of clipping is quite complex. It may involve use of
+ * the Cogl Journal or other Cogl APIs which may end up recursively
+ * wanting to ensure the clip state is flushed. We need to ensure we
+ * don't recurse infinitely...
+ */
+ clip_state->stack_dirty = FALSE;
+
+ stack = clip_state->stacks->data;
+
+ _cogl_clip_stack_flush (stack, &clip_state->stencil_used);
+}
+
+/* XXX: This should never have been made public API! */
+void
+cogl_clip_ensure (void)
+{
+ CoglClipState *clip_state;
+
+ clip_state = _cogl_framebuffer_get_clip_state (_cogl_get_framebuffer ());
+ _cogl_clip_state_flush (clip_state);
+}
+
+static void
+_cogl_clip_stack_save_real (CoglClipState *clip_state)
+{
+ CoglClipStack *stack;
+
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ stack = _cogl_clip_stack_new ();
+
+ clip_state->stacks = g_slist_prepend (clip_state->stacks, stack);
+ clip_state->stack_dirty = TRUE;
+}
+
+void
+cogl_clip_stack_save (void)
+{
+ CoglHandle framebuffer;
+ CoglClipState *clip_state;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ framebuffer = _cogl_get_framebuffer ();
+ clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ _cogl_clip_stack_save_real (clip_state);
+}
+
+static void
+_cogl_clip_stack_restore_real (CoglClipState *clip_state)
+{
+ CoglClipStack *stack;
+
+ g_return_if_fail (clip_state->stacks != NULL);
+
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ stack = clip_state->stacks->data;
+
+ _cogl_clip_stack_free (stack);
+
+ /* Revert to an old stack */
+ clip_state->stacks = g_slist_delete_link (clip_state->stacks,
+ clip_state->stacks);
+
+ clip_state->stack_dirty = TRUE;
+}
+
+void
+cogl_clip_stack_restore (void)
+{
+ CoglHandle framebuffer;
+ CoglClipState *clip_state;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ framebuffer = _cogl_get_framebuffer ();
+ clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ _cogl_clip_stack_restore_real (clip_state);
+}
+
+void
+_cogl_clip_state_init (CoglClipState *clip_state)
+{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ clip_state->stacks = NULL;
+ clip_state->stack_dirty = TRUE;
+
+ /* Add an intial stack */
+ _cogl_clip_stack_save_real (clip_state);
+}
+
+void
+_cogl_clip_state_destroy (CoglClipState *clip_state)
+{
+ /* Destroy all of the stacks */
+ while (clip_state->stacks)
+ _cogl_clip_stack_restore_real (clip_state);
+}
+
+void
+_cogl_clip_state_dirty (CoglClipState *clip_state)
+{
+ clip_state->stack_dirty = TRUE;
+}
diff --git a/cogl/cogl-clip-state.h b/cogl/cogl-clip-state.h
new file mode 100644
index 000000000..0f292dd55
--- /dev/null
+++ b/cogl/cogl-clip-state.h
@@ -0,0 +1,50 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009,2010 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 .
+ *
+ *
+ */
+
+#ifndef __COGL_CLIP_STATE_H
+#define __COGL_CLIP_STATE_H
+
+typedef struct _CoglClipState CoglClipState;
+
+struct _CoglClipState
+{
+ /* Stack of CoglClipStacks */
+ GSList *stacks;
+
+ gboolean stack_dirty;
+ gboolean stencil_used;
+};
+
+void
+_cogl_clip_state_init (CoglClipState *state);
+
+void
+_cogl_clip_state_destroy (CoglClipState *state);
+
+void
+_cogl_clip_state_dirty (CoglClipState *state);
+
+void
+_cogl_clip_state_flush (CoglClipState *clip_state);
+
+#endif /* __COGL_CLIP_STATE_H */
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index d5d19a5fc..71edfa046 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -26,7 +26,7 @@
#include "cogl-handle.h"
#include "cogl-matrix-stack.h"
-#include "cogl-clip-stack.h"
+#include "cogl-clip-state.h"
typedef enum _CoglFramebufferType {
COGL_FRAMEBUFFER_TYPE_ONSCREEN,
@@ -47,7 +47,7 @@ typedef struct
int viewport_width;
int viewport_height;
- CoglClipStackState clip_state;
+ CoglClipState clip_state;
} CoglFramebuffer;
#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X))
@@ -75,7 +75,7 @@ int
_cogl_framebuffer_get_width (CoglHandle handle);
int
_cogl_framebuffer_get_height (CoglHandle handle);
-CoglClipStackState *
+CoglClipState *
_cogl_framebuffer_get_clip_state (CoglHandle handle);
void
_cogl_framebuffer_set_viewport (CoglHandle handle,
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 3b00a8551..082abf5f6 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -131,13 +131,13 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
framebuffer->projection_stack = _cogl_matrix_stack_new ();
/* Initialise the clip stack */
- _cogl_clip_stack_state_init (&framebuffer->clip_state);
+ _cogl_clip_state_init (&framebuffer->clip_state);
}
void
_cogl_framebuffer_free (CoglFramebuffer *framebuffer)
{
- _cogl_clip_stack_state_destroy (&framebuffer->clip_state);
+ _cogl_clip_state_destroy (&framebuffer->clip_state);
_cogl_matrix_stack_destroy (framebuffer->modelview_stack);
framebuffer->modelview_stack = NULL;
@@ -160,7 +160,7 @@ _cogl_framebuffer_get_height (CoglHandle handle)
return framebuffer->height;
}
-CoglClipStackState *
+CoglClipState *
_cogl_framebuffer_get_clip_state (CoglHandle handle)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (handle);
@@ -551,7 +551,7 @@ _cogl_set_framebuffer_real (CoglFramebuffer *framebuffer)
* we flush */
_cogl_matrix_stack_dirty (framebuffer->modelview_stack);
_cogl_matrix_stack_dirty (framebuffer->projection_stack);
- _cogl_clip_stack_state_dirty (&framebuffer->clip_state);
+ _cogl_clip_state_dirty (&framebuffer->clip_state);
}
void
@@ -697,7 +697,7 @@ _cogl_framebuffer_flush_state (CoglHandle handle,
/* XXX: Flushing clip state may trash the modelview and projection
* matrices so we must do it before flushing the matrices...
*/
- _cogl_flush_clip_state (&framebuffer->clip_state);
+ _cogl_clip_state_flush (&framebuffer->clip_state);
if (!(flags & COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW))
_cogl_matrix_stack_flush_to_gl (framebuffer->modelview_stack,
diff --git a/cogl/cogl-path.c b/cogl/cogl-path.c
index 1a7555859..2e1481db6 100644
--- a/cogl/cogl-path.c
+++ b/cogl/cogl-path.c
@@ -563,7 +563,7 @@ _cogl_path_fill_nodes (void)
cogl_features_available (COGL_FEATURE_STENCIL_BUFFER))
{
CoglHandle framebuffer;
- CoglClipStackState *clip_state;
+ CoglClipState *clip_state;
_cogl_journal_flush ();
@@ -586,7 +586,7 @@ _cogl_path_fill_nodes (void)
* we call cogl_flush() to emtpy the journal.
*/
cogl_flush ();
- _cogl_clip_stack_state_dirty (clip_state);
+ _cogl_clip_state_dirty (clip_state);
}
else
{
diff --git a/cogl/cogl.c b/cogl/cogl.c
index 60761af0a..ad2e64eb3 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -1043,7 +1043,7 @@ cogl_set_projection_matrix (CoglMatrix *matrix)
_COGL_MATRIX_DEBUG_PRINT (matrix);
}
-CoglClipStackState *
+CoglClipState *
_cogl_get_clip_state (void)
{
CoglHandle framebuffer;