spriteblitter for memcpy case (for all configs)

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1887103003

Review URL: https://codereview.chromium.org/1887103003
This commit is contained in:
reed 2016-04-15 06:59:38 -07:00 committed by Commit bot
parent 3faf74b836
commit 8c3fd4f1b4
4 changed files with 113 additions and 30 deletions

View File

@ -105,7 +105,7 @@ public:
* Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel
* colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType.
*/
int shiftPerPixel() const { return this->bytesPerPixel() >> 1; }
int shiftPerPixel() const { return this->fInfo.shiftPerPixel(); }
///////////////////////////////////////////////////////////////////////////

View File

@ -105,6 +105,25 @@ static int SkColorTypeBytesPerPixel(SkColorType ct) {
return gSize[ct];
}
static int SkColorTypeShiftPerPixel(SkColorType ct) {
static const uint8_t gShift[] = {
0, // Unknown
0, // Alpha_8
1, // RGB_565
1, // ARGB_4444
2, // RGBA_8888
2, // BGRA_8888
0, // kIndex_8
0, // kGray_8
3, // kRGBA_F16
};
static_assert(SK_ARRAY_COUNT(gShift) == (size_t)(kLastEnum_SkColorType + 1),
"size_mismatch_with_SkColorType_enum");
SkASSERT((size_t)ct < SK_ARRAY_COUNT(gShift));
return gShift[ct];
}
static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
return width * SkColorTypeBytesPerPixel(ct);
}
@ -114,15 +133,10 @@ static inline bool SkColorTypeIsValid(unsigned value) {
}
static inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size_t rowBytes) {
int shift = 0;
switch (SkColorTypeBytesPerPixel(ct)) {
case 8: shift = 3; break;
case 4: shift = 2; break;
case 2: shift = 1; break;
case 1: shift = 0; break;
default: return 0;
if (kUnknown_SkColorType == ct) {
return 0;
}
return y * rowBytes + (x << shift);
return y * rowBytes + (x << SkColorTypeShiftPerPixel(ct));
}
///////////////////////////////////////////////////////////////////////////////
@ -252,9 +266,9 @@ public:
return SkImageInfo::Make(fWidth, fHeight, newColorType, fAlphaType, fProfileType);
}
int bytesPerPixel() const {
return SkColorTypeBytesPerPixel(fColorType);
}
int bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
int shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
uint64_t minRowBytes64() const {
return sk_64_mul(fWidth, this->bytesPerPixel());

View File

@ -80,7 +80,7 @@ public:
* Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel
* colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType.
*/
int shiftPerPixel() const { return fInfo.bytesPerPixel() >> 1; }
int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); }
uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); }
@ -141,6 +141,9 @@ public:
// Writable versions
void* writable_addr() const { return const_cast<void*>(fPixels); }
void* writable_addr(int x, int y) const {
return const_cast<void*>(this->addr(x, y));
}
uint8_t* writable_addr8(int x, int y) const {
return const_cast<uint8_t*>(this->addr8(x, y));
}

View File

@ -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,6 +117,9 @@ SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint,
SkSpriteBlitter* blitter;
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);
@ -73,6 +138,7 @@ SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint,
blitter = nullptr;
break;
}
}
if (blitter) {
blitter->setup(dst, left, top, paint);