[cogl/wip/rib/cogl-1.12: 51/142] Replace cogl_path_{stroke, fill} with framebuffer API



commit a14f2cadd19787439297775b2cfbfd4205b43a69
Author: Neil Roberts <neil linux intel com>
Date:   Wed Apr 18 15:57:33 2012 +0100

    Replace cogl_path_{stroke,fill} with framebuffer API
    
    The existing functions for stroking and filling a path depend on the
    global framebuffer and source stacks. These are now replaced with
    cogl_framebuffer_{stroke,fill}_path which get explicitly passed the
    framebuffer and pipeline.
    
    Reviewed-by: Robert Bragg <robert linux intel com>
    
    (cherry picked from commit 713a8f8160bc5884b091c69eb7a84b069e0950e6)

 cogl-pango/cogl-pango-display-list.c               |    3 +-
 cogl/cogl-clip-stack.c                             |   20 +++-
 cogl/cogl-framebuffer.c                            |   25 ++++
 cogl/cogl-framebuffer.h                            |   41 +++++++
 cogl/cogl-path-private.h                           |   10 ++-
 cogl/cogl2-path.c                                  |  117 ++++++++++++--------
 .../cogl-2.0-experimental-sections.txt             |    4 +-
 tests/conform/test-path.c                          |   64 ++++++-----
 8 files changed, 200 insertions(+), 84 deletions(-)
---
diff --git a/cogl-pango/cogl-pango-display-list.c b/cogl-pango/cogl-pango-display-list.c
index f4f130f..eda3c07 100644
--- a/cogl-pango/cogl-pango-display-list.c
+++ b/cogl-pango/cogl-pango-display-list.c
@@ -437,6 +437,7 @@ _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
 
         case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
           {
+            CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
             float points[8];
             CoglPath *path;
 
@@ -453,7 +454,7 @@ _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
 
             path = cogl_path_new ();
             cogl_path_polygon (path, points, 4);
-            cogl_path_fill (path);
+            cogl_framebuffer_fill_path (framebuffer, node->pipeline, path);
             cogl_object_unref (path);
           }
           break;
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index 1bab67d..e5703c2 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -278,7 +278,9 @@ add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
   GE( ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
 }
 
-typedef void (*SilhouettePaintCallback) (void *user_data);
+typedef void (*SilhouettePaintCallback) (CoglFramebuffer *framebuffer,
+                                         CoglPipeline *pipeline,
+                                         void *user_data);
 
 static void
 add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
@@ -346,7 +348,7 @@ add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
 
   GE (ctx, glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT));
 
-  silhouette_callback (user_data);
+  silhouette_callback (framebuffer, ctx->stencil_pipeline, user_data);
 
   if (merge)
     {
@@ -382,11 +384,15 @@ add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
 }
 
 static void
-paint_path_silhouette (void *user_data)
+paint_path_silhouette (CoglFramebuffer *framebuffer,
+                       CoglPipeline *pipeline,
+                       void *user_data)
 {
   CoglPath *path = user_data;
   if (path->data->path_nodes->len >= 3)
     _cogl_path_fill_nodes (path,
+                           framebuffer,
+                           pipeline,
                            COGL_DRAW_SKIP_JOURNAL_FLUSH |
                            COGL_DRAW_SKIP_PIPELINE_VALIDATION |
                            COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH);
@@ -411,10 +417,12 @@ add_stencil_clip_path (CoglFramebuffer *framebuffer,
 }
 
 static void
-paint_primitive_silhouette (void *user_data)
+paint_primitive_silhouette (CoglFramebuffer *framebuffer,
+                            CoglPipeline *pipeline,
+                            void *user_data)
 {
-  _cogl_framebuffer_draw_primitive (cogl_get_draw_framebuffer (),
-                                    cogl_get_source (),
+  _cogl_framebuffer_draw_primitive (framebuffer,
+                                    pipeline,
                                     user_data,
                                     COGL_DRAW_SKIP_JOURNAL_FLUSH |
                                     COGL_DRAW_SKIP_PIPELINE_VALIDATION |
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index af6ecff..4e24e03 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -47,6 +47,7 @@
 #include "cogl1-context.h"
 #include "cogl-private.h"
 #include "cogl-primitives-private.h"
+#include "cogl-path-private.h"
 
 #ifndef GL_FRAMEBUFFER
 #define GL_FRAMEBUFFER		0x8D40
@@ -3522,3 +3523,27 @@ cogl_framebuffer_draw_textured_rectangles (CoglFramebuffer *framebuffer,
                                                    n_rectangles,
                                                    TRUE);
 }
+
+void
+cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
+                            CoglPipeline *pipeline,
+                            CoglPath *path)
+{
+  _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (framebuffer));
+  _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline));
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  _cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */);
+}
+
+void
+cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
+                              CoglPipeline *pipeline,
+                              CoglPath *path)
+{
+  _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (framebuffer));
+  _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline));
+  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+
+  _cogl_path_stroke_nodes (path, framebuffer, pipeline);
+}
diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h
index 3750ca1..76ce811 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -1491,6 +1491,47 @@ cogl_framebuffer_draw_textured_rectangles (CoglFramebuffer *framebuffer,
                                            const float *coordinates,
                                            unsigned int n_rectangles);
 
