gl/msaa: Only clear parts of the stencil buffer we will use

Writing to the stencil buffer can be expensive, so when using the
stencil buffer for clipping only clear the clip extent. When using the
stencil buffer to prevent overlapping rendering during stroking, only
clear the approximate stroke extents.
This commit is contained in:
Henry Song 2013-01-03 16:03:55 -08:00 committed by Martin Robinson
parent 5e9083f882
commit 9dde964553
3 changed files with 44 additions and 11 deletions

View file

@ -501,8 +501,8 @@ _scissor_to_doubles (cairo_gl_surface_t *surface,
glEnable (GL_SCISSOR_TEST);
}
static void
_scissor_to_rectangle (cairo_gl_surface_t *surface,
void
_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface,
const cairo_rectangle_int_t *r)
{
_scissor_to_doubles (surface, r->x, r->y, r->x+r->width, r->y+r->height);
@ -555,19 +555,22 @@ _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup,
goto disable_stencil_buffer_and_return;
}
/* If we cannot reduce the clip to a rectangular region,
we clip using the stencil buffer. */
glDisable (GL_SCISSOR_TEST);
if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto disable_stencil_buffer_and_return;
}
/* The clip is not rectangular, so use the stencil buffer. */
glDepthMask (GL_TRUE);
glEnable (GL_STENCIL_TEST);
/* Clear the stencil buffer, but only the areas that we are
* going to be drawing to. */
_cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip));
glClearStencil (0);
glClear (GL_STENCIL_BUFFER_BIT);
glDisable (GL_SCISSOR_TEST);
glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
glStencilFunc (GL_EQUAL, 1, 0xffffffff);
glColorMask (0, 0, 0, 0);
@ -787,7 +790,7 @@ _cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t *ctx,
cairo_region_get_rectangle (ctx->clip_region, i, &rect);
_scissor_to_rectangle (ctx->current_target, &rect);
_cairo_gl_scissor_to_rectangle (ctx->current_target, &rect);
_cairo_gl_composite_draw_triangles (ctx, count);
}
}

View file

@ -533,10 +533,15 @@ _stroke_shaper_add_quad (void *closure,
}
static cairo_int_status_t
_prevent_overlapping_drawing (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_composite_rectangles_t *composite)
_prevent_overlapping_strokes (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_composite_rectangles_t *composite,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm)
{
cairo_rectangle_int_t stroke_extents;
if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -545,13 +550,33 @@ _prevent_overlapping_drawing (cairo_gl_context_t *ctx,
return CAIRO_INT_STATUS_SUCCESS;
if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
cairo_bool_t scissor_was_enabled;
/* In case we have pending operations we have to flush before
adding the stencil buffer. */
_cairo_gl_composite_flush (ctx);
/* Enable the stencil buffer, even if we are not using it for clipping,
so we can use it below to prevent overlapping shapes. We initialize
it all to one here which represents infinite clip. */
glDepthMask (GL_TRUE);
glEnable (GL_STENCIL_TEST);
/* We scissor here so that we don't have to clear the entire stencil
* buffer. If the scissor test is already enabled, it was enabled
* for clipping. In that case, instead of calculating an intersection,
* we just reuse it, and risk clearing too much. */
scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
if (! scissor_was_enabled) {
_cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
&stroke_extents);
_cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
}
glClearStencil (1);
glClear (GL_STENCIL_BUFFER_BIT);
if (! scissor_was_enabled)
glDisable (GL_SCISSOR_TEST);
glStencilFunc (GL_EQUAL, 1, 1);
}
@ -655,7 +680,8 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor,
if (unlikely (status))
goto finish;
status = _prevent_overlapping_drawing (info.ctx, &info.setup, composite);
status = _prevent_overlapping_strokes (info.ctx, &info.setup,
composite, path, style, ctm);
if (unlikely (status))
goto finish;

View file

@ -799,6 +799,10 @@ _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
cairo_private cairo_surface_t *
_cairo_gl_white_source (void);
cairo_private void
_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface,
const cairo_rectangle_int_t *r);
static inline cairo_gl_operand_t *
source_to_operand (cairo_surface_t *surface)
{