[cogl/wip/neil/master-next: 9/10] cogl-framebuffer: Force flushing the color mask when changing fbs



commit 807a90f3000082dd21ec75d0dd9da4c35d576b38
Author: Neil Roberts <neil linux intel com>
Date:   Fri Sep 16 11:41:21 2011 +0100

    cogl-framebuffer: Force flushing the color mask when changing fbs
    
    When changing between two framebuffers that have different color masks
    it now forces the pipeline to flush the mask by setting
    current_pipeline_changes_since_flush. For this to work there needs to
    be a common bit of code that gets called when the framebuffers are
    changed that has access to both the old framebuffer and the new
    framebuffer. _cogl_set_framebuffers_real can't be used for this
    because when it is called from cogl_pop_framebuffer the stack entries
    have already changed so it can't know the old framebuffer. This patch
    adds a new function called notify_buffers_changed which should get
    called whenever the buffers are changed and it explicitly gets passed
    pointers to the old and new buffers. cogl_pop_framebuffer now calls
    this instead of trying to use _cogl_set_framebuffers_real to force a
    flush.
    
    This patch also fixes the ctx->window_buffer pointer. Previously this
    was implemented by searching in the framebuffer stack for an onscreen
    framebuffer whenever the current buffers are changed. However it does
    this after the stack has already changed so it won't usually find the
    right buffer.

 cogl/cogl-context.c     |    7 +++
 cogl/cogl-framebuffer.c |   94 ++++++++++++++++++++++++++++------------------
 2 files changed, 64 insertions(+), 37 deletions(-)
---
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 02f05a6..fe86721 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -297,6 +297,7 @@ cogl_context_new (CoglDisplay *display,
   for (i = 0; i < COGL_BUFFER_BIND_TARGET_COUNT; i++)
     context->current_buffer[i] = NULL;
 
+  context->window_buffer = NULL;
   context->framebuffer_stack = _cogl_create_framebuffer_stack ();
 
   /* XXX: In this case the Clutter backend is still responsible for
@@ -399,6 +400,12 @@ _cogl_context_free (CoglContext *context)
 
   _cogl_destroy_texture_units ();
 
+  if (context->window_buffer)
+    {
+      cogl_object_unref (context->window_buffer);
+      context->window_buffer = NULL;
+    }
+
   _cogl_free_framebuffer_stack (context->framebuffer_stack);
 
   if (context->current_path)
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 351ed19..2ba034f 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -1120,6 +1120,55 @@ _cogl_free_framebuffer_stack (GSList *stack)
   g_slist_free (stack);
 }
 
+static void
+notify_buffers_changed (CoglFramebuffer *old_draw_buffer,
+                        CoglFramebuffer *new_draw_buffer,
+                        CoglFramebuffer *old_read_buffer,
+                        CoglFramebuffer *new_read_buffer)
+{
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  ctx->dirty_bound_framebuffer = 1;
+  ctx->dirty_gl_viewport = 1;
+
+  /* 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 */
+  if (new_draw_buffer)
+    {
+      _cogl_matrix_stack_dirty (new_draw_buffer->modelview_stack);
+      _cogl_matrix_stack_dirty (new_draw_buffer->projection_stack);
+    }
+
+  _cogl_clip_stack_dirty ();
+
+  /* If the two draw framebuffers have a different color mask then we
+     need to ensure the logic ops are reflushed the next time
+     something is drawn */
+  if (old_draw_buffer && new_draw_buffer &&
+      cogl_framebuffer_get_color_mask (old_draw_buffer) !=
+      cogl_framebuffer_get_color_mask (new_draw_buffer))
+    {
+      ctx->current_pipeline_changes_since_flush |=
+        COGL_PIPELINE_STATE_LOGIC_OPS;
+      ctx->current_pipeline_age--;
+    }
+
+  /* XXX:
+   * To support the deprecated cogl_set_draw_buffer API we keep track
+   * of the last onscreen framebuffer that was set so that it can
+   * be restored if the COGL_WINDOW_BUFFER enum is used. */
+  if (new_draw_buffer &&
+      new_draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
+    {
+      cogl_object_ref (new_draw_buffer);
+      if (ctx->window_buffer)
+        cogl_object_unref (ctx->window_buffer);
+      ctx->window_buffer = new_draw_buffer;
+    }
+}
+
 /* Set the current framebuffer without checking if it's already the
  * current framebuffer. This is used by cogl_pop_framebuffer while
  * the top of the stack is currently not up to date. */
@@ -1128,7 +1177,6 @@ _cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer,
                              CoglFramebuffer *read_buffer)
 {
   CoglFramebufferStackEntry *entry;
-  GSList *l;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
@@ -1138,8 +1186,10 @@ _cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer,
 
   entry = ctx->framebuffer_stack->data;
 
-  ctx->dirty_bound_framebuffer = 1;
-  ctx->dirty_gl_viewport = 1;
+  notify_buffers_changed (entry->draw_buffer,
+                          draw_buffer,
+                          entry->read_buffer,
+                          read_buffer);
 
   if (draw_buffer)
     cogl_object_ref (draw_buffer);
@@ -1153,31 +1203,6 @@ _cogl_set_framebuffers_real (CoglFramebuffer *draw_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 */
-  if (draw_buffer)
-    {
-      _cogl_matrix_stack_dirty (draw_buffer->modelview_stack);
-      _cogl_matrix_stack_dirty (draw_buffer->projection_stack);
-    }
-
-  _cogl_clip_stack_dirty ();
-
-  /* XXX:
-   * To support the deprecated cogl_set_draw_buffer API we keep track
-   * of the last onscreen framebuffer that was pushed so that it can
-   * be restored if the COGL_WINDOW_BUFFER enum is used. */
-  ctx->window_buffer = NULL;
-  for (l = ctx->framebuffer_stack; l; l = l->next)
-    {
-      entry = l->data;
-      if (entry->draw_buffer &&
-          entry->draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
-        ctx->window_buffer = entry->draw_buffer;
-    }
 }
 
 static void
@@ -1309,7 +1334,6 @@ cogl_pop_framebuffer (void)
 {
   CoglFramebufferStackEntry *to_pop;
   CoglFramebufferStackEntry *to_restore;
-  gboolean changed = FALSE;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
@@ -1329,7 +1353,10 @@ cogl_pop_framebuffer (void)
       _cogl_framebuffer_flush_journal (to_pop->draw_buffer);
       _cogl_framebuffer_flush_journal (to_pop->read_buffer);
 
-      changed = TRUE;
+      notify_buffers_changed (to_pop->draw_buffer,
+                              to_restore->draw_buffer,
+                              to_pop->read_buffer,
+                              to_restore->read_buffer);
     }
 
   cogl_object_unref (to_pop->draw_buffer);
@@ -1339,13 +1366,6 @@ cogl_pop_framebuffer (void)
   ctx->framebuffer_stack =
     g_slist_delete_link (ctx->framebuffer_stack,
                          ctx->framebuffer_stack);
-
-  /* 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 (changed)
-    _cogl_set_framebuffers_real (to_restore->draw_buffer,
-                                 to_restore->read_buffer);
 }
 
 /* XXX: deprecated API */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]