diff options
author | Mike Klein <mtklein@google.com> | 2018-07-10 18:25:03 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-07-10 20:13:26 +0000 |
commit | b82edcc92bb49ca877bd51b9f47cfece68785035 (patch) | |
tree | 26fe067de6cf37a96a93cb94bc18cd41bc7b880b | |
parent | 6eb36214461794626291a01c3150f7239e4a91a3 (diff) |
update (non-sprite) image shader color management
Just another little step... diffs down to ~450 from ~500.
The A8 handling has changed a little, keeping the paint
color in sRGB just to make the append_misc() logic a bit
more streamlined.
I may want to refactor things a little later so that I can
get an easy signal to use to_srgb and from_srgb stages instead
of sending them through the generic parametric stages.
Change-Id: Iefff3206b06a3aa7d81f85fd169272b6ac9c20e0
Reviewed-on: https://skia-review.googlesource.com/140250
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
-rw-r--r-- | src/core/SkColorSpaceXformSteps.cpp | 26 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformSteps.h | 3 | ||||
-rw-r--r-- | src/core/SkRasterPipeline.h | 2 | ||||
-rw-r--r-- | src/opts/SkRasterPipeline_opts.h | 10 | ||||
-rw-r--r-- | src/shaders/SkImageShader.cpp | 42 |
5 files changed, 63 insertions, 20 deletions
diff --git a/src/core/SkColorSpaceXformSteps.cpp b/src/core/SkColorSpaceXformSteps.cpp index ae230ee0fc..4dfe56383a 100644 --- a/src/core/SkColorSpaceXformSteps.cpp +++ b/src/core/SkColorSpaceXformSteps.cpp @@ -6,6 +6,7 @@ */ #include "SkColorSpaceXformSteps.h" +#include "SkRasterPipeline.h" // TODO: explain @@ -66,7 +67,10 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr void SkColorSpaceXformSteps::apply(float* rgba) const { if (flags.unpremul) { - float invA = isfinite(1.0f / rgba[3]) ? 1.0f / rgba[3] : 0; + // I don't know why isfinite(x) stopped working on the Chromecast bots... + auto is_finite = [](float x) { return x*0 == 0; }; + + float invA = is_finite(1.0f / rgba[3]) ? 1.0f / rgba[3] : 0; rgba[0] *= invA; rgba[1] *= invA; rgba[2] *= invA; @@ -95,3 +99,23 @@ void SkColorSpaceXformSteps::apply(float* rgba) const { rgba[2] *= rgba[3]; } } + +void SkColorSpaceXformSteps::apply(SkRasterPipeline* p) const { + if (flags.unpremul) { p->append(SkRasterPipeline::unpremul); } + if (flags.linearize) { + // TODO: missing an opportunity to use from_srgb here. + p->append(SkRasterPipeline::parametric_r, &srcTF); + p->append(SkRasterPipeline::parametric_g, &srcTF); + p->append(SkRasterPipeline::parametric_b, &srcTF); + } + if (flags.gamut_transform) { + p->append(SkRasterPipeline::matrix_3x3, &src_to_dst_matrix); + } + if (flags.encode) { + // TODO: missing an opportunity to use to_srgb here. + p->append(SkRasterPipeline::parametric_r, &dstTFInv); + p->append(SkRasterPipeline::parametric_g, &dstTFInv); + p->append(SkRasterPipeline::parametric_b, &dstTFInv); + } + if (flags.premul) { p->append(SkRasterPipeline::premul); } +} diff --git a/src/core/SkColorSpaceXformSteps.h b/src/core/SkColorSpaceXformSteps.h index 3b2a88cddc..c052ff6d99 100644 --- a/src/core/SkColorSpaceXformSteps.h +++ b/src/core/SkColorSpaceXformSteps.h @@ -11,6 +11,8 @@ #include "SkColorSpace.h" #include "SkImageInfo.h" +class SkRasterPipeline; + struct SkColorSpaceXformSteps { struct Flags { bool unpremul; @@ -39,6 +41,7 @@ struct SkColorSpaceXformSteps { } void apply(float rgba[4]) const; + void apply(SkRasterPipeline*) const; Flags flags; diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h index 36f7ce3eeb..3c14480132 100644 --- a/src/core/SkRasterPipeline.h +++ b/src/core/SkRasterPipeline.h @@ -67,7 +67,7 @@ M(srcover_rgba_8888) M(srcover_bgra_8888) \ M(luminance_to_alpha) \ M(matrix_translate) M(matrix_scale_translate) \ - M(matrix_2x3) M(matrix_3x4) M(matrix_4x5) M(matrix_4x3) \ + M(matrix_2x3) M(matrix_3x3) M(matrix_3x4) M(matrix_4x5) M(matrix_4x3) \ M(matrix_perspective) \ M(parametric_r) M(parametric_g) M(parametric_b) \ M(parametric_a) M(gamma) M(gamma_dst) \ diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index 2431ad78f9..23b5e22829 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h @@ -1803,6 +1803,14 @@ STAGE(matrix_2x3, const float* m) { r = R; g = G; } +STAGE(matrix_3x3, const float* m) { + auto R = mad(r,m[0], mad(g,m[3], b*m[6])), + G = mad(r,m[1], mad(g,m[4], b*m[7])), + B = mad(r,m[2], mad(g,m[5], b*m[8])); + r = R; + g = G; + b = B; +} STAGE(matrix_3x4, const float* m) { auto R = mad(r,m[0], mad(g,m[3], mad(b,m[6], m[ 9]))), G = mad(r,m[1], mad(g,m[4], mad(b,m[7], m[10]))), @@ -3204,7 +3212,7 @@ static NotImplemented store_u16_be, byte_tables, colorburn, colordodge, softlight, hue, saturation, color, luminosity, - matrix_3x4, matrix_4x5, matrix_4x3, + matrix_3x3, matrix_3x4, matrix_4x5, matrix_4x3, parametric_r, parametric_g, parametric_b, parametric_a, gamma, gamma_dst, rgb_to_hsl, hsl_to_rgb, diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp index aa5ecba1ac..22c3f95c04 100644 --- a/src/shaders/SkImageShader.cpp +++ b/src/shaders/SkImageShader.cpp @@ -9,6 +9,7 @@ #include "SkBitmapController.h" #include "SkBitmapProcShader.h" #include "SkBitmapProvider.h" +#include "SkColorSpaceXformSteps.h" #include "SkEmptyShader.h" #include "SkImage_Base.h" #include "SkImageShader.h" @@ -314,8 +315,8 @@ bool SkImageShader::onAppendStages(const StageRec& rec) const { SkColor4f paint_color; }; auto misc = alloc->make<MiscCtx>(); - misc->state = std::move(state); // Extend lifetime to match the pipeline's. - misc->paint_color = SkColor4f_from_SkColor(rec.fPaint.getColor(), rec.fDstCS); + misc->state = std::move(state); // Extend lifetime to match the pipeline's. + swizzle_rb(Sk4f_fromL32(rec.fPaint.getColor())).store(misc->paint_color.vec()); // sRGBA floats p->append_matrix(alloc, matrix); auto gather = alloc->make<SkJumper_GatherCtx>(); @@ -331,8 +332,6 @@ bool SkImageShader::onAppendStages(const StageRec& rec) const { limit_y->scale = pm.height(); limit_y->invScale = 1.0f / pm.height(); - bool is_srgb = rec.fDstCS && (!info.colorSpace() || info.gammaCloseToSRGB()); - SkJumper_DecalTileCtx* decal_ctx = nullptr; bool decal_x_and_y = fTileModeX == kDecal_TileMode && fTileModeY == kDecal_TileMode; if (fTileModeX == kDecal_TileMode || fTileModeY == kDecal_TileMode) { @@ -381,40 +380,49 @@ bool SkImageShader::onAppendStages(const StageRec& rec) const { if (decal_ctx) { p->append(SkRasterPipeline::check_decal_mask, decal_ctx); } - if (is_srgb) { - p->append(SkRasterPipeline::from_srgb); - } }; auto append_misc = [&] { + // TODO: if ref.fDstCS isn't null, we'll premul here then immediately unpremul + // to do the color space transformation. Might be possible to streamline. if (info.colorType() == kAlpha_8_SkColorType) { + // The color for A8 images comes from the (sRGB) paint color. p->append(SkRasterPipeline::set_rgb, &misc->paint_color); - } - if (info.colorType() == kAlpha_8_SkColorType || - info.alphaType() == kUnpremul_SkAlphaType) { + p->append(SkRasterPipeline::premul); + } else if (info.alphaType() == kUnpremul_SkAlphaType) { + // Convert unpremul images to premul before we carry on with the rest of the pipeline. p->append(SkRasterPipeline::premul); } + if (quality > kLow_SkFilterQuality) { // Bicubic filtering naturally produces out of range values on both sides. p->append(SkRasterPipeline::clamp_0); p->append(fClampAsIfUnpremul ? SkRasterPipeline::clamp_1 : SkRasterPipeline::clamp_a); } - append_gamut_transform(p, alloc, - info.colorSpace(), - rec.fDstCS, - fClampAsIfUnpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType); + + if (rec.fDstCS) { + // If color managed, convert from premul source all the way to premul dst color space. + auto srcCS = info.colorSpace(); + if (!srcCS || info.colorType() == kAlpha_8_SkColorType) { + // We treat untagged images as sRGB. + // A8 images get their r,g,b from the paint color, so they're also sRGB. + srcCS = SkColorSpace::MakeSRGB().get(); + } + alloc->make<SkColorSpaceXformSteps>(srcCS, kPremul_SkAlphaType, rec.fDstCS) + ->apply(p); + } + return true; }; - // We've got a fast path for 8888 bilinear clamp/clamp non-color-managed sampling. + // We've got a fast path for 8888 bilinear clamp/clamp sampling. auto ct = info.colorType(); if (true && (ct == kRGBA_8888_SkColorType || ct == kBGRA_8888_SkColorType) && quality == kLow_SkFilterQuality && fTileModeX == SkShader::kClamp_TileMode - && fTileModeY == SkShader::kClamp_TileMode - && !is_srgb) { + && fTileModeY == SkShader::kClamp_TileMode) { p->append(SkRasterPipeline::bilerp_clamp_8888, gather); if (ct == kBGRA_8888_SkColorType) { |