gl: Defer stencil allocation until use

Allocating a stencil and a depth buffer for every destination surface is
simply too expensive and causes major resource issues. So defer the
allocation and attachment of a stencil buffer until just prior to first
use.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2011-12-07 10:19:37 +00:00
parent c7565eeda0
commit 5613b210ff
3 changed files with 42 additions and 19 deletions

View file

@ -295,24 +295,6 @@ _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
glReadBuffer (GL_COLOR_ATTACHMENT0);
#endif
if (ctx->has_packed_depth_stencil) {
#if CAIRO_HAS_GL_SURFACE
GLenum internal_format = GL_DEPTH_STENCIL;
#elif CAIRO_HAS_GLESV2_SURFACE
GLenum internal_format = GL_DEPTH24_STENCIL8_OES,
#endif
dispatch->GenRenderbuffers (1, &surface->depth_stencil);
dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil);
dispatch->RenderbufferStorage (GL_RENDERBUFFER, internal_format,
surface->width, surface->height);
ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, surface->depth_stencil);
ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, surface->depth_stencil);
}
status = dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
const char *str;
@ -333,6 +315,43 @@ _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
}
}
cairo_bool_t
_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
#if CAIRO_HAS_GL_SURFACE
GLenum internal_format = GL_DEPTH_STENCIL;
#elif CAIRO_HAS_GLESV2_SURFACE
GLenum internal_format = GL_DEPTH24_STENCIL8_OES;
#endif
if (surface->depth_stencil)
return TRUE;
if (! ctx->has_packed_depth_stencil)
return FALSE;
_cairo_gl_ensure_framebuffer (ctx, surface);
dispatch->GenRenderbuffers (1, &surface->depth_stencil);
dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil);
dispatch->RenderbufferStorage (GL_RENDERBUFFER, internal_format,
surface->width, surface->height);
ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, surface->depth_stencil);
ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, surface->depth_stencil);
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil);
surface->depth_stencil = 0;
return FALSE;
}
return TRUE;
}
/*
* Stores a parallel projection transformation in matrix 'm',
* using column-major order.

View file

@ -176,7 +176,7 @@ _draw_clip_to_stencil_buffer (cairo_gl_context_t *ctx,
assert (! _cairo_clip_is_all_clipped (clip));
if (! setup->dst->depth_stencil)
if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
glDepthMask (GL_TRUE);

View file

@ -440,6 +440,10 @@ _cairo_gl_context_activate (cairo_gl_context_t *ctx,
cairo_private cairo_bool_t
_cairo_gl_operator_is_supported (cairo_operator_t op);
cairo_private cairo_bool_t
_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface);
cairo_private cairo_status_t
_cairo_gl_composite_init (cairo_gl_composite_t *setup,
cairo_operator_t op,