mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-07 06:18:02 +02: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++)
|
for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
|
||||||
_cairo_gl_glyph_cache_fini (ctx, &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);
|
_gl_unlock (device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,36 +458,59 @@ _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
static cairo_bool_t
|
||||||
_cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
_cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
||||||
cairo_gl_surface_t *surface)
|
cairo_gl_surface_t *surface)
|
||||||
{
|
{
|
||||||
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
||||||
if (surface->msaa_depth_stencil)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
_cairo_gl_ensure_framebuffer (ctx, surface);
|
_cairo_gl_ensure_framebuffer (ctx, surface);
|
||||||
#if CAIRO_HAS_GL_SURFACE
|
#if CAIRO_HAS_GL_SURFACE
|
||||||
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
|
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
|
||||||
_cairo_gl_ensure_multisampling (ctx, surface);
|
_cairo_gl_ensure_multisampling (ctx, surface);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil);
|
if (! ctx->msaa_depth_stencil_info.id ||
|
||||||
dispatch->BindRenderbuffer (GL_RENDERBUFFER,
|
ctx->msaa_depth_stencil_info.width < surface->width ||
|
||||||
surface->msaa_depth_stencil);
|
ctx->msaa_depth_stencil_info.height < surface->height) {
|
||||||
|
_cairo_gl_replace_msaa_depth_stencil_buffer (ctx,
|
||||||
|
surface->width,
|
||||||
|
surface->height);
|
||||||
|
}
|
||||||
|
|
||||||
dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER,
|
assert (ctx->msaa_depth_stencil_info.id);
|
||||||
ctx->num_samples,
|
if (surface->msaa_depth_stencil == ctx->msaa_depth_stencil_info.id)
|
||||||
_get_depth_stencil_format (ctx),
|
return TRUE;
|
||||||
surface->width,
|
|
||||||
surface->height);
|
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 CAIRO_HAS_GL_SURFACE
|
||||||
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
|
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
|
||||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||||
GL_DEPTH_STENCIL_ATTACHMENT,
|
GL_DEPTH_STENCIL_ATTACHMENT,
|
||||||
GL_RENDERBUFFER,
|
GL_RENDERBUFFER,
|
||||||
surface->msaa_depth_stencil);
|
ctx->msaa_depth_stencil_info.id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -491,50 +519,72 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
||||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||||
GL_DEPTH_ATTACHMENT,
|
GL_DEPTH_ATTACHMENT,
|
||||||
GL_RENDERBUFFER,
|
GL_RENDERBUFFER,
|
||||||
surface->msaa_depth_stencil);
|
ctx->msaa_depth_stencil_info.id);
|
||||||
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||||
GL_STENCIL_ATTACHMENT,
|
GL_STENCIL_ATTACHMENT,
|
||||||
GL_RENDERBUFFER,
|
GL_RENDERBUFFER,
|
||||||
surface->msaa_depth_stencil);
|
ctx->msaa_depth_stencil_info.id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
surface->msaa_depth_stencil = ctx->msaa_depth_stencil_info.id;
|
||||||
dispatch->DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
|
|
||||||
surface->msaa_depth_stencil = 0;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
return FALSE;
|
||||||
return TRUE;
|
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
|
static cairo_bool_t
|
||||||
_cairo_gl_ensure_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
_cairo_gl_ensure_depth_stencil_buffer (cairo_gl_context_t *ctx,
|
||||||
cairo_gl_surface_t *surface)
|
cairo_gl_surface_t *surface)
|
||||||
{
|
{
|
||||||
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
|
||||||
|
|
||||||
if (surface->depth_stencil)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
_cairo_gl_ensure_framebuffer (ctx, surface);
|
_cairo_gl_ensure_framebuffer (ctx, surface);
|
||||||
|
|
||||||
dispatch->GenRenderbuffers (1, &surface->depth_stencil);
|
if (! ctx->depth_stencil_info.id ||
|
||||||
dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil);
|
ctx->depth_stencil_info.width < surface->width ||
|
||||||
dispatch->RenderbufferStorage (GL_RENDERBUFFER,
|
ctx->depth_stencil_info.height < surface->height) {
|
||||||
_get_depth_stencil_format (ctx),
|
_cairo_gl_replace_depth_stencil_buffer (ctx,
|
||||||
surface->width, surface->height);
|
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 (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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -301,6 +301,13 @@ typedef struct _cairo_gl_dispatch {
|
||||||
GLint level, GLsizei samples);
|
GLint level, GLsizei samples);
|
||||||
} cairo_gl_dispatch_t;
|
} 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 {
|
struct _cairo_gl_context {
|
||||||
cairo_device_t base;
|
cairo_device_t base;
|
||||||
|
|
||||||
|
|
@ -353,6 +360,12 @@ struct _cairo_gl_context {
|
||||||
|
|
||||||
cairo_bool_t thread_aware;
|
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 (*acquire) (void *ctx);
|
||||||
void (*release) (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;
|
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
|
static cairo_status_t
|
||||||
_cairo_gl_surface_finish (void *abstract_surface)
|
_cairo_gl_surface_finish (void *abstract_surface)
|
||||||
{
|
{
|
||||||
|
|
@ -968,18 +985,24 @@ _cairo_gl_surface_finish (void *abstract_surface)
|
||||||
|
|
||||||
if (surface->fb)
|
if (surface->fb)
|
||||||
ctx->dispatch.DeleteFramebuffers (1, &surface->fb);
|
ctx->dispatch.DeleteFramebuffers (1, &surface->fb);
|
||||||
if (surface->depth_stencil)
|
|
||||||
ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil);
|
|
||||||
if (surface->owns_tex)
|
if (surface->owns_tex)
|
||||||
glDeleteTextures (1, &surface->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 CAIRO_HAS_GL_SURFACE
|
||||||
if (surface->msaa_depth_stencil)
|
|
||||||
ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
|
|
||||||
if (surface->msaa_fb)
|
if (surface->msaa_fb)
|
||||||
ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
|
ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
|
||||||
if (surface->msaa_rb)
|
if (surface->msaa_rb)
|
||||||
ctx->dispatch.DeleteRenderbuffers (1, &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
|
#endif
|
||||||
|
|
||||||
return _cairo_gl_context_release (ctx, status);
|
return _cairo_gl_context_release (ctx, status);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue