add debugging wrapper blitter to ensure unclipped scan-conversion is safe
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4629
Change-Id: Ie6c35b28a6e8e87bf230e50f9940d3924d12969a
Reviewed-on: https://skia-review.googlesource.com/4629
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Yuqian Li <liyuqian@google.com>
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 3643e66..e5c935b 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -1021,3 +1021,49 @@
}
return true;
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_DEBUG
+
+void SkRectClipCheckBlitter::blitH(int x, int y, int width) {
+ SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
+ fBlitter->blitH(x, y, width);
+}
+
+void SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
+ const int16_t* iter = runs;
+ for (; *iter; iter += *iter)
+ ;
+ int width = iter - runs;
+ SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
+ fBlitter->blitAntiH(x, y, aa, runs);
+}
+
+void SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
+ SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height)));
+ fBlitter->blitV(x, y, height, alpha);
+}
+
+void SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) {
+ SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height)));
+ fBlitter->blitRect(x, y, width, height);
+}
+
+void SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height,
+ SkAlpha leftAlpha, SkAlpha rightAlpha) {
+ SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width + 2, height)));
+ fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha);
+}
+
+void SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
+ SkASSERT(mask.fBounds.contains(clip));
+ SkASSERT(fClipRect.contains(clip));
+ fBlitter->blitMask(mask, clip);
+}
+
+const SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) {
+ return fBlitter->justAnOpaqueColor(value);
+}
+
+#endif
diff --git a/src/core/SkBlitter.h b/src/core/SkBlitter.h
index 0e5fedd..c9fed1c 100644
--- a/src/core/SkBlitter.h
+++ b/src/core/SkBlitter.h
@@ -240,6 +240,39 @@
const SkRegion* fRgn;
};
+#ifdef SK_DEBUG
+class SkRectClipCheckBlitter : public SkBlitter {
+public:
+ void init(SkBlitter* blitter, const SkIRect& clipRect) {
+ SkASSERT(blitter);
+ SkASSERT(!clipRect.isEmpty());
+ fBlitter = blitter;
+ fClipRect = clipRect;
+ }
+
+ void blitH(int x, int y, int width) override;
+ void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
+ void blitV(int x, int y, int height, SkAlpha alpha) override;
+ void blitRect(int x, int y, int width, int height) override;
+ void blitAntiRect(int x, int y, int width, int height,
+ SkAlpha leftAlpha, SkAlpha rightAlpha) override;
+ void blitMask(const SkMask&, const SkIRect& clip) override;
+ const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
+
+ int requestRowsPreserved() const override {
+ return fBlitter->requestRowsPreserved();
+ }
+
+ void* allocBlitMemory(size_t sz) override {
+ return fBlitter->allocBlitMemory(sz);
+ }
+
+private:
+ SkBlitter* fBlitter;
+ SkIRect fClipRect;
+};
+#endif
+
/** Factory to set up the appropriate most-efficient wrapper blitter
to apply a clip. Returns a pointer to a member, so lifetime must
be managed carefully.
diff --git a/src/core/SkScanPriv.h b/src/core/SkScanPriv.h
index 798cae6..4ff91bb 100644
--- a/src/core/SkScanPriv.h
+++ b/src/core/SkScanPriv.h
@@ -23,6 +23,9 @@
private:
SkRectClipBlitter fRectBlitter;
SkRgnClipBlitter fRgnBlitter;
+#ifdef SK_DEBUG
+ SkRectClipCheckBlitter fRectClipCheckBlitter;
+#endif
SkBlitter* fBlitter;
const SkIRect* fClipRect;
};
diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp
index 884f785..9ce18b0 100644
--- a/src/core/SkScan_Path.cpp
+++ b/src/core/SkScan_Path.cpp
@@ -561,12 +561,21 @@
if (clip->isRect()) {
if (fClipRect->contains(ir)) {
+#ifdef SK_DEBUG
+ fRectClipCheckBlitter.init(blitter, *fClipRect);
+ blitter = &fRectClipCheckBlitter;
+#endif
fClipRect = nullptr;
} else {
// only need a wrapper blitter if we're horizontally clipped
if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) {
fRectBlitter.init(blitter, *fClipRect);
blitter = &fRectBlitter;
+ } else {
+#ifdef SK_DEBUG
+ fRectClipCheckBlitter.init(blitter, *fClipRect);
+ blitter = &fRectClipCheckBlitter;
+#endif
}
}
} else {