summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2011-10-01 17:55:41 +0100
committerRobert Bragg <robert@linux.intel.com>2011-10-01 18:50:29 +0100
commit80de4f5f905e5aa6cb5d2fc29122a351b53755ec (patch)
treef22c67810978dfeb42ed65991f857365f37326aa
parentf3b04b0f243d5be1fe2708b0acad77367c956c14 (diff)
downloadcogl-80de4f5f905e5aa6cb5d2fc29122a351b53755ec.tar.gz
clip-stack: Move path flushing code to cogl-clip-stack.c
The code that adds the silhouette of a path to the stencil buffer was living in cogl2-path.c which seemed out of place when the bulk of the work really related more to how the stencil buffer is managed and basically only one line (a call to _cogl_path_fill_nodes) really related to the path code directly. This moves the code into cogl-clip-stack.c alone with similar code that can add rectangle masks to the stencil buffer.
-rw-r--r--cogl/cogl-clip-stack.c116
-rw-r--r--cogl/cogl-path-private.h3
-rw-r--r--cogl/cogl2-path.c111
3 files changed, 117 insertions, 113 deletions
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index 004445a2..c01a74c0 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -42,6 +42,7 @@
#include "cogl-matrix-private.h"
#include "cogl-primitives-private.h"
#include "cogl-private.h"
+#include "cogl-pipeline-opengl-private.h"
#ifndef GL_CLIP_PLANE0
#define GL_CLIP_PLANE0 0x3000
@@ -273,6 +274,114 @@ add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
cogl_pop_source ();
}
+void
+add_stencil_clip_path (CoglFramebuffer *framebuffer,
+ CoglPath *path,
+ gboolean merge,
+ gboolean need_clear)
+{
+ CoglPathData *data = path->data;
+ CoglMatrixStack *modelview_stack =
+ _cogl_framebuffer_get_modelview_stack (framebuffer);
+ CoglMatrixStack *projection_stack =
+ _cogl_framebuffer_get_projection_stack (framebuffer);
+ CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+
+ /* This can be called from the clip stack code which doesn't flush
+ the matrix stacks between calls so we need to ensure they're
+ flushed now */
+ _cogl_matrix_stack_flush_to_gl (modelview_stack,
+ COGL_MATRIX_MODELVIEW);
+ _cogl_matrix_stack_flush_to_gl (projection_stack,
+ COGL_MATRIX_PROJECTION);
+
+ /* Just setup a simple pipeline that doesn't use texturing... */
+ _cogl_push_source (ctx->stencil_pipeline, FALSE);
+
+ _cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, FALSE, 0);
+
+ GE( ctx, glEnable (GL_STENCIL_TEST) );
+
+ GE( ctx, glColorMask (FALSE, FALSE, FALSE, FALSE) );
+ GE( ctx, glDepthMask (FALSE) );
+
+ if (merge)
+ {
+ GE (ctx, glStencilMask (2));
+ GE (ctx, glStencilFunc (GL_LEQUAL, 0x2, 0x6));
+ }
+ else
+ {
+ /* If we're not using the stencil buffer for clipping then we
+ don't need to clear the whole stencil buffer, just the area
+ that will be drawn */
+ if (need_clear)
+ /* If this is being called from the clip stack code then it
+ will have set up a scissor for the minimum bounding box of
+ all of the clips. That box will likely mean that this
+ _cogl_clear won't need to clear the entire
+ buffer. _cogl_framebuffer_clear_without_flush4f is used instead
+ of cogl_clear because it won't try to flush the journal */
+ _cogl_framebuffer_clear_without_flush4f (framebuffer,
+ COGL_BUFFER_BIT_STENCIL,
+ 0, 0, 0, 0);
+ else
+ {
+ /* Just clear the bounding box */
+ GE( ctx, glStencilMask (~(GLuint) 0) );
+ GE( ctx, glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) );
+ _cogl_rectangle_immediate (data->path_nodes_min.x,
+ data->path_nodes_min.y,
+ data->path_nodes_max.x,
+ data->path_nodes_max.y);
+ }
+ GE (ctx, glStencilMask (1));
+ GE (ctx, glStencilFunc (GL_LEQUAL, 0x1, 0x3));
+ }
+
+ GE (ctx, glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT));
+
+ if (path->data->path_nodes->len >= 3)
+ _cogl_path_fill_nodes (path);
+
+ if (merge)
+ {
+ /* Now we have the new stencil buffer in bit 1 and the old
+ stencil buffer in bit 0 so we need to intersect them */
+ GE (ctx, glStencilMask (3));
+ GE (ctx, glStencilFunc (GL_NEVER, 0x2, 0x3));
+ GE (ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR));
+ /* Decrement all of the bits twice so that only pixels where the
+ value is 3 will remain */
+
+ _cogl_matrix_stack_push (projection_stack);
+ _cogl_matrix_stack_load_identity (projection_stack);
+ _cogl_matrix_stack_flush_to_gl (projection_stack,
+ COGL_MATRIX_PROJECTION);
+
+ _cogl_matrix_stack_push (modelview_stack);
+ _cogl_matrix_stack_load_identity (modelview_stack);
+ _cogl_matrix_stack_flush_to_gl (modelview_stack,
+ COGL_MATRIX_MODELVIEW);
+
+ _cogl_rectangle_immediate (-1.0, -1.0, 1.0, 1.0);
+ _cogl_rectangle_immediate (-1.0, -1.0, 1.0, 1.0);
+
+ _cogl_matrix_stack_pop (modelview_stack);
+ _cogl_matrix_stack_pop (projection_stack);
+ }
+
+ GE (ctx, glStencilMask (~(GLuint) 0));
+ GE (ctx, glDepthMask (TRUE));
+ GE (ctx, glColorMask (TRUE, TRUE, TRUE, TRUE));
+
+ GE (ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1));
+ GE (ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP));
+
+ /* restore the original pipeline */
+ cogl_pop_source ();
+}
+
static void
disable_stencil_buffer (void)
{
@@ -689,9 +798,10 @@ _cogl_clip_stack_flush (CoglClipStack *stack,
_cogl_matrix_stack_push (modelview_stack);
_cogl_matrix_stack_set (modelview_stack, &path_entry->matrix);
- _cogl_add_path_to_stencil_buffer (path_entry->path,
- using_stencil_buffer,
- TRUE);
+ add_stencil_clip_path (framebuffer,
+ path_entry->path,
+ using_stencil_buffer,
+ TRUE);
_cogl_matrix_stack_pop (modelview_stack);
diff --git a/cogl/cogl-path-private.h b/cogl/cogl-path-private.h
index e85bf3ab..bcdca49a 100644
--- a/cogl/cogl-path-private.h
+++ b/cogl/cogl-path-private.h
@@ -112,4 +112,7 @@ _cogl_path_get_bounds (CoglPath *path,
gboolean
_cogl_path_is_rectangle (CoglPath *path);
+void
+_cogl_path_fill_nodes (CoglPath *path);
+
#endif /* __COGL_PATH_PRIVATE_H */
diff --git a/cogl/cogl2-path.c b/cogl/cogl2-path.c
index c2c478e3..e3143a08 100644
--- a/cogl/cogl2-path.c
+++ b/cogl/cogl2-path.c
@@ -314,7 +314,7 @@ validate_layer_cb (CoglPipelineLayer *layer, void *user_data)
return !*needs_fallback;
}
-static void
+void
_cogl_path_fill_nodes (CoglPath *path)
{
gboolean needs_fallback = FALSE;
@@ -341,115 +341,6 @@ _cogl_path_fill_nodes (CoglPath *path)
}
void
-_cogl_add_path_to_stencil_buffer (CoglPath *path,
- gboolean merge,
- gboolean need_clear)
-{
- CoglPathData *data = path->data;
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (framebuffer);
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (framebuffer);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* This can be called from the clip stack code which doesn't flush
- the matrix stacks between calls so we need to ensure they're
- flushed now */
- _cogl_matrix_stack_flush_to_gl (modelview_stack,
- COGL_MATRIX_MODELVIEW);
- _cogl_matrix_stack_flush_to_gl (projection_stack,
- COGL_MATRIX_PROJECTION);
-
- /* Just setup a simple pipeline that doesn't use texturing... */
- _cogl_push_source (ctx->stencil_pipeline, FALSE);
-
- _cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, FALSE, 0);
-
- GE( ctx, glEnable (GL_STENCIL_TEST) );
-
- GE( ctx, glColorMask (FALSE, FALSE, FALSE, FALSE) );
- GE( ctx, glDepthMask (FALSE) );
-
- if (merge)
- {
- GE (ctx, glStencilMask (2));
- GE (ctx, glStencilFunc (GL_LEQUAL, 0x2, 0x6));
- }
- else
- {
- /* If we're not using the stencil buffer for clipping then we
- don't need to clear the whole stencil buffer, just the area
- that will be drawn */
- if (need_clear)
- /* If this is being called from the clip stack code then it
- will have set up a scissor for the minimum bounding box of
- all of the clips. That box will likely mean that this
- _cogl_clear won't need to clear the entire
- buffer. _cogl_framebuffer_clear_without_flush4f is used instead
- of cogl_clear because it won't try to flush the journal */
- _cogl_framebuffer_clear_without_flush4f (framebuffer,
- COGL_BUFFER_BIT_STENCIL,
- 0, 0, 0, 0);
- else
- {
- /* Just clear the bounding box */
- GE( ctx, glStencilMask (~(GLuint) 0) );
- GE( ctx, glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) );
- _cogl_rectangle_immediate (data->path_nodes_min.x,
- data->path_nodes_min.y,
- data->path_nodes_max.x,
- data->path_nodes_max.y);
- }
- GE (ctx, glStencilMask (1));
- GE (ctx, glStencilFunc (GL_LEQUAL, 0x1, 0x3));
- }
-
- GE (ctx, glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT));
-
- if (path->data->path_nodes->len >= 3)
- _cogl_path_fill_nodes (path);
-
- if (merge)
- {
- /* Now we have the new stencil buffer in bit 1 and the old
- stencil buffer in bit 0 so we need to intersect them */
- GE (ctx, glStencilMask (3));
- GE (ctx, glStencilFunc (GL_NEVER, 0x2, 0x3));
- GE (ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR));
- /* Decrement all of the bits twice so that only pixels where the
- value is 3 will remain */
-
- _cogl_matrix_stack_push (projection_stack);
- _cogl_matrix_stack_load_identity (projection_stack);
- _cogl_matrix_stack_flush_to_gl (projection_stack,
- COGL_MATRIX_PROJECTION);
-
- _cogl_matrix_stack_push (modelview_stack);
- _cogl_matrix_stack_load_identity (modelview_stack);
- _cogl_matrix_stack_flush_to_gl (modelview_stack,
- COGL_MATRIX_MODELVIEW);
-
- _cogl_rectangle_immediate (-1.0, -1.0, 1.0, 1.0);
- _cogl_rectangle_immediate (-1.0, -1.0, 1.0, 1.0);
-
- _cogl_matrix_stack_pop (modelview_stack);
- _cogl_matrix_stack_pop (projection_stack);
- }
-
- GE (ctx, glStencilMask (~(GLuint) 0));
- GE (ctx, glDepthMask (TRUE));
- GE (ctx, glColorMask (TRUE, TRUE, TRUE, TRUE));
-
- GE (ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1));
- GE (ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP));
-
- /* restore the original pipeline */
- cogl_pop_source ();
-}
-
-void
cogl2_path_fill (CoglPath *path)
{
g_return_if_fail (cogl_is_path (path));