From 28930b46487fc94fde206d1283623204c595b0f1 Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Wed, 9 Nov 2016 15:23:26 -0500 Subject: 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 Reviewed-by: Yuqian Li --- src/core/SkBlitter.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/SkBlitter.h | 33 +++++++++++++++++++++++++++++++++ src/core/SkScanPriv.h | 3 +++ src/core/SkScan_Path.cpp | 9 +++++++++ 4 files changed, 91 insertions(+) diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 3643e66760..e5c935b60e 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -1021,3 +1021,49 @@ bool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) { } 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 0e5fedd7eb..c9fed1ce22 100644 --- a/src/core/SkBlitter.h +++ b/src/core/SkBlitter.h @@ -240,6 +240,39 @@ private: 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 798cae6d0f..4ff91bb455 100644 --- a/src/core/SkScanPriv.h +++ b/src/core/SkScanPriv.h @@ -23,6 +23,9 @@ public: 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 884f785299..9ce18b0ee5 100644 --- a/src/core/SkScan_Path.cpp +++ b/src/core/SkScan_Path.cpp @@ -561,12 +561,21 @@ SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, 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 { -- cgit v1.2.3