From d30927290110b1f6443ee8331c272e097217b0b2 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Mon, 5 Oct 2009 13:37:11 +0100 Subject: [PATCH] [cogl-primitives] Don't clear the whole stencil buffer When _cogl_add_path_to_stencil_buffer is used to draw a path we don't need to clear the entire stencil buffer. Instead it can clear just the bounding box of the path. This adds an extra parameter called 'need_clear' which is only set if the stencil buffer is being used for clipping. http://bugzilla.openedhand.com/show_bug.cgi?id=1829 --- cogl/cogl-clip-stack.c | 6 ++++-- cogl/cogl-primitives.c | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c index cd14fc6cc..75ed1d9c8 100644 --- a/cogl/cogl-clip-stack.c +++ b/cogl/cogl-clip-stack.c @@ -41,7 +41,8 @@ void _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, floatVec2 nodes_max, guint path_size, CoglPathNode *path, - gboolean merge); + gboolean merge, + gboolean need_clear); typedef struct _CoglClipStack CoglClipStack; @@ -696,7 +697,8 @@ _cogl_flush_clip_state (CoglClipStackState *clip_state) path->path_nodes_max, path->path_size, path->path, - using_stencil_buffer); + using_stencil_buffer, + TRUE); _cogl_matrix_stack_pop (modelview_stack); diff --git a/cogl/cogl-primitives.c b/cogl/cogl-primitives.c index c72aa740b..8ccbcce14 100644 --- a/cogl/cogl-primitives.c +++ b/cogl/cogl-primitives.c @@ -1109,7 +1109,8 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, floatVec2 nodes_max, unsigned int path_size, CoglPathNode *path, - gboolean merge) + gboolean merge, + gboolean need_clear) { unsigned int path_start = 0; unsigned int sub_path_num = 0; @@ -1151,6 +1152,11 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, _cogl_path_get_bounds (nodes_min, nodes_max, &bounds_x, &bounds_y, &bounds_w, &bounds_h); + GE( glEnable (GL_STENCIL_TEST) ); + + GE( glColorMask (FALSE, FALSE, FALSE, FALSE) ); + GE( glDepthMask (FALSE) ); + if (merge) { GE (glStencilMask (2)); @@ -1158,17 +1164,33 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, } else { - cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL); + /* 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) + cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL); + else + { + /* Just clear the bounding box */ + GE( glStencilMask (~(GLuint) 0) ); + GE( glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) ); + cogl_rectangle (bounds_x, bounds_y, + bounds_x + bounds_w, bounds_y + bounds_h); + /* Make sure the rectangle hits the stencil buffer before + * directly changing other GL state. */ + _cogl_journal_flush (); + /* NB: The journal flushing may trash the modelview state and + * enable flags */ + _cogl_matrix_stack_flush_to_gl (modelview_stack, + COGL_MATRIX_MODELVIEW); + cogl_enable (enable_flags); + } GE (glStencilMask (1)); GE (glStencilFunc (GL_LEQUAL, 0x1, 0x3)); } - GE (glEnable (GL_STENCIL_TEST)); GE (glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT)); - GE (glColorMask (FALSE, FALSE, FALSE, FALSE)); - GE (glDepthMask (FALSE)); - for (i = 0; i < ctx->n_texcoord_arrays_enabled; i++) { GE (glClientActiveTexture (GL_TEXTURE0 + i)); @@ -1468,7 +1490,8 @@ _cogl_path_fill_nodes (void) ctx->path_nodes->len, &g_array_index (ctx->path_nodes, CoglPathNode, 0), - clip_state->stencil_used); + clip_state->stencil_used, + FALSE); cogl_rectangle (bounds_x, bounds_y, bounds_x + bounds_w, bounds_y + bounds_h);