+/**
+ * cogl_framebuffer_fill_path:
+ * @framebuffer: A #CoglFramebuffer
+ * @pipeline: A #CoglPipeline to render with
+ * @path: The #CoglPath to fill
+ *
+ * Fills the interior of the path using the fragment operations
+ * defined by the pipeline.
+ *
+ * The interior of the shape is determined using the fill rule of the
+ * path. See %CoglPathFillRule for details.
+ *
+ * <note>The result of referencing sliced textures in your current
+ * pipeline when filling a path are undefined. You should pass
+ * the %COGL_TEXTURE_NO_SLICING flag when loading any texture you will
+ * use while filling a path.</note>
+ *
+ * Since: 2.0
+ */
+void
+cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
+                            CoglPipeline *pipeline,
+                            CoglPath *path);
+
+/**
+ * cogl_framebuffer_stroke_path:
+ * @framebuffer: A #CoglFramebuffer
+ * @pipeline: A #CoglPipeline to render with
+ * @path: The #CoglPath to stroke
+ *
+ * Strokes the edge of the path using the fragment operations defined
+ * by the pipeline. The stroke line will have a width of 1 pixel
+ * regardless of the current transformation matrix.
+ *
+ * Since: 2.0
+ */
+void
+cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
+                              CoglPipeline *pipeline,
+                              CoglPath *path);
+
 /* XXX: Should we take an n_buffers + buffer id array instead of using
  * the CoglBufferBits type which doesn't seem future proof? */
 /**
diff --git a/cogl/cogl-path-private.h b/cogl/cogl-path-private.h
index c7e94a8..cc0b65c 100644
--- a/cogl/cogl-path-private.h
+++ b/cogl/cogl-path-private.h
@@ -116,6 +116,14 @@ CoglBool
 _cogl_path_is_rectangle (CoglPath *path);
 
 void
-_cogl_path_fill_nodes (CoglPath *path, CoglDrawFlags flags);
+_cogl_path_stroke_nodes (CoglPath *path,
+                         CoglFramebuffer *framebuffer,
+                         CoglPipeline *pipeline);
+
+void
+_cogl_path_fill_nodes (CoglPath *path,
+                       CoglFramebuffer *framebuffer,
+                       CoglPipeline *pipeline,
+                       CoglDrawFlags flags);
 
 #endif /* __COGL_PATH_PRIVATE_H */
diff --git a/cogl/cogl2-path.c b/cogl/cogl2-path.c
index 3934015..f7327ae 100644
--- a/cogl/cogl2-path.c
+++ b/cogl/cogl2-path.c
@@ -202,37 +202,37 @@ _cogl_path_add_node (CoglPath *path,
   data->is_rectangle = FALSE;
 }
 
