sna: Avoid erroneous discarding operations for partial composites
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 23 Jan 2014 17:30:29 +0000 (17:30 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 23 Jan 2014 17:38:27 +0000 (17:38 +0000)
Composite operations were presumed to cover their entire width x height
area. However, a few paths submit boxes that do not cover the clip
region and so the optimisation made during prepare to discard completely
overwritten data is incorrect (and leads to corruption - stale data is
seen which the client expected to have been overdrawn). So along these
more unusual paths, we must add a flag to prevent the overzealous
discard. Notably, xfce4 triggers this as it uses a lot of unantialiased
trapezoids in its theme drawing.

References: https://bugs.freedesktop.org/show_bug.cgi?id=69528
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
16 files changed:
src/sna/gen2_render.c
src/sna/gen3_render.c
src/sna/gen4_render.c
src/sna/gen5_render.c
src/sna/gen6_render.c
src/sna/gen7_render.c
src/sna/gen8_render.c
src/sna/sna_blt.c
src/sna/sna_composite.c
src/sna/sna_display.c
src/sna/sna_glyphs.c
src/sna/sna_render.c
src/sna/sna_render.h
src/sna/sna_tiling.c
src/sna/sna_trapezoids_boxes.c
src/sna/sna_trapezoids_mono.c

index ef7b985..0cb7207 100644 (file)
@@ -1826,6 +1826,7 @@ gen2_render_composite(struct sna *sna,
                      int16_t mask_x, int16_t mask_y,
                      int16_t dst_x,  int16_t dst_y,
                      int16_t width,  int16_t height,
+                     unsigned flags,
                      struct sna_composite_op *tmp)
 {
        DBG(("%s()\n", __FUNCTION__));
@@ -1841,7 +1842,7 @@ gen2_render_composite(struct sna *sna,
                              src_x, src_y,
                              dst_x, dst_y,
                              width, height,
-                             tmp, false))
+                             flags, tmp))
                return true;
 
        if (gen2_composite_fallback(sna, src, mask, dst))
@@ -2053,7 +2054,7 @@ fallback:
                                  src_x, src_y,
                                  dst_x, dst_y,
                                  width, height,
-                                 tmp, true));
+                                 flags | COMPOSITE_FALLBACK, tmp));
 }
 
 fastcall static void
index 58e6204..0079bad 100644 (file)
@@ -3454,6 +3454,7 @@ gen3_render_composite(struct sna *sna,
                      int16_t mask_x, int16_t mask_y,
                      int16_t dst_x,  int16_t dst_y,
                      int16_t width,  int16_t height,
+                     unsigned flags,
                      struct sna_composite_op *tmp)
 {
        DBG(("%s()\n", __FUNCTION__));
@@ -3473,7 +3474,7 @@ gen3_render_composite(struct sna *sna,
                              src_x, src_y,
                              dst_x, dst_y,
                              width, height,
-                             tmp, false))
+                             flags, tmp))
                return true;
 
        if (gen3_composite_fallback(sna, op, src, mask, dst))
@@ -3816,7 +3817,7 @@ fallback:
                                  src_x, src_y,
                                  dst_x, dst_y,
                                  width, height,
-                                 tmp, true));
+                                 flags | COMPOSITE_FALLBACK, tmp));
 }
 
 static void
index 720d5c3..1a559f0 100644 (file)
@@ -1893,6 +1893,7 @@ gen4_render_composite(struct sna *sna,
                      int16_t msk_x, int16_t msk_y,
                      int16_t dst_x, int16_t dst_y,
                      int16_t width, int16_t height,
+                     unsigned flags,
                      struct sna_composite_op *tmp)
 {
        DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
@@ -1907,7 +1908,7 @@ gen4_render_composite(struct sna *sna,
                              src_x, src_y,
                              dst_x, dst_y,
                              width, height,
-                             tmp, false))
+                             flags, tmp))
                return true;
 
        if (gen4_composite_fallback(sna, src, mask, dst))
@@ -2056,7 +2057,7 @@ fallback:
                                  src_x, src_y,
                                  dst_x, dst_y,
                                  width, height,
-                                 tmp, true));
+                                 flags | COMPOSITE_FALLBACK, tmp));
 }
 
 #if !NO_COMPOSITE_SPANS
