Reland "Add sRGB 8888 colortype"
This is a reland of 0f7c10ef56
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>
This commit is contained in:
parent
3a15110898
commit
9f1e06aef9
@ -530,12 +530,13 @@ static skstd::optional<Config> create_config(const SkCommandLineConfig* config)
|
||||
|
||||
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
|
||||
|
||||
|
@ -982,6 +982,7 @@ static Sink* create_sink(const GrContextOptions& grCtxOptions, const SkCommandLi
|
||||
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);
|
||||
|
@ -21,6 +21,7 @@ static const char* colortype_name(SkColorType ct) {
|
||||
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";
|
||||
|
@ -48,6 +48,7 @@ static const char* color_type_name(SkColorType colorType) {
|
||||
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 "";
|
||||
}
|
||||
|
@ -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 @@ enum SkColorType : int {
|
||||
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
|
||||
|
@ -940,8 +940,7 @@ static constexpr SkColorType GrColorTypeToSkColorType(GrColorType ct) {
|
||||
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 @@ static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct) {
|
||||
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 @@ static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct) {
|
||||
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;
|
||||
|
@ -34,6 +34,7 @@ static inline uint32_t SkColorTypeChannelFlags(SkColorType ct) {
|
||||
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 @@ static int SkColorTypeShiftPerPixel(SkColorType ct) {
|
||||
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 @@ static inline bool SkColorTypeIsNormalized(SkColorType ct) {
|
||||
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 @@ static inline int SkColorTypeMaxBitsPerChannel(SkColorType ct) {
|
||||
case kBGRA_8888_SkColorType:
|
||||
case kGray_8_SkColorType:
|
||||
case kR8G8_unorm_SkColorType:
|
||||
case kSRGBA_8888_SkColorType:
|
||||
return 8;
|
||||
|
||||
case kRGBA_1010102_SkColorType:
|
||||
|
@ -101,6 +101,10 @@ static inline bool is_almost_linear(const skcms_TransferFunction& coeffs) {
|
||||
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);
|
||||
|
||||
|
@ -137,6 +137,47 @@ void SkColorSpaceXformSteps::apply(SkRasterPipeline* p) const {
|
||||
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 @@ skvm::Color sk_program_transfer_fn(skvm::Builder* p, skvm::Uniforms* uniforms,
|
||||
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,
|
||||
|
@ -124,7 +124,8 @@ static bool convert_to_alpha8(const SkImageInfo& dstInfo, void* vdst, size
|
||||
}
|
||||
|
||||
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++) {
|
||||
|
@ -33,6 +33,7 @@ int SkColorTypeBytesPerPixel(SkColorType ct) {
|
||||
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 @@ bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
|
||||
[[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:
|
||||
|
@ -543,6 +543,9 @@ SkMipmap* SkMipmap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact,
|
||||
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) {
|
||||
|
@ -128,6 +128,7 @@ float SkPixmap::getAlphaf(int x, int y) const {
|
||||
}
|
||||
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 @@ SkColor SkPixmap::getColor(int x, int y) const {
|
||||
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 @@ bool SkPixmap::computeIsOpaque() const {
|
||||
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);
|
||||
|
@ -210,6 +210,11 @@ void SkRasterPipeline::append_load(SkColorType ct, const SkRasterPipeline_Memory
|
||||
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 @@ void SkRasterPipeline::append_load_dst(SkColorType ct, const SkRasterPipeline_Me
|
||||
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 @@ void SkRasterPipeline::append_store(SkColorType ct, const SkRasterPipeline_Memor
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ class SkData;
|
||||
|
||||
#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) \
|
||||
|
@ -208,7 +208,8 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
|
||||
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:
|
||||
|
@ -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 @@ bool gSkVMJITViaDylib{false};
|
||||
#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 @@ namespace skvm {
|
||||
|
||||
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 @@ namespace skvm {
|
||||
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 @@ namespace skvm {
|
||||
|
||||
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 @@ namespace skvm {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -560,7 +560,7 @@ namespace skvm {
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
@ -114,7 +114,8 @@ namespace {
|
||||
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:
|
||||
|
@ -747,18 +747,3 @@ bool GrClearImage(const GrImageInfo& dstInfo, void* dst, size_t dstRB, std::arra
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -683,7 +683,7 @@ bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTextur
|
||||
}
|
||||
|
||||
GrBackendFormat format = backendTexture.getBackendFormat();
|
||||
GrColorType grColorType = SkColorTypeAndFormatToGrColorType(this->caps(), skColorType, format);
|
||||
GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
|
||||
|
||||
if (!this->caps()->areColorTypeAndFormatCompatible(grColorType, format)) {
|
||||
return false;
|
||||
|
@ -154,7 +154,7 @@ SkImage_Gpu::SkImage_Gpu(sk_sp<GrImageContext> context,
|
||||
#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 @@ SkImage_Gpu::SkImage_Gpu(sk_sp<GrDirectContext> dContext,
|
||||
#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 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrRecordingContext* rContext,
|
||||
|
||||
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 @@ sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrRecordingContext* rContext,
|
||||
|
||||
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 @@ sk_sp<SkImage> SkImage::MakePromiseTexture(sk_sp<GrContextThreadSafeProxy> threa
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrColorType grColorType = SkColorTypeAndFormatToGrColorType(threadSafeProxy->priv().caps(),
|
||||
colorType,
|
||||
backendFormat);
|
||||
GrColorType grColorType = SkColorTypeToGrColorType(colorType);
|
||||
if (GrColorType::kUnknown == grColorType) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -834,9 +832,7 @@ std::tuple<GrSurfaceProxyView, GrColorType> SkImage_Gpu::onAsView(
|
||||
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());
|
||||
}
|
||||
|
@ -489,8 +489,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrRecordingContext* rContext,
|
||||
}
|
||||
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 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrRecordingContext* rCon
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrColorType grColorType = SkColorTypeAndFormatToGrColorType(rContext->priv().caps(), colorType,
|
||||
rt.getBackendFormat());
|
||||
GrColorType grColorType = SkColorTypeToGrColorType(colorType);
|
||||
if (grColorType == GrColorType::kUnknown) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -237,6 +237,11 @@ static transform_scanline_proc choose_proc(const SkImageInfo& info) {
|
||||
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:
|
||||
|
@ -1644,6 +1644,12 @@ STAGE(move_dst_src, Ctx::None) {
|
||||
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 @@ STAGE_PP(move_dst_src, Ctx::None) {
|
||||
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.
|
||||
|
@ -539,6 +539,11 @@ bool SkImageShader::doStages(const SkStageRec& rec, SkImageStageUpdater* updater
|
||||
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) {
|
||||
|
@ -573,6 +573,7 @@ void color_type_backend_allocation_test(const sk_gpu_test::ContextInfo& ctxInfo,
|
||||
{ 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 } },
|
||||
|
@ -39,6 +39,7 @@ static constexpr int min_rgb_channel_bits(SkColorType ct) {
|
||||
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 @@ static constexpr int alpha_channel_bits(SkColorType ct) {
|
||||
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;
|
||||
|
@ -29,6 +29,7 @@ HashAndEncode::HashAndEncode(const SkBitmap& bitmap) : fSize(bitmap.info().dimen
|
||||
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;
|
||||
|
@ -55,6 +55,7 @@ const char* colortype_name(SkColorType ct) {
|
||||
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 @@ const char* colortype_depth(SkColorType ct) {
|
||||
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";
|
||||
|
@ -61,7 +61,9 @@ static const struct {
|
||||
{ "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 @@ static bool parse_option_gpu_api(const SkString& value,
|
||||
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 @@ static bool parse_option_gpu_color(const SkString& value,
|
||||
*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;
|
||||
}
|
||||
|
@ -520,6 +520,7 @@ int main(int argc, char** argv) {
|
||||
{ "f32", kRGBA_F32_SkColorType },
|
||||
{ "rgba", kRGBA_8888_SkColorType },
|
||||
{ "bgra", kBGRA_8888_SkColorType },
|
||||
{ "srgba", kSRGBA_8888_SkColorType },
|
||||
{ "16161616", kR16G16B16A16_unorm_SkColorType },
|
||||
};
|
||||
const FlagOption<SkAlphaType> kAlphaTypes[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user