mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-01 17:20:29 +01:00
gl/msaa: Share the depth/stencil buffer among all surfaces
Instead of allocating a depth/stencil buffer for all surfaces, share a common buffer that's the size of the largest surface. This reduces video memory usage when there are many GL surfaces.
This commit is contained in:
parent
ba4a4eae05
commit
a7d684e6fe
3 changed files with 126 additions and 40 deletions
|
|
@ -112,6 +112,11 @@ _gl_finish (void *device)
|
|||
for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
|
||||
_cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]);
|
||||
|
||||
if (ctx->depth_stencil_info.id)
|
||||
ctx->dispatch.DeleteRenderbuffers (1, &ctx->depth_stencil_info.id);
|
||||
if (ctx->msaa_depth_stencil_info.id)
|
||||
ctx->dispatch.DeleteRenderbuffers (1, &ctx->msaa_depth_stencil_info.id);
|
||||
|
||||
_gl_unlock (device);
|
||||
}
|
||||
|
||||
|
|
@ -453,36 +458,59 @@ _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_cairo_gl_replace_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
||||
|
||||
if (ctx->msaa_depth_stencil_info.id)
|
||||
dispatch->DeleteRenderbuffers (1, &ctx->msaa_depth_stencil_info.id);
|
||||
|
||||
dispatch->GenRenderbuffers (1, &ctx->msaa_depth_stencil_info.id);
|
||||
dispatch->BindRenderbuffer (GL_RENDERBUFFER, ctx->msaa_depth_stencil_info.id);
|
||||
dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER, ctx->num_samples,
|
||||
_get_depth_stencil_format (ctx),
|
||||
width, height);
|
||||
ctx->msaa_depth_stencil_info.width = width;
|
||||
ctx->msaa_depth_stencil_info.height = height;
|
||||
ctx->msaa_depth_stencil_info.surfaces_with_same_size = 0;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
||||
cairo_gl_surface_t *surface)
|
||||
{
|
||||
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
||||
if (surface->msaa_depth_stencil)
|
||||
return TRUE;
|
||||
|
||||
_cairo_gl_ensure_framebuffer (ctx, surface);
|
||||
#if CAIRO_HAS_GL_SURFACE
|
||||
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
|
||||
_cairo_gl_ensure_multisampling (ctx, surface);
|
||||
#endif
|
||||
|
||||
dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil);
|
||||
dispatch->BindRenderbuffer (GL_RENDERBUFFER,
|
||||
surface->msaa_depth_stencil);
|
||||
if (! ctx->msaa_depth_stencil_info.id ||
|
||||
ctx->msaa_depth_stencil_info.width < surface->width ||
|
||||
ctx->msaa_depth_stencil_info.height < surface->height) {
|
||||
_cairo_gl_replace_msaa_depth_stencil_buffer (ctx,
|
||||
surface->width,
|
||||
surface->height);
|
||||
}
|
||||
|
||||
dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER,
|
||||
ctx->num_samples,
|
||||
_get_depth_stencil_format (ctx),
|
||||
surface->width,
|
||||
surface->height);
|
||||
assert (ctx->msaa_depth_stencil_info.id);
|
||||
if (surface->msaa_depth_stencil == ctx->msaa_depth_stencil_info.id)
|
||||
return TRUE;
|
||||
|
||||
if (ctx->msaa_depth_stencil_info.width == surface->width &&
|
||||
ctx->msaa_depth_stencil_info.height == surface->height)
|
||||
ctx->msaa_depth_stencil_info.surfaces_with_same_size++;
|
||||
|
||||
#if CAIRO_HAS_GL_SURFACE
|
||||
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
|
||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||
GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER,
|
||||
surface->msaa_depth_stencil);
|
||||
ctx->msaa_depth_stencil_info.id);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -491,50 +519,72 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
|||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER,
|
||||
surface->msaa_depth_stencil);
|
||||
ctx->msaa_depth_stencil_info.id);
|
||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||
GL_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER,
|
||||
surface->msaa_depth_stencil);
|
||||
ctx->msaa_depth_stencil_info.id);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
dispatch->DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
|
||||
surface->msaa_depth_stencil = 0;
|
||||
return FALSE;
|
||||
}
|
||||
surface->msaa_depth_stencil = ctx->msaa_depth_stencil_info.id;
|
||||
|
||||
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gl_replace_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
||||
|
||||
if (ctx->depth_stencil_info.id)
|
||||
dispatch->DeleteRenderbuffers (1, &ctx->depth_stencil_info.id);
|
||||
|
||||
dispatch->GenRenderbuffers (1, &ctx->depth_stencil_info.id);
|
||||
dispatch->BindRenderbuffer (GL_RENDERBUFFER, ctx->depth_stencil_info.id);
|
||||
dispatch->RenderbufferStorage (GL_RENDERBUFFER,
|
||||
_get_depth_stencil_format (ctx),
|
||||
width, height);
|
||||
ctx->depth_stencil_info.width = width;
|
||||
ctx->depth_stencil_info.height = height;
|
||||
ctx->depth_stencil_info.surfaces_with_same_size = 0;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_gl_ensure_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
||||
cairo_gl_surface_t *surface)
|
||||
{
|
||||
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
||||
|
||||
if (surface->depth_stencil)
|
||||
return TRUE;
|
||||
|
||||
_cairo_gl_ensure_framebuffer (ctx, surface);
|
||||
|
||||
dispatch->GenRenderbuffers (1, &surface->depth_stencil);
|
||||
dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil);
|
||||
dispatch->RenderbufferStorage (GL_RENDERBUFFER,
|
||||
_get_depth_stencil_format (ctx),
|
||||
surface->width, surface->height);
|
||||
|
||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER, surface->depth_stencil);
|
||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER, surface->depth_stencil);
|
||||
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
dispatch->DeleteRenderbuffers (1, &surface->depth_stencil);
|
||||
surface->depth_stencil = 0;
|
||||
return FALSE;
|
||||
if (! ctx->depth_stencil_info.id ||
|
||||
ctx->depth_stencil_info.width < surface->width ||
|
||||
ctx->depth_stencil_info.height < surface->height) {
|
||||
_cairo_gl_replace_depth_stencil_buffer (ctx,
|
||||
surface->width,
|
||||
surface->height);
|
||||
}
|
||||
|
||||
if (surface->depth_stencil == ctx->depth_stencil_info.id)
|
||||
return TRUE;
|
||||
|
||||
if (ctx->depth_stencil_info.width == surface->width &&
|
||||
ctx->depth_stencil_info.height == surface->height)
|
||||
ctx->depth_stencil_info.surfaces_with_same_size++;
|
||||
|
||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER, ctx->depth_stencil_info.id);
|
||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER, ctx->depth_stencil_info.id);
|
||||
surface->depth_stencil = ctx->depth_stencil_info.id;
|
||||
|
||||
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -301,6 +301,13 @@ typedef struct _cairo_gl_dispatch {
|
|||
GLint level, GLsizei samples);
|
||||
} cairo_gl_dispatch_t;
|
||||
|
||||
typedef struct _cairo_gl_shared_depth_stencil_info {
|
||||
GLuint id;
|
||||
int width;
|
||||
int height;
|
||||
unsigned surfaces_with_same_size;
|
||||
} cairo_gl_shared_depth_stencil_info_t;
|
||||
|
||||
struct _cairo_gl_context {
|
||||
cairo_device_t base;
|
||||
|
||||
|
|
@ -353,6 +360,12 @@ struct _cairo_gl_context {
|
|||
|
||||
cairo_bool_t thread_aware;
|
||||
|
||||
/* GL stencil and depth buffers are shared among all surfaces
|
||||
to preserve memory. In the future this could be a pool of renderbuffers
|
||||
with an eviction policy. */
|
||||
cairo_gl_shared_depth_stencil_info_t depth_stencil_info;
|
||||
cairo_gl_shared_depth_stencil_info_t msaa_depth_stencil_info;
|
||||
|
||||
void (*acquire) (void *ctx);
|
||||
void (*release) (void *ctx);
|
||||
|
||||
|
|
|
|||
|
|
@ -946,6 +946,23 @@ static int _cairo_gl_surface_flavor (cairo_gl_surface_t *surface)
|
|||
return ctx->gl_flavor;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gl_shrink_shared_renderbuffer (cairo_gl_context_t *ctx,
|
||||
cairo_gl_shared_depth_stencil_info_t *info,
|
||||
int surface_width,
|
||||
int surface_height)
|
||||
{
|
||||
if (info->width != surface_width || info->height != surface_height)
|
||||
return;
|
||||
|
||||
/* Force the creation of a new shared renderbuffer if we are the
|
||||
* last surface that has the same size as our old shared buffer. */
|
||||
ctx->dispatch.DeleteRenderbuffers (1, &info->id);
|
||||
info->height = 0;
|
||||
info->width = 0;
|
||||
info->id = 0;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
|
@ -968,18 +985,24 @@ _cairo_gl_surface_finish (void *abstract_surface)
|
|||
|
||||
if (surface->fb)
|
||||
ctx->dispatch.DeleteFramebuffers (1, &surface->fb);
|
||||
if (surface->depth_stencil)
|
||||
ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil);
|
||||
if (surface->owns_tex)
|
||||
glDeleteTextures (1, &surface->tex);
|
||||
|
||||
if (surface->depth_stencil) {
|
||||
_cairo_gl_shrink_shared_renderbuffer (ctx, &ctx->depth_stencil_info,
|
||||
surface->width, surface->height);
|
||||
}
|
||||
|
||||
#if CAIRO_HAS_GL_SURFACE
|
||||
if (surface->msaa_depth_stencil)
|
||||
ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
|
||||
if (surface->msaa_fb)
|
||||
ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
|
||||
if (surface->msaa_rb)
|
||||
ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_rb);
|
||||
|
||||
if (surface->msaa_depth_stencil) {
|
||||
_cairo_gl_shrink_shared_renderbuffer (ctx, &ctx->msaa_depth_stencil_info,
|
||||
surface->width, surface->height);
|
||||
}
|
||||
#endif
|
||||
|
||||
return _cairo_gl_context_release (ctx, status);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue