Make raster pipeline support all pixel conversions
BUG=skia:
CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD
Change-Id: Idc76999d0f5591a567b3976cb9db829c350e4be2
Reviewed-on: https://skia-review.googlesource.com/8304
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index ee762d1..aa98e91 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -7,6 +7,9 @@
#include "SkCanvas.h"
#include "SkColorPriv.h"
+#include "SkColorSpace_Base.h"
+#include "SkHalf.h"
+#include "SkImageInfoPriv.h"
#include "SkMathPriv.h"
#include "SkSurface.h"
#include "Test.h"
@@ -484,3 +487,158 @@
}
}
#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+static const uint32_t kNumPixels = 5;
+
+// The five reference pixels are: red, green, blue, white, black.
+// Five is an interesting number to test because we'll exercise a full 4-wide SIMD vector
+// plus a tail pixel.
+static const uint32_t rgba[kNumPixels] = {
+ 0xFF0000FF, 0xFF00FF00, 0xFFFF0000, 0xFFFFFFFF, 0xFF000000
+};
+static const uint32_t bgra[kNumPixels] = {
+ 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF, 0xFF000000
+};
+static const uint16_t rgb565[kNumPixels] = {
+ SK_R16_MASK_IN_PLACE, SK_G16_MASK_IN_PLACE, SK_B16_MASK_IN_PLACE, 0xFFFF, 0x0
+};
+
+static const uint16_t rgba4444[kNumPixels] = { 0xF00F, 0x0F0F, 0x00FF, 0xFFFF, 0x000F };
+
+static const uint64_t kRed = (uint64_t) SK_Half1 << 0;
+static const uint64_t kGreen = (uint64_t) SK_Half1 << 16;
+static const uint64_t kBlue = (uint64_t) SK_Half1 << 32;
+static const uint64_t kAlpha = (uint64_t) SK_Half1 << 48;
+static const uint64_t f16[kNumPixels] = {
+ kAlpha | kRed, kAlpha | kGreen, kAlpha | kBlue, kAlpha | kBlue | kGreen | kRed, kAlpha
+};
+
+#ifdef SK_PMCOLOR_IS_RGBA
+static const SkPMColor index8colors[kNumPixels] = {
+ 0xFF0000FF, 0xFF00FF00, 0xFFFF0000, 0xFFFFFFFF, 0xFF000000
+};
+#else
+static const SkPMColor index8colors[kNumPixels] = {
+ 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF, 0xFF000000
+};
+#endif
+static const uint8_t index8[kNumPixels] = { 0, 1, 2, 3, 4 };
+static const uint8_t alpha8[kNumPixels] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const uint8_t gray8[kNumPixels] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+static const void* five_reference_pixels(SkColorType colorType) {
+ switch (colorType) {
+ case kUnknown_SkColorType:
+ return nullptr;
+ case kAlpha_8_SkColorType:
+ return alpha8;
+ case kRGB_565_SkColorType:
+ return rgb565;
+ case kARGB_4444_SkColorType:
+ return rgba4444;
+ case kRGBA_8888_SkColorType:
+ return rgba;
+ case kBGRA_8888_SkColorType:
+ return bgra;
+ case kIndex_8_SkColorType:
+ return index8;
+ case kGray_8_SkColorType:
+ return gray8;
+ case kRGBA_F16_SkColorType:
+ return f16;
+ }
+
+ SkASSERT(false);
+ return nullptr;
+}
+
+static void test_conversion(skiatest::Reporter* r, const SkImageInfo& dstInfo,
+ const SkImageInfo& srcInfo) {
+ if (!SkImageInfoIsValid(srcInfo)) {
+ return;
+ }
+
+ sk_sp<SkColorTable> srcColorTable = (kIndex_8_SkColorType == srcInfo.colorType())
+ ? sk_make_sp<SkColorTable>(index8colors, 5)
+ : nullptr;
+ sk_sp<SkColorTable> dstColorTable = (kIndex_8_SkColorType == dstInfo.colorType())
+ ? sk_make_sp<SkColorTable>(index8colors, 5)
+ : nullptr;
+
+ const void* srcPixels = five_reference_pixels(srcInfo.colorType());
+ SkPixmap srcPixmap(srcInfo, srcPixels, srcInfo.minRowBytes(), srcColorTable.get());
+ sk_sp<SkImage> src = SkImage::MakeFromRaster(srcPixmap, nullptr, nullptr);
+ REPORTER_ASSERT(r, src);
+
+ // Enough space for 5 pixels when color type is F16, more than enough space in other cases.
+ uint64_t dstPixels[kNumPixels];
+ SkPixmap dstPixmap(dstInfo, dstPixels, dstInfo.minRowBytes(), dstColorTable.get());
+ bool success = src->readPixels(dstPixmap, 0, 0);
+ REPORTER_ASSERT(r, success == SkImageInfoValidConversion(dstInfo, srcInfo));
+
+ if (success) {
+ if (kGray_8_SkColorType == srcInfo.colorType() &&
+ kGray_8_SkColorType != dstInfo.colorType())
+ {
+ // This conversion is legal, but we won't get the "reference" pixels since we cannot
+ // represent colors in kGray8.
+ return;
+ }
+
+ REPORTER_ASSERT(r, 0 == memcmp(dstPixels, five_reference_pixels(dstInfo.colorType()),
+ kNumPixels * SkColorTypeBytesPerPixel(dstInfo.colorType())));
+
+ }
+}
+
+DEF_TEST(ReadPixels_ValidConversion, reporter) {
+ const SkColorType kColorTypes[] = {
+ kUnknown_SkColorType,
+ kAlpha_8_SkColorType,
+ kRGB_565_SkColorType,
+ kARGB_4444_SkColorType,
+ kRGBA_8888_SkColorType,
+ kBGRA_8888_SkColorType,
+ kIndex_8_SkColorType,
+ kGray_8_SkColorType,
+ kRGBA_F16_SkColorType,
+ };
+
+ const SkAlphaType kAlphaTypes[] = {
+ kUnknown_SkAlphaType,
+ kOpaque_SkAlphaType,
+ kPremul_SkAlphaType,
+ kUnpremul_SkAlphaType,
+ };
+
+ const sk_sp<SkColorSpace> kColorSpaces[] = {
+ nullptr,
+ SkColorSpace::MakeSRGB(),
+ };
+
+ for (SkColorType dstCT : kColorTypes) {
+ for (SkAlphaType dstAT: kAlphaTypes) {
+ for (sk_sp<SkColorSpace> dstCS : kColorSpaces) {
+ for (SkColorType srcCT : kColorTypes) {
+ for (SkAlphaType srcAT: kAlphaTypes) {
+ for (sk_sp<SkColorSpace> srcCS : kColorSpaces) {
+ if (kRGBA_F16_SkColorType == dstCT && dstCS) {
+ dstCS = as_CSB(dstCS)->makeLinearGamma();
+ }
+
+ if (kRGBA_F16_SkColorType == srcCT && srcCS) {
+ srcCS = as_CSB(srcCS)->makeLinearGamma();
+ }
+
+ test_conversion(reporter,
+ SkImageInfo::Make(kNumPixels, 1, dstCT, dstAT, dstCS),
+ SkImageInfo::Make(kNumPixels, 1, srcCT, srcAT, srcCS));
+ }
+ }
+ }
+ }
+ }
+ }
+}