Add test for reading back from unpremul texture image

The unpremul->unpremul readback doesn't work today. GrSurfaceContext doesn't track an alpha type and whenever we read into an unpremul buffer we unpremul the texture's colors since we assume they were premuled.

Bug: 7580

Change-Id: I307a168799f27b2015e082cf6adde26b906cfe2b
Reviewed-on: https://skia-review.googlesource.com/103780
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2018-02-05 12:57:10 -05:00 committed by Skia Commit-Bot
parent efb25fd809
commit 9708af826c
2 changed files with 71 additions and 0 deletions

View File

@ -149,6 +149,7 @@ static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes)
for (int x = 0; x < info.width(); ++x) {
row[x] = SkPreMultiplyColor(row[x]);
}
row = (SkColor*)((char*)(row) + rowBytes);
}
}

View File

@ -510,6 +510,76 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsImage, reporter
}
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(UnpremulTextureImage, reporter, ctxInfo) {
SkBitmap bmp;
bmp.allocPixels(
SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType, nullptr));
for (int y = 0; y < 256; ++y) {
for (int x = 0; x < 256; ++x) {
*bmp.getAddr32(x, y) =
SkColorSetARGB((U8CPU)y, 255 - (U8CPU)y, (U8CPU)x, 255 - (U8CPU)x);
}
}
auto texImage = SkImage::MakeFromBitmap(bmp)->makeTextureImage(ctxInfo.grContext(), nullptr);
if (!texImage || texImage->alphaType() != kUnpremul_SkAlphaType) {
ERRORF(reporter, "Failed to make unpremul texture image.");
return;
}
// The GPU backend always unpremuls the values stored in the texture because it assumes they
// are premul values. (skbug.com/7580).
if (false) {
SkBitmap unpremul;
unpremul.allocPixels(SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType,
kUnpremul_SkAlphaType, nullptr));
if (!texImage->readPixels(unpremul.info(), unpremul.getPixels(), unpremul.rowBytes(), 0,
0)) {
ERRORF(reporter, "Unpremul readback failed.");
return;
}
for (int y = 0; y < 256; ++y) {
for (int x = 0; x < 256; ++x) {
if (*bmp.getAddr32(x, y) != *unpremul.getAddr32(x, y)) {
ERRORF(reporter, "unpremul(0x%08x)->unpremul(0x%08x) at %d, %d.",
*bmp.getAddr32(x, y), *unpremul.getAddr32(x, y), x, y);
return;
}
}
}
}
SkBitmap premul;
premul.allocPixels(
SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr));
if (!texImage->readPixels(premul.info(), premul.getPixels(), premul.rowBytes(), 0, 0)) {
ERRORF(reporter, "Unpremul readback failed.");
return;
}
for (int y = 0; y < 256; ++y) {
for (int x = 0; x < 256; ++x) {
// Treat bmp's color as a pm color even though it may be the r/b swap of a PM color.
// SkPremultiplyColor acts the same on both channels.
uint32_t origColor = SkPreMultiplyColor(*bmp.getAddr32(x, y));
int32_t origA = (origColor >> 24) & 0xff;
int32_t origB = (origColor >> 16) & 0xff;
int32_t origG = (origColor >> 8) & 0xff;
int32_t origR = (origColor >> 0) & 0xff;
uint32_t read = *premul.getAddr32(x, y);
int32_t readA = (read >> 24) & 0xff;
int32_t readB = (read >> 16) & 0xff;
int32_t readG = (read >> 8) & 0xff;
int32_t readR = (read >> 0) & 0xff;
// We expect that alpha=1 and alpha=0 should come out exact. Otherwise allow a little
// bit of tolerance for GPU vs CPU premul math.
int32_t tol = (origA == 0 || origA == 255) ? 0 : 1;
if (origA != readA || SkTAbs(readB - origB) > tol || SkTAbs(readG - origG) > tol ||
SkTAbs(readR - origR) > tol) {
ERRORF(reporter, "unpremul(0x%08x)->premul(0x%08x) at %d, %d.",
*bmp.getAddr32(x, y), *premul.getAddr32(x, y), x, y);
return;
}
}
}
}
#endif
class EmptyGenerator : public SkImageGenerator {