framebuffer: Add explicit buffer discard API
This adds cogl_framebuffer_discard_buffers API that allows applications to explicitly discard depth and stencil buffers which really helps when using a tile based GPU architexture by potentially avoiding the need to save the results of depth and stencil buffer changes to system memory between frames since these can usually be handled directly with on-chip memory instead. The semantics for cogl_framebuffer_swap_buffers and cogl_framebuffer_swap_region are now documented to include an implicit discard of all buffers, including the color buffer. We now recommend that all rendering to a CoglOffscreen framebuffer should be followed by a call like: cogl_framebuffer_discard_buffers (fb, COGL_BUFFER_BIT_DEPTH| COGL_BUFFER_BIT_STENCIL); Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
e69e41b2c7
commit
63461c0f8b
@ -649,3 +649,14 @@ COGL_EXT_FUNCTION (void, glEGLImageTargetRenderbufferStorage,
|
||||
(GLenum target,
|
||||
GLeglImageOES image))
|
||||
COGL_EXT_END ()
|
||||
|
||||
COGL_EXT_BEGIN (framebuffer_discard, 255, 255,
|
||||
0, /* not in either GLES */
|
||||
"EXT\0",
|
||||
"framebuffer_discard\0")
|
||||
COGL_EXT_FUNCTION (void, glDiscardFramebuffer,
|
||||
(GLenum target,
|
||||
GLsizei numAttachments,
|
||||
const GLenum *attachments))
|
||||
COGL_EXT_END ()
|
||||
|
||||
|
@ -1693,17 +1693,66 @@ _cogl_blit_framebuffer (unsigned int src_x,
|
||||
GL_NEAREST);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_framebuffer_discard_buffers_real (CoglFramebuffer *framebuffer,
|
||||
unsigned long buffers)
|
||||
{
|
||||
#ifdef GL_EXT_discard_framebuffer
|
||||
CoglContext *ctx = framebuffer->context;
|
||||
|
||||
if (ctx->glDiscardFramebuffer)
|
||||
{
|
||||
GLenum attachments[3];
|
||||
int i = 0;
|
||||
|
||||
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
||||
{
|
||||
if (buffers & COGL_BUFFER_BIT_COLOR)
|
||||
attachments[i++] = GL_COLOR_EXT;
|
||||
if (buffers & COGL_BUFFER_BIT_DEPTH)
|
||||
attachments[i++] = GL_DEPTH_EXT;
|
||||
if (buffers & COGL_BUFFER_BIT_STENCIL)
|
||||
attachments[i++] = GL_STENCIL_EXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buffers & COGL_BUFFER_BIT_COLOR)
|
||||
attachments[i++] = GL_COLOR_ATTACHMENT0;
|
||||
if (buffers & COGL_BUFFER_BIT_DEPTH)
|
||||
attachments[i++] = GL_DEPTH_ATTACHMENT;
|
||||
if (buffers & COGL_BUFFER_BIT_STENCIL)
|
||||
attachments[i++] = GL_STENCIL_ATTACHMENT;
|
||||
}
|
||||
|
||||
GE (ctx, glDiscardFramebuffer (GL_FRAMEBUFFER, i, attachments));
|
||||
}
|
||||
#endif /* GL_EXT_discard_framebuffer */
|
||||
}
|
||||
|
||||
void
|
||||
cogl_framebuffer_discard_buffers (CoglFramebuffer *framebuffer,
|
||||
unsigned long buffers)
|
||||
{
|
||||
g_return_if_fail (buffers & COGL_BUFFER_BIT_COLOR);
|
||||
|
||||
_cogl_framebuffer_discard_buffers_real (framebuffer, buffers);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer)
|
||||
{
|
||||
const CoglWinsysVtable *winsys;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
|
||||
/* FIXME: we shouldn't need to flush *all* journals here! */
|
||||
cogl_flush ();
|
||||
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
||||
{
|
||||
const CoglWinsysVtable *winsys =
|
||||
_cogl_framebuffer_get_winsys (framebuffer);
|
||||
winsys->onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
|
||||
}
|
||||
winsys = _cogl_framebuffer_get_winsys (framebuffer);
|
||||
winsys->onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
|
||||
cogl_framebuffer_discard_buffers (framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
COGL_BUFFER_BIT_DEPTH |
|
||||
COGL_BUFFER_BIT_STENCIL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1711,21 +1760,27 @@ cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
{
|
||||
const CoglWinsysVtable *winsys;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
|
||||
/* FIXME: we shouldn't need to flush *all* journals here! */
|
||||
cogl_flush ();
|
||||
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
||||
{
|
||||
const CoglWinsysVtable *winsys =
|
||||
_cogl_framebuffer_get_winsys (framebuffer);
|
||||
|
||||
/* This should only be called if the winsys advertises
|
||||
COGL_WINSYS_FEATURE_SWAP_REGION */
|
||||
g_return_if_fail (winsys->onscreen_swap_region != NULL);
|
||||
winsys = _cogl_framebuffer_get_winsys (framebuffer);
|
||||
|
||||
winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
}
|
||||
/* This should only be called if the winsys advertises
|
||||
COGL_WINSYS_FEATURE_SWAP_REGION */
|
||||
g_return_if_fail (winsys->onscreen_swap_region != NULL);
|
||||
|
||||
winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
|
||||
cogl_framebuffer_discard_buffers (framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
COGL_BUFFER_BIT_DEPTH |
|
||||
COGL_BUFFER_BIT_STENCIL);
|
||||
}
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
|
@ -342,11 +342,81 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
|
||||
float blue,
|
||||
float alpha);
|
||||
|
||||
/* XXX: Should we take an n_buffers + buffer id array instead of using
|
||||
* the CoglBufferBits type which doesn't seem future proof? */
|
||||
#define cogl_framebuffer_discard_buffers cogl_framebuffer_discard_buffers_EXP
|
||||
/**
|
||||
* cogl_framebuffer_discard_buffers:
|
||||
* @framebuffer: A #CoglFramebuffer
|
||||
* @buffers: A #CoglBufferBit mask of which ancillary buffers you want
|
||||
* to discard.
|
||||
*
|
||||
* Declares that the specified @buffers no longer need to be referenced
|
||||
* by any further rendering commands. This can be an important
|
||||
* optimization to avoid subsequent frames of rendering depending on
|
||||
* the results of a previous frame.
|
||||
*
|
||||
* For example; some tile-based rendering GPUs are able to avoid allocating and
|
||||
* accessing system memory for the depth and stencil buffer so long as these
|
||||
* buffers are not required as input for subsequent frames and that can save a
|
||||
* significant amount of memory bandwidth used to save and restore their
|
||||
* contents to system memory between frames.
|
||||
*
|
||||
* It is currently considered an error to try and explicitly discard the color
|
||||
* buffer by passing %COGL_BUFFER_BIT_COLOR. This is because the color buffer is
|
||||
* already implicitly discard when you finish rendering to a #CoglOnscreen
|
||||
* framebuffer, and it's not meaningful to try and discard the color buffer of
|
||||
* a #CoglOffscreen framebuffer since they are single-buffered.
|
||||
*
|
||||
*
|
||||
* Since: 1.8
|
||||
* Stability: unstable
|
||||
*/
|
||||
void
|
||||
cogl_framebuffer_discard_buffers (CoglFramebuffer *framebuffer,
|
||||
unsigned long buffers);
|
||||
|
||||
/* XXX: Actually should this be renamed too cogl_onscreen_swap_buffers()? */
|
||||
#define cogl_framebuffer_swap_buffers cogl_framebuffer_swap_buffers_EXP
|
||||
/**
|
||||
* cogl_framebuffer_swap_buffers:
|
||||
* @framebuffer: A #CoglFramebuffer
|
||||
*
|
||||
* Swaps the current back buffer being rendered too, to the front for display.
|
||||
*
|
||||
* This function also implicitly discards the contents of the color, depth and
|
||||
* stencil buffers as if cogl_framebuffer_discard_buffers() were used. The
|
||||
* significance of the discard is that you should not expect to be able to
|
||||
* start a new frame that incrementally builds on the contents of the previous
|
||||
* frame.
|
||||
*
|
||||
* Since: 1.8
|
||||
* Stability: unstable
|
||||
*/
|
||||
void
|
||||
cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer);
|
||||
|
||||
#define cogl_framebuffer_swap_region cogl_framebuffer_swap_region_EXP
|
||||
/**
|
||||
* cogl_framebuffer_swap_region:
|
||||
* @framebuffer: A #CoglFramebuffer
|
||||
* @rectangles: An array of integer 4-tuples representing rectangles as
|
||||
* (x, y, width, height) tuples.
|
||||
* @n_rectangles: The number of 4-tuples to be read from @rectangles
|
||||
*
|
||||
* Swaps a region of the back buffer being rendered too, to the front for
|
||||
* display. @rectangles represents the region as array of @n_rectangles each
|
||||
* defined by 4 sequential (x, y, width, height) integers.
|
||||
*
|
||||
* This function also implicitly discards the contents of the color, depth and
|
||||
* stencil buffers as if cogl_framebuffer_discard_buffers() were used. The
|
||||
* significance of the discard is that you should not expect to be able to
|
||||
* start a new frame that incrementally builds on the contents of the previous
|
||||
* frame.
|
||||
*
|
||||
* Since: 1.8
|
||||
* Stability: unstable
|
||||
*/
|
||||
void
|
||||
cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
|
||||
const int *rectangles,
|
||||
|
Loading…
Reference in New Issue
Block a user