| 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) {
|
|
|