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>
This commit is contained in:
Mike Klein 2017-07-25 12:02:13 -04:00 committed by Skia Commit-Bot
parent 066f020bb6
commit 159db0a6a1
4 changed files with 30 additions and 1 deletions

View File

@ -15,6 +15,7 @@ void SkRasterPipeline::reset() {
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 @@ void SkRasterPipeline::extend(const SkRasterPipeline& src) {
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::append_matrix(SkArenaAlloc* alloc, const SkMatrix& matrix
}
}
}
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;
}
}

View File

@ -138,6 +138,11 @@ public:
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 @@ private:
StageList* fStages;
int fNumStages;
int fSlotsNeeded;
bool fClamped;
};
template <size_t bytes>

View File

@ -256,6 +256,10 @@ void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p) const {
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 @@ void SkRasterPipelineBlitter::blitRect(int x, int y, int w, int h) {
&& !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) {

View File

@ -39,11 +39,18 @@ void SkToSRGBColorFilter::onAppendStages(SkRasterPipeline* p,
}
// 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);
}