cogl/framebuffer: Add cogl_framebuffer_flush

In future patches, we'll create additional CoglFramebuffers that
will be shared via DMA-Buf with PipeWire. When recording frames,
we'll blit the current onscreen framebuffer into the shared one.

However, that presents a problem: cogl_framebuffer_blit() mimics
glBlitFramebuffer() semantics, and doesn't do an implicit flush
of the GPU command stream. As a consequence, clients may receive
unblitted or incomplete framebuffers.

We could use cogl_framebuffer_finish() to ensure the commands were
submitted to the GPU, but it is too harsh -- it blocks the CPU
completely until the commands are finished!

Add cogl_framebuffer_flush(), which ensures the command stream is
submitted to the GPU without blocking the CPU. Even though we don't
use the framebuffer specifically, it may be useful in the future
for e.g. a potential Vulkan backend to have access to the framebuffer.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
This commit is contained in:
Georges Basile Stavracas Neto 2020-02-24 12:44:52 -03:00
parent f27de9620a
commit 038a3170bf
10 changed files with 46 additions and 0 deletions

View File

@ -93,6 +93,9 @@ struct _CoglDriverVtable
void void
(* framebuffer_finish) (CoglFramebuffer *framebuffer); (* framebuffer_finish) (CoglFramebuffer *framebuffer);
void
(* framebuffer_flush) (CoglFramebuffer *framebuffer);
void void
(* framebuffer_discard_buffers) (CoglFramebuffer *framebuffer, (* framebuffer_discard_buffers) (CoglFramebuffer *framebuffer,
unsigned long buffers); unsigned long buffers);

View File

@ -1396,6 +1396,17 @@ cogl_framebuffer_finish (CoglFramebuffer *framebuffer)
ctx->driver_vtable->framebuffer_finish (framebuffer); ctx->driver_vtable->framebuffer_finish (framebuffer);
} }
void
cogl_framebuffer_flush (CoglFramebuffer *framebuffer)
{
CoglContext *ctx = framebuffer->context;
_cogl_framebuffer_flush_journal (framebuffer);
ctx->driver_vtable->framebuffer_flush (framebuffer);
}
void void
cogl_framebuffer_push_matrix (CoglFramebuffer *framebuffer) cogl_framebuffer_push_matrix (CoglFramebuffer *framebuffer)
{ {

View File

@ -1555,6 +1555,18 @@ cogl_blit_framebuffer (CoglFramebuffer *src,
int height, int height,
GError **error); GError **error);
/**
* cogl_framebuffer_flush:
* @framebuffer: A #CoglFramebuffer pointer
*
* Flushes @framebuffer to ensure the current batch of commands is
* submitted to the GPU.
*
* Unlike cogl_framebuffer_finish(), this does not block the CPU.
*/
void
cogl_framebuffer_flush (CoglFramebuffer *framebuffer);
G_END_DECLS G_END_DECLS
#endif /* __COGL_FRAMEBUFFER_H */ #endif /* __COGL_FRAMEBUFFER_H */

View File

@ -61,6 +61,9 @@ _cogl_framebuffer_gl_query_bits (CoglFramebuffer *framebuffer,
void void
_cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer); _cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer);
void
_cogl_framebuffer_gl_flush (CoglFramebuffer *framebuffer);
void void
_cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer, _cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer,
unsigned long buffers); unsigned long buffers);

View File

@ -1031,6 +1031,12 @@ _cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer)
GE (framebuffer->context, glFinish ()); GE (framebuffer->context, glFinish ());
} }
void
_cogl_framebuffer_gl_flush (CoglFramebuffer *framebuffer)
{
GE (framebuffer->context, glFlush ());
}
void void
_cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer, _cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer,
unsigned long buffers) unsigned long buffers)

View File

@ -554,6 +554,7 @@ _cogl_driver_gl =
_cogl_framebuffer_gl_clear, _cogl_framebuffer_gl_clear,
_cogl_framebuffer_gl_query_bits, _cogl_framebuffer_gl_query_bits,
_cogl_framebuffer_gl_finish, _cogl_framebuffer_gl_finish,
_cogl_framebuffer_gl_flush,
_cogl_framebuffer_gl_discard_buffers, _cogl_framebuffer_gl_discard_buffers,
_cogl_framebuffer_gl_draw_attributes, _cogl_framebuffer_gl_draw_attributes,
_cogl_framebuffer_gl_draw_indexed_attributes, _cogl_framebuffer_gl_draw_indexed_attributes,

View File

@ -403,6 +403,7 @@ _cogl_driver_gles =
_cogl_framebuffer_gl_clear, _cogl_framebuffer_gl_clear,
_cogl_framebuffer_gl_query_bits, _cogl_framebuffer_gl_query_bits,
_cogl_framebuffer_gl_finish, _cogl_framebuffer_gl_finish,
_cogl_framebuffer_gl_flush,
_cogl_framebuffer_gl_discard_buffers, _cogl_framebuffer_gl_discard_buffers,
_cogl_framebuffer_gl_draw_attributes, _cogl_framebuffer_gl_draw_attributes,
_cogl_framebuffer_gl_draw_indexed_attributes, _cogl_framebuffer_gl_draw_indexed_attributes,

View File

@ -78,6 +78,7 @@ _cogl_driver_nop =
_cogl_framebuffer_nop_clear, _cogl_framebuffer_nop_clear,
_cogl_framebuffer_nop_query_bits, _cogl_framebuffer_nop_query_bits,
_cogl_framebuffer_nop_finish, _cogl_framebuffer_nop_finish,
_cogl_framebuffer_nop_flush,
_cogl_framebuffer_nop_discard_buffers, _cogl_framebuffer_nop_discard_buffers,
_cogl_framebuffer_nop_draw_attributes, _cogl_framebuffer_nop_draw_attributes,
_cogl_framebuffer_nop_draw_indexed_attributes, _cogl_framebuffer_nop_draw_indexed_attributes,

View File

@ -64,6 +64,9 @@ _cogl_framebuffer_nop_query_bits (CoglFramebuffer *framebuffer,
void void
_cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer); _cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer);
void
_cogl_framebuffer_nop_flush (CoglFramebuffer *framebuffer);
void void
_cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer, _cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer,
unsigned long buffers); unsigned long buffers);

View File

@ -76,6 +76,11 @@ _cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer)
{ {
} }
void
_cogl_framebuffer_nop_flush (CoglFramebuffer *framebuffer)
{
}
void void
_cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer, _cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer,
unsigned long buffers) unsigned long buffers)