diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkRasterPipelineBlitter.cpp | 59 |
1 files changed, 27 insertions, 32 deletions
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp index 576ba4ba19..d18decd1cd 100644 --- a/src/core/SkRasterPipelineBlitter.cpp +++ b/src/core/SkRasterPipelineBlitter.cpp @@ -60,10 +60,11 @@ private: // These values are pointed to by the blit pipelines above, // which allows us to adjust them from call to call. - void* fDstPtr = nullptr; - const void* fMaskPtr = nullptr; - float fCurrentCoverage = 0.0f; - int fCurrentY = 0; + void* fDstPtr = nullptr; + const void* fMaskPtr = nullptr; + float fCurrentCoverage = 0.0f; + int fCurrentY = 0; + SkJumper_DitherCtx fDitherCtx = { &fCurrentY, 0.0f }; typedef SkBlitter INHERITED; }; @@ -107,8 +108,21 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, return nullptr; } + // TODO: Think more about under what conditions we dither: + // - if we're drawing anything into 565 and the user has asked us to dither, or + // - if we're drawing a gradient into 565 or 8888. + if ((paint.isDither() && dst.info().colorType() == kRGB_565_SkColorType) || + (shader && shader->asAGradient(nullptr) >= SkShader::kLinear_GradientType)) { + switch (dst.info().colorType()) { + default: blitter->fDitherCtx.rate = 0.0f; break; + case kRGB_565_SkColorType: blitter->fDitherCtx.rate = 1/63.0f; break; + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: blitter->fDitherCtx.rate = 1/255.0f; break; + } + } + bool is_opaque = paintColor->a() == 1.0f, - is_constant = true; + is_constant = blitter->fDitherCtx.rate == 0.0f; if (shader) { pipeline->append(SkRasterPipeline::seed_shader, &blitter->fCurrentY); if (!shader->appendStages(pipeline, dst.colorSpace(), alloc, ctm, paint)) { @@ -119,8 +133,8 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, &paintColor->fVec[SkPM4f::A]); } - is_opaque = is_opaque && shader->isOpaque(); - is_constant = shader->isConstant(); + is_opaque = is_opaque && shader->isOpaque(); + is_constant = is_constant && shader->isConstant(); } else { pipeline->append(SkRasterPipeline::constant_color, paintColor); } @@ -132,30 +146,6 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); } - // TODO: Think more about under what conditions we dither: - // - if we're drawing anything into 565 and the user has asked us to dither, or - // - if we're drawing a gradient into 565 or 8888. - // TODO: move this later in the pipeline, perhaps the first thing we do in append_store()? - if ((paint.isDither() && dst.info().colorType() == kRGB_565_SkColorType) || - (shader && shader->asAGradient(nullptr) >= SkShader::kLinear_GradientType)) { - float rate; - switch (dst.info().colorType()) { - case kRGB_565_SkColorType: rate = 1/63.0f; break; - case kBGRA_8888_SkColorType: - case kRGBA_8888_SkColorType: rate = 1/255.0f; break; - default: rate = 0.0f; break; - } - if (rate) { - auto ctx = alloc->make<SkJumper_DitherCtx>(); - ctx->y = &blitter->fCurrentY; - ctx->rate = rate; - pipeline->append(SkRasterPipeline::dither, ctx); - pipeline->append(SkRasterPipeline::clamp_0); - pipeline->append(SkRasterPipeline::clamp_a); - is_constant = false; - } - } - if (is_constant) { pipeline->append(SkRasterPipeline::store_f32, &paintColor); pipeline->run(0,1); @@ -208,10 +198,15 @@ void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p) const { if (fDst.info().gammaCloseToSRGB()) { p->append(SkRasterPipeline::to_srgb); } + if (fDitherCtx.rate > 0.0f) { + // We dither after any sRGB transfer function to make sure our 1/255.0f is sensible + // over the whole range. If we did it before, 1/255.0f is too big a rate near zero. + p->append(SkRasterPipeline::dither, &fDitherCtx); + } + if (fDst.info().colorType() == kBGRA_8888_SkColorType) { p->append(SkRasterPipeline::swap_rb); } - SkASSERT(supported(fDst.info())); switch (fDst.info().colorType()) { case kAlpha_8_SkColorType: p->append(SkRasterPipeline::store_a8, &fDstPtr); break; |