index 8ec2587..23b0c14 100644 (file)
@@ -1830,6 +1830,7 @@ gen5_render_composite(struct sna *sna,
                      int16_t msk_x, int16_t msk_y,
                      int16_t dst_x, int16_t dst_y,
                      int16_t width, int16_t height,
+                     unsigned flags,
                      struct sna_composite_op *tmp)
 {
        DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
@@ -1846,7 +1847,7 @@ gen5_render_composite(struct sna *sna,
                              src_x, src_y,
                              dst_x, dst_y,
                              width, height,
-                             tmp, false))
+                             flags, tmp))
                return true;
 
        if (gen5_composite_fallback(sna, src, mask, dst))
@@ -1991,7 +1992,7 @@ fallback:
                                  src_x, src_y,
                                  dst_x, dst_y,
                                  width, height,
-                                 tmp, true));
+                                 flags | COMPOSITE_FALLBACK, tmp));
 }
 
 #if !NO_COMPOSITE_SPANS
index a82284d..d0e202f 100644 (file)
@@ -2124,6 +2124,7 @@ gen6_render_composite(struct sna *sna,
                      int16_t msk_x, int16_t msk_y,
                      int16_t dst_x, int16_t dst_y,
                      int16_t width, int16_t height,
+                     unsigned flags,
                      struct sna_composite_op *tmp)
 {
        if (op >= ARRAY_SIZE(gen6_blend_op))
@@ -2139,7 +2140,7 @@ gen6_render_composite(struct sna *sna,
                              src_x, src_y,
                              dst_x, dst_y,
                              width, height,
-                             tmp, false))
+                             flags, tmp))
                return true;
 
        if (gen6_composite_fallback(sna, src, mask, dst))
@@ -2295,7 +2296,7 @@ fallback:
                                  src_x, src_y,
                                  dst_x, dst_y,
                                  width, height,
-                                 tmp, true));
+                                 flags | COMPOSITE_FALLBACK, tmp));
 }
 
 #if !NO_COMPOSITE_SPANS
index e45555b..1ea7392 100644 (file)
@@ -2405,6 +2405,7 @@ gen7_render_composite(struct sna *sna,
                      int16_t msk_x, int16_t msk_y,
                      int16_t dst_x, int16_t dst_y,
                      int16_t width, int16_t height,
+                     unsigned flags,
                      struct sna_composite_op *tmp)
 {
        if (op >= ARRAY_SIZE(gen7_blend_op))
@@ -2420,7 +2421,7 @@ gen7_render_composite(struct sna *sna,
                              src_x, src_y,
                              dst_x, dst_y,
                              width, height,
-                             tmp, false))
+                             flags, tmp))
                return true;
 
        if (gen7_composite_fallback(sna, src, mask, dst))
@@ -2576,7 +2577,7 @@ fallback:
                                  src_x, src_y,
                                  dst_x, dst_y,
                                  width, height,
-                                 tmp, true));
+                                 flags | COMPOSITE_FALLBACK, tmp));
 }
 
 #if !NO_COMPOSITE_SPANS
index 309398d..13e1662 100644 (file)
@@ -2156,6 +2156,7 @@ gen8_render_composite(struct sna *sna,
                      int16_t msk_x, int16_t msk_y,
                      int16_t dst_x, int16_t dst_y,
                      int16_t width, int16_t height,
+                     unsigned flags,
                      struct sna_composite_op *tmp)
 {
        if (op >= ARRAY_SIZE(gen8_blend_op))
@@ -2171,7 +2172,7 @@ gen8_render_composite(struct sna *sna,
                              src_x, src_y,
                              dst_x, dst_y,
                              width, height,
-                             tmp, false))
+                             flags, tmp))
                return true;
 
        if (gen8_composite_fallback(sna, src, mask, dst))
@@ -2327,7 +2328,7 @@ fallback:
                                  src_x, src_y,
                                  dst_x, dst_y,
                                  width, height,
-                                 tmp, true));
+                                 flags | COMPOSITE_FALLBACK, tmp));
 }
 
 #if !NO_COMPOSITE_SPANS