-static void
-_cogl_path_stroke_nodes (CoglPath *path)
+void
+_cogl_path_stroke_nodes (CoglPath *path,
+                         CoglFramebuffer *framebuffer,
+                         CoglPipeline *pipeline)
 {
   CoglPathData *data = path->data;
   CoglPipeline *copy = NULL;
-  CoglPipeline *source;
   unsigned int path_start;
   int path_num = 0;
   CoglPathNode *node;
 
-  source = cogl_get_source ();
+  if (data->path_nodes->len == 0)
+    return;
 
-  if (cogl_pipeline_get_n_layers (source) != 0)
+  if (cogl_pipeline_get_n_layers (pipeline) != 0)
     {
-      copy = cogl_pipeline_copy (source);
+      copy = cogl_pipeline_copy (pipeline);
       _cogl_pipeline_prune_to_n_layers (copy, 0);
-      source = copy;
+      pipeline = copy;
     }
 
   _cogl_path_build_stroke_attribute_buffer (path);
 
-  cogl_push_source (source);
-
   for (path_start = 0;
        path_start < data->path_nodes->len;
        path_start += node->path_size)
     {
       node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
 
-      cogl_framebuffer_vdraw_attributes (cogl_get_draw_framebuffer (),
-                                         source,
+      cogl_framebuffer_vdraw_attributes (framebuffer,
+                                         pipeline,
                                          COGL_VERTICES_MODE_LINE_STRIP,
                                          0, node->path_size,
                                          data->stroke_attributes[path_num],
@@ -241,8 +241,6 @@ _cogl_path_stroke_nodes (CoglPath *path)
       path_num++;
     }
 
-  cogl_pop_source ();
-
   if (copy)
     cogl_object_unref (copy);
 }
@@ -273,10 +271,10 @@ _cogl_path_get_bounds (CoglPath *path,
 }
 
 static void
-_cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path)
+_cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path,
+                                              CoglFramebuffer *framebuffer,
+                                              CoglPipeline *pipeline)
 {
-  CoglFramebuffer *fb;
-
   if (!(path->data->context->private_feature_flags &
         COGL_PRIVATE_FEATURE_STENCIL_BUFFER))
     {
@@ -291,13 +289,14 @@ _cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path)
         }
     }
 
-  fb = cogl_get_draw_framebuffer ();
-  cogl_framebuffer_push_path_clip (fb, 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_framebuffer_pop_clip (fb);
+  cogl_framebuffer_push_path_clip (framebuffer, path);
+  cogl_framebuffer_draw_rectangle (framebuffer,
+                                   pipeline,
+                                   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_framebuffer_pop_clip (framebuffer);
 }
 
 static CoglBool
@@ -321,30 +320,55 @@ validate_layer_cb (CoglPipelineLayer *layer, void *user_data)
 }
 
 void
-_cogl_path_fill_nodes (CoglPath *path, CoglDrawFlags flags)
+_cogl_path_fill_nodes (CoglPath *path,
+                       CoglFramebuffer *framebuffer,
+                       CoglPipeline *pipeline,
+                       CoglDrawFlags flags)
 {
-  gboolean needs_fallback = FALSE;
-  CoglPipeline *pipeline = cogl_get_source ();
+  if (path->data->path_nodes->len == 0)
+    return;
 
-  _cogl_pipeline_foreach_layer_internal (pipeline,
-                                         validate_layer_cb, &needs_fallback);
-  if (needs_fallback)
+  /* If the path is a simple rectangle then we can divert to using
+     cogl_framebuffer_draw_rectangle which should be faster because it
+     can go through the journal instead of uploading the geometry just
+     for two triangles */
+  if (path->data->is_rectangle && flags == 0)
     {
-      _cogl_path_fill_nodes_with_clipped_rectangle (path);
-      return;
+      float x_1, y_1, x_2, y_2;
+
+      _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2);
+      cogl_framebuffer_draw_rectangle (framebuffer,
+                                       pipeline,
+                                       x_1, y_1,
+                                       x_2, y_2);
     }
+  else
+    {
+      CoglBool needs_fallback = FALSE;
 
-  _cogl_path_build_fill_attribute_buffer (path);
-
-  _cogl_framebuffer_draw_indexed_attributes (cogl_get_draw_framebuffer (),
-                                             pipeline,
-                                             COGL_VERTICES_MODE_TRIANGLES,
-                                             0, /* first_vertex */
-                                             path->data->fill_vbo_n_indices,
-                                             path->data->fill_vbo_indices,
-                                             path->data->fill_attributes,
-                                             COGL_PATH_N_ATTRIBUTES,
-                                             flags);
+      _cogl_pipeline_foreach_layer_internal (pipeline,
+                                             validate_layer_cb,
+                                             &needs_fallback);
+      if (needs_fallback)
+        {
+          _cogl_path_fill_nodes_with_clipped_rectangle (path,
+                                                        framebuffer,
+                                                        pipeline);
+          return;
+        }
+
+      _cogl_path_build_fill_attribute_buffer (path);
+
+      _cogl_framebuffer_draw_indexed_attributes (framebuffer,
+                                                 pipeline,
+                                                 COGL_VERTICES_MODE_TRIANGLES,
+                                                 0, /* first_vertex */
+                                                 path->data->fill_vbo_n_indices,
+                                                 path->data->fill_vbo_indices,
+                                                 path->data->fill_attributes,
+                                                 COGL_PATH_N_ATTRIBUTES,
+                                                 flags);
+    }
 }
 
 void
