Index: src/core/SkBlitter_Sprite.cpp |
diff --git a/src/core/SkBlitter_Sprite.cpp b/src/core/SkBlitter_Sprite.cpp |
index 27cbd61768ed6db20aad874e0cbb570d1c449a19..c0b7430d22f4d950661fe530db6fe60fde6d0b98 100644 |
--- a/src/core/SkBlitter_Sprite.cpp |
+++ b/src/core/SkBlitter_Sprite.cpp |
@@ -38,6 +38,68 @@ void SkSpriteBlitter::blitMask(const SkMask&, const SkIRect& clip) { |
/////////////////////////////////////////////////////////////////////////////// |
+// Only valid if... |
+// 1. src == dst format |
+// 2. paint has no modifiers (i.e. alpha, colorfilter, etc.) |
+// 3. xfermode needs no blending: e.g. kSrc_Mode or kSrcOver_Mode + opaque src |
+// |
+class SkSpriteBlitter_memcpy : public SkSpriteBlitter { |
+public: |
+ static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { |
+ if (dst.colorType() != src.colorType()) { |
+ return false; |
+ } |
+ if (dst.info().profileType() != src.info().profileType()) { |
+ return false; |
+ } |
+ if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { |
+ return false; |
+ } |
+ if (0xFF != paint.getAlpha()) { |
+ return false; |
+ } |
+ SkXfermode::Mode mode; |
+ if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { |
+ return false; |
+ } |
+ if (SkXfermode::kSrc_Mode == mode) { |
+ return true; |
+ } |
+ if (SkXfermode::kSrcOver_Mode == mode && src.isOpaque()) { |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ SkSpriteBlitter_memcpy(const SkPixmap& src) : INHERITED(src) {} |
+ |
+ void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override { |
+ SkASSERT(Supports(dst, fSource, paint)); |
+ this->INHERITED::setup(dst, left, top, paint); |
+ } |
+ |
+ void blitRect(int x, int y, int width, int height) override { |
+ SkASSERT(fDst.colorType() == fSource.colorType()); |
+ SkASSERT(fDst.info().profileType() == fSource.info().profileType()); |
+ SkASSERT(width > 0 && height > 0); |
+ |
+ char* dst = (char*)fDst.writable_addr(x, y); |
+ const char* src = (const char*)fSource.addr(x - fLeft, y - fTop); |
+ const size_t dstRB = fDst.rowBytes(); |
+ const size_t srcRB = fSource.rowBytes(); |
+ const size_t bytesToCopy = width << fSource.shiftPerPixel(); |
+ |
+ while (--height >= 0) { |
+ memcpy(dst, src, bytesToCopy); |
+ dst += dstRB; |
+ src += srcRB; |
+ } |
+ } |
+ |
+ typedef SkSpriteBlitter INHERITED; |
+}; |
+ |
+ |
// returning null means the caller will call SkBlitter::Choose() and |
// have wrapped the source bitmap inside a shader |
SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint, |
@@ -55,23 +117,27 @@ SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint, |
SkSpriteBlitter* blitter; |
- switch (dst.colorType()) { |
- case kRGB_565_SkColorType: |
- blitter = SkSpriteBlitter::ChooseD16(source, paint, allocator); |
- break; |
- case kN32_SkColorType: |
- if (dst.info().isSRGB()) { |
- blitter = SkSpriteBlitter::ChooseS32(source, paint, allocator); |
- } else { |
- blitter = SkSpriteBlitter::ChooseL32(source, paint, allocator); |
- } |
- break; |
- case kRGBA_F16_SkColorType: |
- blitter = SkSpriteBlitter::ChooseF16(source, paint, allocator); |
- break; |
- default: |
- blitter = nullptr; |
- break; |
+ if (SkSpriteBlitter_memcpy::Supports(dst, source, paint)) { |
+ blitter = allocator->createT<SkSpriteBlitter_memcpy>(source); |
+ } else { |
+ switch (dst.colorType()) { |
+ case kRGB_565_SkColorType: |
+ blitter = SkSpriteBlitter::ChooseD16(source, paint, allocator); |
+ break; |
+ case kN32_SkColorType: |
+ if (dst.info().isSRGB()) { |
+ blitter = SkSpriteBlitter::ChooseS32(source, paint, allocator); |
+ } else { |
+ blitter = SkSpriteBlitter::ChooseL32(source, paint, allocator); |
+ } |
+ break; |
+ case kRGBA_F16_SkColorType: |
+ blitter = SkSpriteBlitter::ChooseF16(source, paint, allocator); |
+ break; |
+ default: |
+ blitter = nullptr; |
+ break; |
+ } |
} |
if (blitter) { |