index 7f3fc3e..9fad292 100644 (file)
@@ -2253,8 +2253,8 @@ sna_blt_composite(struct sna *sna,
                  int16_t x, int16_t y,
                  int16_t dst_x, int16_t dst_y,
                  int16_t width, int16_t height,
-                 struct sna_composite_op *tmp,
-                 bool fallback)
+                 unsigned flags,
+                 struct sna_composite_op *tmp)
 {
        PictFormat src_format = src->format;
        PixmapPtr src_pixmap;
@@ -2269,7 +2269,6 @@ sna_blt_composite(struct sna *sna,
 #if DEBUG_NO_BLT || NO_BLT_COMPOSITE
        return false;
 #endif
-
        DBG(("%s (%d, %d), (%d, %d), %dx%d\n",
             __FUNCTION__, x, y, dst_x, dst_y, width, height));
 
@@ -2309,22 +2308,25 @@ clear:
                hint = 0;
                if (can_render(sna)) {
                        hint |= PREFER_GPU;
-                       if (dst->pCompositeClip->data == NULL && (width | height)) {
+                       if (dst->pCompositeClip->data == NULL &&
+                           (flags & COMPOSITE_PARTIAL) == 0) {
                                hint |= IGNORE_CPU;
-                               if (width == tmp->dst.pixmap->drawable.width &&
+                               if (width  == tmp->dst.pixmap->drawable.width &&
                                    height == tmp->dst.pixmap->drawable.height)
                                        hint |= REPLACES;
                        }
                }
                tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
                                                  &dst_box, &tmp->damage);
-               if (tmp->dst.bo && !kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
-                       DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
-                            __FUNCTION__, tmp->dst.bo->tiling, tmp->dst.bo->pitch));
-                       return false;
-               }
-
-               if (!tmp->dst.bo) {
+               if (tmp->dst.bo) {
+                       if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
+                               DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
+                                    __FUNCTION__, tmp->dst.bo->tiling, tmp->dst.bo->pitch));
+                               return false;
+                       }
+                       if (hint & REPLACES)
+                               kgem_bo_undo(&sna->kgem, tmp->dst.bo);
+               } else {
                        RegionRec region;
 
                        region.extents = dst_box;
@@ -2333,8 +2335,7 @@ clear:
                        if (!sna_drawable_move_region_to_cpu(dst->pDrawable, &region,
                                                             MOVE_INPLACE_HINT | MOVE_WRITE))
                                return false;
-               } else if (hint & REPLACES)
-                       kgem_bo_undo(&sna->kgem, tmp->dst.bo);
+               }
 
                return prepare_blt_clear(sna, tmp);
        }
@@ -2363,31 +2364,34 @@ fill:
                hint = 0;
                if (can_render(sna)) {
                        hint |= PREFER_GPU;
-                       if (dst->pCompositeClip->data == NULL && (width | height))
+                       if (dst->pCompositeClip->data == NULL &&
+                           (flags & COMPOSITE_PARTIAL) == 0) {
                                hint |= IGNORE_CPU;
-                       if (width == tmp->dst.pixmap->drawable.width &&
-                           height == tmp->dst.pixmap->drawable.height)
-                               hint |= REPLACES;
+                               if (width  == tmp->dst.pixmap->drawable.width &&
+                                   height == tmp->dst.pixmap->drawable.height)
+                                       hint |= REPLACES;
+                       }
                }
                tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
                                                  &dst_box, &tmp->damage);
-               if (tmp->dst.bo && !kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
-                       DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
-                            __FUNCTION__, tmp->dst.bo->tiling, tmp->dst.bo->pitch));
-                       return false;
-               }
-
-               if (!tmp->dst.bo) {
+               if (tmp->dst.bo) {
+                       if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
+                               DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
+                                    __FUNCTION__, tmp->dst.bo->tiling, tmp->dst.bo->pitch));
+                               return false;
+                       }
+                       if (hint & REPLACES)
+                               kgem_bo_undo(&sna->kgem, tmp->dst.bo);
+               } else {
                        RegionRec region;
 
                        region.extents = dst_box;
                        region.data = NULL;
 
                        if (!sna_drawable_move_region_to_cpu(dst->pDrawable, &region,
-                                                       MOVE_INPLACE_HINT | MOVE_WRITE))
+                                                            MOVE_INPLACE_HINT | MOVE_WRITE))
                                return false;
-               } else if (hint & REPLACES)
-                       kgem_bo_undo(&sna->kgem, tmp->dst.bo);
+               }
 
                return prepare_blt_fill(sna, tmp, color);
        }
