aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@google.com>2018-07-10 18:25:03 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-10 20:13:26 +0000
commitb82edcc92bb49ca877bd51b9f47cfece68785035 (patch)
tree26fe067de6cf37a96a93cb94bc18cd41bc7b880b
parent6eb36214461794626291a01c3150f7239e4a91a3 (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.cpp26
-rw-r--r--src/core/SkColorSpaceXformSteps.h3
-rw-r--r--src/core/SkRasterPipeline.h2
-rw-r--r--src/opts/SkRasterPipeline_opts.h10
-rw-r--r--src/shaders/SkImageShader.cpp42
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) {