[cogl] framebuffer: deal with winding state like other state



commit 2112af0bc51c5173a4b8fe2c6ea6bdca9274c5b3
Author: Robert Bragg <robert linux intel com>
Date:   Mon Nov 21 20:48:23 2011 +0000

    framebuffer: deal with winding state like other state
    
    We should not be deciding whether we need to really update the GL face
    winding state at the point where a new framebuffer has been pushed, we
    should be waiting until we have really been asked to flush some
    framebuffer state otherwise we may do redundant work if multiple
    framebuffers are pushed/popped before something is really drawn.
    
    This integrates the face winding state tracking with the design we have
    for handling most of the other framebuffer state so we benefit from the
    optimizations for minimizing the cost of _cogl_framebuffer_flush_state()
    
    Reviewed-by: Neil Roberts <neil linux intel com>

 cogl/cogl-framebuffer-private.h |   32 +++++++++--------
 cogl/cogl-framebuffer.c         |   70 +++++++++++++++++++++++++++-----------
 2 files changed, 67 insertions(+), 35 deletions(-)
---
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 9fbf54b..fce41e6 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -65,25 +65,27 @@ typedef enum
  */
 typedef enum _CoglFramebufferStateIndex
 {
-  COGL_FRAMEBUFFER_STATE_INDEX_BIND       = 0,
-  COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT   = 1,
-  COGL_FRAMEBUFFER_STATE_INDEX_CLIP       = 2,
-  COGL_FRAMEBUFFER_STATE_INDEX_DITHER     = 3,
-  COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW  = 4,
-  COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION = 5,
-  COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK = 6,
-  COGL_FRAMEBUFFER_STATE_INDEX_MAX        = 7
+  COGL_FRAMEBUFFER_STATE_INDEX_BIND               = 0,
+  COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT           = 1,
+  COGL_FRAMEBUFFER_STATE_INDEX_CLIP               = 2,
+  COGL_FRAMEBUFFER_STATE_INDEX_DITHER             = 3,
+  COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW          = 4,
+  COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION         = 5,
+  COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK         = 6,
+  COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING = 7,
+  COGL_FRAMEBUFFER_STATE_INDEX_MAX                = 8
 } CoglFramebufferStateIndex;
 
 typedef enum _CoglFramebufferState
 {
-  COGL_FRAMEBUFFER_STATE_BIND       = 1<<0,
-  COGL_FRAMEBUFFER_STATE_VIEWPORT   = 1<<1,
-  COGL_FRAMEBUFFER_STATE_CLIP       = 1<<2,
-  COGL_FRAMEBUFFER_STATE_DITHER     = 1<<3,
-  COGL_FRAMEBUFFER_STATE_MODELVIEW  = 1<<4,
-  COGL_FRAMEBUFFER_STATE_PROJECTION = 1<<5,
-  COGL_FRAMEBUFFER_STATE_COLOR_MASK = 1<<6
+  COGL_FRAMEBUFFER_STATE_BIND               = 1<<0,
+  COGL_FRAMEBUFFER_STATE_VIEWPORT           = 1<<1,
+  COGL_FRAMEBUFFER_STATE_CLIP               = 1<<2,
+  COGL_FRAMEBUFFER_STATE_DITHER             = 1<<3,
+  COGL_FRAMEBUFFER_STATE_MODELVIEW          = 1<<4,
+  COGL_FRAMEBUFFER_STATE_PROJECTION         = 1<<5,
+  COGL_FRAMEBUFFER_STATE_COLOR_MASK         = 1<<6,
+  COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING = 1<<7
 } CoglFramebufferState;
 
 #define COGL_FRAMEBUFFER_STATE_ALL ((1<<COGL_FRAMEBUFFER_STATE_INDEX_MAX) - 1)
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 5ed3b5e..f8fc101 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -1104,25 +1104,6 @@ notify_buffers_changed (CoglFramebuffer *old_draw_buffer,
                         CoglFramebuffer *old_read_buffer,
                         CoglFramebuffer *new_read_buffer)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  if (old_draw_buffer && new_draw_buffer)