@@ -2505,7 +2509,7 @@ fill:
                if (src_pixmap->drawable.width  <= sna->render.max_3d_size &&
                    src_pixmap->drawable.height <= sna->render.max_3d_size &&
                    bo->pitch <= sna->render.max_3d_pitch &&
-                   !fallback)
+                   (flags & COMPOSITE_FALLBACK) == 0)
                {
                        return false;
                }
@@ -2516,9 +2520,10 @@ fill:
        hint = 0;
        if (bo || can_render(sna)) {
                hint |= PREFER_GPU;
-               if (dst->pCompositeClip->data == NULL && (width | height)) {
+               if (dst->pCompositeClip->data == NULL &&
+                   (flags & COMPOSITE_PARTIAL) == 0) {
                        hint |= IGNORE_CPU;
-                       if (width == tmp->dst.pixmap->drawable.width &&
+                       if (width  == tmp->dst.pixmap->drawable.width &&
                            height == tmp->dst.pixmap->drawable.height)
                                hint |= REPLACES;
                }
@@ -2536,7 +2541,7 @@ fill:
                if (!tmp->dst.bo) {
                        DBG(("%s: fallback -- unaccelerated read back\n",
                             __FUNCTION__));
-                       if (fallback || !kgem_bo_is_busy(bo))
+                       if (flags & COMPOSITE_FALLBACK || !kgem_bo_is_busy(bo))
                                goto put;
                } else if (bo->snoop && tmp->dst.bo->snoop) {
                        DBG(("%s: fallback -- can not copy between snooped bo\n",
@@ -2545,11 +2550,11 @@ fill:
                } else if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
                        DBG(("%s: fallback -- unaccelerated upload\n",
                             __FUNCTION__));
-                       if (fallback || !kgem_bo_is_busy(bo))
+                       if (flags & COMPOSITE_FALLBACK || !kgem_bo_is_busy(bo))
                                goto put;
                } else {
                        ret = prepare_blt_copy(sna, tmp, bo, alpha_fixup);
-                       if (fallback && !ret)
+                       if (flags & COMPOSITE_FALLBACK && !ret)
                                goto put;
                }
        } else {
index a36ffe0..6a2eff6 100644 (file)
@@ -720,7 +720,7 @@ sna_composite(CARD8 op,
                                   region.extents.y1,
                                   region.extents.x2 - region.extents.x1,
                                   region.extents.y2 - region.extents.y1,
-                                  memset(&tmp, 0, sizeof(tmp)))) {
+                                  0, memset(&tmp, 0, sizeof(tmp)))) {
                DBG(("%s: fallback due unhandled composite op\n", __FUNCTION__));
                goto fallback;
        }
index 9e811ca..30a0133 100644 (file)
@@ -4374,7 +4374,7 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
                                   0, 0,
                                   0, 0,
                                   crtc->mode.HDisplay, crtc->mode.VDisplay,
-                                  memset(&tmp, 0, sizeof(tmp)))) {
+                                  0, memset(&tmp, 0, sizeof(tmp)))) {
                DBG(("%s: unsupported operation!\n", __FUNCTION__));
                sna_crtc_redisplay__fallback(crtc, region, bo);
                goto free_dst;
index d90dac8..d06d52a 100644 (file)
@@ -622,7 +622,7 @@ glyphs_to_dst(struct sna *sna,
                                                           op, src, p->atlas, dst,
                                                           0, 0, 0, 0, 0, 0,
                                                           0, 0,
-                                                          &tmp))
+                                                          COMPOSITE_PARTIAL, &tmp))
                                        return false;
 
                                glyph_atlas = p->atlas;
@@ -785,7 +785,7 @@ glyphs0_to_dst(struct sna *sna,
                                                           op, src, p->atlas, dst,
                                                           0, 0, 0, 0, 0, 0,
                                                           0, 0,
-                                                          &tmp))
+                                                          COMPOSITE_PARTIAL, &tmp))
                                        return false;
 
                                glyph_atlas = p->atlas;
@@ -954,7 +954,7 @@ glyphs_slow(struct sna *sna,
                                                   y - glyph->info.y,
                                                   glyph->info.width,
                                                   glyph->info.height,
-                                                  memset(&tmp, 0, sizeof(tmp))))
+                                                  COMPOSITE_PARTIAL, memset(&tmp, 0, sizeof(tmp))))
                                return false;
 
                        rects = REGION_RECTS(dst->pCompositeClip);
@@ -1351,13 +1351,13 @@ next_image:
                                                                           p->atlas, NULL, mask,
                                                                           0, 0, 0, 0, 0, 0,
                                                                           0, 0,
-                                                                          &tmp);
+                                                                          COMPOSITE_PARTIAL, &tmp);
                                        } else {
                                                ok = sna->render.composite(sna, PictOpAdd,
                                                                           sna->render.white_picture, p->atlas, mask,
                                                                           0, 0, 0, 0, 0, 0,
                                                                           0, 0,
-                                                                          &tmp);
+                                                                          COMPOSITE_PARTIAL, &tmp);
                                        }
                                        if (!ok) {
                                                DBG(("%s: fallback -- can not handle PictOpAdd of glyph onto mask!\n",
index c183b28..7acca36 100644 (file)
@@ -93,6 +93,7 @@ no_render_composite(struct sna *sna,
                    int16_t mask_x, int16_t mask_y,
                    int16_t dst_x, int16_t dst_y,
                    int16_t width, int16_t height,
+                   unsigned flags,
                    struct sna_composite_op *tmp)
 {
        DBG(("%s (op=%d, mask? %d)\n", __FUNCTION__, op, mask != NULL));
@@ -109,7 +110,7 @@ no_render_composite(struct sna *sna,
                                 src_x, src_y,
                                 dst_x, dst_y,
                                 width, height,
-                                tmp, true);
+                                flags | COMPOSITE_FALLBACK, tmp);
        (void)mask_x;
        (void)mask_y;
 }
@@ -849,7 +850,7 @@ fixup:
                                                   0, 0,
                                                   b.x1, b.y1,
                                                   b.x2 - b.x1, b.y2 - b.y1,
-                                                  &op))
+                                                  0, &op))
                                goto cleanup_src;
 
                        op.box(sna, &op, &b);
index 0368556..67848b9 100644 (file)
@@ -231,7 +231,10 @@ struct sna_render {
                          int16_t msk_x, int16_t msk_y,
                          int16_t dst_x, int16_t dst_y,
                          int16_t w, int16_t h,
+                         unsigned flags,
                          struct sna_composite_op *tmp);
+#define COMPOSITE_PARTIAL 0x1
+#define COMPOSITE_FALLBACK 0x80000000
 
        bool (*check_composite_spans)(struct sna *sna, uint8_t op,
                                      PicturePtr dst, PicturePtr src,
@@ -661,8 +664,8 @@ bool sna_blt_composite(struct sna *sna,
                       int16_t src_x, int16_t src_y,
                       int16_t dst_x, int16_t dst_y,
                       int16_t width, int16_t height,
-                      struct sna_composite_op *tmp,
-                      bool fallback);
+                      unsigned flags,
+                      struct sna_composite_op *tmp);
 bool sna_blt_composite__convert(struct sna *sna,
                                int x, int y,
                                int width, int height,
index 6f0b96a..8bb4fbc 100644 (file)
@@ -168,7 +168,7 @@ sna_tiling_composite_done(struct sna *sna,
                                                  tile->mask_x + x, tile->mask_y + y,
                                                  tile->dst_x + x,  tile->dst_y + y,
                                                  width, height,
-                                                 memset(&tmp, 0, sizeof(tmp)))) {
+                                                 COMPOSITE_PARTIAL, memset(&tmp, 0, sizeof(tmp)))) {
                                for (n = 0; n < tile->rect_count; n++) {
                                        const struct sna_composite_rectangles *r = &tile->rects[n];
                                        int x1, x2, dx, y1, y2, dy;
index 3bb895a..b462de5 100644 (file)
@@ -200,7 +200,7 @@ composite_aligned_boxes(struct sna *sna,
                                   clip.extents.x1,  clip.extents.y1,
                                   clip.extents.x2 - clip.extents.x1,
                                   clip.extents.y2 - clip.extents.y1,
-                                  memset(&tmp, 0, sizeof(tmp)))) {
+                                  COMPOSITE_PARTIAL, memset(&tmp, 0, sizeof(tmp)))) {
                unsigned int flags;
                pixman_box16_t *b;
                int i, count;
index be2e3a6..49296a3 100644 (file)
@@ -813,7 +813,7 @@ mono_trapezoids_span_converter(struct sna *sna,
                                       mono.clip.extents.x1,  mono.clip.extents.y1,
                                       mono.clip.extents.x2 - mono.clip.extents.x1,
                                       mono.clip.extents.y2 - mono.clip.extents.y1,
-                                      memset(&mono.op, 0, sizeof(mono.op))))
+                                      COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op))))
                return false;
 
        num_threads = 1;
