From a067e7a16b52488b0bf66845959d649de4ca0d43 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 2 Feb 2011 14:23:53 +0000 Subject: [PATCH] cogl-framebuffer: Separate the draw and read buffer The current framebuffer is now internally separated so that there can be a different draw and read buffer. This is required to use the GL_EXT_framebuffer_blit extension. The current draw and read buffers are stored as a pair in a single stack so that pushing the draw and read buffer is done simultaneously with the new _cogl_push_framebuffers internal function. Calling cogl_pop_framebuffer will restore both the draw and read buffer to the previous state. The public cogl_push_framebuffer function is layered on top of the new function so that it just pushes the same buffer for both drawing and reading. When flushing the framebuffer state, the cogl_framebuffer_flush_state function now tackes a pointer to both the draw and the read buffer. Anywhere that was just flushing the state for the current framebuffer with _cogl_get_framebuffer now needs to call both _cogl_get_draw_buffer and _cogl_get_read_buffer. --- cogl/cogl-attribute.c | 8 +- cogl/cogl-clip-stack.c | 10 +- cogl/cogl-clip-state.c | 14 +- cogl/cogl-framebuffer-private.h | 23 ++- cogl/cogl-framebuffer.c | 253 +++++++++++++++++++++++--------- cogl/cogl-journal.c | 11 +- cogl/cogl-matrix-stack.c | 2 +- cogl/cogl-primitives.c | 4 +- cogl/cogl-texture.c | 2 +- cogl/cogl.c | 50 ++++--- cogl/cogl2-path.c | 8 +- 11 files changed, 264 insertions(+), 121 deletions(-) diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c index 5cb898687..5872aa232 100644 --- a/cogl/cogl-attribute.c +++ b/cogl/cogl-attribute.c @@ -480,7 +480,7 @@ enable_gl_state (CoglDrawFlags flags, CoglAttribute **attributes, ValidateLayerState *state) { - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); int i; #ifdef MAY_HAVE_PROGRAMABLE_GL GLuint generic_index = 0; @@ -1060,7 +1060,7 @@ flush_state (CoglDrawFlags flags, { if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH)) { - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); _cogl_journal_flush (framebuffer->journal, framebuffer); } @@ -1080,7 +1080,9 @@ flush_state (CoglDrawFlags flags, * stack can cause some drawing which would change the array * pointers. */ if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH)) - _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0); + _cogl_framebuffer_flush_state (_cogl_get_draw_buffer (), + _cogl_get_read_buffer (), + 0); } /* This can be called directly by the CoglJournal to draw attributes diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c index ef0313be3..c8685d98b 100644 --- a/cogl/cogl-clip-stack.c +++ b/cogl/cogl-clip-stack.c @@ -77,7 +77,7 @@ set_clip_plane (GLint plane_num, GLdouble plane[4]; #endif GLfloat angle; - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); CoglMatrixStack *modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer); CoglMatrixStack *projection_stack = @@ -131,7 +131,7 @@ set_clip_planes (float x_1, float x_2, float y_2) { - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); CoglMatrixStack *modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer); CoglMatrix modelview_matrix; @@ -192,7 +192,7 @@ add_stencil_clip_rectangle (float x_1, float y_2, gboolean first) { - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); CoglMatrixStack *modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer); CoglMatrixStack *projection_stack = @@ -586,7 +586,7 @@ _cogl_clip_stack_flush (CoglClipStack *stack) ctx->current_clip_stack = _cogl_clip_stack_ref (stack); modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES); @@ -617,7 +617,7 @@ _cogl_clip_stack_flush (CoglClipStack *stack) scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = scissor_y_start = 0; else { - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); /* We store the entry coordinates in Cogl coordinate space * but OpenGL requires the window origin to be the bottom diff --git a/cogl/cogl-clip-state.c b/cogl/cogl-clip-state.c index 4e6adca8b..a4a3b1ab2 100644 --- a/cogl/cogl-clip-state.c +++ b/cogl/cogl-clip-state.c @@ -51,7 +51,7 @@ cogl_clip_push_window_rectangle (int x_offset, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); clip_state = _cogl_framebuffer_get_clip_state (framebuffer); clip_state->stacks->data = @@ -82,7 +82,7 @@ cogl_clip_push_rectangle (float x_1, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); clip_state = _cogl_framebuffer_get_clip_state (framebuffer); cogl_get_modelview_matrix (&modelview_matrix); @@ -115,7 +115,7 @@ cogl_clip_push_from_path_preserve (void) _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); clip_state = _cogl_framebuffer_get_clip_state (framebuffer); cogl_get_modelview_matrix (&modelview_matrix); @@ -151,7 +151,7 @@ cogl_clip_pop (void) _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); clip_state = _cogl_framebuffer_get_clip_state (framebuffer); _cogl_clip_pop_real (clip_state); @@ -169,7 +169,7 @@ _cogl_clip_state_flush (CoglClipState *clip_state) void cogl_clip_ensure (void) { - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); CoglClipState *clip_state; clip_state = _cogl_framebuffer_get_clip_state (framebuffer); @@ -195,7 +195,7 @@ cogl_clip_stack_save (void) _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); clip_state = _cogl_framebuffer_get_clip_state (framebuffer); _cogl_clip_stack_save_real (clip_state); @@ -225,7 +225,7 @@ cogl_clip_stack_restore (void) _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); clip_state = _cogl_framebuffer_get_clip_state (framebuffer); _cogl_clip_stack_restore_real (clip_state); diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h index 6f69d0699..ce7a7d709 100644 --- a/cogl/cogl-framebuffer-private.h +++ b/cogl/cogl-framebuffer-private.h @@ -236,14 +236,18 @@ typedef enum _CoglFramebufferFlushFlags } CoglFramebufferFlushFlags; void -_cogl_framebuffer_flush_state (CoglFramebuffer *framebuffer, +_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, CoglFramebufferFlushFlags flags); CoglHandle _cogl_onscreen_new (void); CoglFramebuffer * -_cogl_get_framebuffer (void); +_cogl_get_draw_buffer (void); + +CoglFramebuffer * +_cogl_get_read_buffer (void); GSList * _cogl_create_framebuffer_stack (void); @@ -269,5 +273,20 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle, CoglOffscreenFlags create_flags, unsigned int level); +/* + * _cogl_push_framebuffers: + * @draw_buffer: A pointer to the buffer used for drawing + * @read_buffer: A pointer to the buffer used for reading back pixels + * + * Redirects drawing and reading to the specified framebuffers as in + * cogl_push_framebuffer() except that it allows the draw and read + * buffer to be different. The buffers are pushed as a pair so that + * they can later both be restored with a single call to + * cogl_pop_framebuffer(). + */ +void +_cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer); + #endif /* __COGL_FRAMEBUFFER_PRIVATE_H */ diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c index 23b851116..fd98bee3d 100644 --- a/cogl/cogl-framebuffer.c +++ b/cogl/cogl-framebuffer.c @@ -99,6 +99,12 @@ #ifndef GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE #define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 #endif +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER 0x8CA8 +#endif +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif typedef enum { _TRY_DEPTH_STENCIL = 1L<<0, @@ -106,6 +112,12 @@ typedef enum { _TRY_STENCIL = 1L<<2 } TryFBOFlags; +typedef struct _CoglFramebufferStackEntry +{ + CoglFramebuffer *draw_buffer; + CoglFramebuffer *read_buffer; +} CoglFramebufferStackEntry; + static void _cogl_framebuffer_free (CoglFramebuffer *framebuffer); static void _cogl_onscreen_free (CoglOnscreen *onscreen); static void _cogl_offscreen_free (CoglOffscreen *offscreen); @@ -364,7 +376,7 @@ _cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer, /* NB: _cogl_framebuffer_flush_state may disrupt various state (such * as the pipeline state) when flushing the clip stack, so should * always be done first when preparing to draw. */ - _cogl_framebuffer_flush_state (framebuffer, 0); + _cogl_framebuffer_flush_state (framebuffer, framebuffer, 0); _cogl_clear4f (buffers, red, green, blue, alpha);; @@ -505,7 +517,7 @@ _cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer, framebuffer->viewport_width = width; framebuffer->viewport_height = height; - if (_cogl_get_framebuffer () == framebuffer) + if (_cogl_get_draw_buffer () == framebuffer) ctx->dirty_gl_viewport = TRUE; } @@ -988,12 +1000,27 @@ _cogl_onscreen_clutter_backend_set_size (int width, int height) ctx->dirty_gl_viewport = 1; } +static CoglFramebufferStackEntry * +create_stack_entry (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) +{ + CoglFramebufferStackEntry *entry = g_slice_new (CoglFramebufferStackEntry); + + entry->draw_buffer = draw_buffer; + entry->read_buffer = read_buffer; + + return entry; +} + GSList * _cogl_create_framebuffer_stack (void) { + CoglFramebufferStackEntry *entry; GSList *stack = NULL; - return g_slist_prepend (stack, COGL_INVALID_HANDLE); + entry = create_stack_entry (COGL_INVALID_HANDLE, COGL_INVALID_HANDLE); + + return g_slist_prepend (stack, entry); } void @@ -1003,11 +1030,19 @@ _cogl_free_framebuffer_stack (GSList *stack) for (l = stack; l != NULL; l = l->next) { - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (l->data); - if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) - _cogl_offscreen_free (COGL_OFFSCREEN (framebuffer)); + CoglFramebufferStackEntry *entry = l->data; + + if (entry->draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) + _cogl_offscreen_free (COGL_OFFSCREEN (entry->draw_buffer)); else - _cogl_onscreen_free (COGL_ONSCREEN (framebuffer)); + _cogl_onscreen_free (COGL_ONSCREEN (entry->draw_buffer)); + + if (entry->read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) + _cogl_offscreen_free (COGL_OFFSCREEN (entry->read_buffer)); + else + _cogl_onscreen_free (COGL_ONSCREEN (entry->read_buffer)); + + g_slice_free (CoglFramebufferStackEntry, entry); } g_slist_free (stack); } @@ -1016,42 +1051,55 @@ _cogl_free_framebuffer_stack (GSList *stack) * current framebuffer. This is used by cogl_pop_framebuffer while * the top of the stack is currently not up to date. */ static void -_cogl_set_framebuffer_real (CoglFramebuffer *framebuffer) +_cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) { - CoglFramebuffer **entry; + CoglFramebufferStackEntry *entry; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - entry = (CoglFramebuffer **)&ctx->framebuffer_stack->data; + entry = ctx->framebuffer_stack->data; ctx->dirty_bound_framebuffer = 1; ctx->dirty_gl_viewport = 1; - if (framebuffer) - cogl_object_ref (framebuffer); - if (*entry) - cogl_object_unref (*entry); + if (draw_buffer) + cogl_object_ref (draw_buffer); + if (entry->draw_buffer) + cogl_object_unref (entry->draw_buffer); - *entry = framebuffer; + if (read_buffer) + cogl_object_ref (read_buffer); + if (entry->read_buffer) + cogl_object_unref (entry->read_buffer); + + entry->draw_buffer = draw_buffer; + entry->read_buffer = read_buffer; /* We've effectively just switched the current modelview and * projection matrix stacks and clip state so we need to dirty * them to ensure they get flushed for the next batch of geometry * we flush */ - _cogl_matrix_stack_dirty (framebuffer->modelview_stack); - _cogl_matrix_stack_dirty (framebuffer->projection_stack); + _cogl_matrix_stack_dirty (draw_buffer->modelview_stack); + _cogl_matrix_stack_dirty (draw_buffer->projection_stack); _cogl_clip_stack_dirty (); } -void -cogl_set_framebuffer (CoglFramebuffer *framebuffer) +static void +_cogl_set_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) { - CoglFramebuffer *current; + CoglFramebuffer *current_draw_buffer; + CoglFramebuffer *current_read_buffer; - g_return_if_fail (_cogl_is_framebuffer (framebuffer)); + g_return_if_fail (_cogl_is_framebuffer (draw_buffer)); + g_return_if_fail (_cogl_is_framebuffer (read_buffer)); - current = _cogl_get_framebuffer (); - if (current != framebuffer) + current_draw_buffer = _cogl_get_draw_buffer (); + current_read_buffer = _cogl_get_read_buffer (); + + if (current_draw_buffer != draw_buffer || + current_read_buffer != read_buffer) { /* XXX: eventually we want to remove this implicit journal flush * so we can log into the journal beyond framebuffer changes to @@ -1059,12 +1107,20 @@ cogl_set_framebuffer (CoglFramebuffer *framebuffer) * mid-scene renders to textures. Current will be NULL when the * framebuffer stack is first created so we need to guard * against that here */ - if (current) - _cogl_framebuffer_flush_journal (current); - _cogl_set_framebuffer_real (framebuffer); + if (current_draw_buffer) + _cogl_framebuffer_flush_journal (current_draw_buffer); + if (current_read_buffer) + _cogl_framebuffer_flush_journal (current_read_buffer); + _cogl_set_framebuffers_real (draw_buffer, read_buffer); } } +void +cogl_set_framebuffer (CoglFramebuffer *framebuffer) +{ + _cogl_set_framebuffers (framebuffer, framebuffer); +} + /* XXX: deprecated API */ void cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle handle) @@ -1074,48 +1130,83 @@ cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle handle) if (target == COGL_WINDOW_BUFFER) handle = ctx->window_buffer; + /* This is deprecated public API. The public API doesn't currently + really expose the concept of separate draw and read buffers so + for the time being this actually just sets both buffers */ cogl_set_framebuffer (handle); } CoglFramebuffer * -_cogl_get_framebuffer (void) +_cogl_get_draw_buffer (void) { + CoglFramebufferStackEntry *entry; + _COGL_GET_CONTEXT (ctx, NULL); g_assert (ctx->framebuffer_stack); - return ctx->framebuffer_stack->data; + entry = ctx->framebuffer_stack->data; + + return entry->draw_buffer; +} + +CoglFramebuffer * +_cogl_get_read_buffer (void) +{ + CoglFramebufferStackEntry *entry; + + _COGL_GET_CONTEXT (ctx, NULL); + + g_assert (ctx->framebuffer_stack); + + entry = ctx->framebuffer_stack->data; + + return entry->read_buffer; +} + +void +_cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) +{ + CoglFramebuffer *old_draw_buffer, *old_read_buffer; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + g_return_if_fail (_cogl_is_framebuffer (draw_buffer)); + g_return_if_fail (_cogl_is_framebuffer (read_buffer)); + g_assert (ctx->framebuffer_stack); + + /* Copy the top of the stack so that when we call cogl_set_framebuffer + it will still know what the old framebuffer was */ + old_draw_buffer = cogl_object_ref (_cogl_get_draw_buffer ()); + old_read_buffer = cogl_object_ref (_cogl_get_read_buffer ()); + ctx->framebuffer_stack = + g_slist_prepend (ctx->framebuffer_stack, + create_stack_entry (old_draw_buffer, + old_read_buffer)); + + _cogl_set_framebuffers (draw_buffer, read_buffer); } void cogl_push_framebuffer (CoglFramebuffer *buffer) { - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - g_return_if_fail (_cogl_is_framebuffer (buffer)); - g_assert (ctx->framebuffer_stack); - - /* Copy the top of the stack so that when we call cogl_set_framebuffer - it will still know what the old framebuffer was */ - ctx->framebuffer_stack = - g_slist_prepend (ctx->framebuffer_stack, - cogl_object_ref (_cogl_get_framebuffer ())); - - cogl_set_framebuffer (buffer); + _cogl_push_framebuffers (buffer, buffer); } /* XXX: deprecated API */ void cogl_push_draw_buffer (void) { - cogl_push_framebuffer (_cogl_get_framebuffer ()); + cogl_push_framebuffer (_cogl_get_draw_buffer ()); } void cogl_pop_framebuffer (void) { - CoglFramebuffer *to_pop; - CoglFramebuffer *to_restore; + CoglFramebufferStackEntry *to_pop; + CoglFramebufferStackEntry *to_restore; + gboolean changed = FALSE; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -1125,16 +1216,23 @@ cogl_pop_framebuffer (void) to_pop = ctx->framebuffer_stack->data; to_restore = ctx->framebuffer_stack->next->data; - if (to_pop != to_restore) + if (to_pop->draw_buffer != to_restore->draw_buffer || + to_pop->read_buffer != to_restore->read_buffer) { /* XXX: eventually we want to remove this implicit journal flush * so we can log into the journal beyond framebuffer changes to * support batching scenes that depend on the results of * mid-scene renders to textures. */ - _cogl_framebuffer_flush_journal (to_pop); + _cogl_framebuffer_flush_journal (to_pop->draw_buffer); + _cogl_framebuffer_flush_journal (to_pop->read_buffer); + + changed = TRUE; } - cogl_object_unref (to_pop); + cogl_object_unref (to_pop->draw_buffer); + cogl_object_unref (to_pop->read_buffer); + g_slice_free (CoglFramebufferStackEntry, to_pop); + ctx->framebuffer_stack = g_slist_delete_link (ctx->framebuffer_stack, ctx->framebuffer_stack); @@ -1142,8 +1240,9 @@ cogl_pop_framebuffer (void) /* If the framebuffer has changed as a result of popping the top * then re-assert the current buffer so as to dirty state as * necessary. */ - if (to_pop != to_restore) - _cogl_set_framebuffer_real (to_restore); + if (changed) + _cogl_set_framebuffers_real (to_restore->draw_buffer, + to_restore->read_buffer); } /* XXX: deprecated API */ @@ -1153,8 +1252,21 @@ cogl_pop_draw_buffer (void) cogl_pop_framebuffer (); } +static void +bind_gl_framebuffer (GLenum target, CoglFramebuffer *framebuffer) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) + GE (glBindFramebuffer (target, + COGL_OFFSCREEN (framebuffer)->fbo_handle)); + else + GE (glBindFramebuffer (target, 0)); +} + void -_cogl_framebuffer_flush_state (CoglFramebuffer *framebuffer, +_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, CoglFramebufferFlushFlags flags) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -1162,13 +1274,15 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *framebuffer, if (cogl_features_available (COGL_FEATURE_OFFSCREEN) && ctx->dirty_bound_framebuffer) { - if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) - { - GE (glBindFramebuffer (GL_FRAMEBUFFER, - COGL_OFFSCREEN (framebuffer)->fbo_handle)); - } + if (!cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT) || + draw_buffer == read_buffer) + bind_gl_framebuffer (GL_FRAMEBUFFER, draw_buffer); else - GE (glBindFramebuffer (GL_FRAMEBUFFER, 0)); + { + bind_gl_framebuffer (GL_DRAW_FRAMEBUFFER, draw_buffer); + bind_gl_framebuffer (GL_READ_FRAMEBUFFER, read_buffer); + } + ctx->dirty_bound_framebuffer = FALSE; } @@ -1181,41 +1295,42 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *framebuffer, * left, while Cogl defines them to be top left. * NB: We render upside down to offscreen framebuffers so we don't * need to convert the y offset in this case. */ - if (cogl_is_offscreen (framebuffer)) - gl_viewport_y = framebuffer->viewport_y; + if (cogl_is_offscreen (draw_buffer)) + gl_viewport_y = draw_buffer->viewport_y; else - gl_viewport_y = framebuffer->height - - (framebuffer->viewport_y + framebuffer->viewport_height); + gl_viewport_y = draw_buffer->height - + (draw_buffer->viewport_y + draw_buffer->viewport_height); COGL_NOTE (OPENGL, "Calling glViewport(%d, %d, %d, %d)", - framebuffer->viewport_x, + draw_buffer->viewport_x, gl_viewport_y, - framebuffer->viewport_width, - framebuffer->viewport_height); + draw_buffer->viewport_width, + draw_buffer->viewport_height); - GE (glViewport (framebuffer->viewport_x, + GE (glViewport (draw_buffer->viewport_x, gl_viewport_y, - framebuffer->viewport_width, - framebuffer->viewport_height)); + draw_buffer->viewport_width, + draw_buffer->viewport_height)); ctx->dirty_gl_viewport = FALSE; } /* since we might have changed the framebuffer, we should initialize * the bits; this is a no-op if they have already been initialized */ - _cogl_framebuffer_init_bits (framebuffer); + _cogl_framebuffer_init_bits (draw_buffer); + _cogl_framebuffer_init_bits (read_buffer); /* XXX: Flushing clip state may trash the modelview and projection * matrices so we must do it before flushing the matrices... */ if (!(flags & COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE)) - _cogl_clip_state_flush (&framebuffer->clip_state); + _cogl_clip_state_flush (&draw_buffer->clip_state); if (!(flags & COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW)) - _cogl_matrix_stack_flush_to_gl (framebuffer->modelview_stack, + _cogl_matrix_stack_flush_to_gl (draw_buffer->modelview_stack, COGL_MATRIX_MODELVIEW); - _cogl_matrix_stack_flush_to_gl (framebuffer->projection_stack, + _cogl_matrix_stack_flush_to_gl (draw_buffer->projection_stack, COGL_MATRIX_PROJECTION); } diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c index 7ec25cdfc..cdfb3c7ef 100644 --- a/cogl/cogl-journal.c +++ b/cogl/cogl-journal.c @@ -1312,6 +1312,7 @@ _cogl_journal_flush (CoglJournal *journal, /* NB: the journal deals with flushing the modelview stack and clip state manually */ _cogl_framebuffer_flush_state (framebuffer, + framebuffer, COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW | COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE); @@ -1518,7 +1519,7 @@ _cogl_journal_log_quad (CoglJournal *journal, entry->pipeline = _cogl_pipeline_journal_ref (source); - clip_stack = _cogl_framebuffer_get_clip_stack (_cogl_get_framebuffer ()); + clip_stack = _cogl_framebuffer_get_clip_stack (_cogl_get_draw_buffer ()); entry->clip_stack = _cogl_clip_stack_ref (clip_stack); if (G_UNLIKELY (source != pipeline)) @@ -1528,7 +1529,7 @@ _cogl_journal_log_quad (CoglJournal *journal, _cogl_pipeline_foreach_layer_internal (pipeline, add_framebuffer_deps_cb, - _cogl_get_framebuffer ()); + _cogl_get_draw_buffer ()); /* XXX: It doesn't feel very nice that in this case we just assume * that the journal is associated with the current framebuffer. I @@ -1536,7 +1537,7 @@ _cogl_journal_log_quad (CoglJournal *journal, * the reason we don't have that currently is that it would * introduce a circular reference. */ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BATCHING))) - _cogl_framebuffer_flush_journal (_cogl_get_framebuffer ()); + _cogl_framebuffer_flush_journal (_cogl_get_draw_buffer ()); COGL_TIMER_STOP (_cogl_uprof_context, log_timer); } @@ -1587,7 +1588,7 @@ entry_to_screen_polygon (const CoglJournalEntry *entry, 4 /* n_points */); projection_stack = - _cogl_framebuffer_get_projection_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_projection_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_get (projection_stack, &projection); cogl_matrix_project_points (&projection, @@ -1599,7 +1600,7 @@ entry_to_screen_polygon (const CoglJournalEntry *entry, poly, /* points_out */ 4 /* n_points */); - _cogl_framebuffer_get_viewport4fv (_cogl_get_framebuffer (), + _cogl_framebuffer_get_viewport4fv (_cogl_get_draw_buffer (), viewport); /* Scale from OpenGL normalized device coordinates (ranging from -1 to 1) diff --git a/cogl/cogl-matrix-stack.c b/cogl/cogl-matrix-stack.c index d0d34ef97..fd6541248 100644 --- a/cogl/cogl-matrix-stack.c +++ b/cogl/cogl-matrix-stack.c @@ -434,7 +434,7 @@ _cogl_matrix_stack_prepare_for_flush (CoglMatrixStack *stack, * always render upside down to offscreen buffers. */ if (mode == COGL_MATRIX_PROJECTION && - cogl_is_offscreen (_cogl_get_framebuffer ())) + cogl_is_offscreen (_cogl_get_draw_buffer ())) { CoglMatrix flipped_projection; CoglMatrix *projection = diff --git a/cogl/cogl-primitives.c b/cogl/cogl-primitives.c index 8628ee434..6719fe6d8 100644 --- a/cogl/cogl-primitives.c +++ b/cogl/cogl-primitives.c @@ -78,7 +78,7 @@ log_quad_sub_textures_cb (CoglHandle texture_handle, void *user_data) { TextureSlicedQuadState *state = user_data; - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); CoglHandle texture_override; float quad_coords[4]; @@ -542,7 +542,7 @@ _cogl_multitexture_quad_single_primitive (const float *position, if (state.override_pipeline) pipeline = state.override_pipeline; - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); _cogl_journal_log_quad (framebuffer->journal, position, pipeline, diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index 41aa68b95..2b4c09762 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -1048,7 +1048,7 @@ _cogl_texture_draw_and_read (CoglHandle handle, bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); /* Viewport needs to have some size and be inside the window for this */ _cogl_framebuffer_get_viewport4fv (framebuffer, viewport); if (viewport[0] < 0 || viewport[1] < 0 || diff --git a/cogl/cogl.c b/cogl/cogl.c index 333ef9a64..515e4dd3c 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -151,7 +151,7 @@ cogl_check_extension (const char *name, const char *ext) void cogl_clear (const CoglColor *color, unsigned long buffers) { - _cogl_framebuffer_clear (_cogl_get_framebuffer (), buffers, color); + _cogl_framebuffer_clear (_cogl_get_draw_buffer (), buffers, color); } static gboolean @@ -282,7 +282,7 @@ cogl_set_backface_culling_enabled (gboolean setting) return; /* Currently the journal can't track changes to backface culling state... */ - _cogl_framebuffer_flush_journal (_cogl_get_framebuffer ()); + _cogl_framebuffer_flush_journal (_cogl_get_draw_buffer ()); ctx->enable_backface_culling = setting; } @@ -311,7 +311,7 @@ _cogl_flush_face_winding (void) * all offscreen rendering is done upside down resulting in reversed winding * for all triangles. */ - if (cogl_is_offscreen (_cogl_get_framebuffer ())) + if (cogl_is_offscreen (_cogl_get_draw_buffer ())) winding = COGL_FRONT_WINDING_CLOCKWISE; else winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE; @@ -360,7 +360,7 @@ cogl_set_viewport (int x, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); _cogl_framebuffer_set_viewport (framebuffer, x, @@ -415,7 +415,7 @@ cogl_get_viewport (float v[4]) _COGL_GET_CONTEXT (ctx, NO_RETVAL); - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); _cogl_framebuffer_get_viewport4fv (framebuffer, viewport); for (i = 0; i < 4; i++) @@ -430,7 +430,7 @@ cogl_get_bitmasks (int *red, { CoglFramebuffer *framebuffer; - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); if (red) *red = _cogl_framebuffer_get_red_bits (framebuffer); @@ -497,7 +497,7 @@ _cogl_read_pixels_with_rowstride (int x, guint8 *pixels, int rowstride) { - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_read_buffer (); int framebuffer_height; int bpp; CoglBitmap *bmp; @@ -537,7 +537,9 @@ _cogl_read_pixels_with_rowstride (int x, */ cogl_flush (); - _cogl_framebuffer_flush_state (framebuffer, 0); + _cogl_framebuffer_flush_state (_cogl_get_draw_buffer (), + framebuffer, + 0); framebuffer_height = _cogl_framebuffer_get_height (framebuffer); @@ -706,7 +708,9 @@ cogl_begin_gl (void) * NB: _cogl_framebuffer_flush_state may disrupt various state (such * as the pipeline state) when flushing the clip stack, so should * always be done first when preparing to draw. */ - _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0); + _cogl_framebuffer_flush_state (_cogl_get_draw_buffer (), + _cogl_get_read_buffer (), + 0); /* Setup the state for the current pipeline */ @@ -762,7 +766,7 @@ void cogl_push_matrix (void) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_push (modelview_stack); } @@ -770,7 +774,7 @@ void cogl_pop_matrix (void) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_pop (modelview_stack); } @@ -778,7 +782,7 @@ void cogl_scale (float x, float y, float z) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_scale (modelview_stack, x, y, z); } @@ -786,7 +790,7 @@ void cogl_translate (float x, float y, float z) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_translate (modelview_stack, x, y, z); } @@ -794,7 +798,7 @@ void cogl_rotate (float angle, float x, float y, float z) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_rotate (modelview_stack, angle, x, y, z); } @@ -802,7 +806,7 @@ void cogl_transform (const CoglMatrix *matrix) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_multiply (modelview_stack, matrix); } @@ -831,7 +835,7 @@ cogl_frustum (float left, float z_far) { CoglMatrixStack *projection_stack = - _cogl_framebuffer_get_projection_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_projection_stack (_cogl_get_draw_buffer ()); _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -856,7 +860,7 @@ cogl_ortho (float left, { CoglMatrix ortho; CoglMatrixStack *projection_stack = - _cogl_framebuffer_get_projection_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_projection_stack (_cogl_get_draw_buffer ()); _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -869,7 +873,7 @@ void cogl_get_modelview_matrix (CoglMatrix *matrix) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_get (modelview_stack, matrix); _COGL_MATRIX_DEBUG_PRINT (matrix); } @@ -878,7 +882,7 @@ void cogl_set_modelview_matrix (CoglMatrix *matrix) { CoglMatrixStack *modelview_stack = - _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_modelview_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_set (modelview_stack, matrix); _COGL_MATRIX_DEBUG_PRINT (matrix); } @@ -887,7 +891,7 @@ void cogl_get_projection_matrix (CoglMatrix *matrix) { CoglMatrixStack *projection_stack = - _cogl_framebuffer_get_projection_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_projection_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_get (projection_stack, matrix); _COGL_MATRIX_DEBUG_PRINT (matrix); } @@ -896,7 +900,7 @@ void cogl_set_projection_matrix (CoglMatrix *matrix) { CoglMatrixStack *projection_stack = - _cogl_framebuffer_get_projection_stack (_cogl_get_framebuffer ()); + _cogl_framebuffer_get_projection_stack (_cogl_get_draw_buffer ()); _cogl_matrix_stack_set (projection_stack, matrix); /* FIXME: Update the inverse projection matrix!! Presumably use @@ -909,7 +913,7 @@ _cogl_get_clip_state (void) { CoglFramebuffer *framebuffer; - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); return _cogl_framebuffer_get_clip_state (framebuffer); } @@ -1119,5 +1123,5 @@ _cogl_swap_buffers_notify (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - _cogl_framebuffer_swap_notify (_cogl_get_framebuffer ()); + _cogl_framebuffer_swap_notify (_cogl_get_draw_buffer ()); } diff --git a/cogl/cogl2-path.c b/cogl/cogl2-path.c index d812290d4..f1f0e4532 100644 --- a/cogl/cogl2-path.c +++ b/cogl/cogl2-path.c @@ -355,7 +355,7 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path, gboolean need_clear) { CoglPathData *data = path->data; - CoglFramebuffer *framebuffer = _cogl_get_framebuffer (); + CoglFramebuffer *framebuffer = _cogl_get_draw_buffer (); CoglMatrixStack *modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer); CoglMatrixStack *projection_stack = @@ -466,14 +466,16 @@ cogl2_path_fill (CoglPath *path) if (path->data->path_nodes->len == 0) return; - framebuffer = _cogl_get_framebuffer (); + framebuffer = _cogl_get_draw_buffer (); _cogl_framebuffer_flush_journal (framebuffer); /* NB: _cogl_framebuffer_flush_state may disrupt various state (such * as the pipeline state) when flushing the clip stack, so should * always be done first when preparing to draw. */ - _cogl_framebuffer_flush_state (framebuffer, 0); + _cogl_framebuffer_flush_state (framebuffer, + _cogl_get_read_buffer (), + 0); _cogl_path_fill_nodes (path); }