@@ -367,7 +391,10 @@ cogl2_path_fill (CoglPath *path)
       cogl_rectangle (x_1, y_1, x_2, y_2);
     }
   else
-    _cogl_path_fill_nodes (path, 0);
+    _cogl_path_fill_nodes (path,
+                           cogl_get_draw_framebuffer (),
+                           cogl_get_source (),
+                           0);
 }
 
 void
@@ -378,7 +405,9 @@ cogl2_path_stroke (CoglPath *path)
   if (path->data->path_nodes->len == 0)
     return;
 
-  _cogl_path_stroke_nodes (path);
+  _cogl_path_stroke_nodes (path,
+                           cogl_get_draw_framebuffer (),
+                           cogl_get_source ());
 }
 
 void
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
index ade861d..da3d431 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
@@ -286,8 +286,6 @@ cogl_path_ellipse
 CoglPathFillRule
 cogl_path_set_fill_rule
 cogl_path_get_fill_rule
-cogl_path_fill
-cogl_path_stroke
 </SECTION>
 
 <SECTION>
@@ -425,6 +423,8 @@ cogl_framebuffer_draw_textured_rectangle
 cogl_framebuffer_draw_multitextured_rectangle
 cogl_framebuffer_draw_rectangles
 cogl_framebuffer_draw_textured_rectangles
+cogl_framebuffer_stroke_path
+cogl_framebuffer_fill_path
 
 <SUBSECTION>
 cogl_framebuffer_swap_buffers
diff --git a/tests/conform/test-path.c b/tests/conform/test-path.c
index fbe1fcd..286d6d1 100644
--- a/tests/conform/test-path.c
+++ b/tests/conform/test-path.c
@@ -15,11 +15,13 @@ typedef struct _TestState
 } TestState;
 
 static void
-draw_path_at (int x, int y)
+draw_path_at (CoglPath *path, CoglPipeline *pipeline, int x, int y)
 {
   cogl_framebuffer_push_matrix (fb);
   cogl_framebuffer_translate (fb, x * BLOCK_SIZE, y * BLOCK_SIZE, 0.0f);
-  cogl_path_fill ();
+
+  cogl_framebuffer_fill_path (fb, pipeline, path);
+
   cogl_framebuffer_pop_matrix (fb);
 }
 
@@ -64,9 +66,10 @@ check_block (int block_x, int block_y, int block_mask)
 static void
 paint (TestState *state)
 {
-  CoglHandle path_a, path_b, path_c;
+  CoglPath *path_a, *path_b, *path_c;
+  CoglPipeline *white = cogl_pipeline_new (ctx);
 
-  cogl_set_source_color4ub (255, 255, 255, 255);
+  cogl_pipeline_set_color4f (white, 1, 1, 1, 1);
 
   /* Create a path filling just a quarter of a block. It will use two
      rectangles so that we have a sub path in the path */
@@ -75,22 +78,21 @@ paint (TestState *state)
                        BLOCK_SIZE, BLOCK_SIZE);
   cogl_path_rectangle (BLOCK_SIZE / 2, BLOCK_SIZE / 2,
                        BLOCK_SIZE * 3 / 4, BLOCK_SIZE);
-  path_a = cogl_handle_ref (cogl_get_path ());
-  draw_path_at (0, 0);
+  path_a = cogl_object_ref (cogl_get_path ());
+  draw_path_at (path_a, white, 0, 0);
 
   /* Create another path filling the whole block */
+  cogl_path_new ();
   cogl_path_rectangle (0, 0, BLOCK_SIZE, BLOCK_SIZE);
-  path_b = cogl_handle_ref (cogl_get_path ());
-  draw_path_at (1, 0);
+  path_b = cogl_object_ref (cogl_get_path ());
+  draw_path_at (path_b, white, 1, 0);
 
   /* Draw the first path again */
-  cogl_set_path (path_a);
-  draw_path_at (2, 0);
+  draw_path_at (path_a, white, 2, 0);
 
   /* Draw a copy of path a */
   path_c = cogl_path_copy (path_a);
