static cairo_int_status_t _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup, cairo_gl_context_t *ctx, int vertex_size) { cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; cairo_gl_surface_t *dst = setup->dst; cairo_clip_t *clip = setup->clip; if (clip->num_boxes == 1 && clip->path == NULL) { _scissor_to_box (dst, &clip->boxes[0]); 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; } glDepthMask (GL_TRUE); glEnable (GL_STENCIL_TEST); glClearStencil (0); glClear (GL_STENCIL_BUFFER_BIT); glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE); glStencilFunc (GL_EQUAL, 1, 0xffffffff); glColorMask (0, 0, 0, 0); status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip); if (unlikely (status)) { glColorMask (1, 1, 1, 1); goto disable_stencil_buffer_and_return; } /* We want to only render to the stencil buffer, so draw everything now. Flushing also unbinds the VBO, which we want to rebind for regular drawing. */ _cairo_gl_composite_flush (ctx); _cairo_gl_composite_setup_vbo (ctx, vertex_size); glColorMask (1, 1, 1, 1); glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc (GL_EQUAL, 1, 0xffffffff); return CAIRO_INT_STATUS_SUCCESS; disable_stencil_buffer_and_return: _disable_stencil_buffer (); return status; }
static cairo_int_status_t _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup, cairo_gl_context_t *ctx, int vertex_size, cairo_bool_t equal_clip) { cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; cairo_gl_surface_t *dst = setup->dst; cairo_clip_t *clip = setup->clip; cairo_traps_t traps; const cairo_rectangle_int_t *clip_extents; if (clip->num_boxes == 1 && clip->path == NULL) { _scissor_to_box (dst, &clip->boxes[0]); goto disable_stencil_buffer_and_return; } if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto disable_stencil_buffer_and_return; } if (! ctx->states_cache.depth_mask ) { glDepthMask (GL_TRUE); ctx->states_cache.depth_mask = TRUE; } glEnable (GL_STENCIL_TEST); clip_extents = _cairo_clip_get_extents ((const cairo_clip_t *)clip); _cairo_gl_scissor_to_extents (dst, clip_extents); if (equal_clip) return CAIRO_INT_STATUS_SUCCESS; glClearStencil (0); glClear (GL_STENCIL_BUFFER_BIT); glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE); glStencilFunc (GL_EQUAL, 1, 0xffffffff); glColorMask (0, 0, 0, 0); _cairo_traps_init (&traps); status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip, &traps); _cairo_traps_fini (&traps); if (unlikely (status)) { glColorMask (1, 1, 1, 1); goto disable_stencil_buffer_and_return; } /* We want to only render to the stencil buffer, so draw everything now. Flushing also unbinds the VBO, which we want to rebind for regular drawing. */ _cairo_gl_composite_flush (ctx); _cairo_gl_composite_setup_vbo (ctx, vertex_size); glColorMask (1, 1, 1, 1); glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc (GL_EQUAL, 1, 0xffffffff); return CAIRO_INT_STATUS_SUCCESS; disable_stencil_buffer_and_return: _disable_stencil_buffer (); return status; }
static cairo_int_status_t _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup, cairo_gl_context_t *ctx, int vertex_size) { cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; cairo_gl_surface_t *dst = setup->dst; cairo_clip_t *clip = setup->clip; if (clip->num_boxes == 1 && clip->path == NULL) { _scissor_to_box (dst, &clip->boxes[0]); goto disable_stencil_buffer_and_return; } if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto disable_stencil_buffer_and_return; } /* We only want to clear the part of the stencil buffer * that we are about to use. It also does not hurt to * scissor around the painted clip. */ _cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip)); /* The clip is not rectangular, so use the stencil buffer. */ glDepthMask (GL_TRUE); glEnable (GL_STENCIL_TEST); /* Texture surfaces have private depth/stencil buffers, so we can * rely on any previous clip being cached there. */ if (_cairo_gl_surface_is_texture (setup->dst)) { cairo_clip_t *old_clip = setup->dst->clip_on_stencil_buffer; if (_cairo_clip_equal (old_clip, setup->clip)) goto activate_stencil_buffer_and_return; if (old_clip) { _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer); } setup->dst->clip_on_stencil_buffer = _cairo_clip_copy (setup->clip); } glClearStencil (0); glClear (GL_STENCIL_BUFFER_BIT); glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE); glStencilFunc (GL_EQUAL, 1, 0xffffffff); glColorMask (0, 0, 0, 0); status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip); if (unlikely (status)) { glColorMask (1, 1, 1, 1); goto disable_stencil_buffer_and_return; } /* We want to only render to the stencil buffer, so draw everything now. Flushing also unbinds the VBO, which we want to rebind for regular drawing. */ _cairo_gl_composite_flush (ctx); _cairo_gl_composite_setup_vbo (ctx, vertex_size); activate_stencil_buffer_and_return: glColorMask (1, 1, 1, 1); glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc (GL_EQUAL, 1, 0xffffffff); return CAIRO_INT_STATUS_SUCCESS; disable_stencil_buffer_and_return: _disable_stencil_buffer (); return status; }