implement SkConvertPixels color xform with steps
Opaque destinations like 565 prove the assert I just added can't be quite so strong. This kills off another nemesis, append_gamut_transform(). Change-Id: I5030ce094ae0f6a34d0301f6fe060b50342c7ef4 Reviewed-on: https://skia-review.googlesource.com/147106 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
0edad3e46d
commit
6a2a197602
@ -12,8 +12,10 @@
|
||||
|
||||
SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType srcAT,
|
||||
SkColorSpace* dst, SkAlphaType dstAT) {
|
||||
// We can exploit that srcs are opaque, but it doesn't make sense to ask for opaque output.
|
||||
SkASSERT(dstAT != kOpaque_SkAlphaType);
|
||||
// It's mildly interesting to know the output is opaque, but mechanically that's just unpremul.
|
||||
if (dstAT == kOpaque_SkAlphaType) {
|
||||
dstAT = kUnpremul_SkAlphaType;
|
||||
}
|
||||
|
||||
// Set all bools to false, all floats to 0.0f.
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
@ -173,8 +173,7 @@ static void convert_to_alpha8(uint8_t* dst, size_t dstRB, const SkImageInfo& src
|
||||
|
||||
// Default: Use the pipeline.
|
||||
static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
|
||||
const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
|
||||
bool isColorAware) {
|
||||
const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB) {
|
||||
|
||||
SkJumper_MemoryCtx src = { (void*)srcRow, (int)(srcRB / srcInfo.bytesPerPixel()) },
|
||||
dst = { (void*)dstRow, (int)(dstRB / dstInfo.bytesPerPixel()) };
|
||||
@ -218,53 +217,16 @@ static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size
|
||||
break;
|
||||
}
|
||||
|
||||
SkAlphaType premulState = srcInfo.alphaType();
|
||||
if (kPremul_SkAlphaType == premulState) {
|
||||
pipeline.append(SkRasterPipeline::unpremul);
|
||||
premulState = kUnpremul_SkAlphaType;
|
||||
}
|
||||
// Interpret any untagged source as sRGB.
|
||||
auto srcCS = srcInfo.colorSpace() ? srcInfo.colorSpace() : sk_srgb_singleton();
|
||||
|
||||
SkColorSpaceTransferFn srcFn;
|
||||
if (isColorAware && srcInfo.gammaCloseToSRGB()) {
|
||||
pipeline.append(SkRasterPipeline::from_srgb);
|
||||
} else if (isColorAware && !srcInfo.colorSpace()->gammaIsLinear()) {
|
||||
SkAssertResult(srcInfo.colorSpace()->isNumericalTransferFn(&srcFn));
|
||||
if (is_just_gamma(srcFn)) {
|
||||
pipeline.append(SkRasterPipeline::gamma, &srcFn.fG);
|
||||
} else {
|
||||
pipeline.append(SkRasterPipeline::parametric, &srcFn);
|
||||
}
|
||||
}
|
||||
// An untagged destination implies no color space transform is needed,
|
||||
// but SkColorSpaceXformSteps may still do premul/unpremul conversion.
|
||||
auto dstCS = dstInfo.colorSpace() ? dstInfo.colorSpace() : srcCS;
|
||||
|
||||
SkSTArenaAlloc<12*sizeof(float)> alloc;
|
||||
if (isColorAware) {
|
||||
append_gamut_transform(&pipeline, &alloc,
|
||||
srcInfo.colorSpace(), dstInfo.colorSpace(), premulState);
|
||||
}
|
||||
|
||||
SkColorSpaceTransferFn dstFn;
|
||||
if (isColorAware && dstInfo.gammaCloseToSRGB()) {
|
||||
pipeline.append(SkRasterPipeline::to_srgb);
|
||||
} else if (isColorAware && !dstInfo.colorSpace()->gammaIsLinear()) {
|
||||
SkAssertResult(dstInfo.colorSpace()->isNumericalTransferFn(&dstFn));
|
||||
dstFn = dstFn.invert();
|
||||
if (is_just_gamma(dstFn)) {
|
||||
pipeline.append(SkRasterPipeline::gamma, &dstFn.fG);
|
||||
} else {
|
||||
pipeline.append(SkRasterPipeline::parametric, &dstFn);
|
||||
}
|
||||
}
|
||||
|
||||
SkAlphaType dat = dstInfo.alphaType();
|
||||
if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat)
|
||||
{
|
||||
pipeline.append(SkRasterPipeline::premul);
|
||||
premulState = kPremul_SkAlphaType;
|
||||
}
|
||||
|
||||
// The final premul state must equal the dst alpha type. Note that if we are "converting"
|
||||
// opaque to another alpha type, there's no need to worry about multiplication.
|
||||
SkASSERT(premulState == dat || kOpaque_SkAlphaType == srcInfo.alphaType());
|
||||
SkColorSpaceXformSteps steps{srcCS, srcInfo.alphaType(),
|
||||
dstCS, dstInfo.alphaType()};
|
||||
steps.apply(&pipeline);
|
||||
|
||||
// We'll dither if we're decreasing precision below 32-bit.
|
||||
float dither_rate = 0.0f;
|
||||
@ -338,12 +300,9 @@ void SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isColorAware = dstInfo.colorSpace();
|
||||
SkASSERT(srcInfo.colorSpace() || !isColorAware);
|
||||
|
||||
// Fast Path 2: Simple swizzles and premuls.
|
||||
if (swizzle_and_multiply_color_type(srcInfo.colorType()) &&
|
||||
swizzle_and_multiply_color_type(dstInfo.colorType()) && !isColorAware) {
|
||||
swizzle_and_multiply_color_type(dstInfo.colorType()) && !dstInfo.colorSpace()) {
|
||||
swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
|
||||
return;
|
||||
}
|
||||
@ -355,5 +314,5 @@ void SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
|
||||
}
|
||||
|
||||
// Default: Use the pipeline.
|
||||
convert_with_pipeline(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware);
|
||||
convert_with_pipeline(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
|
||||
}
|
||||
|
@ -83,36 +83,4 @@ static inline uint32_t Sk4f_toS32(const Sk4f& px) {
|
||||
return s32;
|
||||
}
|
||||
|
||||
static inline void append_gamut_transform(SkRasterPipeline* p,
|
||||
SkArenaAlloc* alloc,
|
||||
SkColorSpace* src,
|
||||
SkColorSpace* dst,
|
||||
SkAlphaType srcAT) {
|
||||
if (src == dst || !dst || !src) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SkMatrix44 *fromSrc = src-> toXYZD50(),
|
||||
*toDst = dst->fromXYZD50();
|
||||
if (!fromSrc || !toDst) {
|
||||
SkDEBUGFAIL("We can't handle non-XYZ color spaces in append_gamut_transform().");
|
||||
return;
|
||||
}
|
||||
|
||||
// Slightly more sophisticated version of if (src == dst)
|
||||
if (src->toXYZD50Hash() == dst->toXYZD50Hash()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert from 4x4 to (column-major) 3x4.
|
||||
SkMatrix44 m44(*toDst, *fromSrc);
|
||||
float* ptr = alloc->makeArrayDefault<float>(12);
|
||||
*ptr++ = m44.get(0,0); *ptr++ = m44.get(1,0); *ptr++ = m44.get(2,0);
|
||||
*ptr++ = m44.get(0,1); *ptr++ = m44.get(1,1); *ptr++ = m44.get(2,1);
|
||||
*ptr++ = m44.get(0,2); *ptr++ = m44.get(1,2); *ptr++ = m44.get(2,2);
|
||||
*ptr++ = m44.get(0,3); *ptr++ = m44.get(1,3); *ptr++ = m44.get(2,3);
|
||||
p->append(SkRasterPipeline::matrix_3x4, ptr-12);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user