cogl/journal: Track viewport
CoglJournal tracks a few OpenGL states so that they can be batch-applied if necessary. It also has a nice property of allowing purely CPU-based glReadPixels() when the scene is composed of simple rectangles. However, the current journal implementation leaves various other GL states out, such as dithering and the viewport. In Clutter, that causes the journal to be flushed when picking, touching the GPU when we didn't really need to. Track the viewport of the framebuffer in the journal so that we can avoid flushing the journal so often. https://gitlab.gnome.org/GNOME/mutter/merge_requests/402
This commit is contained in:
parent
d57dbe1d4c
commit
0556138b9f
@ -414,6 +414,11 @@ _cogl_framebuffer_try_creating_gl_fbo (CoglContext *ctx,
|
|||||||
CoglOffscreenAllocateFlags flags,
|
CoglOffscreenAllocateFlags flags,
|
||||||
CoglGLFramebuffer *gl_framebuffer);
|
CoglGLFramebuffer *gl_framebuffer);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_framebuffer_set_viewport4fv (CoglFramebuffer *framebuffer,
|
||||||
|
float *viewport);
|
||||||
|
|
||||||
unsigned long
|
unsigned long
|
||||||
_cogl_framebuffer_compare (CoglFramebuffer *a,
|
_cogl_framebuffer_compare (CoglFramebuffer *a,
|
||||||
CoglFramebuffer *b,
|
CoglFramebuffer *b,
|
||||||
|
@ -481,6 +481,23 @@ _cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer,
|
|||||||
framebuffer->clip_stack = stack;
|
framebuffer->clip_stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_framebuffer_set_viewport4fv (CoglFramebuffer *framebuffer,
|
||||||
|
float *viewport)
|
||||||
|
{
|
||||||
|
if (framebuffer->viewport_x == viewport[0] &&
|
||||||
|
framebuffer->viewport_y == viewport[1] &&
|
||||||
|
framebuffer->viewport_width == viewport[2] &&
|
||||||
|
framebuffer->viewport_height == viewport[3])
|
||||||
|
return;
|
||||||
|
|
||||||
|
framebuffer->viewport_x = viewport[0];
|
||||||
|
framebuffer->viewport_y = viewport[1];
|
||||||
|
framebuffer->viewport_width = viewport[2];
|
||||||
|
framebuffer->viewport_height = viewport[3];
|
||||||
|
framebuffer->viewport_age++;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
|
cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
|
||||||
float x,
|
float x,
|
||||||
@ -488,8 +505,6 @@ cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
|
|||||||
float width,
|
float width,
|
||||||
float height)
|
float height)
|
||||||
{
|
{
|
||||||
CoglContext *context = framebuffer->context;
|
|
||||||
|
|
||||||
g_return_if_fail (width > 0 && height > 0);
|
g_return_if_fail (width > 0 && height > 0);
|
||||||
|
|
||||||
if (framebuffer->viewport_x == x &&
|
if (framebuffer->viewport_x == x &&
|
||||||
@ -498,16 +513,10 @@ cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
|
|||||||
framebuffer->viewport_height == height)
|
framebuffer->viewport_height == height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_cogl_framebuffer_flush_journal (framebuffer);
|
|
||||||
|
|
||||||
framebuffer->viewport_x = x;
|
framebuffer->viewport_x = x;
|
||||||
framebuffer->viewport_y = y;
|
framebuffer->viewport_y = y;
|
||||||
framebuffer->viewport_width = width;
|
framebuffer->viewport_width = width;
|
||||||
framebuffer->viewport_height = height;
|
framebuffer->viewport_height = height;
|
||||||
framebuffer->viewport_age++;
|
|
||||||
|
|
||||||
if (context->current_draw_buffer == framebuffer)
|
|
||||||
context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_VIEWPORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
|
@ -78,6 +78,7 @@ typedef struct _CoglJournalEntry
|
|||||||
CoglPipeline *pipeline;
|
CoglPipeline *pipeline;
|
||||||
CoglMatrixEntry *modelview_entry;
|
CoglMatrixEntry *modelview_entry;
|
||||||
CoglClipStack *clip_stack;
|
CoglClipStack *clip_stack;
|
||||||
|
float viewport[4];
|
||||||
/* Offset into ctx->logged_vertices */
|
/* Offset into ctx->logged_vertices */
|
||||||
size_t array_offset;
|
size_t array_offset;
|
||||||
int n_layers;
|
int n_layers;
|
||||||
|
@ -1044,6 +1044,55 @@ compare_entry_clip_stacks (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
|
|||||||
return entry0->clip_stack == entry1->clip_stack;
|
return entry0->clip_stack == entry1->clip_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_journal_flush_viewport_and_entries (CoglJournalEntry *batch_start,
|
||||||
|
int batch_len,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
CoglJournalFlushState *state = data;
|
||||||
|
CoglFramebuffer *framebuffer = state->journal->framebuffer;
|
||||||
|
CoglContext *ctx = framebuffer->context;
|
||||||
|
float current_viewport[4];
|
||||||
|
|
||||||
|
COGL_STATIC_TIMER (time_flush_viewport_and_entries,
|
||||||
|
"Journal Flush", /* parent */
|
||||||
|
"flush: viewport+clip+vbo+texcoords+pipeline+entries",
|
||||||
|
"The time spent flushing viewport + clip + vbo + texcoord offsets + "
|
||||||
|
"pipeline + entries",
|
||||||
|
0 /* no application private data */);
|
||||||
|
|
||||||
|
COGL_TIMER_START (_cogl_uprof_context, time_flush_viewport_and_entries);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
|
||||||
|
g_print ("BATCHING: viewport batch len = %d\n", batch_len);
|
||||||
|
|
||||||
|
ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_VIEWPORT;
|
||||||
|
|
||||||
|
cogl_framebuffer_get_viewport4fv (framebuffer, current_viewport);
|
||||||
|
cogl_framebuffer_set_viewport4fv (framebuffer, batch_start->viewport);
|
||||||
|
|
||||||
|
_cogl_framebuffer_flush_state (framebuffer,
|
||||||
|
framebuffer,
|
||||||
|
COGL_FRAMEBUFFER_STATE_VIEWPORT);
|
||||||
|
|
||||||
|
batch_and_call (batch_start,
|
||||||
|
batch_len,
|
||||||
|
compare_entry_clip_stacks,
|
||||||
|
_cogl_journal_flush_clip_stacks_and_entries,
|
||||||
|
state);
|
||||||
|
|
||||||
|
if (memcmp (batch_start->viewport, current_viewport, sizeof (float) * 4) != 0)
|
||||||
|
cogl_framebuffer_set_viewport4fv (framebuffer, current_viewport);
|
||||||
|
|
||||||
|
COGL_TIMER_STOP (_cogl_uprof_context, time_flush_viewport_and_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
compare_entry_viewports (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
|
||||||
|
{
|
||||||
|
return memcmp (entry0->viewport, entry1->viewport, sizeof (float) * 4) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Gets a new vertex array from the pool. A reference is taken on the
|
/* Gets a new vertex array from the pool. A reference is taken on the
|
||||||
array so it can be treated as if it was just newly allocated */
|
array so it can be treated as if it was just newly allocated */
|
||||||
static CoglAttributeBuffer *
|
static CoglAttributeBuffer *
|
||||||
@ -1331,12 +1380,13 @@ _cogl_journal_flush (CoglJournal *journal)
|
|||||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
|
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
|
||||||
g_print ("BATCHING: journal len = %d\n", journal->entries->len);
|
g_print ("BATCHING: journal len = %d\n", journal->entries->len);
|
||||||
|
|
||||||
/* NB: the journal deals with flushing the modelview stack and clip
|
/* NB: the journal deals with flushing the viewport, the modelview
|
||||||
state manually */
|
* stack and clip state manually */
|
||||||
_cogl_framebuffer_flush_state (framebuffer,
|
_cogl_framebuffer_flush_state (framebuffer,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
COGL_FRAMEBUFFER_STATE_ALL &
|
COGL_FRAMEBUFFER_STATE_ALL &
|
||||||
~(COGL_FRAMEBUFFER_STATE_MODELVIEW |
|
~(COGL_FRAMEBUFFER_STATE_VIEWPORT |
|
||||||
|
COGL_FRAMEBUFFER_STATE_MODELVIEW |
|
||||||
COGL_FRAMEBUFFER_STATE_CLIP));
|
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
|
||||||
@ -1395,11 +1445,11 @@ _cogl_journal_flush (CoglJournal *journal)
|
|||||||
* Note: Splitting by modelview changes is skipped when are doing the
|
* Note: Splitting by modelview changes is skipped when are doing the
|
||||||
* vertex transformation in software at log time.
|
* vertex transformation in software at log time.
|
||||||
*/
|
*/
|
||||||
batch_and_call ((CoglJournalEntry *)journal->entries->data, /* first entry */
|
batch_and_call ((CoglJournalEntry *)journal->entries->data,
|
||||||
journal->entries->len, /* max number of entries to consider */
|
journal->entries->len,
|
||||||
compare_entry_clip_stacks,
|
compare_entry_viewports,
|
||||||
_cogl_journal_flush_clip_stacks_and_entries, /* callback */
|
_cogl_journal_flush_viewport_and_entries,
|
||||||
&state); /* data */
|
&state);
|
||||||
|
|
||||||
for (i = 0; i < state.attributes->len; i++)
|
for (i = 0; i < state.attributes->len; i++)
|
||||||
cogl_object_unref (g_array_index (state.attributes, CoglAttribute *, i));
|
cogl_object_unref (g_array_index (state.attributes, CoglAttribute *, i));
|
||||||
@ -1553,6 +1603,8 @@ _cogl_journal_log_quad (CoglJournal *journal,
|
|||||||
clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
|
clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
|
||||||
entry->clip_stack = _cogl_clip_stack_ref (clip_stack);
|
entry->clip_stack = _cogl_clip_stack_ref (clip_stack);
|
||||||
|
|
||||||
|
cogl_framebuffer_get_viewport4fv (framebuffer, entry->viewport);
|
||||||
|
|
||||||
if (G_UNLIKELY (final_pipeline != pipeline))
|
if (G_UNLIKELY (final_pipeline != pipeline))
|
||||||
cogl_object_unref (final_pipeline);
|
cogl_object_unref (final_pipeline);
|
||||||
|
|
||||||
@ -1582,7 +1634,7 @@ entry_to_screen_polygon (CoglFramebuffer *framebuffer,
|
|||||||
CoglMatrix projection;
|
CoglMatrix projection;
|
||||||
CoglMatrix modelview;
|
CoglMatrix modelview;
|
||||||
int i;
|
int i;
|
||||||
float viewport[4];
|
const float *viewport = entry->viewport;
|
||||||
|
|
||||||
poly[0] = vertices[0];
|
poly[0] = vertices[0];
|
||||||
poly[1] = vertices[1];
|
poly[1] = vertices[1];
|
||||||
@ -1631,8 +1683,6 @@ entry_to_screen_polygon (CoglFramebuffer *framebuffer,
|
|||||||
poly, /* points_out */
|
poly, /* points_out */
|
||||||
4 /* n_points */);
|
4 /* n_points */);
|
||||||
|
|
||||||
cogl_framebuffer_get_viewport4fv (framebuffer, viewport);
|
|
||||||
|
|
||||||
/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
|
/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
|
||||||
* to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with
|
* to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with
|
||||||
* (0,0) being top left. */
|
* (0,0) being top left. */
|
||||||
|
Loading…
Reference in New Issue
Block a user