[cogl/wip/for-cairo-cogl] path: handle slice tex fallback using clip stack



commit f3b04b0f243d5be1fe2708b0acad77367c956c14
Author: Robert Bragg <robert linux intel com>
Date:   Sat Oct 1 18:40:10 2011 +0100

    path: handle slice tex fallback using clip stack
    
    If we are asked to fill a path using any sliced textures then we need
    to fallback to adding a mask of the path to the stencil buffer
    and then drawing a bounding rectangle with the source textures instead.
    
    Previously we were sharing some of the clip-stack code for adding
    the path mask to the stencil buffer and being careful to check
    that the current clip stack has been flushed already. We then made
    sure to dirty the clip stack to be sure the path mask would be cleared
    from the stencil buffer later.
    
    This patch aims to simplify how this fallback is dealt with by just
    using the public clipping API instead of relying on more fiddly tricks
    to modify the stencil buffer directly without conflicting with the clip
    stack.

 cogl/cogl2-path.c |  106 +++++++++++++++++++++-------------------------------
 1 files changed, 43 insertions(+), 63 deletions(-)
---
diff --git a/cogl/cogl2-path.c b/cogl/cogl2-path.c
index a5d6ad0..c2c478e 100644
--- a/cogl/cogl2-path.c
+++ b/cogl/cogl2-path.c
@@ -269,67 +269,62 @@ _cogl_path_get_bounds (CoglPath *path,
 }
 
 static void
-_cogl_path_fill_nodes_with_stencil_buffer (CoglPath *path)
+_cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path)
 {
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  g_assert (ctx->current_clip_stack_valid);
+  if (!cogl_features_available (COGL_FEATURE_STENCIL_BUFFER))
+    {
+      static gboolean seen_warning = FALSE;
 
-  _cogl_add_path_to_stencil_buffer (path,
-                                    ctx->current_clip_stack_uses_stencil,
-                                    FALSE);
+      if (!seen_warning)
+        {
+          g_warning ("Paths can not be filled using materials with "
+                     "sliced textures unless there is a stencil "
+                     "buffer");
+          seen_warning = TRUE;
+        }
+    }
 
-  _cogl_rectangle_immediate (path->data->path_nodes_min.x,
-                             path->data->path_nodes_min.y,
-                             path->data->path_nodes_max.x,
-                             path->data->path_nodes_max.y);
+  cogl_clip_push_from_path (path);
+  cogl_rectangle (path->data->path_nodes_min.x,
+                  path->data->path_nodes_min.y,
+                  path->data->path_nodes_max.x,
+                  path->data->path_nodes_max.y);
+  cogl_clip_pop ();
+}
 
-  /* The stencil buffer now contains garbage so the clip area needs to
-   * be rebuilt.
-   *
-   * NB: We only ever try and update the clip state during
-   * _cogl_journal_init (when we flush the framebuffer state) which is
-   * only called when the journal first gets something logged in it; so
-   * we call cogl_flush() to emtpy the journal.
+static gboolean
+validate_layer_cb (CoglPipelineLayer *layer, void *user_data)
+{
+  gboolean *needs_fallback = user_data;
+  CoglTexture *texture = _cogl_pipeline_layer_get_texture (layer);
+
+  /* If any of the layers of the current pipeline contain sliced
+   * textures or textures with waste then it won't work to draw the
+   * path directly. Instead we fallback to pushing the path as a clip
+   * on the clip-stack and drawing the path's bounding rectangle
+   * instead.
    */
-  _cogl_clip_stack_dirty ();
+
+  if (texture != NULL && (cogl_texture_is_sliced (texture) ||
+                          !_cogl_texture_can_hardware_repeat (texture)))
+    *needs_fallback = TRUE;
+
+  return !*needs_fallback;
 }
 
 static void
 _cogl_path_fill_nodes (CoglPath *path)
 {
-  const GList *l;
+  gboolean needs_fallback = FALSE;
 
-  /* If any of the layers of the current pipeline contain sliced
-     textures or textures with waste then it won't work to draw the
-     path directly. Instead we can use draw the texture as a quad
-     clipped to the stencil buffer. */
-  for (l = _cogl_pipeline_get_layers (cogl_get_source ()); l; l = l->next)
+  _cogl_pipeline_foreach_layer_internal (cogl_get_source (),
+                                         validate_layer_cb, &needs_fallback);
+  if (needs_fallback)
     {
-      CoglHandle layer = l->data;
-      CoglTexture *texture = _cogl_pipeline_layer_get_texture (layer);
-
-      if (texture != NULL &&
-          (cogl_texture_is_sliced (texture) ||
-           !_cogl_texture_can_hardware_repeat (texture)))
-        {
-          if (cogl_features_available (COGL_FEATURE_STENCIL_BUFFER))
-            _cogl_path_fill_nodes_with_stencil_buffer (path);
-          else
-            {
-              static gboolean seen_warning = FALSE;
-
-              if (!seen_warning)
-                {
-                  g_warning ("Paths can not be filled using materials with "
-                             "sliced textures unless there is a stencil "
-                             "buffer");
-                  seen_warning = TRUE;
-                }
-            }
-
-          return;
-        }
+      _cogl_path_fill_nodes_with_clipped_rectangle (path);
+      return;
     }
 
   _cogl_path_build_fill_attribute_buffer (path);
@@ -457,8 +452,6 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path,
 void
 cogl2_path_fill (CoglPath *path)
 {
-  CoglFramebuffer *framebuffer;
-
   g_return_if_fail (cogl_is_path (path));
 
   if (path->data->path_nodes->len == 0)
@@ -476,20 +469,7 @@ cogl2_path_fill (CoglPath *path)
       cogl_rectangle (x_1, y_1, x_2, y_2);
     }
   else
-    {
-      framebuffer = cogl_get_draw_framebuffer ();
-
-      _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,
-                                     _cogl_get_read_framebuffer (),
-                                     0);
-
-      _cogl_path_fill_nodes (path);
-    }
+    _cogl_path_fill_nodes (path);
 }
 
 void



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