implement A8 destination fast-path for SkPixelInfo::CopyPixels
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2407093002 Review-Url: https://codereview.chromium.org/2407093002
This commit is contained in:
parent
0f61faa7b7
commit
a2415accf1
@ -8,6 +8,7 @@
|
||||
#include "SkAtomics.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkConfig8888.h"
|
||||
#include "SkData.h"
|
||||
#include "SkFilterQuality.h"
|
||||
#include "SkMallocPixelRef.h"
|
||||
@ -906,72 +907,21 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowBytes) {
|
||||
for (int y = 0; y < size.height(); ++y) {
|
||||
memset(array, value, size.width());
|
||||
array += rowBytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
|
||||
SkColorType colorType = pmap.colorType();
|
||||
int w = pmap.width();
|
||||
int h = pmap.height();
|
||||
size_t rb = pmap.rowBytes();
|
||||
|
||||
if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) {
|
||||
const uint8_t* s = pmap.addr8(0, 0);
|
||||
while (--h >= 0) {
|
||||
memcpy(alpha, s, w);
|
||||
s += rb;
|
||||
alpha += alphaRowBytes;
|
||||
}
|
||||
} else if (kN32_SkColorType == colorType && !pmap.isOpaque()) {
|
||||
const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0);
|
||||
while (--h >= 0) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
alpha[x] = SkGetPackedA32(s[x]);
|
||||
}
|
||||
s = (const SkPMColor*)((const char*)s + rb);
|
||||
alpha += alphaRowBytes;
|
||||
}
|
||||
} else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) {
|
||||
const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0);
|
||||
while (--h >= 0) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
alpha[x] = SkPacked4444ToA32(s[x]);
|
||||
}
|
||||
s = (const SkPMColor16*)((const char*)s + rb);
|
||||
alpha += alphaRowBytes;
|
||||
}
|
||||
} else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) {
|
||||
const SkColorTable* ct = pmap.ctable();
|
||||
if (ct) {
|
||||
const SkPMColor* SK_RESTRICT table = ct->readColors();
|
||||
const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0);
|
||||
while (--h >= 0) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
alpha[x] = SkGetPackedA32(table[s[x]]);
|
||||
}
|
||||
s += rb;
|
||||
alpha += alphaRowBytes;
|
||||
}
|
||||
}
|
||||
} else { // src is opaque, so just fill alpha[] with 0xFF
|
||||
rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes);
|
||||
}
|
||||
}
|
||||
|
||||
static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
|
||||
SkASSERT(alpha != nullptr);
|
||||
SkASSERT(alphaRowBytes >= src.width());
|
||||
|
||||
SkAutoPixmapUnlock apl;
|
||||
if (!src.requestLock(&apl)) {
|
||||
rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes);
|
||||
for (int y = 0; y < src.height(); ++y) {
|
||||
memset(alpha, 0, src.width());
|
||||
alpha += alphaRowBytes;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes);
|
||||
const SkPixmap& pmap = apl.pixmap();
|
||||
SkPixelInfo::CopyPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
|
||||
pmap.info(), pmap.addr(), pmap.rowBytes(), pmap.ctable());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,64 @@ static void copy_32_to_g8(void* dst, size_t dstRB, const void* src, size_t srcRB
|
||||
}
|
||||
}
|
||||
|
||||
static bool extract_alpha(void* dst, size_t dstRB, const void* src, size_t srcRB,
|
||||
const SkImageInfo& srcInfo, SkColorTable* ctable) {
|
||||
uint8_t* SK_RESTRICT dst8 = (uint8_t*)dst;
|
||||
|
||||
const int w = srcInfo.width();
|
||||
const int h = srcInfo.height();
|
||||
if (srcInfo.isOpaque()) {
|
||||
// src is opaque, so just fill alpha with 0xFF
|
||||
for (int y = 0; y < h; ++y) {
|
||||
memset(dst8, 0xFF, w);
|
||||
dst8 += dstRB;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (srcInfo.colorType()) {
|
||||
case kN32_SkColorType: {
|
||||
const SkPMColor* SK_RESTRICT src32 = (const SkPMColor*)src;
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
dst8[x] = SkGetPackedA32(src32[x]);
|
||||
}
|
||||
dst8 += dstRB;
|
||||
src32 = (const SkPMColor*)((const char*)src32 + srcRB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kARGB_4444_SkColorType: {
|
||||
const SkPMColor16* SK_RESTRICT src16 = (const SkPMColor16*)src;
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
dst8[x] = SkPacked4444ToA32(src16[x]);
|
||||
}
|
||||
dst8 += dstRB;
|
||||
src16 = (const SkPMColor16*)((const char*)src16 + srcRB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kIndex_8_SkColorType: {
|
||||
if (nullptr == ctable) {
|
||||
return false;
|
||||
}
|
||||
const SkPMColor* SK_RESTRICT table = ctable->readColors();
|
||||
const uint8_t* SK_RESTRICT src8 = (const uint8_t*)src;
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
dst8[x] = SkGetPackedA32(table[src8[x]]);
|
||||
}
|
||||
dst8 += dstRB;
|
||||
src8 += srcRB;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
|
||||
const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
|
||||
SkColorTable* ctable) {
|
||||
@ -241,6 +299,11 @@ bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t
|
||||
return true;
|
||||
}
|
||||
|
||||
if (kAlpha_8_SkColorType == dstInfo.colorType() &&
|
||||
extract_alpha(dstPixels, dstRB, srcPixels, srcRB, srcInfo, ctable)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can no longer draw directly into 4444, but we can manually whack it for a few combinations
|
||||
if (kARGB_4444_SkColorType == dstInfo.colorType() &&
|
||||
(kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) {
|
||||
|
@ -135,8 +135,14 @@ static void fill_dst_bmp_with_init_data(SkBitmap* bitmap) {
|
||||
intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels());
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
|
||||
*pixel = get_dst_bmp_init_color(x, y, w);
|
||||
SkPMColor initColor = get_dst_bmp_init_color(x, y, w);
|
||||
if (kAlpha_8_SkColorType == bitmap->colorType()) {
|
||||
uint8_t* alpha = reinterpret_cast<uint8_t*>(pixels + y * bitmap->rowBytes() + x);
|
||||
*alpha = SkGetPackedA32(initColor);
|
||||
} else {
|
||||
SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
|
||||
*pixel = initColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -168,14 +174,13 @@ static bool check_read(skiatest::Reporter* reporter,
|
||||
const SkBitmap& bitmap,
|
||||
int x, int y,
|
||||
bool checkCanvasPixels,
|
||||
bool checkBitmapPixels) {
|
||||
SkASSERT(4 == bitmap.bytesPerPixel());
|
||||
bool checkBitmapPixels,
|
||||
SkColorType ct,
|
||||
SkAlphaType at) {
|
||||
SkASSERT(ct == bitmap.colorType() && at == bitmap.alphaType());
|
||||
SkASSERT(!bitmap.isNull());
|
||||
SkASSERT(checkCanvasPixels || checkBitmapPixels);
|
||||
|
||||
const SkColorType ct = bitmap.colorType();
|
||||
const SkAlphaType at = bitmap.alphaType();
|
||||
|
||||
int bw = bitmap.width();
|
||||
int bh = bitmap.height();
|
||||
|
||||
@ -185,6 +190,34 @@ static bool check_read(skiatest::Reporter* reporter,
|
||||
clippedSrcRect.setEmpty();
|
||||
}
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
if (kAlpha_8_SkColorType == ct) {
|
||||
for (int by = 0; by < bh; ++by) {
|
||||
for (int bx = 0; bx < bw; ++bx) {
|
||||
int devx = bx + srcRect.fLeft;
|
||||
int devy = by + srcRect.fTop;
|
||||
const uint8_t* alpha = bitmap.getAddr8(bx, by);
|
||||
|
||||
if (clippedSrcRect.contains(devx, devy)) {
|
||||
if (checkCanvasPixels) {
|
||||
uint8_t canvasAlpha = SkGetPackedA32(get_src_color(devx, devy));
|
||||
if (canvasAlpha != *alpha) {
|
||||
ERRORF(reporter, "Expected readback alpha (%d, %d) value 0x%02x, got 0x%02x. ",
|
||||
bx, by, canvasAlpha, *alpha);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (checkBitmapPixels) {
|
||||
uint32_t origDstAlpha = SkGetPackedA32(get_dst_bmp_init_color(bx, by, bw));
|
||||
if (origDstAlpha != *alpha) {
|
||||
ERRORF(reporter, "Expected clipped out area of readback to be unchanged. "
|
||||
"Expected 0x%02x, got 0x%02x", origDstAlpha, *alpha);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for (int by = 0; by < bh; ++by) {
|
||||
for (int bx = 0; bx < bw; ++bx) {
|
||||
int devx = bx + srcRect.fLeft;
|
||||
@ -249,10 +282,10 @@ static void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init,
|
||||
case kTight_BitmapInit:
|
||||
break;
|
||||
case kRowBytes_BitmapInit:
|
||||
rowBytes = (info.width() + 16) * sizeof(SkPMColor);
|
||||
rowBytes = SkAlign4((info.width() + 16) * info.bytesPerPixel());
|
||||
break;
|
||||
case kRowBytesOdd_BitmapInit:
|
||||
rowBytes = (info.width() * sizeof(SkPMColor)) + 3;
|
||||
rowBytes = SkAlign4(info.width() * info.bytesPerPixel()) + 3;
|
||||
break;
|
||||
default:
|
||||
SkASSERT(0);
|
||||
@ -274,6 +307,7 @@ static const struct {
|
||||
{ kRGBA_8888_SkColorType, kUnpremul_SkAlphaType },
|
||||
{ kBGRA_8888_SkColorType, kPremul_SkAlphaType },
|
||||
{ kBGRA_8888_SkColorType, kUnpremul_SkAlphaType },
|
||||
{ kAlpha_8_SkColorType, kPremul_SkAlphaType },
|
||||
};
|
||||
const SkIRect gReadPixelsTestRects[] = {
|
||||
// entire thing
|
||||
@ -354,7 +388,8 @@ static void test_readpixels(skiatest::Reporter* reporter, const sk_sp<SkSurface>
|
||||
|
||||
if (success || startsWithPixels) {
|
||||
check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop,
|
||||
success, startsWithPixels);
|
||||
success, startsWithPixels,
|
||||
gReadPixelsConfigs[c].fColorType, gReadPixelsConfigs[c].fAlphaType);
|
||||
} else {
|
||||
// if we had no pixels beforehand and the readPixels
|
||||
// failed then our bitmap should still not have pixels
|
||||
@ -371,7 +406,8 @@ static void test_readpixels(skiatest::Reporter* reporter, const sk_sp<SkSurface>
|
||||
REPORTER_ASSERT(reporter, kN32_SkColorType == wkbmp.colorType());
|
||||
REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.alphaType());
|
||||
check_read(reporter, wkbmp, clippedRect.fLeft,
|
||||
clippedRect.fTop, true, false);
|
||||
clippedRect.fTop, true, false,
|
||||
kN32_SkColorType, kPremul_SkAlphaType);
|
||||
} else {
|
||||
REPORTER_ASSERT(reporter, !success);
|
||||
}
|
||||
@ -427,7 +463,8 @@ static void test_readpixels_texture(skiatest::Reporter* reporter, GrTexture* tex
|
||||
bmp.rowBytes(), flags);
|
||||
bmp.unlockPixels();
|
||||
check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop,
|
||||
success, true);
|
||||
success, true,
|
||||
gReadPixelsConfigs[c].fColorType, gReadPixelsConfigs[c].fAlphaType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user