-  cogl_set_path (path_c);
-  draw_path_at (3, 0);
+  draw_path_at (path_c, white, 3, 0);
 
   /* Add another rectangle to path a. We'll use line_to's instead of
      cogl_rectangle so that we don't create another sub-path because
@@ -100,11 +102,10 @@ paint (TestState *state)
   cogl_path_line_to (0, 0);
   cogl_path_line_to (BLOCK_SIZE / 2, 0);
   cogl_path_line_to (BLOCK_SIZE / 2, BLOCK_SIZE / 2);
-  draw_path_at (4, 0);
+  draw_path_at (path_a, white, 4, 0);
 
   /* Draw the copy again. It should not have changed */
-  cogl_set_path (path_c);
-  draw_path_at (5, 0);
+  draw_path_at (path_c, white, 5, 0);
 
   /* Add another rectangle to path c. It will be added in two halves,
      one as an extension of the previous path and the other as a new
@@ -115,32 +116,39 @@ paint (TestState *state)
   cogl_path_line_to (BLOCK_SIZE * 3 / 4, BLOCK_SIZE / 2);
   cogl_path_line_to (BLOCK_SIZE / 2, BLOCK_SIZE / 2);
   cogl_path_rectangle (BLOCK_SIZE * 3 / 4, 0, BLOCK_SIZE, BLOCK_SIZE / 2);
-  draw_path_at (6, 0);
+  draw_path_at (path_c, white, 6, 0);
 
   /* Draw the original path again. It should not have changed */
   cogl_set_path (path_a);
-  draw_path_at (7, 0);
+  draw_path_at (path_a, white, 7, 0);
 
-  cogl_handle_unref (path_a);
-  cogl_handle_unref (path_b);
-  cogl_handle_unref (path_c);
+  cogl_object_unref (path_a);
+  cogl_object_unref (path_b);
+  cogl_object_unref (path_c);
 
   /* Draw a self-intersecting path. The part that intersects should be
      inverted */
+  cogl_path_new ();
   cogl_path_rectangle (0, 0, BLOCK_SIZE, BLOCK_SIZE);
   cogl_path_line_to (0, BLOCK_SIZE / 2);
   cogl_path_line_to (BLOCK_SIZE / 2, BLOCK_SIZE / 2);
   cogl_path_line_to (BLOCK_SIZE / 2, 0);
   cogl_path_close ();
-  draw_path_at (8, 0);
+  path_a = cogl_object_ref (cogl_get_path ());
+  draw_path_at (path_a, white, 8, 0);
+  cogl_object_unref (path_a);
 
   /* Draw two sub paths. Where the paths intersect it should be
      inverted */
+  cogl_path_new ();
   cogl_path_rectangle (0, 0, BLOCK_SIZE, BLOCK_SIZE);
   cogl_path_rectangle (BLOCK_SIZE / 2, BLOCK_SIZE / 2, BLOCK_SIZE, BLOCK_SIZE);
-  draw_path_at (9, 0);
+  path_a = cogl_object_ref (cogl_get_path ());
+  draw_path_at (path_a, white, 9, 0);
+  cogl_object_unref (path_a);
 
   /* Draw a clockwise outer path */
+  cogl_path_new ();
   cogl_path_move_to (0, 0);
   cogl_path_line_to (BLOCK_SIZE, 0);
   cogl_path_line_to (BLOCK_SIZE, BLOCK_SIZE);
@@ -159,15 +167,15 @@ paint (TestState *state)
   cogl_path_line_to (BLOCK_SIZE, 0);
   cogl_path_close ();
   /* Retain the path for the next test */
-  path_a = cogl_handle_ref (cogl_get_path ());
-  draw_path_at (10, 0);
+  path_a = cogl_object_ref (cogl_get_path ());
+  draw_path_at (path_a, white, 10, 0);
 
   /* Draw the same path again with the other fill rule */
   cogl_set_path (path_a);
   cogl_path_set_fill_rule (COGL_PATH_FILL_RULE_NON_ZERO);
-  draw_path_at (11, 0);
+  draw_path_at (path_a, white, 11, 0);
 
-  cogl_handle_unref (path_a);
+  cogl_object_unref (path_a);
 }
 
 static void
@@ -199,11 +207,7 @@ test_path (void)
                                  -1,
                                  100);
 
-  /* XXX: we have to push/pop a framebuffer since this test currently
-   * uses the legacy cogl_rectangle() api. */
-  cogl_push_framebuffer (fb);
   paint (&state);
-  cogl_pop_framebuffer ();
   validate_result ();
 
   if (cogl_test_verbose ())



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