Reland "Add sRGB 8888 colortype"
This is a reland of 0f7c10ef5681d5c739bcd8862c58d856fd663a0c
Original change's description:
> Add sRGB 8888 colortype
>
> A color type that linearizes just after loading, and re-encodes to sRGB
> just before storing, mimicking the GPU formats that work the same way.
>
> Notes:
> - No mipmap support
> - No SkPngEncoder support (HashAndEncode's .pngs are ok, though?)
> - Needs better testing
>
> This is a re-creation of reviews.skia.org/392990
>
> Change-Id: I4739c2280211e7176aae98ba0a8476a7fe5efa72
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/438219
> Commit-Queue: Brian Osman <brianosman@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
Change-Id: I5b6bb28c4c1faa6c97fcad7552d12c331535714d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/441402
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index c16eeb0..65a2d87 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -530,12 +530,13 @@
CPU_CONFIG("nonrendering", kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
- CPU_CONFIG("a8", kRaster_Backend, kAlpha_8_SkColorType, kPremul_SkAlphaType)
- CPU_CONFIG("565", kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
- CPU_CONFIG("8888", kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
- CPU_CONFIG("rgba", kRaster_Backend, kRGBA_8888_SkColorType, kPremul_SkAlphaType)
- CPU_CONFIG("bgra", kRaster_Backend, kBGRA_8888_SkColorType, kPremul_SkAlphaType)
- CPU_CONFIG("f16", kRaster_Backend, kRGBA_F16_SkColorType, kPremul_SkAlphaType)
+ CPU_CONFIG("a8", kRaster_Backend, kAlpha_8_SkColorType, kPremul_SkAlphaType)
+ CPU_CONFIG("565", kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
+ CPU_CONFIG("8888", kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
+ CPU_CONFIG("rgba", kRaster_Backend, kRGBA_8888_SkColorType, kPremul_SkAlphaType)
+ CPU_CONFIG("bgra", kRaster_Backend, kBGRA_8888_SkColorType, kPremul_SkAlphaType)
+ CPU_CONFIG("f16", kRaster_Backend, kRGBA_F16_SkColorType, kPremul_SkAlphaType)
+ CPU_CONFIG("srgba", kRaster_Backend, kSRGBA_8888_SkColorType, kPremul_SkAlphaType)
#undef CPU_CONFIG
diff --git a/dm/DM.cpp b/dm/DM.cpp
index c179a83..10cd5db 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -982,6 +982,7 @@
SINK("f16", RasterSink, kRGBA_F16_SkColorType);
SINK("f16norm", RasterSink, kRGBA_F16Norm_SkColorType);
SINK("f32", RasterSink, kRGBA_F32_SkColorType);
+ SINK("srgba", RasterSink, kSRGBA_8888_SkColorType);
SINK("pdf", PDFSink, false, SK_ScalarDefaultRasterDPI);
SINK("skp", SKPSink);
diff --git a/docs/examples/unexpected_setAlphaType.cpp b/docs/examples/unexpected_setAlphaType.cpp
index 1ec1d9f..8c3daf2 100644
--- a/docs/examples/unexpected_setAlphaType.cpp
+++ b/docs/examples/unexpected_setAlphaType.cpp
@@ -21,6 +21,7 @@
case kRGB_565_SkColorType: return "RGB_565";
case kARGB_4444_SkColorType: return "ARGB_4444";
case kRGBA_8888_SkColorType: return "RGBA_8888";
+ case kSRGBA_8888_SkColorType: return "SRGBA_8888";
case kRGB_888x_SkColorType: return "RGB_888x";
case kBGRA_8888_SkColorType: return "BGRA_8888";
case kRGBA_1010102_SkColorType: return "RGBA_1010102";
diff --git a/gm/bitmapcopy.cpp b/gm/bitmapcopy.cpp
index 3f83da6..f3f3820 100644
--- a/gm/bitmapcopy.cpp
+++ b/gm/bitmapcopy.cpp
@@ -48,6 +48,7 @@
case kA16_float_SkColorType: return "A16_float";
case kR16G16_float_SkColorType: return "R16G16_float";
case kR16G16B16A16_unorm_SkColorType: return "R16G16B16A16_unorm";
+ case kSRGBA_8888_SkColorType: return "SRGBA_8888";
}
return "";
}
diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h
index 426c234..8deda88 100644
--- a/include/core/SkImageInfo.h
+++ b/include/core/SkImageInfo.h
@@ -16,6 +16,9 @@
#include "include/private/SkTFitsIn.h"
#include "include/private/SkTo.h"
+// Temporary guard for Chromium
+#define SK_HAS_SRGBA_COLOR_TYPE
+
class SkReadBuffer;
class SkWriteBuffer;
@@ -91,7 +94,9 @@
kR16G16B16A16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red, green, blue
// and alpha
- kLastEnum_SkColorType = kR16G16B16A16_unorm_SkColorType, //!< last valid value
+ kSRGBA_8888_SkColorType,
+
+ kLastEnum_SkColorType = kSRGBA_8888_SkColorType, //!< last valid value
#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
kN32_SkColorType = kBGRA_8888_SkColorType,//!< native 32-bit BGRA encoding
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 6677836..5a8a0fa 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -940,8 +940,7 @@
case GrColorType::kBGR_565: return kRGB_565_SkColorType;
case GrColorType::kABGR_4444: return kARGB_4444_SkColorType;
case GrColorType::kRGBA_8888: return kRGBA_8888_SkColorType;
- // 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 kSRGBA_8888_SkColorType;
case GrColorType::kRGB_888x: return kRGB_888x_SkColorType;
case GrColorType::kRG_88: return kR8G8_unorm_SkColorType;
case GrColorType::kBGRA_8888: return kBGRA_8888_SkColorType;
@@ -978,6 +977,7 @@
case kRGB_565_SkColorType: return GrColorType::kBGR_565;
case kARGB_4444_SkColorType: return GrColorType::kABGR_4444;
case kRGBA_8888_SkColorType: return GrColorType::kRGBA_8888;
+ case kSRGBA_8888_SkColorType: return GrColorType::kRGBA_8888_SRGB;
case kRGB_888x_SkColorType: return GrColorType::kRGB_888x;
case kBGRA_8888_SkColorType: return GrColorType::kBGRA_8888;
case kGray_8_SkColorType: return GrColorType::kGray_8;
@@ -998,12 +998,6 @@
SkUNREACHABLE;
}
-// This is a temporary means of mapping an SkColorType and format to a
-// GrColorType::kRGBA_8888_SRGB. Once we have an SRGB SkColorType this can go away.
-GrColorType SkColorTypeAndFormatToGrColorType(const GrCaps* caps,
- SkColorType skCT,
- const GrBackendFormat& format);
-
static constexpr uint32_t GrColorTypeChannelFlags(GrColorType ct) {
switch (ct) {
case GrColorType::kUnknown: return 0;
diff --git a/include/private/SkImageInfoPriv.h b/include/private/SkImageInfoPriv.h
index 0d86130..5e4abb8 100644
--- a/include/private/SkImageInfoPriv.h
+++ b/include/private/SkImageInfoPriv.h
@@ -34,6 +34,7 @@
case kA16_float_SkColorType: return kAlpha_SkColorChannelFlag;
case kR16G16_float_SkColorType: return kRG_SkColorChannelFlags;
case kR16G16B16A16_unorm_SkColorType: return kRGBA_SkColorChannelFlags;
+ case kSRGBA_8888_SkColorType: return kRGBA_SkColorChannelFlags;
}
SkUNREACHABLE;
}
@@ -69,6 +70,7 @@
case kA16_float_SkColorType: return 1;
case kR16G16_float_SkColorType: return 2;
case kR16G16B16A16_unorm_SkColorType: return 3;
+ case kSRGBA_8888_SkColorType: return 2;
}
SkUNREACHABLE;
}
@@ -107,7 +109,8 @@
case kA16_unorm_SkColorType:
case kA16_float_SkColorType: /*subtle... alpha is always [0,1]*/
case kR16G16_unorm_SkColorType:
- case kR16G16B16A16_unorm_SkColorType: return true;
+ case kR16G16B16A16_unorm_SkColorType:
+ case kSRGBA_8888_SkColorType: return true;
case kRGBA_F16_SkColorType:
case kRGBA_F32_SkColorType:
@@ -133,6 +136,7 @@
case kBGRA_8888_SkColorType:
case kGray_8_SkColorType:
case kR8G8_unorm_SkColorType:
+ case kSRGBA_8888_SkColorType:
return 8;
case kRGBA_1010102_SkColorType:
diff --git a/src/core/SkColorSpacePriv.h b/src/core/SkColorSpacePriv.h
index 9b4fad9..d4e3f4d 100644
--- a/src/core/SkColorSpacePriv.h
+++ b/src/core/SkColorSpacePriv.h
@@ -101,6 +101,10 @@
return linearExp || linearFn;
}
+skvm::F32 sk_program_transfer_fn(
+ skvm::F32 v, TFKind,
+ skvm::F32 G, skvm::F32 A, skvm::F32 B, skvm::F32 C, skvm::F32 D, skvm::F32 E, skvm::F32 F);
+
skvm::Color sk_program_transfer_fn(skvm::Builder*, skvm::Uniforms*,
const skcms_TransferFunction&, skvm::Color);
diff --git a/src/core/SkColorSpaceXformSteps.cpp b/src/core/SkColorSpaceXformSteps.cpp
index c091d6a..501f8b4 100644
--- a/src/core/SkColorSpaceXformSteps.cpp
+++ b/src/core/SkColorSpaceXformSteps.cpp
@@ -137,6 +137,47 @@
if (flags.premul) { p->append(SkRasterPipeline::premul); }
}
+skvm::F32 sk_program_transfer_fn(
+ skvm::F32 v, TFKind tf_kind,
+ skvm::F32 G, skvm::F32 A, skvm::F32 B, skvm::F32 C, skvm::F32 D, skvm::F32 E, skvm::F32 F)
+{
+ // Strip off the sign bit and save it for later.
+ skvm::I32 bits = pun_to_I32(v),
+ sign = bits & 0x80000000;
+ v = pun_to_F32(bits ^ sign);
+
+ switch (tf_kind) {
+ case Bad_TF: SkASSERT(false); break;
+
+ case sRGBish_TF: {
+ v = select(v <= D, C*v + F
+ , approx_powf(A*v + B, G) + E);
+ } break;
+
+ case PQish_TF: {
+ skvm::F32 vC = approx_powf(v, C);
+ v = approx_powf(max(B * vC + A, 0.0f) / (E * vC + D), F);
+ } break;
+
+ case HLGish_TF: {
+ skvm::F32 vA = v*A,
+ K = F + 1.0f;
+ v = K*select(vA <= 1.0f, approx_powf(vA, B)
+ , approx_exp((v-E) * C + D));
+ } break;
+
+ case HLGinvish_TF: {
+ skvm::F32 K = F + 1.0f;
+ v /= K;
+ v = select(v <= 1.0f, A * approx_powf(v, B)
+ , C * approx_log(v-D) + E);
+ } break;
+ }
+
+ // Re-apply the original sign bit on our way out the door.
+ return pun_to_F32(sign | pun_to_I32(v));
+}
+
skvm::Color sk_program_transfer_fn(skvm::Builder* p, skvm::Uniforms* uniforms,
const skcms_TransferFunction& tf, skvm::Color c) {
skvm::F32 G = p->uniformF(uniforms->pushF(tf.g)),
@@ -146,46 +187,13 @@
D = p->uniformF(uniforms->pushF(tf.d)),
E = p->uniformF(uniforms->pushF(tf.e)),
F = p->uniformF(uniforms->pushF(tf.f));
-
- auto apply = [&](skvm::F32 v) -> skvm::F32 {
- // Strip off the sign bit and save it for later.
- skvm::I32 bits = pun_to_I32(v),
- sign = bits & 0x80000000;
- v = pun_to_F32(bits ^ sign);
-
- switch (classify_transfer_fn(tf)) {
- case Bad_TF: SkASSERT(false); break;
-
- case sRGBish_TF:
- v = select(v <= D, C*v + F
- , approx_powf(A*v + B, G) + E);
- break;
-
- case PQish_TF: {
- skvm::F32 vC = approx_powf(v, C);
- v = approx_powf(max(B * vC + A, 0.0f) / (E * vC + D), F);
- } break;
-
- case HLGish_TF: {
- skvm::F32 vA = v*A,
- K = F + 1.0f;
- v = K*select(vA <= 1.0f, approx_powf(vA, B)
- , approx_exp((v-E) * C + D));
- } break;
-
- case HLGinvish_TF:
- skvm::F32 K = F + 1.0f;
- v /= K;
- v = select(v <= 1.0f, A * approx_powf(v, B)
- , C * approx_log(v-D) + E);
- break;
- }
-
- // Re-apply the original sign bit on our way out the door.
- return pun_to_F32(sign | pun_to_I32(v));
+ TFKind tf_kind = classify_transfer_fn(tf);
+ return {
+ sk_program_transfer_fn(c.r, tf_kind, G,A,B,C,D,E,F),
+ sk_program_transfer_fn(c.g, tf_kind, G,A,B,C,D,E,F),
+ sk_program_transfer_fn(c.b, tf_kind, G,A,B,C,D,E,F),
+ c.a,
};
-
- return {apply(c.r), apply(c.g), apply(c.b), c.a};
}
skvm::Color SkColorSpaceXformSteps::program(skvm::Builder* p, skvm::Uniforms* uniforms,
diff --git a/src/core/SkConvertPixels.cpp b/src/core/SkConvertPixels.cpp
index 42b2aa0..f00042b 100644
--- a/src/core/SkConvertPixels.cpp
+++ b/src/core/SkConvertPixels.cpp
@@ -124,7 +124,8 @@
}
case kBGRA_8888_SkColorType:
- case kRGBA_8888_SkColorType: {
+ case kRGBA_8888_SkColorType:
+ case kSRGBA_8888_SkColorType: {
auto src32 = (const uint32_t*) src;
for (int y = 0; y < srcInfo.height(); y++) {
for (int x = 0; x < srcInfo.width(); x++) {
diff --git a/src/core/SkImageInfo.cpp b/src/core/SkImageInfo.cpp
index 81994fb..dc045ec 100644
--- a/src/core/SkImageInfo.cpp
+++ b/src/core/SkImageInfo.cpp
@@ -33,6 +33,7 @@
case kA16_float_SkColorType: return 2;
case kR16G16_float_SkColorType: return 4;
case kR16G16B16A16_unorm_SkColorType: return 8;
+ case kSRGBA_8888_SkColorType: return 4;
}
SkUNREACHABLE;
}
@@ -93,6 +94,7 @@
[[fallthrough]];
case kARGB_4444_SkColorType:
case kRGBA_8888_SkColorType:
+ case kSRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
case kRGBA_1010102_SkColorType:
case kBGRA_1010102_SkColorType:
diff --git a/src/core/SkMipmap.cpp b/src/core/SkMipmap.cpp
index eef99dc..5074a00 100644
--- a/src/core/SkMipmap.cpp
+++ b/src/core/SkMipmap.cpp
@@ -543,6 +543,9 @@
case kBGR_101010x_SkColorType: // TODO: use 1010102?
case kRGBA_F32_SkColorType:
return nullptr;
+
+ case kSRGBA_8888_SkColorType: // TODO: needs careful handling
+ return nullptr;
}
if (src.width() <= 1 && src.height() <= 1) {
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 2545c62..47a9974 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -128,6 +128,7 @@
}
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
+ case kSRGBA_8888_SkColorType:
value = static_cast<const uint8_t*>(srcPtr)[3] * (1.0f/255);
break;
case kRGBA_1010102_SkColorType:
@@ -326,6 +327,30 @@
SkPMColor c = SkSwizzle_RGBA_to_PMColor(value);
return toColor(c);
}
+ case kSRGBA_8888_SkColorType: {
+ auto srgb_to_linear = [](float x) {
+ return (x <= 0.04045f) ? x * (1 / 12.92f)
+ : sk_float_pow(x * (1 / 1.055f) + (0.055f / 1.055f), 2.4f);
+ };
+
+ uint32_t value = *this->addr32(x, y);
+ float r = ((value >> 0) & 0xff) * (1/255.0f),
+ g = ((value >> 8) & 0xff) * (1/255.0f),
+ b = ((value >> 16) & 0xff) * (1/255.0f),
+ a = ((value >> 24) & 0xff) * (1/255.0f);
+ r = srgb_to_linear(r);
+ g = srgb_to_linear(g);
+ b = srgb_to_linear(b);
+ if (a != 0 && needsUnpremul) {
+ r = SkTPin(r/a, 0.0f, 1.0f);
+ g = SkTPin(g/a, 0.0f, 1.0f);
+ b = SkTPin(b/a, 0.0f, 1.0f);
+ }
+ return (uint32_t)( r * 255.0f ) << 16
+ | (uint32_t)( g * 255.0f ) << 8
+ | (uint32_t)( b * 255.0f ) << 0
+ | (uint32_t)( a * 255.0f ) << 24;
+ }
case kRGB_101010x_SkColorType: {
uint32_t value = *this->addr32(x, y);
// Convert 10-bit rgb to 8-bit bgr, and mask in 0xff alpha at the top.
@@ -481,7 +506,8 @@
return true;
}
case kBGRA_8888_SkColorType:
- case kRGBA_8888_SkColorType: {
+ case kRGBA_8888_SkColorType:
+ case kSRGBA_8888_SkColorType: {
SkPMColor c = (SkPMColor)~0;
for (int y = 0; y < height; ++y) {
const SkPMColor* row = this->addr32(0, y);
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index b5d30be..93ad3a9 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -210,6 +210,11 @@
case kBGRA_8888_SkColorType: this->append(load_8888, ctx);
this->append(swap_rb);
break;
+
+ case kSRGBA_8888_SkColorType:
+ this->append(load_8888, ctx);
+ this->append_transfer_function(*skcms_sRGB_TransferFunction());
+ break;
}
}
@@ -256,6 +261,14 @@
case kBGRA_8888_SkColorType: this->append(load_8888_dst, ctx);
this->append(swap_rb_dst);
break;
+
+ case kSRGBA_8888_SkColorType:
+ // TODO: We could remove the double-swap if we had _dst versions of all the TF stages
+ this->append(load_8888_dst, ctx);
+ this->append(swap_src_dst);
+ this->append_transfer_function(*skcms_sRGB_TransferFunction());
+ this->append(swap_src_dst);
+ break;
}
}
@@ -302,6 +315,11 @@
case kBGRA_8888_SkColorType: this->append(swap_rb);
this->append(store_8888, ctx);
break;
+
+ case kSRGBA_8888_SkColorType:
+ this->append_transfer_function(*skcms_sRGB_Inverse_TransferFunction());
+ this->append(store_8888, ctx);
+ break;
}
}
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index 6e8b4be..3b03020 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -38,7 +38,7 @@
#define SK_RASTER_PIPELINE_STAGES(M) \
M(callback) \
- M(move_src_dst) M(move_dst_src) \
+ M(move_src_dst) M(move_dst_src) M(swap_src_dst) \
M(clamp_0) M(clamp_1) M(clamp_a) M(clamp_gamut) \
M(unpremul) M(premul) M(premul_dst) \
M(force_opaque) M(force_opaque_dst) \
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index fd3fc5f..b1313de 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -208,7 +208,8 @@
case kGray_8_SkColorType:
case kRGB_888x_SkColorType:
case kRGBA_8888_SkColorType:
- case kBGRA_8888_SkColorType: blitter->fDitherRate = 1/255.0f; break;
+ case kBGRA_8888_SkColorType:
+ case kSRGBA_8888_SkColorType: blitter->fDitherRate = 1/255.0f; break;
case kRGB_101010x_SkColorType:
case kRGBA_1010102_SkColorType:
case kBGR_101010x_SkColorType:
diff --git a/src/core/SkVM.cpp b/src/core/SkVM.cpp
index 8c760d5..967b593 100644
--- a/src/core/SkVM.cpp
+++ b/src/core/SkVM.cpp
@@ -13,6 +13,7 @@
#include "include/private/SkTFitsIn.h"
#include "include/private/SkThreadID.h"
#include "include/private/SkVx.h"
+#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkCpu.h"
#include "src/core/SkEnumerate.h"
@@ -112,7 +113,20 @@
#endif
#endif
+#if defined(SKSL_STANDALONE)
+ // skslc needs to link against this module (for the VM code generator). This module pulls in
+ // color-space code, but attempting to add those transitive dependencies to skslc gets out of
+ // hand. So we terminate the chain here with stub functions. Note that skslc's usage of SkVM
+ // never cares about color management.
+ skvm::F32 sk_program_transfer_fn(
+ skvm::F32 v, TFKind tf_kind,
+ skvm::F32 G, skvm::F32 A, skvm::F32 B, skvm::F32 C, skvm::F32 D, skvm::F32 E, skvm::F32 F) {
+ return v;
+ }
+ const skcms_TransferFunction* skcms_sRGB_TransferFunction() { return nullptr; }
+ const skcms_TransferFunction* skcms_sRGB_Inverse_TransferFunction() { return nullptr; }
+#endif
namespace skvm {
@@ -1043,6 +1057,7 @@
PixelFormat SkColorType_to_PixelFormat(SkColorType ct) {
auto UNORM = PixelFormat::UNORM,
+ SRGB = PixelFormat::SRGB,
FLOAT = PixelFormat::FLOAT;
switch (ct) {
case kUnknown_SkColorType: break;
@@ -1065,6 +1080,7 @@
case kRGBA_8888_SkColorType: return {UNORM, 8,8,8,8, 0,8,16,24};
case kRGB_888x_SkColorType: return {UNORM, 8,8,8,0, 0,8,16,32}; // 32-bit
case kBGRA_8888_SkColorType: return {UNORM, 8,8,8,8, 16,8, 0,24};
+ case kSRGBA_8888_SkColorType: return { SRGB, 8,8,8,8, 0,8,16,24};
case kRGBA_1010102_SkColorType: return {UNORM, 10,10,10,2, 0,10,20,30};
case kBGRA_1010102_SkColorType: return {UNORM, 10,10,10,2, 20,10, 0,30};
@@ -1091,19 +1107,43 @@
static Color unpack(PixelFormat f, I32 x) {
SkASSERT(byte_size(f) <= 4);
- auto unpack_channel = [=](int bits, int shift) {
+
+ auto from_srgb = [](int bits, I32 channel) -> F32 {
+ const skcms_TransferFunction* tf = skcms_sRGB_TransferFunction();
+ F32 v = from_unorm(bits, channel);
+ return sk_program_transfer_fn(v, sRGBish_TF,
+ v->splat(tf->g),
+ v->splat(tf->a),
+ v->splat(tf->b),
+ v->splat(tf->c),
+ v->splat(tf->d),
+ v->splat(tf->e),
+ v->splat(tf->f));
+ };
+
+ auto unpack_rgb = [=](int bits, int shift) -> F32 {
I32 channel = extract(x, shift, (1<<bits)-1);
switch (f.encoding) {
case PixelFormat::UNORM: return from_unorm(bits, channel);
+ case PixelFormat:: SRGB: return from_srgb (bits, channel);
+ case PixelFormat::FLOAT: return from_fp16 ( channel);
+ }
+ SkUNREACHABLE;
+ };
+ auto unpack_alpha = [=](int bits, int shift) -> F32 {
+ I32 channel = extract(x, shift, (1<<bits)-1);
+ switch (f.encoding) {
+ case PixelFormat::UNORM:
+ case PixelFormat:: SRGB: return from_unorm(bits, channel);
case PixelFormat::FLOAT: return from_fp16 ( channel);
}
SkUNREACHABLE;
};
return {
- f.r_bits ? unpack_channel(f.r_bits, f.r_shift) : x->splat(0.0f),
- f.g_bits ? unpack_channel(f.g_bits, f.g_shift) : x->splat(0.0f),
- f.b_bits ? unpack_channel(f.b_bits, f.b_shift) : x->splat(0.0f),
- f.a_bits ? unpack_channel(f.a_bits, f.a_shift) : x->splat(1.0f),
+ f.r_bits ? unpack_rgb (f.r_bits, f.r_shift) : x->splat(0.0f),
+ f.g_bits ? unpack_rgb (f.g_bits, f.g_shift) : x->splat(0.0f),
+ f.b_bits ? unpack_rgb (f.b_bits, f.b_shift) : x->splat(0.0f),
+ f.a_bits ? unpack_alpha(f.a_bits, f.a_shift) : x->splat(1.0f),
};
}
@@ -1211,19 +1251,42 @@
static I32 pack32(PixelFormat f, Color c) {
SkASSERT(byte_size(f) <= 4);
+
+ auto to_srgb = [](int bits, F32 v) {
+ const skcms_TransferFunction* tf = skcms_sRGB_Inverse_TransferFunction();
+ return to_unorm(bits, sk_program_transfer_fn(v, sRGBish_TF,
+ v->splat(tf->g),
+ v->splat(tf->a),
+ v->splat(tf->b),
+ v->splat(tf->c),
+ v->splat(tf->d),
+ v->splat(tf->e),
+ v->splat(tf->f)));
+ };
+
I32 packed = c->splat(0);
- auto pack_channel = [&](F32 channel, int bits, int shift) {
+ auto pack_rgb = [&](F32 channel, int bits, int shift) {
I32 encoded;
switch (f.encoding) {
case PixelFormat::UNORM: encoded = to_unorm(bits, channel); break;
+ case PixelFormat:: SRGB: encoded = to_srgb (bits, channel); break;
case PixelFormat::FLOAT: encoded = to_fp16 ( channel); break;
}
packed = pack(packed, encoded, shift);
};
- if (f.r_bits) { pack_channel(c.r, f.r_bits, f.r_shift); }
- if (f.g_bits) { pack_channel(c.g, f.g_bits, f.g_shift); }
- if (f.b_bits) { pack_channel(c.b, f.b_bits, f.b_shift); }
- if (f.a_bits) { pack_channel(c.a, f.a_bits, f.a_shift); }
+ auto pack_alpha = [&](F32 channel, int bits, int shift) {
+ I32 encoded;
+ switch (f.encoding) {
+ case PixelFormat::UNORM:
+ case PixelFormat:: SRGB: encoded = to_unorm(bits, channel); break;
+ case PixelFormat::FLOAT: encoded = to_fp16 ( channel); break;
+ }
+ packed = pack(packed, encoded, shift);
+ };
+ if (f.r_bits) { pack_rgb (c.r, f.r_bits, f.r_shift); }
+ if (f.g_bits) { pack_rgb (c.g, f.g_bits, f.g_shift); }
+ if (f.b_bits) { pack_rgb (c.b, f.b_bits, f.b_shift); }
+ if (f.a_bits) { pack_alpha(c.a, f.a_bits, f.a_shift); }
return packed;
}
diff --git a/src/core/SkVM.h b/src/core/SkVM.h
index 670e1cd..60277e8 100644
--- a/src/core/SkVM.h
+++ b/src/core/SkVM.h
@@ -560,7 +560,7 @@
};
struct PixelFormat {
- enum { UNORM, FLOAT} encoding;
+ enum { UNORM, SRGB, FLOAT} encoding;
int r_bits, g_bits, b_bits, a_bits,
r_shift, g_shift, b_shift, a_shift;
};
diff --git a/src/core/SkVMBlitter.cpp b/src/core/SkVMBlitter.cpp
index 76415cf..3be35ee 100644
--- a/src/core/SkVMBlitter.cpp
+++ b/src/core/SkVMBlitter.cpp
@@ -114,7 +114,8 @@
case kGray_8_SkColorType:
case kRGB_888x_SkColorType:
case kRGBA_8888_SkColorType:
- case kBGRA_8888_SkColorType: rate = 1/255.0f; break;
+ case kBGRA_8888_SkColorType:
+ case kSRGBA_8888_SkColorType: rate = 1/255.0f; break;
case kRGB_101010x_SkColorType:
case kRGBA_1010102_SkColorType:
case kBGR_101010x_SkColorType:
diff --git a/src/gpu/GrDataUtils.cpp b/src/gpu/GrDataUtils.cpp
index 0d449d6..d14c466 100644
--- a/src/gpu/GrDataUtils.cpp
+++ b/src/gpu/GrDataUtils.cpp
@@ -747,18 +747,3 @@
return true;
}
-
-GrColorType SkColorTypeAndFormatToGrColorType(const GrCaps* caps,
- SkColorType skCT,
- const GrBackendFormat& format) {
- GrColorType grCT = SkColorTypeToGrColorType(skCT);
- // Until we support SRGB in the SkColorType we have to do this manual check here to make sure
- // we use the correct GrColorType.
- if (caps->isFormatSRGB(format)) {
- if (grCT != GrColorType::kRGBA_8888) {
- return GrColorType::kUnknown;
- }
- grCT = GrColorType::kRGBA_8888_SRGB;
- }
- return grCT;
-}
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index cb9edf0..4ada100 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -683,7 +683,7 @@
}
GrBackendFormat format = backendTexture.getBackendFormat();
- GrColorType grColorType = SkColorTypeAndFormatToGrColorType(this->caps(), skColorType, format);
+ GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
if (!this->caps()->areColorTypeAndFormatCompatible(grColorType, format)) {
return false;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 9468369..b8a8971 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -154,7 +154,7 @@
#ifdef SK_DEBUG
const GrBackendFormat& format = fChooser.backendFormat();
const GrCaps* caps = this->context()->priv().caps();
- GrColorType grCT = SkColorTypeAndFormatToGrColorType(caps, this->colorType(), format);
+ GrColorType grCT = SkColorTypeToGrColorType(this->colorType());
SkASSERT(caps->isFormatCompressed(format) ||
caps->areColorTypeAndFormatCompatible(grCT, format));
#endif
@@ -179,7 +179,7 @@
#ifdef SK_DEBUG
const GrBackendFormat& format = fChooser.backendFormat();
const GrCaps* caps = this->context()->priv().caps();
- GrColorType grCT = SkColorTypeAndFormatToGrColorType(caps, this->colorType(), format);
+ GrColorType grCT = SkColorTypeToGrColorType(this->colorType());
SkASSERT(caps->isFormatCompressed(format) ||
caps->areColorTypeAndFormatCompatible(grCT, format));
#endif
@@ -457,7 +457,7 @@
const GrCaps* caps = rContext->priv().caps();
- GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
+ GrColorType grColorType = SkColorTypeToGrColorType(ct);
if (GrColorType::kUnknown == grColorType) {
return nullptr;
}
@@ -482,7 +482,7 @@
const GrCaps* caps = dContext->priv().caps();
- GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
+ GrColorType grColorType = SkColorTypeToGrColorType(ct);
if (GrColorType::kUnknown == grColorType) {
return nullptr;
}
@@ -595,9 +595,7 @@
return nullptr;
}
- GrColorType grColorType = SkColorTypeAndFormatToGrColorType(threadSafeProxy->priv().caps(),
- colorType,
- backendFormat);
+ GrColorType grColorType = SkColorTypeToGrColorType(colorType);
if (GrColorType::kUnknown == grColorType) {
return nullptr;
}
@@ -834,9 +832,7 @@
SkColorTypeToGrColorType(this->colorType())};
}
GrSurfaceProxyView view = this->makeView(recordingContext);
- GrColorType ct = SkColorTypeAndFormatToGrColorType(recordingContext->priv().caps(),
- this->colorType(),
- view.proxy()->backendFormat());
+ GrColorType ct = SkColorTypeToGrColorType(this->colorType());
if (mipmapped == GrMipmapped::kYes) {
view = FindOrMakeCachedMipmappedView(recordingContext, std::move(view), this->uniqueID());
}
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 873b431..6a7662e 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -489,8 +489,7 @@
}
sampleCnt = std::max(1, sampleCnt);
- GrColorType grColorType = SkColorTypeAndFormatToGrColorType(rContext->priv().caps(), colorType,
- tex.getBackendFormat());
+ GrColorType grColorType = SkColorTypeToGrColorType(colorType);
if (grColorType == GrColorType::kUnknown) {
return nullptr;
}
@@ -607,8 +606,7 @@
return nullptr;
}
- GrColorType grColorType = SkColorTypeAndFormatToGrColorType(rContext->priv().caps(), colorType,
- rt.getBackendFormat());
+ GrColorType grColorType = SkColorTypeToGrColorType(colorType);
if (grColorType == GrColorType::kUnknown) {
return nullptr;
}
diff --git a/src/images/SkPngEncoder.cpp b/src/images/SkPngEncoder.cpp
index d3957f7..2cf3ba4 100644
--- a/src/images/SkPngEncoder.cpp
+++ b/src/images/SkPngEncoder.cpp
@@ -237,6 +237,11 @@
case kUnknown_SkColorType:
break;
+ // TODO: I don't think this can just use kRGBA's procs.
+ // kPremul is especially tricky here, since it's presumably TF⁻¹(rgb * a),
+ // so to get at unpremul rgb we'd need to undo the transfer function first.
+ case kSRGBA_8888_SkColorType: return nullptr;
+
case kRGBA_8888_SkColorType:
switch (info.alphaType()) {
case kOpaque_SkAlphaType:
diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h
index ff0d8c1..33a067f 100644
--- a/src/opts/SkRasterPipeline_opts.h
+++ b/src/opts/SkRasterPipeline_opts.h
@@ -1644,6 +1644,12 @@
b = db;
a = da;
}
+STAGE(swap_src_dst, Ctx::None) {
+ std::swap(r, dr);
+ std::swap(g, dg);
+ std::swap(b, db);
+ std::swap(a, da);
+}
STAGE(premul, Ctx::None) {
r = r * a;
@@ -3288,6 +3294,13 @@
a = da;
}
+STAGE_PP(swap_src_dst, Ctx::None) {
+ std::swap(r, dr);
+ std::swap(g, dg);
+ std::swap(b, db);
+ std::swap(a, da);
+}
+
// ~~~~~~ Blend modes ~~~~~~ //
// The same logic applied to all 4 channels.
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index d126df0..2e44dd0 100755
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -539,6 +539,11 @@
case kBGRA_8888_SkColorType: p->append(SkRasterPipeline::gather_8888, ctx);
p->append(SkRasterPipeline::swap_rb ); break;
+ case kSRGBA_8888_SkColorType:
+ p->append(SkRasterPipeline::gather_8888, ctx);
+ p->append_transfer_function(*skcms_sRGB_TransferFunction());
+ break;
+
case kUnknown_SkColorType: SkASSERT(false);
}
if (decal_ctx) {
diff --git a/tests/BackendAllocationTest.cpp b/tests/BackendAllocationTest.cpp
index 5800e6e..6c883a4 100644
--- a/tests/BackendAllocationTest.cpp
+++ b/tests/BackendAllocationTest.cpp
@@ -573,6 +573,7 @@
{ kRGB_565_SkColorType, SkColors::kRed },
{ kARGB_4444_SkColorType, SkColors::kGreen },
{ kRGBA_8888_SkColorType, SkColors::kBlue },
+ { kSRGBA_8888_SkColorType, { 0.25f, 0.5f, 0.75f, 1.0f}},
{ kRGB_888x_SkColorType, SkColors::kCyan },
// TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
{ kBGRA_8888_SkColorType, { 1, 0, 0, 1.0f } },
diff --git a/tests/ReadWritePixelsGpuTest.cpp b/tests/ReadWritePixelsGpuTest.cpp
index 3b546eb..8fd263a 100644
--- a/tests/ReadWritePixelsGpuTest.cpp
+++ b/tests/ReadWritePixelsGpuTest.cpp
@@ -39,6 +39,7 @@
case kR16G16_unorm_SkColorType: return 16;
case kR16G16_float_SkColorType: return 16;
case kRGBA_8888_SkColorType: return 8;
+ case kSRGBA_8888_SkColorType: return 8;
case kRGB_888x_SkColorType: return 8;
case kBGRA_8888_SkColorType: return 8;
case kRGBA_1010102_SkColorType: return 10;
@@ -66,6 +67,7 @@
case kR16G16_unorm_SkColorType: return 0;
case kR16G16_float_SkColorType: return 0;
case kRGBA_8888_SkColorType: return 8;
+ case kSRGBA_8888_SkColorType: return 8;
case kRGB_888x_SkColorType: return 0;
case kBGRA_8888_SkColorType: return 8;
case kRGBA_1010102_SkColorType: return 2;
diff --git a/tools/HashAndEncode.cpp b/tools/HashAndEncode.cpp
index 0f5841b..9e7a8a1 100644
--- a/tools/HashAndEncode.cpp
+++ b/tools/HashAndEncode.cpp
@@ -29,6 +29,7 @@
case kARGB_4444_SkColorType: srcFmt = skcms_PixelFormat_ABGR_4444; break;
case kRGBA_8888_SkColorType: srcFmt = skcms_PixelFormat_RGBA_8888; break;
case kBGRA_8888_SkColorType: srcFmt = skcms_PixelFormat_BGRA_8888; break;
+ case kSRGBA_8888_SkColorType: srcFmt = skcms_PixelFormat_RGBA_8888_sRGB; break;
case kRGBA_1010102_SkColorType: srcFmt = skcms_PixelFormat_RGBA_1010102; break;
case kBGRA_1010102_SkColorType: srcFmt = skcms_PixelFormat_BGRA_1010102; break;
case kGray_8_SkColorType: srcFmt = skcms_PixelFormat_G_8; break;
diff --git a/tools/ToolUtils.cpp b/tools/ToolUtils.cpp
index 1eed400..681ac22 100644
--- a/tools/ToolUtils.cpp
+++ b/tools/ToolUtils.cpp
@@ -55,6 +55,7 @@
case kRGB_565_SkColorType: return "RGB_565";
case kARGB_4444_SkColorType: return "ARGB_4444";
case kRGBA_8888_SkColorType: return "RGBA_8888";
+ case kSRGBA_8888_SkColorType: return "SRGBA_8888";
case kRGB_888x_SkColorType: return "RGB_888x";
case kBGRA_8888_SkColorType: return "BGRA_8888";
case kRGBA_1010102_SkColorType: return "RGBA_1010102";
@@ -83,6 +84,7 @@
case kRGB_565_SkColorType: return "565";
case kARGB_4444_SkColorType: return "4444";
case kRGBA_8888_SkColorType: return "8888";
+ case kSRGBA_8888_SkColorType: return "8888";
case kRGB_888x_SkColorType: return "888";
case kBGRA_8888_SkColorType: return "8888";
case kRGBA_1010102_SkColorType: return "1010102";
diff --git a/tools/flags/CommonFlagsConfig.cpp b/tools/flags/CommonFlagsConfig.cpp
index d3adc4e..d4dfd82 100644
--- a/tools/flags/CommonFlagsConfig.cpp
+++ b/tools/flags/CommonFlagsConfig.cpp
@@ -61,7 +61,9 @@
{ "gles1010102", "gpu", "api=gles,color=1010102" },
{ "glf16", "gpu", "api=gl,color=f16" },
{ "glf16norm", "gpu", "api=gl,color=f16norm" },
+ { "glsrgba", "gpu", "api=gl,color=srgba" },
{ "glesf16", "gpu", "api=gles,color=f16" },
+ { "glessrgba", "gpu", "api=gles,color=srgba" },
{ "glnostencils", "gpu", "api=gl,stencils=false" },
{ "gldft", "gpu", "api=gl,dit=true" },
{ "glesdft", "gpu", "api=gles,dit=true" },
@@ -339,9 +341,9 @@
return false;
}
-static bool parse_option_gpu_color(const SkString& value,
- SkColorType* outColorType,
- SkAlphaType* alphaType) {
+static bool parse_option_gpu_color(const SkString& value,
+ SkColorType* outColorType,
+ SkAlphaType* alphaType) {
// We always use premul unless the color type is 565.
*alphaType = kPremul_SkAlphaType;
@@ -362,6 +364,8 @@
*outColorType = kRGBA_F16_SkColorType;
} else if (value.equals("f16norm")) {
*outColorType = kRGBA_F16Norm_SkColorType;
+ } else if (value.equals("srgba")) {
+ *outColorType = kSRGBA_8888_SkColorType;
} else {
return false;
}
diff --git a/tools/fm/fm.cpp b/tools/fm/fm.cpp
index 9a26f6a..67624eb 100644
--- a/tools/fm/fm.cpp
+++ b/tools/fm/fm.cpp
@@ -520,6 +520,7 @@
{ "f32", kRGBA_F32_SkColorType },
{ "rgba", kRGBA_8888_SkColorType },
{ "bgra", kBGRA_8888_SkColorType },
+ { "srgba", kSRGBA_8888_SkColorType },
{ "16161616", kR16G16B16A16_unorm_SkColorType },
};
const FlagOption<SkAlphaType> kAlphaTypes[] = {