summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-10-04 20:38:01 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-10-04 20:38:01 -0400
commit413b32014e7ee5bfeccd8c47d4aa49b9b1f084e2 (patch)
treebcd7a9dcd7315637e38a75a2a92680256d1e8f58
parent7707f3487b16a49b74e700a2e4c2ba8f33afa6c3 (diff)
full apply
-rw-r--r--fragment.c103
1 files changed, 92 insertions, 11 deletions
diff --git a/fragment.c b/fragment.c
index 03dc330..efe8ee3 100644
--- a/fragment.c
+++ b/fragment.c
@@ -296,25 +296,70 @@ fragment_free (fragment_t *fragment)
state_unref (fragment->state);
}
+static const pixman_color_t white =
+{
+ 0xffff, 0xffff, 0xffff, 0xffff
+};
+
static void
-state_apply (state_t *state, pixman_op_t op, pixman_image_t *image)
+state_apply (state_t *state, pixman_image_t *image)
{
int width = pixman_image_get_width (image);
int height = pixman_image_get_height (image);
+ pixman_image_t *white_img, *temp;
+ pixman_format_code_t mask_format;
+ pixman_glyph_cache_t *glyph_cache;
+ pixman_glyph_t *glyphs;
+ int n_glyphs;
+
+ white_img = pixman_image_create_solid_fill (&white);
+ if (!white_img)
+ return; /* FIXME status - FIXME: only create when necessary */
switch (state->common.type)
{
+ case STATE_BLANK:
+ pixman_image_composite32 (
+ PIXMAN_OP_CLEAR, white_img, NULL, image,
+ 0, 0, 0, 0, 0, 0, width, height);
+ break;
+
+ case STATE_TRAPS:
+ /* FIXME: there may be a pixman bug here that we need
+ * to work around: it incorrectly clips rendering to the extent
+ * of the trapezoids
+ */
+ pixman_composite_trapezoids (
+ PIXMAN_OP_SRC, white_img, image, PIXMAN_a8,
+ 0, 0, 0, 0, state->traps.n_traps, state->traps.traps);
+ break;
+
+ case STATE_GLYPHS:
+ glyph_cache = state->glyphs.cache;
+ n_glyphs = state->glyphs.n_glyphs;
+ glyphs = state->glyphs.glyphs;
+
+ mask_format = pixman_glyph_get_mask_format (
+ glyph_cache, n_glyphs, glyphs);
+ pixman_composite_glyphs (
+ PIXMAN_OP_SRC, white_img, image, mask_format,
+ 0, 0, 0, 0, 0, 0, width, height,
+ glyph_cache, n_glyphs, glyphs);
+ break;
+
+ case STATE_WHITE:
+ pixman_image_composite32 (
+ PIXMAN_OP_SRC, white_img, NULL, image,
+ 0, 0, 0, 0, 0, 0, width, height);
+ break;
+
case STATE_IMAGE:
if (state->image.image == image)
- {
- assert (op == PIXMAN_OP_SRC);
- break;
- }
+ return;
pixman_image_composite (
- op, state->image.image, NULL, image,
- 0, 0, 0, 0, 0, 0,
- width, height);
+ PIXMAN_OP_SRC, state->image.image, NULL, image,
+ 0, 0, 0, 0, 0, 0, width, height);
break;
case STATE_COMMAND:
@@ -334,9 +379,45 @@ state_apply (state_t *state, pixman_op_t op, pixman_image_t *image)
*
* In the case where source is just a "foo IN bar",
* we can simpify to "apply (foo, bar, dest)".
+ *
+ * The correct thing is actually to:
+ * - copy dest to a temp image
+ * - composite SRC onto temp using command.op
+ * - composite temp onto image using argument op.
+ *
+ * which simplifies a bit if one or both of the ops is SRC
+ * if both: simply SRC source onto image
+ * if op, but not comamnd.op:
+ * SRC dst onto image, then source command.op onto image.
+ * if command.op, but not op:
+ * apply source to image using command.op
+ * These optimizations should probably take place at
+ * composite time, not apply time.
+ */
+ /* What if there is no arg-op (or equivalently defined to be SRC?
+ * Then the answer is
+ * - apply dest to image
+ * - create temp image
+ * - apply source to temp
+ * - composite temp with command op to image
*/
- state_apply (state->command.dest, PIXMAN_OP_SRC, image);
- state_apply (state->command.source, state->command.op, image);
+ /* FIXME: track alpha-only */
+ temp = pixman_image_create_bits (
+ PIXMAN_a8r8g8b8, width, height, NULL, -1);
+
+ if (!temp)
+ break; /* FIXME: status */
+
+ state_apply (state->command.dest, image);
+
+ /* FIXME: check if source can be expressed as (s IN m) */
+ state_apply (state->command.source, temp);
+
+ pixman_image_composite32 (
+ state->command.op, temp, NULL, image,
+ 0, 0, 0, 0, 0, 0, width, height);
+
+ pixman_image_unref (temp);
break;
}
}
@@ -349,7 +430,7 @@ fragment_apply (fragment_t *fragment, pixman_image_t *image)
pixman_image_set_clip_region32 (image, &fragment->region);
- state_apply (fragment->state, PIXMAN_OP_SRC, image);
+ state_apply (fragment->state, image);
return TRUE;
}