@@ -924,7 +924,6 @@ mono_trapezoids_span_converter(struct sna *sna,
                                      traps[n].top, traps[n].bottom,
                                      &traps[n].right.p1, &traps[n].right.p2, -1);
                }
-               memset(&mono.op, 0, sizeof(mono.op));
                if (mono.sna->render.composite(mono.sna,
                                               PictOpClear,
                                               mono.sna->clear, NULL, dst,
@@ -933,7 +932,7 @@ mono_trapezoids_span_converter(struct sna *sna,
                                               mono.clip.extents.x1,  mono.clip.extents.y1,
                                               mono.clip.extents.x2 - mono.clip.extents.x1,
                                               mono.clip.extents.y2 - mono.clip.extents.y1,
-                                              &mono.op)) {
+                                              COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
                        mono_render(&mono);
                        mono.op.done(mono.sna, &mono.op);
                }
@@ -1273,14 +1272,13 @@ mono_trap_span_converter(struct sna *sna,
                              &p1, &p2, -1);
        }
 
-       memset(&mono.op, 0, sizeof(mono.op));
        if (mono.sna->render.composite(mono.sna, PictOpAdd, src, NULL, dst,
-                                       0, 0,
-                                       0, 0,
-                                       mono.clip.extents.x1,  mono.clip.extents.y1,
-                                       mono.clip.extents.x2 - mono.clip.extents.x1,
-                                       mono.clip.extents.y2 - mono.clip.extents.y1,
-                                       &mono.op)) {
+                                      0, 0,
+                                      0, 0,
+                                      mono.clip.extents.x1,  mono.clip.extents.y1,
+                                      mono.clip.extents.x2 - mono.clip.extents.x1,
+                                      mono.clip.extents.y2 - mono.clip.extents.y1,
+                                      COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
                mono_render(&mono);
                mono.op.done(mono.sna, &mono.op);
        }
@@ -1356,7 +1354,6 @@ mono_triangles_span_converter(struct sna *sna,
                              &tri[n].p3, &tri[n].p1, 1);
        }
 
-       memset(&mono.op, 0, sizeof(mono.op));
        if (mono.sna->render.composite(mono.sna, op, src, NULL, dst,
                                       src_x + mono.clip.extents.x1 - dst_x - dx,
                                       src_y + mono.clip.extents.y1 - dst_y - dy,
@@ -1364,7 +1361,7 @@ mono_triangles_span_converter(struct sna *sna,
                                       mono.clip.extents.x1,  mono.clip.extents.y1,
                                       mono.clip.extents.x2 - mono.clip.extents.x1,
                                       mono.clip.extents.y2 - mono.clip.extents.y1,
-                                      &mono.op)) {
+                                      COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
                if (mono.clip.data == NULL && mono.op.damage == NULL)
                        mono.span = mono_span__fast;
                else
@@ -1402,7 +1399,6 @@ mono_triangles_span_converter(struct sna *sna,
                                      &tri[n].p3, &tri[n].p1, 1);
                }
 
-               memset(&mono.op, 0, sizeof(mono.op));
                if (mono.sna->render.composite(mono.sna,
                                               PictOpClear,
                                               mono.sna->clear, NULL, dst,
@@ -1411,7 +1407,7 @@ mono_triangles_span_converter(struct sna *sna,
                                               mono.clip.extents.x1,  mono.clip.extents.y1,
                                               mono.clip.extents.x2 - mono.clip.extents.x1,
                                               mono.clip.extents.y2 - mono.clip.extents.y1,
-                                              &mono.op)) {
+                                              COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
                        if (mono.clip.data == NULL && mono.op.damage == NULL)
                                mono.span = mono_span__fast;
                        else