mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 08:00:42 -05:00
cogl: Move "flush framebuffers" under the context scope
It was namespaced as a CoglFramebuffer function, but was passed two framebuffers, and operated on state kept in CoglContext. Move and rename accordingly. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1514>
This commit is contained in:
parent
5be5529269
commit
e3de0be678
@ -603,16 +603,19 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
|||||||
validate_layer_cb,
|
validate_layer_cb,
|
||||||
&layers_state);
|
&layers_state);
|
||||||
|
|
||||||
/* NB: _cogl_framebuffer_flush_state may disrupt various state (such
|
/* NB: cogl_context_flush_framebuffer_state may disrupt various state (such
|
||||||
* as the pipeline state) when flushing the clip stack, so should
|
* as the pipeline state) when flushing the clip stack, so should
|
||||||
* always be done first when preparing to draw. We need to do this
|
* always be done first when preparing to draw. We need to do this
|
||||||
* before setting up the array pointers because setting up the clip
|
* before setting up the array pointers because setting up the clip
|
||||||
* stack can cause some drawing which would change the array
|
* stack can cause some drawing which would change the array
|
||||||
* pointers. */
|
* pointers. */
|
||||||
if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH))
|
if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH))
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
{
|
||||||
framebuffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
COGL_FRAMEBUFFER_STATE_ALL);
|
framebuffer,
|
||||||
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
/* In cogl_read_pixels we have a fast-path when reading a single
|
/* In cogl_read_pixels we have a fast-path when reading a single
|
||||||
* pixel and the scene is just comprised of simple rectangles still
|
* pixel and the scene is just comprised of simple rectangles still
|
||||||
|
@ -82,9 +82,10 @@ struct _CoglDriverVtable
|
|||||||
(* offscreen_free) (CoglOffscreen *offscreen);
|
(* offscreen_free) (CoglOffscreen *offscreen);
|
||||||
|
|
||||||
void
|
void
|
||||||
(* framebuffer_flush_state) (CoglFramebuffer *draw_buffer,
|
(* flush_framebuffer_state) (CoglContext *context,
|
||||||
CoglFramebuffer *read_buffer,
|
CoglFramebuffer *draw_buffer,
|
||||||
CoglFramebufferState state);
|
CoglFramebuffer *read_buffer,
|
||||||
|
CoglFramebufferState state);
|
||||||
|
|
||||||
void
|
void
|
||||||
(* framebuffer_clear) (CoglFramebuffer *framebuffer,
|
(* framebuffer_clear) (CoglFramebuffer *framebuffer,
|
||||||
|
@ -189,9 +189,10 @@ void
|
|||||||
_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer);
|
_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
|
cogl_context_flush_framebuffer_state (CoglContext *context,
|
||||||
CoglFramebuffer *read_buffer,
|
CoglFramebuffer *draw_buffer,
|
||||||
CoglFramebufferState state);
|
CoglFramebuffer *read_buffer,
|
||||||
|
CoglFramebufferState state);
|
||||||
|
|
||||||
CoglFramebuffer *
|
CoglFramebuffer *
|
||||||
_cogl_get_read_framebuffer (void);
|
_cogl_get_read_framebuffer (void);
|
||||||
|
@ -477,6 +477,7 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
|
|||||||
{
|
{
|
||||||
CoglFramebufferPrivate *priv =
|
CoglFramebufferPrivate *priv =
|
||||||
cogl_framebuffer_get_instance_private (framebuffer);
|
cogl_framebuffer_get_instance_private (framebuffer);
|
||||||
|
CoglContext *context = cogl_framebuffer_get_context (framebuffer);
|
||||||
CoglClipStack *clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
|
CoglClipStack *clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
|
||||||
gboolean had_depth_and_color_buffer_bits;
|
gboolean had_depth_and_color_buffer_bits;
|
||||||
int scissor_x0;
|
int scissor_x0;
|
||||||
@ -580,11 +581,12 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
|
|||||||
|
|
||||||
_cogl_framebuffer_flush_journal (framebuffer);
|
_cogl_framebuffer_flush_journal (framebuffer);
|
||||||
|
|
||||||
/* NB: _cogl_framebuffer_flush_state may disrupt various state (such
|
/* NB: cogl_context_flush_framebuffer_state may disrupt various state (such
|
||||||
* as the pipeline state) when flushing the clip stack, so should
|
* as the pipeline state) when flushing the clip stack, so should
|
||||||
* always be done first when preparing to draw. */
|
* always be done first when preparing to draw. */
|
||||||
_cogl_framebuffer_flush_state (framebuffer, framebuffer,
|
cogl_context_flush_framebuffer_state (context,
|
||||||
COGL_FRAMEBUFFER_STATE_ALL);
|
framebuffer, framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_ALL);
|
||||||
|
|
||||||
_cogl_framebuffer_clear_without_flush4f (framebuffer, buffers,
|
_cogl_framebuffer_clear_without_flush4f (framebuffer, buffers,
|
||||||
red, green, blue, alpha);
|
red, green, blue, alpha);
|
||||||
@ -1074,13 +1076,13 @@ _cogl_framebuffer_compare (CoglFramebuffer *a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
|
cogl_context_flush_framebuffer_state (CoglContext *ctx,
|
||||||
CoglFramebuffer *read_buffer,
|
CoglFramebuffer *draw_buffer,
|
||||||
CoglFramebufferState state)
|
CoglFramebuffer *read_buffer,
|
||||||
|
CoglFramebufferState state)
|
||||||
{
|
{
|
||||||
CoglContext *ctx = cogl_framebuffer_get_context (draw_buffer);
|
ctx->driver_vtable->flush_framebuffer_state (ctx,
|
||||||
|
draw_buffer,
|
||||||
ctx->driver_vtable->framebuffer_flush_state (draw_buffer,
|
|
||||||
read_buffer,
|
read_buffer,
|
||||||
state);
|
state);
|
||||||
}
|
}
|
||||||
@ -1593,10 +1595,11 @@ cogl_blit_framebuffer (CoglFramebuffer *framebuffer,
|
|||||||
|
|
||||||
/* Make sure the current framebuffers are bound. We explicitly avoid
|
/* Make sure the current framebuffers are bound. We explicitly avoid
|
||||||
flushing the clip state so we can bind our own empty state */
|
flushing the clip state so we can bind our own empty state */
|
||||||
_cogl_framebuffer_flush_state (dst,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
framebuffer,
|
dst,
|
||||||
COGL_FRAMEBUFFER_STATE_ALL &
|
framebuffer,
|
||||||
~COGL_FRAMEBUFFER_STATE_CLIP);
|
(COGL_FRAMEBUFFER_STATE_ALL &
|
||||||
|
~COGL_FRAMEBUFFER_STATE_CLIP));
|
||||||
|
|
||||||
/* Flush any empty clip stack because glBlitFramebuffer is affected
|
/* Flush any empty clip stack because glBlitFramebuffer is affected
|
||||||
by the scissor and we want to hide this feature for the Cogl API
|
by the scissor and we want to hide this feature for the Cogl API
|
||||||
|
@ -1051,9 +1051,10 @@ _cogl_journal_flush_dither_and_entries (CoglJournalEntry *batch_start,
|
|||||||
cogl_framebuffer_set_dither_enabled (framebuffer, batch_start->dither_enabled);
|
cogl_framebuffer_set_dither_enabled (framebuffer, batch_start->dither_enabled);
|
||||||
ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_DITHER;
|
ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_DITHER;
|
||||||
|
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_DITHER);
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_DITHER);
|
||||||
|
|
||||||
batch_and_call (batch_start,
|
batch_and_call (batch_start,
|
||||||
batch_len,
|
batch_len,
|
||||||
@ -1097,9 +1098,10 @@ _cogl_journal_flush_viewport_and_entries (CoglJournalEntry *batch_start,
|
|||||||
cogl_framebuffer_get_viewport4fv (framebuffer, current_viewport);
|
cogl_framebuffer_get_viewport4fv (framebuffer, current_viewport);
|
||||||
cogl_framebuffer_set_viewport4fv (framebuffer, batch_start->viewport);
|
cogl_framebuffer_set_viewport4fv (framebuffer, batch_start->viewport);
|
||||||
|
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_VIEWPORT);
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_VIEWPORT);
|
||||||
|
|
||||||
batch_and_call (batch_start,
|
batch_and_call (batch_start,
|
||||||
batch_len,
|
batch_len,
|
||||||
@ -1402,13 +1404,14 @@ _cogl_journal_flush (CoglJournal *journal)
|
|||||||
|
|
||||||
/* NB: the journal deals with flushing the viewport, the modelview
|
/* NB: the journal deals with flushing the viewport, the modelview
|
||||||
* stack and clip state manually */
|
* stack and clip state manually */
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_ALL &
|
framebuffer,
|
||||||
~(COGL_FRAMEBUFFER_STATE_DITHER |
|
COGL_FRAMEBUFFER_STATE_ALL &
|
||||||
COGL_FRAMEBUFFER_STATE_VIEWPORT |
|
~(COGL_FRAMEBUFFER_STATE_DITHER |
|
||||||
COGL_FRAMEBUFFER_STATE_MODELVIEW |
|
COGL_FRAMEBUFFER_STATE_VIEWPORT |
|
||||||
COGL_FRAMEBUFFER_STATE_CLIP));
|
COGL_FRAMEBUFFER_STATE_MODELVIEW |
|
||||||
|
COGL_FRAMEBUFFER_STATE_CLIP));
|
||||||
|
|
||||||
/* We need to mark the current modelview state of the framebuffer as
|
/* We need to mark the current modelview state of the framebuffer as
|
||||||
* dirty because we are going to manually replace it */
|
* dirty because we are going to manually replace it */
|
||||||
|
@ -52,11 +52,6 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
|
|||||||
void
|
void
|
||||||
_cogl_offscreen_gl_free (CoglOffscreen *offscreen);
|
_cogl_offscreen_gl_free (CoglOffscreen *offscreen);
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
|
|
||||||
CoglFramebuffer *read_buffer,
|
|
||||||
CoglFramebufferState state);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer,
|
_cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer,
|
||||||
unsigned long buffers,
|
unsigned long buffers,
|
||||||
@ -111,6 +106,10 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
|
|||||||
CoglBitmap *bitmap,
|
CoglBitmap *bitmap,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_gl_framebuffer_flush_state_differences (CoglGlFramebuffer *gl_framebuffer,
|
||||||
|
unsigned long differences);
|
||||||
|
|
||||||
#endif /* __COGL_FRAMEBUFFER_GL_PRIVATE_H__ */
|
#endif /* __COGL_FRAMEBUFFER_GL_PRIVATE_H__ */
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,6 +303,55 @@ _cogl_framebuffer_gl_flush_stereo_mode_state (CoglFramebuffer *framebuffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_gl_framebuffer_flush_state_differences (CoglGlFramebuffer *gl_framebuffer,
|
||||||
|
unsigned long differences)
|
||||||
|
{
|
||||||
|
CoglFramebufferDriver *driver = COGL_FRAMEBUFFER_DRIVER (gl_framebuffer);
|
||||||
|
CoglFramebuffer *framebuffer =
|
||||||
|
cogl_framebuffer_driver_get_framebuffer (driver);
|
||||||
|
int bit;
|
||||||
|
|
||||||
|
COGL_FLAGS_FOREACH_START (&differences, 1, bit)
|
||||||
|
{
|
||||||
|
/* XXX: We considered having an array of callbacks for each state index
|
||||||
|
* that we'd call here but decided that this way the compiler is more
|
||||||
|
* likely going to be able to in-line the flush functions and use the
|
||||||
|
* index to jump straight to the required code. */
|
||||||
|
switch (bit)
|
||||||
|
{
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT:
|
||||||
|
_cogl_framebuffer_gl_flush_viewport_state (framebuffer);
|
||||||
|
break;
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_CLIP:
|
||||||
|
_cogl_framebuffer_gl_flush_clip_state (framebuffer);
|
||||||
|
break;
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_DITHER:
|
||||||
|
_cogl_framebuffer_gl_flush_dither_state (framebuffer);
|
||||||
|
break;
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW:
|
||||||
|
_cogl_framebuffer_gl_flush_modelview_state (framebuffer);
|
||||||
|
break;
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION:
|
||||||
|
_cogl_framebuffer_gl_flush_projection_state (framebuffer);
|
||||||
|
break;
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING:
|
||||||
|
_cogl_framebuffer_gl_flush_front_face_winding_state (framebuffer);
|
||||||
|
break;
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE:
|
||||||
|
/* Nothing to do for depth write state change; the state will always
|
||||||
|
* be taken into account when flushing the pipeline's depth state. */
|
||||||
|
break;
|
||||||
|
case COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE:
|
||||||
|
_cogl_framebuffer_gl_flush_stereo_mode_state (framebuffer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_warn_if_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
COGL_FLAGS_FOREACH_END;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target)
|
_cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target)
|
||||||
{
|
{
|
||||||
@ -354,132 +403,6 @@ _cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
|
|
||||||
CoglFramebuffer *read_buffer,
|
|
||||||
CoglFramebufferState state)
|
|
||||||
{
|
|
||||||
CoglContext *ctx = cogl_framebuffer_get_context (draw_buffer);
|
|
||||||
unsigned long differences;
|
|
||||||
int bit;
|
|
||||||
|
|
||||||
/* We can assume that any state that has changed for the current
|
|
||||||
* framebuffer is different to the currently flushed value. */
|
|
||||||
differences = ctx->current_draw_buffer_changes;
|
|
||||||
|
|
||||||
/* Any state of the current framebuffer that hasn't already been
|
|
||||||
* flushed is assumed to be unknown so we will always flush that
|
|
||||||
* state if asked. */
|
|
||||||
differences |= ~ctx->current_draw_buffer_state_flushed;
|
|
||||||
|
|
||||||
/* We only need to consider the state we've been asked to flush */
|
|
||||||
differences &= state;
|
|
||||||
|
|
||||||
if (ctx->current_draw_buffer != draw_buffer)
|
|
||||||
{
|
|
||||||
/* If the previous draw buffer is NULL then we'll assume
|
|
||||||
everything has changed. This can happen if a framebuffer is
|
|
||||||
destroyed while it is the last flushed draw buffer. In that
|
|
||||||
case the framebuffer destructor will set
|
|
||||||
ctx->current_draw_buffer to NULL */
|
|
||||||
if (ctx->current_draw_buffer == NULL)
|
|
||||||
differences |= state;
|
|
||||||
else
|
|
||||||
/* NB: we only need to compare the state we're being asked to flush
|
|
||||||
* and we don't need to compare the state we've already decided
|
|
||||||
* we will definitely flush... */
|
|
||||||
differences |= _cogl_framebuffer_compare (ctx->current_draw_buffer,
|
|
||||||
draw_buffer,
|
|
||||||
state & ~differences);
|
|
||||||
|
|
||||||
/* NB: we don't take a reference here, to avoid a circular
|
|
||||||
* reference. */
|
|
||||||
ctx->current_draw_buffer = draw_buffer;
|
|
||||||
ctx->current_draw_buffer_state_flushed = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->current_read_buffer != read_buffer &&
|
|
||||||
state & COGL_FRAMEBUFFER_STATE_BIND)
|
|
||||||
{
|
|
||||||
differences |= COGL_FRAMEBUFFER_STATE_BIND;
|
|
||||||
/* NB: we don't take a reference here, to avoid a circular
|
|
||||||
* reference. */
|
|
||||||
ctx->current_read_buffer = read_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!differences)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Lazily ensure the framebuffers have been allocated */
|
|
||||||
if (G_UNLIKELY (!cogl_framebuffer_is_allocated (draw_buffer)))
|
|
||||||
cogl_framebuffer_allocate (draw_buffer, NULL);
|
|
||||||
if (G_UNLIKELY (!cogl_framebuffer_is_allocated (read_buffer)))
|
|
||||||
cogl_framebuffer_allocate (read_buffer, NULL);
|
|
||||||
|
|
||||||
/* We handle buffer binding separately since the method depends on whether
|
|
||||||
* we are binding the same buffer for read and write or not unlike all
|
|
||||||
* other state that only relates to the draw_buffer. */
|
|
||||||
if (differences & COGL_FRAMEBUFFER_STATE_BIND)
|
|
||||||
{
|
|
||||||
if (draw_buffer == read_buffer)
|
|
||||||
_cogl_framebuffer_gl_bind (draw_buffer, GL_FRAMEBUFFER);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* NB: Currently we only take advantage of binding separate
|
|
||||||
* read/write buffers for framebuffer blit purposes. */
|
|
||||||
g_return_if_fail (cogl_has_feature
|
|
||||||
(ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER));
|
|
||||||
|
|
||||||
_cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
|
|
||||||
_cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);
|
|
||||||
}
|
|
||||||
|
|
||||||
differences &= ~COGL_FRAMEBUFFER_STATE_BIND;
|
|
||||||
}
|
|
||||||
|
|
||||||
COGL_FLAGS_FOREACH_START (&differences, 1, bit)
|
|
||||||
{
|
|
||||||
/* XXX: We considered having an array of callbacks for each state index
|
|
||||||
* that we'd call here but decided that this way the compiler is more
|
|
||||||
* likely going to be able to in-line the flush functions and use the
|
|
||||||
* index to jump straight to the required code. */
|
|
||||||
switch (bit)
|
|
||||||
{
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT:
|
|
||||||
_cogl_framebuffer_gl_flush_viewport_state (draw_buffer);
|
|
||||||
break;
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_CLIP:
|
|
||||||
_cogl_framebuffer_gl_flush_clip_state (draw_buffer);
|
|
||||||
break;
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_DITHER:
|
|
||||||
_cogl_framebuffer_gl_flush_dither_state (draw_buffer);
|
|
||||||
break;
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW:
|
|
||||||
_cogl_framebuffer_gl_flush_modelview_state (draw_buffer);
|
|
||||||
break;
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION:
|
|
||||||
_cogl_framebuffer_gl_flush_projection_state (draw_buffer);
|
|
||||||
break;
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING:
|
|
||||||
_cogl_framebuffer_gl_flush_front_face_winding_state (draw_buffer);
|
|
||||||
break;
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE:
|
|
||||||
/* Nothing to do for depth write state change; the state will always
|
|
||||||
* be taken into account when flushing the pipeline's depth state. */
|
|
||||||
break;
|
|
||||||
case COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE:
|
|
||||||
_cogl_framebuffer_gl_flush_stereo_mode_state (draw_buffer);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_warn_if_reached ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
COGL_FLAGS_FOREACH_END;
|
|
||||||
|
|
||||||
ctx->current_draw_buffer_state_flushed |= state;
|
|
||||||
ctx->current_draw_buffer_changes &= ~state;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
try_creating_renderbuffers (CoglContext *ctx,
|
try_creating_renderbuffers (CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
@ -902,6 +825,12 @@ _cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer,
|
|||||||
GE (ctx, glClear (gl_buffers));
|
GE (ctx, glClear (gl_buffers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoglGlFramebuffer *
|
||||||
|
cogl_gl_framebuffer_from_framebuffer (CoglFramebuffer *framebuffer)
|
||||||
|
{
|
||||||
|
return ensure_gl_framebuffer (framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
static CoglGlFramebuffer *
|
static CoglGlFramebuffer *
|
||||||
ensure_gl_framebuffer (CoglFramebuffer *framebuffer)
|
ensure_gl_framebuffer (CoglFramebuffer *framebuffer)
|
||||||
{
|
{
|
||||||
@ -935,9 +864,10 @@ _cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
|
|||||||
|
|
||||||
cogl_framebuffer_allocate (framebuffer, NULL);
|
cogl_framebuffer_allocate (framebuffer, NULL);
|
||||||
|
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_BIND);
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_BIND);
|
||||||
|
|
||||||
#ifdef HAVE_COGL_GL
|
#ifdef HAVE_COGL_GL
|
||||||
if ((ctx->driver == COGL_DRIVER_GL3 &&
|
if ((ctx->driver == COGL_DRIVER_GL3 &&
|
||||||
@ -1072,9 +1002,10 @@ _cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer,
|
|||||||
attachments[i++] = GL_STENCIL_ATTACHMENT;
|
attachments[i++] = GL_STENCIL_ATTACHMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_BIND);
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_BIND);
|
||||||
GE (ctx, glDiscardFramebuffer (GL_FRAMEBUFFER, i, attachments));
|
GE (ctx, glDiscardFramebuffer (GL_FRAMEBUFFER, i, attachments));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1190,9 +1121,10 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
|
|||||||
|
|
||||||
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE);
|
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE);
|
||||||
|
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_BIND);
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_BIND);
|
||||||
|
|
||||||
/* The y coordinate should be given in OpenGL's coordinate system
|
/* The y coordinate should be given in OpenGL's coordinate system
|
||||||
* so 0 is the bottom row
|
* so 0 is the bottom row
|
||||||
|
@ -499,10 +499,11 @@ _cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d,
|
|||||||
/* Make sure the current framebuffers are bound, though we don't need to
|
/* Make sure the current framebuffers are bound, though we don't need to
|
||||||
* flush the clip state here since we aren't going to draw to the
|
* flush the clip state here since we aren't going to draw to the
|
||||||
* framebuffer. */
|
* framebuffer. */
|
||||||
_cogl_framebuffer_flush_state (ctx->current_draw_buffer,
|
cogl_context_flush_framebuffer_state (ctx,
|
||||||
src_fb,
|
ctx->current_draw_buffer,
|
||||||
COGL_FRAMEBUFFER_STATE_ALL &
|
src_fb,
|
||||||
~COGL_FRAMEBUFFER_STATE_CLIP);
|
(COGL_FRAMEBUFFER_STATE_ALL &
|
||||||
|
~COGL_FRAMEBUFFER_STATE_CLIP));
|
||||||
|
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture);
|
tex_2d->gl_texture);
|
||||||
|
@ -94,6 +94,12 @@ _cogl_driver_gl_context_init (CoglContext *context);
|
|||||||
void
|
void
|
||||||
_cogl_driver_gl_context_deinit (CoglContext *context);
|
_cogl_driver_gl_context_deinit (CoglContext *context);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_driver_gl_flush_framebuffer_state (CoglContext *context,
|
||||||
|
CoglFramebuffer *draw_buffer,
|
||||||
|
CoglFramebuffer *read_buffer,
|
||||||
|
CoglFramebufferState state);
|
||||||
|
|
||||||
GLenum
|
GLenum
|
||||||
_cogl_gl_util_get_error (CoglContext *ctx);
|
_cogl_gl_util_get_error (CoglContext *ctx);
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "cogl-types.h"
|
#include "cogl-types.h"
|
||||||
#include "cogl-context-private.h"
|
#include "cogl-context-private.h"
|
||||||
|
#include "driver/gl/cogl-framebuffer-gl-private.h"
|
||||||
#include "driver/gl/cogl-pipeline-opengl-private.h"
|
#include "driver/gl/cogl-pipeline-opengl-private.h"
|
||||||
#include "driver/gl/cogl-util-gl-private.h"
|
#include "driver/gl/cogl-util-gl-private.h"
|
||||||
|
|
||||||
@ -130,6 +131,97 @@ _cogl_driver_gl_context_deinit (CoglContext *context)
|
|||||||
g_free (context->driver_context);
|
g_free (context->driver_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_driver_gl_flush_framebuffer_state (CoglContext *ctx,
|
||||||
|
CoglFramebuffer *draw_buffer,
|
||||||
|
CoglFramebuffer *read_buffer,
|
||||||
|
CoglFramebufferState state)
|
||||||
|
{
|
||||||
|
CoglGlFramebuffer *draw_gl_framebuffer;
|
||||||
|
unsigned long differences;
|
||||||
|
|
||||||
|
/* We can assume that any state that has changed for the current
|
||||||
|
* framebuffer is different to the currently flushed value. */
|
||||||
|
differences = ctx->current_draw_buffer_changes;
|
||||||
|
|
||||||
|
/* Any state of the current framebuffer that hasn't already been
|
||||||
|
* flushed is assumed to be unknown so we will always flush that
|
||||||
|
* state if asked. */
|
||||||
|
differences |= ~ctx->current_draw_buffer_state_flushed;
|
||||||
|
|
||||||
|
/* We only need to consider the state we've been asked to flush */
|
||||||
|
differences &= state;
|
||||||
|
|
||||||
|
if (ctx->current_draw_buffer != draw_buffer)
|
||||||
|
{
|
||||||
|
/* If the previous draw buffer is NULL then we'll assume
|
||||||
|
everything has changed. This can happen if a framebuffer is
|
||||||
|
destroyed while it is the last flushed draw buffer. In that
|
||||||
|
case the framebuffer destructor will set
|
||||||
|
ctx->current_draw_buffer to NULL */
|
||||||
|
if (ctx->current_draw_buffer == NULL)
|
||||||
|
differences |= state;
|
||||||
|
else
|
||||||
|
/* NB: we only need to compare the state we're being asked to flush
|
||||||
|
* and we don't need to compare the state we've already decided
|
||||||
|
* we will definitely flush... */
|
||||||
|
differences |= _cogl_framebuffer_compare (ctx->current_draw_buffer,
|
||||||
|
draw_buffer,
|
||||||
|
state & ~differences);
|
||||||
|
|
||||||
|
/* NB: we don't take a reference here, to avoid a circular
|
||||||
|
* reference. */
|
||||||
|
ctx->current_draw_buffer = draw_buffer;
|
||||||
|
ctx->current_draw_buffer_state_flushed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->current_read_buffer != read_buffer &&
|
||||||
|
state & COGL_FRAMEBUFFER_STATE_BIND)
|
||||||
|
{
|
||||||
|
differences |= COGL_FRAMEBUFFER_STATE_BIND;
|
||||||
|
/* NB: we don't take a reference here, to avoid a circular
|
||||||
|
* reference. */
|
||||||
|
ctx->current_read_buffer = read_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!differences)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Lazily ensure the framebuffers have been allocated */
|
||||||
|
if (G_UNLIKELY (!cogl_framebuffer_is_allocated (draw_buffer)))
|
||||||
|
cogl_framebuffer_allocate (draw_buffer, NULL);
|
||||||
|
if (G_UNLIKELY (!cogl_framebuffer_is_allocated (read_buffer)))
|
||||||
|
cogl_framebuffer_allocate (read_buffer, NULL);
|
||||||
|
|
||||||
|
/* We handle buffer binding separately since the method depends on whether
|
||||||
|
* we are binding the same buffer for read and write or not unlike all
|
||||||
|
* other state that only relates to the draw_buffer. */
|
||||||
|
if (differences & COGL_FRAMEBUFFER_STATE_BIND)
|
||||||
|
{
|
||||||
|
if (draw_buffer == read_buffer)
|
||||||
|
_cogl_framebuffer_gl_bind (draw_buffer, GL_FRAMEBUFFER);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* NB: Currently we only take advantage of binding separate
|
||||||
|
* read/write buffers for framebuffer blit purposes. */
|
||||||
|
g_return_if_fail (cogl_has_feature
|
||||||
|
(ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER));
|
||||||
|
|
||||||
|
_cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
|
||||||
|
_cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
differences &= ~COGL_FRAMEBUFFER_STATE_BIND;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_gl_framebuffer = cogl_gl_framebuffer_from_framebuffer (draw_buffer);
|
||||||
|
cogl_gl_framebuffer_flush_state_differences (draw_gl_framebuffer,
|
||||||
|
differences);
|
||||||
|
|
||||||
|
ctx->current_draw_buffer_state_flushed |= state;
|
||||||
|
ctx->current_draw_buffer_changes &= ~state;
|
||||||
|
}
|
||||||
|
|
||||||
GLenum
|
GLenum
|
||||||
_cogl_gl_util_get_error (CoglContext *ctx)
|
_cogl_gl_util_get_error (CoglContext *ctx)
|
||||||
{
|
{
|
||||||
|
@ -571,7 +571,7 @@ _cogl_driver_gl =
|
|||||||
_cogl_driver_update_features,
|
_cogl_driver_update_features,
|
||||||
_cogl_offscreen_gl_allocate,
|
_cogl_offscreen_gl_allocate,
|
||||||
_cogl_offscreen_gl_free,
|
_cogl_offscreen_gl_free,
|
||||||
_cogl_framebuffer_gl_flush_state,
|
_cogl_driver_gl_flush_framebuffer_state,
|
||||||
_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,
|
||||||
|
@ -459,7 +459,7 @@ _cogl_driver_gles =
|
|||||||
_cogl_driver_update_features,
|
_cogl_driver_update_features,
|
||||||
_cogl_offscreen_gl_allocate,
|
_cogl_offscreen_gl_allocate,
|
||||||
_cogl_offscreen_gl_free,
|
_cogl_offscreen_gl_free,
|
||||||
_cogl_framebuffer_gl_flush_state,
|
_cogl_driver_gl_flush_framebuffer_state,
|
||||||
_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,
|
||||||
|
@ -67,6 +67,14 @@ _cogl_driver_nop_is_hardware_accelerated (CoglContext *context)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_driver_nop_flush_framebuffer_state (CoglContext *ctx,
|
||||||
|
CoglFramebuffer *draw_buffer,
|
||||||
|
CoglFramebuffer *read_buffer,
|
||||||
|
CoglFramebufferState state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const CoglDriverVtable
|
const CoglDriverVtable
|
||||||
_cogl_driver_nop =
|
_cogl_driver_nop =
|
||||||
{
|
{
|
||||||
@ -79,7 +87,7 @@ _cogl_driver_nop =
|
|||||||
_cogl_driver_update_features,
|
_cogl_driver_update_features,
|
||||||
_cogl_offscreen_nop_allocate,
|
_cogl_offscreen_nop_allocate,
|
||||||
_cogl_offscreen_nop_free,
|
_cogl_offscreen_nop_free,
|
||||||
_cogl_framebuffer_nop_flush_state,
|
_cogl_driver_nop_flush_framebuffer_state,
|
||||||
_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,
|
||||||
|
@ -45,11 +45,6 @@ _cogl_offscreen_nop_allocate (CoglOffscreen *offscreen,
|
|||||||
void
|
void
|
||||||
_cogl_offscreen_nop_free (CoglOffscreen *offscreen);
|
_cogl_offscreen_nop_free (CoglOffscreen *offscreen);
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_framebuffer_nop_flush_state (CoglFramebuffer *draw_buffer,
|
|
||||||
CoglFramebuffer *read_buffer,
|
|
||||||
CoglFramebufferState state);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_framebuffer_nop_clear (CoglFramebuffer *framebuffer,
|
_cogl_framebuffer_nop_clear (CoglFramebuffer *framebuffer,
|
||||||
unsigned long buffers,
|
unsigned long buffers,
|
||||||
|
@ -35,13 +35,6 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_framebuffer_nop_flush_state (CoglFramebuffer *draw_buffer,
|
|
||||||
CoglFramebuffer *read_buffer,
|
|
||||||
CoglFramebufferState state)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_offscreen_nop_allocate (CoglOffscreen *offscreen,
|
_cogl_offscreen_nop_allocate (CoglOffscreen *offscreen,
|
||||||
CoglOffscreenFlags flags,
|
CoglOffscreenFlags flags,
|
||||||
|
@ -240,9 +240,10 @@ _cogl_winsys_onscreen_egl_swap_region (CoglOnscreen *onscreen,
|
|||||||
swap must be bound to the current context. It looks like Mesa
|
swap must be bound to the current context. It looks like Mesa
|
||||||
also validates that this is the case for eglSwapBuffersRegion so
|
also validates that this is the case for eglSwapBuffersRegion so
|
||||||
we must bind here too */
|
we must bind here too */
|
||||||
_cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen),
|
cogl_context_flush_framebuffer_state (context,
|
||||||
COGL_FRAMEBUFFER (onscreen),
|
COGL_FRAMEBUFFER (onscreen),
|
||||||
COGL_FRAMEBUFFER_STATE_BIND);
|
COGL_FRAMEBUFFER (onscreen),
|
||||||
|
COGL_FRAMEBUFFER_STATE_BIND);
|
||||||
|
|
||||||
if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
|
if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
|
||||||
priv->egl_surface,
|
priv->egl_surface,
|
||||||
@ -274,9 +275,10 @@ _cogl_winsys_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
although it may change in future. Mesa explicitly checks for this
|
although it may change in future. Mesa explicitly checks for this
|
||||||
and just returns an error if this is not the case so we can't
|
and just returns an error if this is not the case so we can't
|
||||||
just pretend this isn't in the spec. */
|
just pretend this isn't in the spec. */
|
||||||
_cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen),
|
cogl_context_flush_framebuffer_state (context,
|
||||||
COGL_FRAMEBUFFER (onscreen),
|
COGL_FRAMEBUFFER (onscreen),
|
||||||
COGL_FRAMEBUFFER_STATE_BIND);
|
COGL_FRAMEBUFFER (onscreen),
|
||||||
|
COGL_FRAMEBUFFER_STATE_BIND);
|
||||||
|
|
||||||
if (n_rectangles && egl_renderer->pf_eglSwapBuffersWithDamage)
|
if (n_rectangles && egl_renderer->pf_eglSwapBuffersWithDamage)
|
||||||
{
|
{
|
||||||
|
@ -721,9 +721,10 @@ _cogl_winsys_onscreen_glx_swap_region (CoglOnscreen *onscreen,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (context,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_BIND);
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_BIND);
|
||||||
|
|
||||||
have_counter = glx_display->have_vblank_counter;
|
have_counter = glx_display->have_vblank_counter;
|
||||||
can_wait = glx_display->can_vblank_wait;
|
can_wait = glx_display->can_vblank_wait;
|
||||||
@ -891,9 +892,10 @@ _cogl_winsys_onscreen_glx_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
* the Intel drivers we have see that if we don't call
|
* the Intel drivers we have see that if we don't call
|
||||||
* glXMakeContextCurrent for the drawable we are swapping then
|
* glXMakeContextCurrent for the drawable we are swapping then
|
||||||
* we get a BadDrawable error from the X server. */
|
* we get a BadDrawable error from the X server. */
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
cogl_context_flush_framebuffer_state (context,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_BIND);
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_BIND);
|
||||||
|
|
||||||
drawable = onscreen_glx->glxwin ? onscreen_glx->glxwin : onscreen_glx->xwin;
|
drawable = onscreen_glx->glxwin ? onscreen_glx->glxwin : onscreen_glx->xwin;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user