cogl: Implement retained clip stacks

This adds three new internal API functions which can be used to retain
the clip stack state and restore it later:

 _cogl_get_clip_stack
 _cogl_set_clip_stack
 _cogl_clip_stack_copy

The functions are currently internal and not yet used but we may want
to make them public in future to replace the cogl_clip_stack_save()
and cogl_clip_stack_restore() APIs.

The get function just returns the handle to the clip stack at the top
of the stack of stacks and the set function just replaces it.

The copy function makes a cheap copy of an existing stack by taking a
reference to the top stack entry. This ends up working like a deep
copy because there is no way to modify entries of a stack but it
doesn't actually copy the data.
This commit is contained in:
Neil Roberts 2010-04-15 10:58:28 +01:00
parent 3a58bc440b
commit 708bbc72e1
4 changed files with 107 additions and 0 deletions

View File

@ -682,3 +682,29 @@ _cogl_clip_stack_free (CoglClipStack *stack)
g_slice_free (CoglClipStack, stack);
}
CoglHandle
_cogl_clip_stack_copy (CoglHandle handle)
{
CoglHandle new_handle;
CoglClipStack *new_stack, *old_stack;
if (!cogl_is_clip_stack (handle))
return COGL_INVALID_HANDLE;
old_stack = COGL_CLIP_STACK (handle);
new_handle = _cogl_clip_stack_new ();
new_stack = COGL_CLIP_STACK (new_handle);
/* We can copy the stack by just referencing the other stack's
data. There's no need to implement copy-on-write because the
entries of the stack can't be modified. If the other stack pops
some entries off they will still be kept alive because this stack
holds a reference. */
new_stack->stack_top = old_stack->stack_top;
if (new_stack->stack_top)
new_stack->stack_top->ref_count++;
return new_handle;
}

View File

@ -53,4 +53,23 @@ void
_cogl_clip_stack_flush (CoglHandle handle,
gboolean *stencil_used_p);
/* TODO: we may want to make this function public because it can be
* used to implement a better API than cogl_clip_stack_save() and
* cogl_clip_stack_restore().
*/
/*
* _cogl_clip_stack_copy:
* @handle: A handle to a clip stack
*
* Creates a copy of the given clip stack and returns a new handle to
* it. The data from the original stack is shared with the new stack
* so making copies is relatively cheap. Modifying the original stack
* does not affect the new stack.
*
* Return value: a new clip stack with the same data as @handle
*/
CoglHandle
_cogl_clip_stack_copy (CoglHandle handle);
#endif /* __COGL_CLIP_STACK_H */

View File

@ -403,3 +403,37 @@ _cogl_clip_state_dirty (CoglClipState *clip_state)
{
clip_state->stack_dirty = TRUE;
}
CoglHandle
_cogl_get_clip_stack (void)
{
CoglHandle framebuffer;
CoglClipState *clip_state;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
framebuffer = _cogl_get_framebuffer ();
clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
return clip_state->stacks->data;
}
void
_cogl_set_clip_stack (CoglHandle handle)
{
CoglHandle framebuffer;
CoglClipState *clip_state;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (handle == COGL_INVALID_HANDLE)
return;
framebuffer = _cogl_get_framebuffer ();
clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
/* Replace the top of the stack of stacks */
cogl_handle_ref (handle);
cogl_handle_unref (clip_state->stacks->data);
clip_state->stacks->data = handle;
}

View File

@ -47,4 +47,32 @@ _cogl_clip_state_dirty (CoglClipState *state);
void
_cogl_clip_state_flush (CoglClipState *clip_state);
/* TODO: we may want to make these two functions public because they
* can be used to implement a better API than cogl_clip_stack_save()
* and cogl_clip_stack_restore().
*/
/*
* _cogl_get_clip_stack:
*
* Gets a handle to the current clip stack. This can be used to later
* return to the same clip stack state with _cogl_set_clip_stack(). A
* reference is not taken on the stack so if you want to keep it you
* should call cogl_handle_ref() or _cogl_clip_stack_copy().
*
* Return value: a handle to the current clip stack.
*/
CoglHandle
_cogl_get_clip_stack (void);
/*
* _cogl_set_clip_stack:
* @handle: a handle to the replacement clip stack
*
* Replaces the current clip stack with @handle.
*
* Return value: a handle to the current clip stack.
*/
void
_cogl_set_clip_stack (CoglHandle handle);
#endif /* __COGL_CLIP_STATE_H */