rough clamped tracking in SkRasterPipeline
This should make srgb_color_filter draw correctly in software.
Previously the Rec2020 block would overflow.
Change-Id: Ied4516728039e54214886d55bba92662beee9a26
Reviewed-on: https://skia-review.googlesource.com/26562
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index a7b25d7..5484c9f 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -15,6 +15,7 @@
fStages = nullptr;
fNumStages = 0;
fSlotsNeeded = 1; // We always need one extra slot for just_return().
+ fClamped = true;
}
void SkRasterPipeline::append(StockStage stage, void* ctx) {
@@ -46,6 +47,7 @@
fStages = &stages[src.fNumStages - 1];
fNumStages += src.fNumStages;
fSlotsNeeded += src.fSlotsNeeded - 1; // Don't double count just_returns().
+ fClamped = fClamped && src.fClamped;
}
void SkRasterPipeline::dump() const {
@@ -162,3 +164,12 @@
}
}
}
+
+void SkRasterPipeline::clamp_if_unclamped(SkAlphaType alphaType) {
+ if (!fClamped) {
+ this->append(SkRasterPipeline::clamp_0);
+ this->append(alphaType == kPremul_SkAlphaType ? SkRasterPipeline::clamp_a
+ : SkRasterPipeline::clamp_1);
+ fClamped = true;
+ }
+}
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index 4e2feb3..e9cb886 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -138,6 +138,11 @@
bool empty() const { return fStages == nullptr; }
+ // Used to track if we're handling values outside [0.0f, 1.0f],
+ // and to clamp back to [0.0f, 1.0f] if so.
+ void set_clamped(bool clamped) { fClamped = clamped; }
+ void clamp_if_unclamped(SkAlphaType);
+
private:
struct StageList {
StageList* prev;
@@ -152,6 +157,7 @@
StageList* fStages;
int fNumStages;
int fSlotsNeeded;
+ bool fClamped;
};
template <size_t bytes>
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index 993d735..158217e 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -256,6 +256,10 @@
p->append(SkRasterPipeline::dither, &fDitherRate);
}
+ if (fDst.info().colorType() != kRGBA_F16_SkColorType) {
+ p->clamp_if_unclamped(kPremul_SkAlphaType);
+ }
+
switch (fDst.info().colorType()) {
case kGray_8_SkColorType: p->append(SkRasterPipeline::luminance_to_alpha); // fallthru
case kAlpha_8_SkColorType: p->append(SkRasterPipeline::store_a8, &fDstPtr); break;
@@ -318,6 +322,7 @@
&& !fDst.colorSpace()
&& fDst.info().alphaType() != kUnpremul_SkAlphaType
&& fDitherRate == 0.0f) {
+ p.clamp_if_unclamped(kPremul_SkAlphaType);
p.append(SkRasterPipeline::srcover_rgba_8888, &fDstPtr);
} else {
if (fBlend != SkBlendMode::kSrc) {
diff --git a/src/effects/SkToSRGBColorFilter.cpp b/src/effects/SkToSRGBColorFilter.cpp
index 7b96fcc..f2ffc08 100644
--- a/src/effects/SkToSRGBColorFilter.cpp
+++ b/src/effects/SkToSRGBColorFilter.cpp
@@ -39,11 +39,18 @@
}
// Step 2: Transform to sRGB gamut, without clamping.
+ float* gamut_transform = alloc->makeArrayDefault<float>(12);
(void)append_gamut_transform_noclamp(p,
- alloc->makeArrayDefault<float>(12),
+ gamut_transform,
fSrcColorSpace.get(),
SkColorSpace::MakeSRGB().get());
+ bool needs_clamp_0, needs_clamp_1;
+ analyze_3x4_matrix(gamut_transform, &needs_clamp_0, &needs_clamp_1);
+ if (needs_clamp_0 || needs_clamp_1) {
+ p->set_clamped(false);
+ }
+
// Step 3: Back to sRGB encoding.
p->append(SkRasterPipeline::to_srgb);
}