mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 11:08:12 +02:00
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:
parent
5e9083f882
commit
9dde964553
3 changed files with 44 additions and 11 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue