Add kRG_88_SkColorType

Bug: skia:9121

Change-Id: Id2a12a5d607b84ce393d2b58233bf8e23f646059
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235797
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Robert Phillips 2019-09-04 15:05:35 -04:00 committed by Skia Commit-Bot
parent 4655534302
commit d470e1b905
30 changed files with 440 additions and 111 deletions

View File

@ -90,3 +90,7 @@ Milestone 78
* Changed GrContextOptions' fDisallowGLSLBinaryCaching to fShaderCacheStrategy, * Changed GrContextOptions' fDisallowGLSLBinaryCaching to fShaderCacheStrategy,
and allow caching SkSL. and allow caching SkSL.
https://review.skia.org/238856 https://review.skia.org/238856
* Added kRG_88_SkColorType. This is intended to help support YUV uses case (e.g., NV12).
As such, it the addition is focused on allowing creation of SkPixmaps and SkImages and not
SkSurfaces (i.e., who wants to render to RG?)

View File

@ -40,6 +40,7 @@ static const char* color_type_name(SkColorType colorType) {
case kRGBA_F16Norm_SkColorType: return "F16Norm"; case kRGBA_F16Norm_SkColorType: return "F16Norm";
case kRGBA_F16_SkColorType: return "F16"; case kRGBA_F16_SkColorType: return "F16";
case kRGBA_F32_SkColorType: return "F32"; case kRGBA_F32_SkColorType: return "F32";
case kRG_88_SkColorType: return "RG88";
} }
return ""; return "";
} }

View File

@ -523,7 +523,7 @@ static void extract_planes(const SkBitmap& bm, SkYUVColorSpace yuvColorSpace, Pl
} }
} }
// Create a 2x2 downsampled SkBitmap. It is stored in an RGBA texture. It can optionally be // Create a 2x2 downsampled SkBitmap. It is stored in an RG texture. It can optionally be
// uv (i.e., for P016, P010 and NV12) or vu (i.e., NV21). // uv (i.e., for P016, P010 and NV12) or vu (i.e., NV21).
static SkBitmap make_quarter_2_channel(const SkBitmap& fullY, static SkBitmap make_quarter_2_channel(const SkBitmap& fullY,
const SkBitmap& quarterU, const SkBitmap& quarterU,
@ -531,10 +531,9 @@ static SkBitmap make_quarter_2_channel(const SkBitmap& fullY,
bool uv) { bool uv) {
SkBitmap result; SkBitmap result;
// There isn't a RG color type. Approx w/ RGBA.
result.allocPixels(SkImageInfo::Make(fullY.width()/2, result.allocPixels(SkImageInfo::Make(fullY.width()/2,
fullY.height()/2, fullY.height()/2,
kRGBA_8888_SkColorType, kRG_88_SkColorType,
kUnpremul_SkAlphaType)); kUnpremul_SkAlphaType));
for (int y = 0; y < fullY.height()/2; ++y) { for (int y = 0; y < fullY.height()/2; ++y) {
@ -543,13 +542,9 @@ static SkBitmap make_quarter_2_channel(const SkBitmap& fullY,
uint8_t v8 = *quarterV.getAddr8(x, y); uint8_t v8 = *quarterV.getAddr8(x, y);
if (uv) { if (uv) {
// NOT premul! *result.getAddr16(x, y) = (v8 << 8) | u8;
// U and 0 swapped to match RGBA layout
*result.getAddr32(x, y) = SkColorSetARGB(0xFF, 0, v8, u8);
} else { } else {
// NOT premul! *result.getAddr16(x, y) = (u8 << 8) | v8;
// V and 0 swapped to match RGBA layout
*result.getAddr32(x, y) = SkColorSetARGB(0xFF, 0, u8, v8);
} }
} }
} }
@ -698,6 +693,24 @@ static uint8_t look_up(float x1, float y1, const SkBitmap& bm, SkColorChannel ch
if (kAlpha_8_SkColorType == bm.colorType() || kGray_8_SkColorType == bm.colorType()) { if (kAlpha_8_SkColorType == bm.colorType() || kGray_8_SkColorType == bm.colorType()) {
SkASSERT(SkColorChannel::kA == channel || SkColorChannel::kR == channel); SkASSERT(SkColorChannel::kA == channel || SkColorChannel::kR == channel);
result = *bm.getAddr8(x, y); result = *bm.getAddr8(x, y);
} else if (kRG_88_SkColorType == bm.colorType()) {
SkASSERT(SkColorChannel::kR == channel || SkColorChannel::kG == channel);
SkColor c = bm.getColor(x, y);
switch (channel) {
case SkColorChannel::kR:
result = SkColorGetR(c);
break;
case SkColorChannel::kG:
result = SkColorGetG(c);
break;
case SkColorChannel::kB:
result = 0;
break;
case SkColorChannel::kA:
result = 255;
break;
}
} else if (kRGBA_8888_SkColorType == bm.colorType()) { } else if (kRGBA_8888_SkColorType == bm.colorType()) {
SkColor c = *bm.getAddr32(x, y); SkColor c = *bm.getAddr32(x, y);
@ -918,36 +931,12 @@ static void draw_row_label(SkCanvas* canvas, int y, int yuvFormat) {
canvas->drawString(rowLabel, 0, y, font, paint); canvas->drawString(rowLabel, 0, y, font, paint);
} }
static void make_RG_88(const GrCaps* caps,
const SkBitmap& bm, YUVFormat yuvFormat,
SkAutoTMalloc<uint8_t>* pixels,
GrBackendFormat* format, size_t* rowBytes) {
SkASSERT(kNV12_YUVFormat == yuvFormat || kNV21_YUVFormat == yuvFormat);
SkASSERT(kRGBA_8888_SkColorType == bm.colorType()); // uv stored in rg
*rowBytes = bm.width() * 2 * sizeof(uint8_t);
pixels->reset(*rowBytes * bm.height());
uint8_t* currPixel = pixels->get();
for (int y = 0; y < bm.height(); ++y) {
for (int x = 0; x < bm.width(); ++x) {
SkColor color = bm.getColor(x, y);
uint8_t u8 = SkColorGetR(color);
uint8_t v8 = SkColorGetG(color);
currPixel[0] = u8;
currPixel[1] = v8;
currPixel += 2;
}
}
*format = caps->getDefaultBackendFormat(GrColorType::kRG_88, GrRenderable::kNo);
}
static void make_RG_1616(const GrCaps* caps, static void make_RG_1616(const GrCaps* caps,
const SkBitmap& bm, YUVFormat yuvFormat, const SkBitmap& bm, YUVFormat yuvFormat,
SkAutoTMalloc<uint8_t>* pixels, SkAutoTMalloc<uint8_t>* pixels,
GrBackendFormat* format, size_t* rowBytes) { GrBackendFormat* format, size_t* rowBytes) {
SkASSERT(kP016_YUVFormat == yuvFormat || kP010_YUVFormat == yuvFormat); SkASSERT(kP016_YUVFormat == yuvFormat || kP010_YUVFormat == yuvFormat);
SkASSERT(kRGBA_8888_SkColorType == bm.colorType()); // uv stored in rg SkASSERT(kRG_88_SkColorType == bm.colorType()); // uv stored in rg
uint16_t u16, v16; uint16_t u16, v16;
*rowBytes = bm.width() * 2 * sizeof(uint16_t); *rowBytes = bm.width() * 2 * sizeof(uint16_t);
@ -1053,8 +1042,6 @@ static GrBackendTexture create_yuva_texture(GrContext* context, const SkBitmap&
} }
} }
GrBackendTexture tex;
if (format_uses_16_bpp(yuvFormat) || 2 == channelCount) { if (format_uses_16_bpp(yuvFormat) || 2 == channelCount) {
// Due to the limitations of SkPixmap these cases need to be handled separately // Due to the limitations of SkPixmap these cases need to be handled separately
const GrCaps* caps = context->priv().caps(); const GrCaps* caps = context->priv().caps();
@ -1068,7 +1055,10 @@ static GrBackendTexture create_yuva_texture(GrContext* context, const SkBitmap&
if (format_uses_16_bpp(yuvFormat)) { if (format_uses_16_bpp(yuvFormat)) {
make_RG_1616(caps, bm, yuvFormat, &pixels, &format, &rowBytes); make_RG_1616(caps, bm, yuvFormat, &pixels, &format, &rowBytes);
} else { } else {
make_RG_88(caps, bm, yuvFormat, &pixels, &format, &rowBytes); SkASSERT(kRG_88_SkColorType == bm.colorType());
return context->priv().createBackendTexture(&bm.pixmap(), 1,
GrRenderable::kNo, GrProtected::kNo);
} }
} else { } else {
if (kRGBA_8888_SkColorType == bm.colorType()) { if (kRGBA_8888_SkColorType == bm.colorType()) {
@ -1078,17 +1068,15 @@ static GrBackendTexture create_yuva_texture(GrContext* context, const SkBitmap&
} }
} }
// TODO: SkColorType needs to be expanded to allow this to be done via the // TODO: SkColorType needs to be expanded to allow RG_1616, RGBA_16 and R_16 to be done
// GrContext::createBackendTexture API // via GrContext::createBackendTexture
tex = gpu->createBackendTexture(bm.width(), bm.height(), format, return gpu->createBackendTexture(bm.width(), bm.height(), format,
GrMipMapped::kNo, GrRenderable::kNo, GrMipMapped::kNo, GrRenderable::kNo,
pixels, rowBytes, nullptr, GrProtected::kNo); pixels, rowBytes, nullptr, GrProtected::kNo);
} else {
tex = context->priv().createBackendTexture(&bm.pixmap(), 1,
GrRenderable::kNo, GrProtected::kNo);
} }
return tex; return context->priv().createBackendTexture(&bm.pixmap(), 1,
GrRenderable::kNo, GrProtected::kNo);
} }
static sk_sp<SkColorFilter> yuv_to_rgb_colorfilter() { static sk_sp<SkColorFilter> yuv_to_rgb_colorfilter() {

View File

@ -70,6 +70,7 @@ tests_sources = [
"$_tests/EncodeTest.cpp", "$_tests/EncodeTest.cpp",
"$_tests/EncodedInfoTest.cpp", "$_tests/EncodedInfoTest.cpp",
"$_tests/ExifTest.cpp", "$_tests/ExifTest.cpp",
"$_tests/ExtendedSkColorTypeTests.cpp",
"$_tests/F16StagesTest.cpp", "$_tests/F16StagesTest.cpp",
"$_tests/FakeStreams.h", "$_tests/FakeStreams.h",
"$_tests/FillPathTest.cpp", "$_tests/FillPathTest.cpp",

View File

@ -85,7 +85,8 @@ enum SkColorType {
kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha; in 64-bit word kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha; in 64-bit word
kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha; in 64-bit word kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha; in 64-bit word
kRGBA_F32_SkColorType, //!< pixel using C float for red, green, blue, alpha; in 128-bit word kRGBA_F32_SkColorType, //!< pixel using C float for red, green, blue, alpha; in 128-bit word
kLastEnum_SkColorType = kRGBA_F32_SkColorType,//!< last valid value kRG_88_SkColorType, //<! pixel with 8 bits each for red, green; in 16-bit word
kLastEnum_SkColorType = kRG_88_SkColorType,//!< last valid value
#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
kN32_SkColorType = kBGRA_8888_SkColorType,//!< native ARGB 32-bit encoding kN32_SkColorType = kBGRA_8888_SkColorType,//!< native ARGB 32-bit encoding

View File

@ -247,6 +247,10 @@ public:
* use maxSurfaceSampleCountForColorType(). * use maxSurfaceSampleCountForColorType().
*/ */
bool colorTypeSupportedAsSurface(SkColorType colorType) const { bool colorTypeSupportedAsSurface(SkColorType colorType) const {
if (kRG_88_SkColorType == colorType) {
return false;
}
return this->maxSurfaceSampleCountForColorType(colorType) > 0; return this->maxSurfaceSampleCountForColorType(colorType) > 0;
} }

View File

@ -1075,10 +1075,10 @@ static constexpr SkColorType GrColorTypeToSkColorType(GrColorType ct) {
case GrColorType::kBGR_565: return kRGB_565_SkColorType; case GrColorType::kBGR_565: return kRGB_565_SkColorType;
case GrColorType::kABGR_4444: return kARGB_4444_SkColorType; case GrColorType::kABGR_4444: return kARGB_4444_SkColorType;
case GrColorType::kRGBA_8888: return kRGBA_8888_SkColorType; case GrColorType::kRGBA_8888: return kRGBA_8888_SkColorType;
// Once we a kRGBA_8888_SRGB_SkColorType we should return that here. // Once we add kRGBA_8888_SRGB_SkColorType we should return that here.
case GrColorType::kRGBA_8888_SRGB: return kRGBA_8888_SkColorType; case GrColorType::kRGBA_8888_SRGB: return kRGBA_8888_SkColorType;
case GrColorType::kRGB_888x: return kRGB_888x_SkColorType; case GrColorType::kRGB_888x: return kRGB_888x_SkColorType;
case GrColorType::kRG_88: return kUnknown_SkColorType; case GrColorType::kRG_88: return kRG_88_SkColorType;
case GrColorType::kBGRA_8888: return kBGRA_8888_SkColorType; case GrColorType::kBGRA_8888: return kBGRA_8888_SkColorType;
case GrColorType::kRGBA_1010102: return kRGBA_1010102_SkColorType; case GrColorType::kRGBA_1010102: return kRGBA_1010102_SkColorType;
case GrColorType::kGray_8: return kGray_8_SkColorType; case GrColorType::kGray_8: return kGray_8_SkColorType;
@ -1113,6 +1113,7 @@ static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct) {
case kRGBA_1010102_SkColorType: return GrColorType::kRGBA_1010102; case kRGBA_1010102_SkColorType: return GrColorType::kRGBA_1010102;
case kRGB_101010x_SkColorType: return GrColorType::kUnknown; case kRGB_101010x_SkColorType: return GrColorType::kUnknown;
case kRGBA_F32_SkColorType: return GrColorType::kRGBA_F32; case kRGBA_F32_SkColorType: return GrColorType::kRGBA_F32;
case kRG_88_SkColorType: return GrColorType::kRG_88;
} }
SkUNREACHABLE; SkUNREACHABLE;
} }

View File

@ -16,6 +16,8 @@ enum SkColorTypeComponentFlag {
kBlue_SkColorTypeComponentFlag = 0x4, kBlue_SkColorTypeComponentFlag = 0x4,
kAlpha_SkColorTypeComponentFlag = 0x8, kAlpha_SkColorTypeComponentFlag = 0x8,
kGray_SkColorTypeComponentFlag = 0x10, kGray_SkColorTypeComponentFlag = 0x10,
kRG_SkColorTypeComponentFlags = kRed_SkColorTypeComponentFlag |
kGreen_SkColorTypeComponentFlag,
kRGB_SkColorTypeComponentFlags = kRed_SkColorTypeComponentFlag | kRGB_SkColorTypeComponentFlags = kRed_SkColorTypeComponentFlag |
kGreen_SkColorTypeComponentFlag | kGreen_SkColorTypeComponentFlag |
kBlue_SkColorTypeComponentFlag, kBlue_SkColorTypeComponentFlag,
@ -38,8 +40,9 @@ static inline uint32_t SkColorTypeComponentFlags(SkColorType ct) {
case kRGBA_F16Norm_SkColorType: return kRGBA_SkColorTypeComponentFlags; case kRGBA_F16Norm_SkColorType: return kRGBA_SkColorTypeComponentFlags;
case kRGBA_F16_SkColorType: return kRGBA_SkColorTypeComponentFlags; case kRGBA_F16_SkColorType: return kRGBA_SkColorTypeComponentFlags;
case kRGBA_F32_SkColorType: return kRGBA_SkColorTypeComponentFlags; case kRGBA_F32_SkColorType: return kRGBA_SkColorTypeComponentFlags;
case kRG_88_SkColorType: return kRG_SkColorTypeComponentFlags;
} }
return 0; SkUNREACHABLE;
} }
static inline bool SkColorTypeIsAlphaOnly(SkColorType ct) { static inline bool SkColorTypeIsAlphaOnly(SkColorType ct) {
@ -72,8 +75,9 @@ static int SkColorTypeShiftPerPixel(SkColorType ct) {
case kRGBA_F16Norm_SkColorType: return 3; case kRGBA_F16Norm_SkColorType: return 3;
case kRGBA_F16_SkColorType: return 3; case kRGBA_F16_SkColorType: return 3;
case kRGBA_F32_SkColorType: return 4; case kRGBA_F32_SkColorType: return 4;
case kRG_88_SkColorType: return 1;
} }
return 0; SkUNREACHABLE;
} }
static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) { static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {

View File

@ -1234,7 +1234,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
.value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType) .value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType)
.value("Gray_8", SkColorType::kGray_8_SkColorType) .value("Gray_8", SkColorType::kGray_8_SkColorType)
.value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType) .value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType)
.value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType); .value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType)
.value("RG_88", SkColorType::kRG_88_SkColorType);
enum_<SkPath::FillType>("FillType") enum_<SkPath::FillType>("FillType")
.value("Winding", SkPath::FillType::kWinding_FillType) .value("Winding", SkPath::FillType::kWinding_FillType)

View File

@ -86,6 +86,7 @@ static bool convert_to_alpha8(const SkImageInfo& dstInfo, void* vdst, size
case kGray_8_SkColorType: case kGray_8_SkColorType:
case kRGB_565_SkColorType: case kRGB_565_SkColorType:
case kRG_88_SkColorType:
case kRGB_888x_SkColorType: case kRGB_888x_SkColorType:
case kRGB_101010x_SkColorType: { case kRGB_101010x_SkColorType: {
for (int y = 0; y < srcInfo.height(); ++y) { for (int y = 0; y < srcInfo.height(); ++y) {

View File

@ -25,8 +25,9 @@ int SkColorTypeBytesPerPixel(SkColorType ct) {
case kRGBA_F16Norm_SkColorType: return 8; case kRGBA_F16Norm_SkColorType: return 8;
case kRGBA_F16_SkColorType: return 8; case kRGBA_F16_SkColorType: return 8;
case kRGBA_F32_SkColorType: return 16; case kRGBA_F32_SkColorType: return 16;
case kRG_88_SkColorType: return 2;
} }
return 0; SkUNREACHABLE;
} }
bool SkColorTypeIsAlwaysOpaque(SkColorType ct) { bool SkColorTypeIsAlwaysOpaque(SkColorType ct) {
@ -83,6 +84,7 @@ bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
} }
break; break;
case kGray_8_SkColorType: case kGray_8_SkColorType:
case kRG_88_SkColorType:
case kRGB_565_SkColorType: case kRGB_565_SkColorType:
case kRGB_888x_SkColorType: case kRGB_888x_SkColorType:
case kRGB_101010x_SkColorType: case kRGB_101010x_SkColorType:

View File

@ -100,6 +100,7 @@ float SkPixmap::getAlphaf(int x, int y) const {
case kUnknown_SkColorType: case kUnknown_SkColorType:
return 0; return 0;
case kGray_8_SkColorType: case kGray_8_SkColorType:
case kRG_88_SkColorType:
case kRGB_565_SkColorType: case kRGB_565_SkColorType:
case kRGB_888x_SkColorType: case kRGB_888x_SkColorType:
case kRGB_101010x_SkColorType: case kRGB_101010x_SkColorType:
@ -266,6 +267,12 @@ SkColor SkPixmap::getColor(int x, int y) const {
SkPMColor c = SkPixel4444ToPixel32(value); SkPMColor c = SkPixel4444ToPixel32(value);
return toColor(c); return toColor(c);
} }
case kRG_88_SkColorType: {
uint16_t value = *this->addr16(x, y);
return (uint32_t)( ((value >> 0) & 0xff) ) << 16
| (uint32_t)( ((value >> 8) & 0xff) ) << 8
| 0xff000000;
}
case kRGB_888x_SkColorType: { case kRGB_888x_SkColorType: {
uint32_t value = *this->addr32(x, y); uint32_t value = *this->addr32(x, y);
return SkSwizzle_RB(value | 0xff000000); return SkSwizzle_RB(value | 0xff000000);
@ -359,6 +366,7 @@ bool SkPixmap::computeIsOpaque() const {
} break; } break;
case kRGB_565_SkColorType: case kRGB_565_SkColorType:
case kGray_8_SkColorType: case kGray_8_SkColorType:
case kRG_88_SkColorType:
case kRGB_888x_SkColorType: case kRGB_888x_SkColorType:
case kRGB_101010x_SkColorType: case kRGB_101010x_SkColorType:
return true; return true;

View File

@ -168,6 +168,7 @@ void SkRasterPipeline::append_load(SkColorType ct, const SkRasterPipeline_Memory
case kAlpha_8_SkColorType: this->append(load_a8, ctx); break; case kAlpha_8_SkColorType: this->append(load_a8, ctx); break;
case kRGB_565_SkColorType: this->append(load_565, ctx); break; case kRGB_565_SkColorType: this->append(load_565, ctx); break;
case kARGB_4444_SkColorType: this->append(load_4444, ctx); break; case kARGB_4444_SkColorType: this->append(load_4444, ctx); break;
case kRG_88_SkColorType: this->append(load_rg88, ctx); break;
case kRGBA_8888_SkColorType: this->append(load_8888, ctx); break; case kRGBA_8888_SkColorType: this->append(load_8888, ctx); break;
case kRGBA_1010102_SkColorType: this->append(load_1010102, ctx); break; case kRGBA_1010102_SkColorType: this->append(load_1010102, ctx); break;
case kRGBA_F16Norm_SkColorType: case kRGBA_F16Norm_SkColorType:
@ -199,6 +200,7 @@ void SkRasterPipeline::append_load_dst(SkColorType ct, const SkRasterPipeline_Me
case kAlpha_8_SkColorType: this->append(load_a8_dst, ctx); break; case kAlpha_8_SkColorType: this->append(load_a8_dst, ctx); break;
case kRGB_565_SkColorType: this->append(load_565_dst, ctx); break; case kRGB_565_SkColorType: this->append(load_565_dst, ctx); break;
case kARGB_4444_SkColorType: this->append(load_4444_dst, ctx); break; case kARGB_4444_SkColorType: this->append(load_4444_dst, ctx); break;
case kRG_88_SkColorType: this->append(load_rg88_dst, ctx); break;
case kRGBA_8888_SkColorType: this->append(load_8888_dst, ctx); break; case kRGBA_8888_SkColorType: this->append(load_8888_dst, ctx); break;
case kRGBA_1010102_SkColorType: this->append(load_1010102_dst, ctx); break; case kRGBA_1010102_SkColorType: this->append(load_1010102_dst, ctx); break;
case kRGBA_F16Norm_SkColorType: case kRGBA_F16Norm_SkColorType:
@ -230,6 +232,7 @@ void SkRasterPipeline::append_store(SkColorType ct, const SkRasterPipeline_Memor
case kAlpha_8_SkColorType: this->append(store_a8, ctx); break; case kAlpha_8_SkColorType: this->append(store_a8, ctx); break;
case kRGB_565_SkColorType: this->append(store_565, ctx); break; case kRGB_565_SkColorType: this->append(store_565, ctx); break;
case kARGB_4444_SkColorType: this->append(store_4444, ctx); break; case kARGB_4444_SkColorType: this->append(store_4444, ctx); break;
case kRG_88_SkColorType: this->append(store_rg88, ctx); break;
case kRGBA_8888_SkColorType: this->append(store_8888, ctx); break; case kRGBA_8888_SkColorType: this->append(store_8888, ctx); break;
case kRGBA_1010102_SkColorType: this->append(store_1010102, ctx); break; case kRGBA_1010102_SkColorType: this->append(store_1010102, ctx); break;
case kRGBA_F16Norm_SkColorType: case kRGBA_F16Norm_SkColorType:

View File

@ -53,7 +53,7 @@
M(load_f32) M(load_f32_dst) M(store_f32) M(gather_f32) \ M(load_f32) M(load_f32_dst) M(store_f32) M(gather_f32) \
M(load_rgf32) M(store_rgf32) \ M(load_rgf32) M(store_rgf32) \
M(load_8888) M(load_8888_dst) M(store_8888) M(gather_8888) \ M(load_8888) M(load_8888_dst) M(store_8888) M(gather_8888) \
M(load_rg88) M(store_rg88) \ M(load_rg88) M(load_rg88_dst) M(store_rg88) M(gather_rg88) \
M(load_a16) M(store_a16) \ M(load_a16) M(store_a16) \
M(load_rg1616) M(store_rg1616) \ M(load_rg1616) M(store_rg1616) \
M(load_16161616) M(store_16161616) \ M(load_16161616) M(store_16161616) \

View File

@ -203,7 +203,7 @@ static bool fill_buffer_with_color(GrPixelConfig config, int width, int height,
break; break;
} }
case kRG_88_GrPixelConfig: { case kRG_88_GrPixelConfig: {
uint16_t rg88 = (r << 8) | g; uint16_t rg88 = (g << 8) | r;
sk_memset16((uint16_t*) dest, rg88, width * height); sk_memset16((uint16_t*) dest, rg88, width * height);
break; break;

View File

@ -86,8 +86,12 @@ sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context,
if (!renderTargetContext || context->priv().abandoned()) { if (!renderTargetContext || context->priv().abandoned()) {
return nullptr; return nullptr;
} }
SkColorType ct = GrColorTypeToSkColorType(renderTargetContext->colorSpaceInfo().colorType());
unsigned flags; unsigned flags;
if (!CheckAlphaTypeAndGetFlags(nullptr, init, &flags)) { if (!context->colorTypeSupportedAsSurface(ct) ||
!CheckAlphaTypeAndGetFlags(nullptr, init, &flags)) {
return nullptr; return nullptr;
} }
return sk_sp<SkGpuDevice>(new SkGpuDevice(context, std::move(renderTargetContext), flags)); return sk_sp<SkGpuDevice>(new SkGpuDevice(context, std::move(renderTargetContext), flags));
@ -98,7 +102,8 @@ sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context, SkBudgeted budgeted,
GrSurfaceOrigin origin, const SkSurfaceProps* props, GrSurfaceOrigin origin, const SkSurfaceProps* props,
GrMipMapped mipMapped, InitContents init) { GrMipMapped mipMapped, InitContents init) {
unsigned flags; unsigned flags;
if (!CheckAlphaTypeAndGetFlags(&info, init, &flags)) { if (!context->colorTypeSupportedAsSurface(info.colorType()) ||
!CheckAlphaTypeAndGetFlags(&info, init, &flags)) {
return nullptr; return nullptr;
} }

View File

@ -257,6 +257,8 @@ GrPixelConfig SkColorType2GrPixelConfig(const SkColorType type) {
return kRGBA_half_GrPixelConfig; return kRGBA_half_GrPixelConfig;
case kRGBA_F32_SkColorType: case kRGBA_F32_SkColorType:
return kRGBA_float_GrPixelConfig; return kRGBA_float_GrPixelConfig;
case kRG_88_SkColorType:
return kRG_88_GrPixelConfig;
} }
SkASSERT(0); // shouldn't get here SkASSERT(0); // shouldn't get here
return kUnknown_GrPixelConfig; return kUnknown_GrPixelConfig;

View File

@ -42,6 +42,10 @@ bool SkSurfaceValidateRasterInfo(const SkImageInfo& info, size_t rowBytes) {
return false; return false;
} }
if (info.colorType() == kRG_88_SkColorType) {
return false;
}
if (kIgnoreRowBytesValue == rowBytes) { if (kIgnoreRowBytesValue == rowBytes) {
return true; return true;
} }

View File

@ -315,6 +315,8 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) {
return transform_scanline_101010x; return transform_scanline_101010x;
case kAlpha_8_SkColorType: case kAlpha_8_SkColorType:
return transform_scanline_A8_to_GrayAlpha; return transform_scanline_A8_to_GrayAlpha;
case kRG_88_SkColorType:
return nullptr;
} }
SkASSERT(false); SkASSERT(false);
return nullptr; return nullptr;

View File

@ -1983,16 +1983,27 @@ STAGE(store_8888, const SkRasterPipeline_MemoryCtx* ctx) {
} }
STAGE(load_rg88, const SkRasterPipeline_MemoryCtx* ctx) { STAGE(load_rg88, const SkRasterPipeline_MemoryCtx* ctx) {
auto ptr = ptr_at_xy<const uint16_t>(ctx, dx,dy); auto ptr = ptr_at_xy<const uint16_t>(ctx, dx, dy);
from_88(load<U16>(ptr, tail), &r, &g);
b = 0;
a = 1;
}
STAGE(load_rg88_dst, const SkRasterPipeline_MemoryCtx* ctx) {
auto ptr = ptr_at_xy<const uint16_t>(ctx, dx, dy);
from_88(load<U16>(ptr, tail), &dr, &dg);
db = 0;
da = 1;
}
STAGE(gather_rg88, const SkRasterPipeline_GatherCtx* ctx) {
const uint16_t* ptr;
U32 ix = ix_and_ptr(&ptr, ctx, r, g);
from_88(gather(ptr, ix), &r, &g);
b = 0; b = 0;
a = 1; a = 1;
from_88(load<U16>(ptr, tail), &r,&g);
} }
STAGE(store_rg88, const SkRasterPipeline_MemoryCtx* ctx) { STAGE(store_rg88, const SkRasterPipeline_MemoryCtx* ctx) {
auto ptr = ptr_at_xy<uint16_t>(ctx, dx,dy); auto ptr = ptr_at_xy<uint16_t>(ctx, dx, dy);
U16 px = pack( to_unorm(r, 255) | to_unorm(g, 255) << 8 );
U16 px = pack( to_unorm(r, 255)
| to_unorm(g, 255) << 8);
store(ptr, px, tail); store(ptr, px, tail);
} }
@ -3604,13 +3615,25 @@ SI void store_88_(uint16_t* ptr, size_t tail, U16 r, U16 g) {
} }
STAGE_PP(load_rg88, const SkRasterPipeline_MemoryCtx* ctx) { STAGE_PP(load_rg88, const SkRasterPipeline_MemoryCtx* ctx) {
load_88_(ptr_at_xy<const uint16_t>(ctx, dx, dy), tail, &r, &g);
b = 0; b = 0;
a = 255; a = 255;
load_88_(ptr_at_xy<const uint16_t>(ctx, dx,dy), tail, &r,&g); }
STAGE_PP(load_rg88_dst, const SkRasterPipeline_MemoryCtx* ctx) {
load_88_(ptr_at_xy<const uint16_t>(ctx, dx, dy), tail, &dr, &dg);
db = 0;
da = 255;
} }
STAGE_PP(store_rg88, const SkRasterPipeline_MemoryCtx* ctx) { STAGE_PP(store_rg88, const SkRasterPipeline_MemoryCtx* ctx) {
store_88_(ptr_at_xy<uint16_t>(ctx, dx, dy), tail, r, g); store_88_(ptr_at_xy<uint16_t>(ctx, dx, dy), tail, r, g);
} }
STAGE_GP(gather_rg88, const SkRasterPipeline_GatherCtx* ctx) {
const uint16_t* ptr;
U32 ix = ix_and_ptr(&ptr, ctx, x, y);
from_88(gather<U16>(ptr, ix), &r, &g);
b = 0;
a = 255;
}
// ~~~~~~ 8-bit memory loads and stores ~~~~~~ // // ~~~~~~ 8-bit memory loads and stores ~~~~~~ //

View File

@ -423,6 +423,7 @@ bool SkImageShader::doStages(const SkStageRec& rec, SkImageStageUpdater* updater
case kAlpha_8_SkColorType: p->append(SkRasterPipeline::gather_a8, ctx); break; case kAlpha_8_SkColorType: p->append(SkRasterPipeline::gather_a8, ctx); break;
case kRGB_565_SkColorType: p->append(SkRasterPipeline::gather_565, ctx); break; case kRGB_565_SkColorType: p->append(SkRasterPipeline::gather_565, ctx); break;
case kARGB_4444_SkColorType: p->append(SkRasterPipeline::gather_4444, ctx); break; case kARGB_4444_SkColorType: p->append(SkRasterPipeline::gather_4444, ctx); break;
case kRG_88_SkColorType: p->append(SkRasterPipeline::gather_rg88, ctx); break;
case kRGBA_8888_SkColorType: p->append(SkRasterPipeline::gather_8888, ctx); break; case kRGBA_8888_SkColorType: p->append(SkRasterPipeline::gather_8888, ctx); break;
case kRGBA_1010102_SkColorType: p->append(SkRasterPipeline::gather_1010102, ctx); break; case kRGBA_1010102_SkColorType: p->append(SkRasterPipeline::gather_1010102, ctx); break;
case kRGBA_F16Norm_SkColorType: case kRGBA_F16Norm_SkColorType:

View File

@ -47,7 +47,7 @@ void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
return; return;
} }
if (GrRenderable::kYes == renderable) { if (GrRenderable::kYes == renderable && context->colorTypeSupportedAsSurface(skColorType)) {
sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context, sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
backendTex, backendTex,
kTopLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin,
@ -176,7 +176,7 @@ void test_color_init(GrContext* context, skiatest::Reporter* reporter,
SkAssertResult(actual.tryAlloc(ii)); SkAssertResult(actual.tryAlloc(ii));
actual.erase(SkColors::kTransparent); actual.erase(SkColors::kTransparent);
if (GrRenderable::kYes == renderable) { if (GrRenderable::kYes == renderable && context->colorTypeSupportedAsSurface(skColorType)) {
sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context, sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
backendTex, backendTex,
kTopLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin,
@ -426,6 +426,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctx
{ kRGBA_F16Norm_SkColorType, kRGBA_half_Clamped_GrPixelConfig, SkColors::kLtGray }, { kRGBA_F16Norm_SkColorType, kRGBA_half_Clamped_GrPixelConfig, SkColors::kLtGray },
{ kRGBA_F16_SkColorType, kRGBA_half_GrPixelConfig, SkColors::kYellow }, { kRGBA_F16_SkColorType, kRGBA_half_GrPixelConfig, SkColors::kYellow },
{ kRGBA_F32_SkColorType, kRGBA_float_GrPixelConfig, SkColors::kGray }, { kRGBA_F32_SkColorType, kRGBA_float_GrPixelConfig, SkColors::kGray },
{ kRG_88_SkColorType, kRG_88_GrPixelConfig, SkColors::kRed },
}; };
GR_STATIC_ASSERT(kLastEnum_SkColorType == SK_ARRAY_COUNT(combinations)); GR_STATIC_ASSERT(kLastEnum_SkColorType == SK_ARRAY_COUNT(combinations));
@ -571,7 +572,7 @@ DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLBackendAllocationTest, reporter, ctxInfo) {
{ GrColorType::kRGBA_F16_Clamped, GR_GL_RGBA16F, SkColors::kLtGray }, { GrColorType::kRGBA_F16_Clamped, GR_GL_RGBA16F, SkColors::kLtGray },
{ GrColorType::kRGBA_F16, GR_GL_RGBA16F, SkColors::kYellow }, { GrColorType::kRGBA_F16, GR_GL_RGBA16F, SkColors::kYellow },
{ GrColorType::kRG_88, GR_GL_RG8, { 0.5f, 0.5f, 0, 0 } }, { GrColorType::kRG_88, GR_GL_RG8, { 1, 0.5f, 0, 1 } },
{ GrColorType::kAlpha_F16, GR_GL_R16F, { 1.0f, 0, 0, 0.5f } }, { GrColorType::kAlpha_F16, GR_GL_R16F, { 1.0f, 0, 0, 0.5f } },
{ GrColorType::kAlpha_F16, GR_GL_LUMINANCE16F, kGrayCol }, { GrColorType::kAlpha_F16, GR_GL_LUMINANCE16F, kGrayCol },
@ -707,7 +708,7 @@ DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest, reporter, ctxInfo) {
{ GrColorType::kRGBA_F16, VK_FORMAT_R16G16B16A16_SFLOAT, SkColors::kYellow }, { GrColorType::kRGBA_F16, VK_FORMAT_R16G16B16A16_SFLOAT, SkColors::kYellow },
// These backend formats don't have SkColorType equivalents // These backend formats don't have SkColorType equivalents
{ GrColorType::kRG_88, VK_FORMAT_R8G8_UNORM, { 0.5f, 0.5f, 0, 0 }}, { GrColorType::kRG_88, VK_FORMAT_R8G8_UNORM, { 1, 0.5f, 0, 1 } },
{ GrColorType::kAlpha_F16, VK_FORMAT_R16_SFLOAT, { 1.0f, 0, 0, 0.5f }}, { GrColorType::kAlpha_F16, VK_FORMAT_R16_SFLOAT, { 1.0f, 0, 0, 0.5f }},
{ GrColorType::kR_16, VK_FORMAT_R16_UNORM, SkColors::kRed }, { GrColorType::kR_16, VK_FORMAT_R16_UNORM, SkColors::kRed },

View File

@ -178,20 +178,9 @@ DEF_TEST(Bitmap_eraseColor_Premul, r) {
// Test that SkBitmap::ComputeOpaque() is correct for various colortypes. // Test that SkBitmap::ComputeOpaque() is correct for various colortypes.
DEF_TEST(Bitmap_compute_is_opaque, r) { DEF_TEST(Bitmap_compute_is_opaque, r) {
SkColorType colorTypes[] = {
kAlpha_8_SkColorType, for (int i = 1; i <= kLastEnum_SkColorType; ++i) {
kRGB_565_SkColorType, SkColorType ct = (SkColorType) i;
kARGB_4444_SkColorType,
kRGBA_8888_SkColorType,
kRGB_888x_SkColorType,
kBGRA_8888_SkColorType,
kRGBA_1010102_SkColorType,
kRGB_101010x_SkColorType,
kGray_8_SkColorType,
kRGBA_F16_SkColorType,
kRGBA_F32_SkColorType,
};
for (auto ct : colorTypes) {
SkBitmap bm; SkBitmap bm;
SkAlphaType at = SkColorTypeIsAlwaysOpaque(ct) ? kOpaque_SkAlphaType : kPremul_SkAlphaType; SkAlphaType at = SkColorTypeIsAlwaysOpaque(ct) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
bm.allocPixels(SkImageInfo::Make(13, 17, ct, at)); bm.allocPixels(SkImageInfo::Make(13, 17, ct, at));
@ -342,6 +331,7 @@ DEF_TEST(getalphaf, reporter) {
} recs[] = { } recs[] = {
{ kRGB_565_SkColorType, opaque }, { kRGB_565_SkColorType, opaque },
{ kGray_8_SkColorType, opaque }, { kGray_8_SkColorType, opaque },
{ kRG_88_SkColorType, opaque },
{ kRGB_888x_SkColorType, opaque }, { kRGB_888x_SkColorType, opaque },
{ kRGB_101010x_SkColorType, opaque }, { kRGB_101010x_SkColorType, opaque },

View File

@ -144,6 +144,10 @@ public:
SkSurfaceCharacterization createCharacterization(GrContext* context) const { SkSurfaceCharacterization createCharacterization(GrContext* context) const {
size_t maxResourceBytes = context->getResourceCacheLimit(); size_t maxResourceBytes = context->getResourceCacheLimit();
if (!context->colorTypeSupportedAsSurface(fColorType)) {
return SkSurfaceCharacterization();
}
// Note that Ganesh doesn't make use of the SkImageInfo's alphaType // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType, SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
kPremul_SkAlphaType, fColorSpace); kPremul_SkAlphaType, fColorSpace);

View File

@ -0,0 +1,294 @@
/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkImage.h"
#include "include/core/SkSurface.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/gpu/GrContextPriv.h"
#include "tests/Test.h"
#include "tests/TestUtils.h"
static constexpr int kSize = 32;
static SkColor4f get_trans_black_expected_color(SkColorTypeComponentFlag components) {
float a = 0;
if (!(components & kAlpha_SkColorTypeComponentFlag)) {
a = 1;
}
return { 0, 0, 0, a };
}
static SkColor4f get_opaque_white_expected_color(SkColorTypeComponentFlag components) {
if (components & kGray_SkColorTypeComponentFlag) {
return { 1, 1, 1, 1 };
}
float r = 1, g = 1, b = 1;
if (!(components & kRed_SkColorTypeComponentFlag)) {
r = 0;
}
if (!(components & kGreen_SkColorTypeComponentFlag)) {
g = 0;
}
if (!(components & kBlue_SkColorTypeComponentFlag)) {
b = 0;
}
return { r, g, b, 1.0f };
}
struct TestCase {
SkColorType fColorType;
SkAlphaType fAlphaType;
SkColorTypeComponentFlag fComponents;
bool fCanMakeSurfaces;
};
static const TestCase gTests[] = {
{ kAlpha_8_SkColorType, kPremul_SkAlphaType, kAlpha_SkColorTypeComponentFlag, true },
{ kRGB_565_SkColorType, kOpaque_SkAlphaType, kRGB_SkColorTypeComponentFlags, true },
{ kARGB_4444_SkColorType, kPremul_SkAlphaType, kRGBA_SkColorTypeComponentFlags, true },
{ kRGBA_8888_SkColorType, kPremul_SkAlphaType, kRGBA_SkColorTypeComponentFlags, true },
{ kRGB_888x_SkColorType, kOpaque_SkAlphaType, kRGB_SkColorTypeComponentFlags, true },
{ kBGRA_8888_SkColorType, kPremul_SkAlphaType, kRGBA_SkColorTypeComponentFlags, true },
{ kRGBA_1010102_SkColorType, kPremul_SkAlphaType, kRGBA_SkColorTypeComponentFlags, true },
{ kRGB_101010x_SkColorType, kOpaque_SkAlphaType, kRGB_SkColorTypeComponentFlags, true },
{ kGray_8_SkColorType, kOpaque_SkAlphaType, kGray_SkColorTypeComponentFlag, true },
{ kRGBA_F16Norm_SkColorType, kPremul_SkAlphaType, kRGBA_SkColorTypeComponentFlags, true },
{ kRGBA_F16_SkColorType, kPremul_SkAlphaType, kRGBA_SkColorTypeComponentFlags, true },
{ kRGBA_F32_SkColorType, kPremul_SkAlphaType, kRGBA_SkColorTypeComponentFlags, true },
{ kRG_88_SkColorType, kOpaque_SkAlphaType, kRG_SkColorTypeComponentFlags, false }
};
static void raster_tests(skiatest::Reporter* reporter, const TestCase& test) {
const SkImageInfo nativeII = SkImageInfo::Make(kSize, kSize, test.fColorType, test.fAlphaType);
const SkImageInfo f32Unpremul = SkImageInfo::Make(kSize, kSize, kRGBA_F32_SkColorType,
kUnpremul_SkAlphaType);
uint32_t actualComponents = SkColorTypeComponentFlags(test.fColorType);
REPORTER_ASSERT(reporter, test.fComponents == actualComponents);
// Not all colorTypes can be drawn to
{
auto s = SkSurface::MakeRaster(nativeII);
REPORTER_ASSERT(reporter, SkToBool(s) == test.fCanMakeSurfaces);
}
// opaque formats should make transparent black become opaque
{
SkAutoPixmapStorage pm;
pm.alloc(nativeII);
pm.erase(SkColors::kTransparent);
SkColor actual = pm.getColor(0, 0);
SkColor4f expected = get_trans_black_expected_color(test.fComponents);
REPORTER_ASSERT(reporter, expected.toSkColor() == actual);
}
// unused channels should drop out
{
SkAutoPixmapStorage pm;
pm.alloc(nativeII);
pm.erase(SkColors::kWhite);
SkColor actual = pm.getColor(0, 0);
SkColor4f expected = get_opaque_white_expected_color(test.fComponents);
REPORTER_ASSERT(reporter, expected.toSkColor() == actual);
}
// Reading back from an image to the same colorType should always work
{
SkAutoPixmapStorage srcPM;
srcPM.alloc(nativeII);
srcPM.erase(SkColors::kWhite);
auto i = SkImage::MakeFromRaster(srcPM, nullptr, nullptr);
REPORTER_ASSERT(reporter, SkToBool(i));
SkAutoPixmapStorage readbackPM;
readbackPM.alloc(nativeII);
readbackPM.erase(SkColors::kTransparent);
REPORTER_ASSERT(reporter, i->readPixels(readbackPM, 0, 0));
SkColor expected = srcPM.getColor(0, 0);
SkColor actual = readbackPM.getColor(0, 0);
REPORTER_ASSERT(reporter, expected == actual);
}
// Rendering to an F32 surface should always work
{
SkAutoPixmapStorage srcPM;
srcPM.alloc(nativeII);
srcPM.erase(SkColors::kWhite);
auto i = SkImage::MakeFromRaster(srcPM, nullptr, nullptr);
REPORTER_ASSERT(reporter, SkToBool(i));
auto s = SkSurface::MakeRaster(f32Unpremul);
REPORTER_ASSERT(reporter, SkToBool(s));
{
auto c = s->getCanvas();
c->drawImage(i, 0, 0);
}
SkAutoPixmapStorage readbackPM;
readbackPM.alloc(f32Unpremul);
readbackPM.erase(SkColors::kTransparent);
REPORTER_ASSERT(reporter, i->readPixels(readbackPM, 0, 0));
SkColor expected = srcPM.getColor(0, 0);
SkColor actual = readbackPM.getColor(0, 0);
REPORTER_ASSERT(reporter, expected == actual);
}
}
static void compare_pixmaps(skiatest::Reporter* reporter,
const SkPixmap& expected, const SkPixmap& actual,
SkColorType nativeCT, const char* label) {
const float tols[4] = {0.0f, 0.0f, 0.0f, 0};
auto error = std::function<ComparePixmapsErrorReporter>(
[reporter, nativeCT, label](int x, int y, const float diffs[4]) {
SkASSERT(x >= 0 && y >= 0);
ERRORF(reporter, "%d %s - mismatch at %d, %d (%f, %f, %f %f)",
nativeCT, label, x, y,
diffs[0], diffs[1], diffs[2], diffs[3]);
});
compare_pixels(expected, actual, tols, error);
}
static void gpu_tests(GrContext* context, skiatest::Reporter* reporter, const TestCase& test) {
const SkImageInfo nativeII = SkImageInfo::Make(kSize, kSize, test.fColorType, test.fAlphaType);
const SkImageInfo f32Unpremul = SkImageInfo::Make(kSize, kSize, kRGBA_F32_SkColorType,
kUnpremul_SkAlphaType);
// We had better not be able to render to prohibited colorTypes
if (!test.fCanMakeSurfaces) {
auto s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, nativeII);
REPORTER_ASSERT(reporter, !SkToBool(s));
}
if (!context->colorTypeSupportedAsImage(test.fColorType)) {
return;
}
SkAutoPixmapStorage nativeExpected;
nativeExpected.alloc(nativeII);
nativeExpected.erase(SkColors::kWhite);
for (bool fullInit : { false, true }) {
GrBackendTexture backendTex;
if (fullInit) {
backendTex = context->priv().createBackendTexture(&nativeExpected, 1,
GrRenderable::kNo,
GrProtected::kNo);
} else {
backendTex = context->createBackendTexture(kSize, kSize, test.fColorType,
SkColors::kWhite, GrMipMapped::kNo,
GrRenderable::kNo, GrProtected::kNo);
}
REPORTER_ASSERT(reporter, backendTex.isValid());
auto img = SkImage::MakeFromTexture(context, backendTex, kTopLeft_GrSurfaceOrigin,
test.fColorType, test.fAlphaType, nullptr);
REPORTER_ASSERT(reporter, SkToBool(img));
{
SkAutoPixmapStorage nativeActual;
nativeActual.alloc(nativeII);
nativeActual.erase(SkColors::kTransparent);
if (img->readPixels(nativeActual, 0, 0)) {
compare_pixmaps(reporter, nativeExpected, nativeActual,
test.fColorType, "SkImage::readPixels to native CT");
}
// SkSurface::readPixels with the same colorType as the source pixels round trips
// (when allowed)
if (context->colorTypeSupportedAsSurface(test.fColorType)) {
auto s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, nativeII);
REPORTER_ASSERT(reporter, SkToBool(s));
{
SkCanvas* c = s->getCanvas();
c->drawImage(img, 0, 0);
}
nativeActual.erase(SkColors::kTransparent);
REPORTER_ASSERT(reporter, s->readPixels(nativeActual, 0, 0));
compare_pixmaps(reporter, nativeExpected, nativeActual,
test.fColorType, "SkSurface::readPixels to native CT");
}
}
{
SkAutoPixmapStorage f32Expected;
f32Expected.alloc(f32Unpremul);
f32Expected.erase(get_opaque_white_expected_color(test.fComponents));
// read back to F32 if possible
{
SkAutoPixmapStorage f32Actual;
f32Actual.alloc(f32Unpremul);
f32Actual.erase(SkColors::kTransparent);
if (img->readPixels(f32Actual, 0, 0)) {
compare_pixmaps(reporter, f32Expected, f32Actual,
test.fColorType, "SkImage::readPixels to F32");
}
}
// drawing a native SkImage works appropriately (as assessed by reading back from an
// RGBA8 surface to an F32 pixmap)
{
const SkImageInfo rgba8888Premul = SkImageInfo::Make(kSize, kSize,
kRGBA_8888_SkColorType,
kPremul_SkAlphaType);
auto s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, rgba8888Premul);
REPORTER_ASSERT(reporter, SkToBool(s));
{
SkCanvas* c = s->getCanvas();
c->drawImage(img, 0, 0);
}
SkAutoPixmapStorage f32Actual;
f32Actual.alloc(f32Unpremul);
f32Actual.erase(SkColors::kTransparent);
REPORTER_ASSERT(reporter, s->readPixels(f32Actual, 0, 0));
compare_pixmaps(reporter, f32Expected, f32Actual,
test.fColorType, "SkSurface::drawn to RGBA8888");
}
}
img.reset();
context->flush();
context->deleteBackendTexture(backendTex);
}
}
DEF_TEST(ExtendedSkColorTypeTests_raster, reporter) {
for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
raster_tests(reporter, gTests[i]);
}
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ExtendedSkColorTypeTests_gpu, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
gpu_tests(context, reporter, gTests[i]);
}
}

View File

@ -63,7 +63,7 @@ DEF_GPUTEST_FOR_METAL_CONTEXT(MtlBackendAllocationTest, reporter, ctxInfo) {
{ GrColorType::kRGBA_F16_Clamped, MTLPixelFormatRGBA16Float, SkColors::kLtGray }, { GrColorType::kRGBA_F16_Clamped, MTLPixelFormatRGBA16Float, SkColors::kLtGray },
{ GrColorType::kRGBA_F16, MTLPixelFormatRGBA16Float, SkColors::kYellow }, { GrColorType::kRGBA_F16, MTLPixelFormatRGBA16Float, SkColors::kYellow },
{ GrColorType::kRG_88, MTLPixelFormatRG8Unorm, { 0.5f, 0.5f, 0, 0 } }, { GrColorType::kRG_88, MTLPixelFormatRG8Unorm, { 0.5f, 0.5f, 0, 1 } },
{ GrColorType::kAlpha_F16, MTLPixelFormatR16Float, { 1.0f, 0, 0, 0.5f } }, { GrColorType::kAlpha_F16, MTLPixelFormatR16Float, { 1.0f, 0, 0, 0.5f } },
{ GrColorType::kR_16, MTLPixelFormatR16Unorm, SkColors::kRed }, { GrColorType::kR_16, MTLPixelFormatR16Unorm, SkColors::kRed },

View File

@ -626,6 +626,7 @@ static int min_rgb_channel_bits(SkColorType ct) {
case kAlpha_8_SkColorType: return 8; case kAlpha_8_SkColorType: return 8;
case kRGB_565_SkColorType: return 5; case kRGB_565_SkColorType: return 5;
case kARGB_4444_SkColorType: return 4; case kARGB_4444_SkColorType: return 4;
case kRG_88_SkColorType: return 8;
case kRGBA_8888_SkColorType: return 8; case kRGBA_8888_SkColorType: return 8;
case kRGB_888x_SkColorType: return 8; case kRGB_888x_SkColorType: return 8;
case kBGRA_8888_SkColorType: return 8; case kBGRA_8888_SkColorType: return 8;

View File

@ -55,43 +55,23 @@ sk_sp<SkData> DDLPromiseImageHelper::deflateSKP(const SkPicture* inputPicture) {
return inputPicture->serialize(&procs); return inputPicture->serialize(&procs);
} }
// needed until we have SkRG_88_ColorType;
static GrBackendTexture create_yuva_texture(GrContext* context, const SkPixmap& pm, static GrBackendTexture create_yuva_texture(GrContext* context, const SkPixmap& pm,
const SkYUVAIndex yuvaIndices[4], int texIndex) { const SkYUVAIndex yuvaIndices[4], int texIndex) {
SkASSERT(texIndex >= 0 && texIndex <= 3); SkASSERT(texIndex >= 0 && texIndex <= 3);
#ifdef SK_DEBUG
int channelCount = 0; int channelCount = 0;
for (int i = 0; i < SkYUVAIndex::kIndexCount; ++i) { for (int i = 0; i < SkYUVAIndex::kIndexCount; ++i) {
if (yuvaIndices[i].fIndex == texIndex) { if (yuvaIndices[i].fIndex == texIndex) {
++channelCount; ++channelCount;
} }
} }
// Need to create an RG texture for two-channel planes
GrBackendTexture tex;
if (2 == channelCount) { if (2 == channelCount) {
const GrCaps* caps = context->priv().caps(); SkASSERT(kRG_88_SkColorType == pm.colorType());
GrGpu* gpu = context->priv().getGpu();
SkASSERT(kRGBA_8888_SkColorType == pm.colorType());
SkAutoTMalloc<char> pixels(2 * pm.width()*pm.height());
char* currPixel = pixels;
for (int y = 0; y < pm.height(); ++y) {
for (int x = 0; x < pm.width(); ++x) {
SkColor color = pm.getColor(x, y);
currPixel[0] = SkColorGetR(color);
currPixel[1] = SkColorGetG(color);
currPixel += 2;
}
}
GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRG_88,
GrRenderable::kNo);
tex = gpu->createBackendTexture(pm.width(), pm.height(), format,
GrMipMapped::kNo, GrRenderable::kNo,
pixels, 2 * pm.width(), nullptr, GrProtected::kNo);
} else {
tex = context->priv().createBackendTexture(&pm, 1, GrRenderable::kNo, GrProtected::kNo);
} }
return tex; #endif
return context->priv().createBackendTexture(&pm, 1, GrRenderable::kNo, GrProtected::kNo);
} }
void DDLPromiseImageHelper::uploadAllToGPU(GrContext* context) { void DDLPromiseImageHelper::uploadAllToGPU(GrContext* context) {
@ -281,7 +261,7 @@ int DDLPromiseImageHelper::addImage(SkImage* image) {
newImageInfo.setYUVData(std::move(yuvData), yuvaIndices, yuvColorSpace); newImageInfo.setYUVData(std::move(yuvData), yuvaIndices, yuvColorSpace);
// determine colortypes from index data // determine colortypes from index data
// for testing we only ever use A8 or RGBA8888 // for testing we only ever use A8, RG_88
SkColorType colorTypes[SkYUVASizeInfo::kMaxCount] = { SkColorType colorTypes[SkYUVASizeInfo::kMaxCount] = {
kUnknown_SkColorType, kUnknown_SkColorType, kUnknown_SkColorType, kUnknown_SkColorType,
kUnknown_SkColorType, kUnknown_SkColorType kUnknown_SkColorType, kUnknown_SkColorType
@ -295,7 +275,7 @@ int DDLPromiseImageHelper::addImage(SkImage* image) {
if (kUnknown_SkColorType == colorTypes[texIdx]) { if (kUnknown_SkColorType == colorTypes[texIdx]) {
colorTypes[texIdx] = kAlpha_8_SkColorType; colorTypes[texIdx] = kAlpha_8_SkColorType;
} else { } else {
colorTypes[texIdx] = kRGBA_8888_SkColorType; colorTypes[texIdx] = kRG_88_SkColorType;
} }
} }

View File

@ -39,6 +39,7 @@ HashAndEncode::HashAndEncode(const SkBitmap& bitmap) : fSize(bitmap.info().dimen
srcAlpha = skcms_AlphaFormat_Opaque; break; srcAlpha = skcms_AlphaFormat_Opaque; break;
case kRGB_101010x_SkColorType: srcFmt = skcms_PixelFormat_RGBA_1010102; case kRGB_101010x_SkColorType: srcFmt = skcms_PixelFormat_RGBA_1010102;
srcAlpha = skcms_AlphaFormat_Opaque; break; srcAlpha = skcms_AlphaFormat_Opaque; break;
case kRG_88_SkColorType: return;
} }
skcms_ICCProfile srcProfile = *skcms_sRGB_profile(); skcms_ICCProfile srcProfile = *skcms_sRGB_profile();

View File

@ -61,6 +61,7 @@ const char* colortype_name(SkColorType ct) {
case kRGBA_F16Norm_SkColorType: return "RGBA_F16Norm"; case kRGBA_F16Norm_SkColorType: return "RGBA_F16Norm";
case kRGBA_F16_SkColorType: return "RGBA_F16"; case kRGBA_F16_SkColorType: return "RGBA_F16";
case kRGBA_F32_SkColorType: return "RGBA_F32"; case kRGBA_F32_SkColorType: return "RGBA_F32";
case kRG_88_SkColorType: return "RG_88";
} }
SkASSERT(false); SkASSERT(false);
return "unexpected colortype"; return "unexpected colortype";
@ -81,6 +82,7 @@ const char* colortype_depth(SkColorType ct) {
case kRGBA_F16Norm_SkColorType: return "F16Norm"; // TODO: "F16"? case kRGBA_F16Norm_SkColorType: return "F16Norm"; // TODO: "F16"?
case kRGBA_F16_SkColorType: return "F16"; case kRGBA_F16_SkColorType: return "F16";
case kRGBA_F32_SkColorType: return "F32"; case kRGBA_F32_SkColorType: return "F32";
case kRG_88_SkColorType: return "88";
} }
SkASSERT(false); SkASSERT(false);
return "unexpected colortype"; return "unexpected colortype";