diff options
-rw-r--r-- | src/core/SkPM4fPriv.h | 66 | ||||
-rw-r--r-- | src/effects/SkToSRGBColorFilter.cpp | 46 |
2 files changed, 75 insertions, 37 deletions
diff --git a/src/core/SkPM4fPriv.h b/src/core/SkPM4fPriv.h index 2789d3763e..0ded5e5116 100644 --- a/src/core/SkPM4fPriv.h +++ b/src/core/SkPM4fPriv.h @@ -99,51 +99,65 @@ static inline void analyze_3x4_matrix(const float matrix[12], *can_overflow = overflow; } - // N.B. scratch_matrix_3x4 must live at least as long as p. -static inline void append_gamut_transform(SkRasterPipeline* p, float scratch_matrix_3x4[12], - SkColorSpace* src, SkColorSpace* dst, - SkAlphaType alphaType) { - if (src == dst) { return; } // That was easy. - if (!dst) { return; } // Legacy modes intentionally ignore color gamut. - if (!src) { return; } // A null src color space means linear gamma, dst gamut. - - auto toXYZ = as_CSB(src)-> toXYZD50(), - fromXYZ = as_CSB(dst)->fromXYZD50(); - if (!toXYZ || !fromXYZ) { - SkASSERT(false); // We really don't want to get here with a weird colorspace. - return; +// Returns false if no gamut tranformation was necessary. +static inline bool append_gamut_transform_noclamp(SkRasterPipeline* p, + float scratch_matrix_3x4[12], + SkColorSpace* src, + SkColorSpace* dst) { + if (src == dst || !dst || !src) { + return false; + } + + const SkMatrix44 *fromSrc = as_CSB(src)-> toXYZD50(), + *toDst = as_CSB(dst)->fromXYZD50(); + if (!fromSrc || !toDst) { + SkDEBUGFAIL("We can't handle non-XYZ color spaces in append_gamut_transform()."); + return false; } // Slightly more sophisticated version of if (src == dst) if (as_CSB(src)->toXYZD50Hash() == as_CSB(dst)->toXYZD50Hash()) { - return; + return false; } - SkMatrix44 m44(*fromXYZ, *toXYZ); - // Convert from 4x4 to (column-major) 3x4. + SkMatrix44 m44(*toDst, *fromSrc); auto ptr = scratch_matrix_3x4; *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); - bool needs_clamp_0, needs_clamp_1; - analyze_3x4_matrix(scratch_matrix_3x4, &needs_clamp_0, &needs_clamp_1); - p->append(SkRasterPipeline::matrix_3x4, scratch_matrix_3x4); - if (needs_clamp_0) { p->append(SkRasterPipeline::clamp_0); } - if (needs_clamp_1) { - (kPremul_SkAlphaType == alphaType) ? p->append(SkRasterPipeline::clamp_a) - : p->append(SkRasterPipeline::clamp_1); + return true; +} + + +// N.B. scratch_matrix_3x4 must live at least as long as p. +static inline void append_gamut_transform(SkRasterPipeline* p, + float scratch_matrix_3x4[12], + SkColorSpace* src, + SkColorSpace* dst, + SkAlphaType alphaType) { + if (append_gamut_transform_noclamp(p, scratch_matrix_3x4, src, dst)) { + bool needs_clamp_0, needs_clamp_1; + analyze_3x4_matrix(scratch_matrix_3x4, &needs_clamp_0, &needs_clamp_1); + + if (needs_clamp_0) { p->append(SkRasterPipeline::clamp_0); } + if (needs_clamp_1) { + (kPremul_SkAlphaType == alphaType) ? p->append(SkRasterPipeline::clamp_a) + : p->append(SkRasterPipeline::clamp_1); + } } } -static inline void append_gamut_transform(SkRasterPipeline* p, SkArenaAlloc* scratch, - SkColorSpace* src, SkColorSpace* dst, +static inline void append_gamut_transform(SkRasterPipeline* p, + SkArenaAlloc* alloc, + SkColorSpace* src, + SkColorSpace* dst, SkAlphaType alphaType) { - append_gamut_transform(p, scratch->makeArrayDefault<float>(12), src, dst, alphaType); + append_gamut_transform(p, alloc->makeArrayDefault<float>(12), src, dst, alphaType); } static inline SkColor4f to_colorspace(const SkColor4f& c, SkColorSpace* src, SkColorSpace* dst) { diff --git a/src/effects/SkToSRGBColorFilter.cpp b/src/effects/SkToSRGBColorFilter.cpp index 7b6b3e6b84..253fea1427 100644 --- a/src/effects/SkToSRGBColorFilter.cpp +++ b/src/effects/SkToSRGBColorFilter.cpp @@ -5,26 +5,50 @@ * found in the LICENSE file. */ -#include "SkToSRGBColorFilter.h" -#include "SkPM4f.h" -#include "SkColorPriv.h" -#include "SkColorSpace.h" #include "SkColorSpace_Base.h" +#include "SkPM4fPriv.h" #include "SkRasterPipeline.h" #include "SkString.h" +#include "SkToSRGBColorFilter.h" #if SK_SUPPORT_GPU -#include "GrContext.h" -#include "effects/GrNonlinearColorSpaceXformEffect.h" -#include "glsl/GrGLSLFragmentProcessor.h" -#include "glsl/GrGLSLFragmentShaderBuilder.h" + #include "effects/GrNonlinearColorSpaceXformEffect.h" #endif void SkToSRGBColorFilter::onAppendStages(SkRasterPipeline* p, - SkColorSpace* dst, - SkArenaAlloc* scratch, + SkColorSpace* /*dst color space*/, + SkArenaAlloc* alloc, bool shaderIsOpaque) const { - // TODO + if (fSrcColorSpace->isSRGB()) { + // That was easy. + return; + } + + // Step 1: Linearize by undoing the src transfer function. + // Linear and sRGB will return true to isNumericalTransferFn(), so we check them first. + SkColorSpaceTransferFn srcFn; + if (fSrcColorSpace->gammaIsLinear()) { + // Nothing to do. + } else if (fSrcColorSpace->gammaCloseToSRGB()) { + p->append_from_srgb(shaderIsOpaque ? kOpaque_SkAlphaType + : kPremul_SkAlphaType); + } else if (fSrcColorSpace->isNumericalTransferFn(&srcFn)) { + p->append(SkRasterPipeline::parametric_r, &srcFn); + p->append(SkRasterPipeline::parametric_g, &srcFn); + p->append(SkRasterPipeline::parametric_b, &srcFn); + } else { + SkDEBUGFAIL("Looks like we got a table transfer function here, quite unexpectedly."); + // TODO: If we really need to handle this, we can, but I don't think Ganesh does. + } + + // Step 2: Transform to sRGB gamut, without clamping. + (void)append_gamut_transform_noclamp(p, + alloc->makeArrayDefault<float>(12), + fSrcColorSpace.get(), + SkColorSpace::MakeSRGB().get()); + + // Step 3: Back to sRGB encoding. + p->append(SkRasterPipeline::to_srgb); } sk_sp<SkColorFilter> SkToSRGBColorFilter::Make(sk_sp<SkColorSpace> srcColorSpace) { |