summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2011-10-01 18:40:10 +0100
committerRobert Bragg <robert@linux.intel.com>2011-10-01 18:40:41 +0100
commitf3b04b0f243d5be1fe2708b0acad77367c956c14 (patch)
tree679996f8f736867c223f79b22d409ec18aeeba74
parent90f8c200ec8a3ec731573f3d25b55fd5ffe9f9bf (diff)
downloadcogl-f3b04b0f243d5be1fe2708b0acad77367c956c14.tar.gz
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.
-rw-r--r--cogl/cogl2-path.c106
1 files changed, 43 insertions, 63 deletions
diff --git a/cogl/cogl2-path.c b/cogl/cogl2-path.c
index a5d6ad06..c2c478e3 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