-    {
-      /* If we're switching from onscreen to offscreen and the last
-         flush pipeline is using backface culling then we also need to
-         reflush the cull face state because the winding order of the
-         front face is flipped for offscreen buffers */
-      if (old_draw_buffer->type != new_draw_buffer->type &&
-          ctx->current_pipeline &&
-          cogl_pipeline_get_cull_face_mode (ctx->current_pipeline) !=
-          COGL_PIPELINE_CULL_FACE_MODE_NONE)
-        {
-          ctx->current_pipeline_changes_since_flush |=
-            COGL_PIPELINE_STATE_CULL_FACE;
-          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. A
@@ -1132,7 +1113,7 @@ notify_buffers_changed (CoglFramebuffer *old_draw_buffer,
    * _cogl_onscreen_free as a kind of a cheap weak reference */
   if (new_draw_buffer &&
       new_draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
-    ctx->window_buffer = new_draw_buffer;
+    new_draw_buffer->context->window_buffer = new_draw_buffer;
 }
 
 /* Set the current framebuffer without checking if it's already the
@@ -1429,6 +1410,16 @@ _cogl_framebuffer_compare_color_mask_state (CoglFramebuffer *a,
 }
 
 static unsigned long
+_cogl_framebuffer_compare_front_face_winding_state (CoglFramebuffer *a,
+                                                    CoglFramebuffer *b)
+{
+  if (a->type != b->type)
+    return COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING;
+  else
+    return 0;
+}
+
+static unsigned long
 _cogl_framebuffer_compare (CoglFramebuffer *a,
                            CoglFramebuffer *b,
                            unsigned long state)
@@ -1472,6 +1463,10 @@ _cogl_framebuffer_compare (CoglFramebuffer *a,
           differences |=
             _cogl_framebuffer_compare_color_mask_state (a, b);
           break;
+        case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING:
+          differences |=
+            _cogl_framebuffer_compare_front_face_winding_state (a, b);
+          break;
         default:
           g_warn_if_reached ();
         }
@@ -1565,6 +1560,38 @@ _cogl_framebuffer_flush_color_mask_state (CoglFramebuffer *framebuffer)
   context->current_pipeline_age--;
 }
 
+static void
+_cogl_framebuffer_flush_front_face_winding_state (CoglFramebuffer *framebuffer)
+{
+  CoglContext *context = framebuffer->context;
+  CoglPipelineCullFaceMode mode;
+
+  /* NB: The face winding state is actually owned by the current
+   * CoglPipeline.
+   *
+   * If we don't have a current pipeline then we can just assume that
+   * when we later do flush a pipeline we will check the current
+   * framebuffer to know how to setup the winding */
+  if (!context->current_pipeline)
+    return;
+
+  mode = cogl_pipeline_get_cull_face_mode (context->current_pipeline);
+
+  /* If the current CoglPipeline has a culling mode that doesn't care
+   * about the winding we can avoid forcing an update of the state and
+   * bail out. */
+  if (mode == COGL_PIPELINE_CULL_FACE_MODE_NONE ||
+      mode == COGL_PIPELINE_CULL_FACE_MODE_BOTH)
+    return;
+
+  /* Since the winding state is really owned by the current pipeline
+   * the way we "flush" an updated winding is to dirty the pipeline
+   * state... */
+  context->current_pipeline_changes_since_flush |=
+    COGL_PIPELINE_STATE_CULL_FACE;
+  context->current_pipeline_age--;
+}
+
 void
 _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
                                CoglFramebuffer *read_buffer,
@@ -1668,6 +1695,9 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
         case COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK:
           _cogl_framebuffer_flush_color_mask_state (draw_buffer);
           break;
+        case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING:
+          _cogl_framebuffer_flush_front_face_winding_state (draw_buffer);
+          break;
         default:
           g_warn_if_reached ();
         }



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