[Cogl] [PATCH] Replace cogl_path_{stroke, fill} with framebuffer API
Neil Roberts
neil at linux.intel.com
Wed Apr 18 08:37:52 PDT 2012
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.
---
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/cogl-path.c | 126 +++++++++++++++-----------------
cogl/cogl-path.h | 37 +---------
doc/reference/cogl2/cogl2-sections.txt | 4 +-
tests/conform/test-path.c | 31 ++++----
9 files changed, 167 insertions(+), 130 deletions(-)
diff --git a/cogl-pango/cogl-pango-display-list.c b/cogl-pango/cogl-pango-display-list.c
index 5802ef9..28b5351 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 (ctx);
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 6bdd023..1de2960 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 3918636..c099506 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
@@ -3500,3 +3501,27 @@ cogl_framebuffer_draw_textured_rectangles (CoglFramebuffer *framebuffer,
rects,
n_rectangles);
}
+
+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 bccde36..0b030a2 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -1470,6 +1470,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/cogl-path.c b/cogl/cogl-path.c
index b849345..f14d8c1 100644
--- a/cogl/cogl-path.c
+++ b/cogl/cogl-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,64 +320,55 @@ validate_layer_cb (CoglPipelineLayer *layer, void *user_data)
}
void
-_cogl_path_fill_nodes (CoglPath *path, CoglDrawFlags flags)
-{
- CoglBool needs_fallback = FALSE;
- CoglPipeline *pipeline = cogl_get_source ();
-
- _cogl_pipeline_foreach_layer_internal (pipeline,
- validate_layer_cb, &needs_fallback);
- if (needs_fallback)
- {
- _cogl_path_fill_nodes_with_clipped_rectangle (path);
- return;
- }
-
- _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);
-}
-
-void
-cogl_path_fill (CoglPath *path)
+_cogl_path_fill_nodes (CoglPath *path,
+ CoglFramebuffer *framebuffer,
+ CoglPipeline *pipeline,
+ CoglDrawFlags flags)
{
- _COGL_RETURN_IF_FAIL (cogl_is_path (path));
-
if (path->data->path_nodes->len == 0)
return;
/* If the path is a simple rectangle then we can divert to using
- cogl_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)
+ 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)
{
float x_1, y_1, x_2, y_2;
_cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2);
- cogl_rectangle (x_1, y_1, x_2, y_2);
+ cogl_framebuffer_draw_rectangle (framebuffer,
+ pipeline,
+ x_1, y_1,
+ x_2, y_2);
}
else
- _cogl_path_fill_nodes (path, 0);
-}
-
-void
-cogl_path_stroke (CoglPath *path)
-{
- _COGL_RETURN_IF_FAIL (cogl_is_path (path));
+ {
+ CoglBool needs_fallback = FALSE;
- if (path->data->path_nodes->len == 0)
- return;
+ _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_stroke_nodes (path);
+ _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
diff --git a/cogl/cogl-path.h b/cogl/cogl-path.h
index fa2b707..8e2b234 100644
--- a/cogl/cogl-path.h
+++ b/cogl/cogl-path.h
@@ -430,10 +430,8 @@ typedef enum {
* @fill_rule: The new fill rule.
*
* Sets the fill rule of the current path to @fill_rule. This will
- * affect how the path is filled when cogl_path_fill() is later
- * called. Note that the fill rule state is attached to the path so
- * calling cogl_get_path() will preserve the fill rule and calling
- * cogl_path_new() will reset the fill rule back to the default.
+ * affect how the path is filled when cogl_framebuffer_fill_path() is
+ * later called.
*
* Since: 2.0
*/
@@ -452,37 +450,6 @@ cogl_path_set_fill_rule (CoglPath *path, CoglPathFillRule fill_rule);
CoglPathFillRule
cogl_path_get_fill_rule (CoglPath *path);
-/**
- * cogl_path_fill:
- *
- * Fills the interior of the constructed shape using the current
- * drawing color.
- *
- * 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_path_fill (CoglPath *path);
-
-/**
- * cogl_path_stroke:
- *
- * Strokes the constructed shape using the current drawing color and a
- * width of 1 pixel (regardless of the current transformation
- * matrix).
- *
- * Since: 2.0
- */
-void
-cogl_path_stroke (CoglPath *path);
-
G_END_DECLS
#endif /* __COGL_PATH_H__ */
diff --git a/doc/reference/cogl2/cogl2-sections.txt b/doc/reference/cogl2/cogl2-sections.txt
index baebaa4..9c10d68 100644
--- a/doc/reference/cogl2/cogl2-sections.txt
+++ b/doc/reference/cogl2/cogl2-sections.txt
@@ -285,8 +285,6 @@ cogl_path_ellipse
CoglPathFillRule
cogl_path_set_fill_rule
cogl_path_get_fill_rule
-cogl_path_fill
-cogl_path_stroke
</SECTION>
<SECTION>
@@ -424,6 +422,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 47dc3af..bf1e267 100644
--- a/tests/conform/test-path.c
+++ b/tests/conform/test-path.c
@@ -15,15 +15,12 @@ typedef struct _TestState
} TestState;
static void
-draw_path_at (CoglPath *path, int x, int y)
+draw_path_at (CoglPath *path, CoglPipeline *pipeline, int x, int y)
{
cogl_framebuffer_push_matrix (test_fb);
cogl_framebuffer_translate (test_fb, x * BLOCK_SIZE, y * BLOCK_SIZE, 0.0f);
- /* FIXME: we need some cogl_framebuffer_fill_path() api */
- cogl_push_framebuffer (test_fb);
- cogl_path_fill (path);
- cogl_pop_framebuffer ();
+ cogl_framebuffer_fill_path (test_fb, pipeline, path);
cogl_framebuffer_pop_matrix (test_fb);
}
@@ -83,19 +80,19 @@ paint (TestState *state)
cogl_path_rectangle (path_a,
BLOCK_SIZE / 2, BLOCK_SIZE / 2,
BLOCK_SIZE * 3 / 4, BLOCK_SIZE);
- draw_path_at (path_a, 0, 0);
+ draw_path_at (path_a, white, 0, 0);
/* Create another path filling the whole block */
path_b = cogl_path_new (test_ctx);
cogl_path_rectangle (path_b, 0, 0, BLOCK_SIZE, BLOCK_SIZE);
- draw_path_at (path_b, 1, 0);
+ draw_path_at (path_b, white, 1, 0);
/* Draw the first path again */
- draw_path_at (path_a, 2, 0);
+ draw_path_at (path_a, white, 2, 0);
/* Draw a copy of path a */
path_c = cogl_path_copy (path_a);
- draw_path_at (path_c, 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
@@ -104,10 +101,10 @@ paint (TestState *state)
cogl_path_line_to (path_a, 0, 0);
cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0);
cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2);
- draw_path_at (path_a, 4, 0);
+ draw_path_at (path_a, white, 4, 0);
/* Draw the copy again. It should not have changed */
- draw_path_at (path_c, 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
@@ -118,10 +115,10 @@ paint (TestState *state)
cogl_path_line_to (path_c, BLOCK_SIZE / 2, BLOCK_SIZE / 2);
cogl_path_rectangle (path_c,
BLOCK_SIZE * 3 / 4, 0, BLOCK_SIZE, BLOCK_SIZE / 2);
- draw_path_at (path_c, 6, 0);
+ draw_path_at (path_c, white, 6, 0);
/* Draw the original path again. It should not have changed */
- draw_path_at (path_a, 7, 0);
+ draw_path_at (path_a, white, 7, 0);
cogl_object_unref (path_a);
cogl_object_unref (path_b);
@@ -135,7 +132,7 @@ paint (TestState *state)
cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2);
cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0);
cogl_path_close (path_a);
- draw_path_at (path_a, 8, 0);
+ draw_path_at (path_a, white, 8, 0);
cogl_object_unref (path_a);
/* Draw two sub paths. Where the paths intersect it should be
@@ -144,7 +141,7 @@ paint (TestState *state)
cogl_path_rectangle (path_a, 0, 0, BLOCK_SIZE, BLOCK_SIZE);
cogl_path_rectangle (path_a,
BLOCK_SIZE / 2, BLOCK_SIZE / 2, BLOCK_SIZE, BLOCK_SIZE);
- draw_path_at (path_a, 9, 0);
+ draw_path_at (path_a, white, 9, 0);
cogl_object_unref (path_a);
/* Draw a clockwise outer path */
@@ -167,11 +164,11 @@ paint (TestState *state)
cogl_path_line_to (path_a, BLOCK_SIZE, 0);
cogl_path_close (path_a);
/* Retain the path for the next test */
- draw_path_at (path_a, 10, 0);
+ draw_path_at (path_a, white, 10, 0);
/* Draw the same path again with the other fill rule */
cogl_path_set_fill_rule (path_a, COGL_PATH_FILL_RULE_NON_ZERO);
- draw_path_at (path_a, 11, 0);
+ draw_path_at (path_a, white, 11, 0);
cogl_object_unref (path_a);
}
--
1.7.3.16.g9464b
More information about the Cogl
mailing list