From 7d022e099ba586804bd326fcb45c1a2d805d7c7d Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Mon, 15 May 2017 15:06:39 -0400 Subject: [PATCH] Always use raster pipeline for SkSweepGradient Add an opt-in mechanism (SkShader::isRasterPipelineOnly) and switch SkSweepGradient to always-RP. This also repurposes the existing SK_LEGACY_SWEEP_GRADIENT guard. Change-Id: Iabf0a701eda56f009d331120f0c987f96bd35d27 Reviewed-on: https://skia-review.googlesource.com/16912 Reviewed-by: Mike Reed Reviewed-by: Mike Klein Commit-Queue: Florin Malita --- include/core/SkShader.h | 4 ++++ src/core/SkBlitter.cpp | 10 ++++++++-- src/core/SkBlitter.h | 2 ++ src/core/SkComposeShader.cpp | 4 ++++ src/core/SkComposeShader.h | 2 ++ src/core/SkLocalMatrixShader.h | 4 ++++ src/core/SkShader.cpp | 3 +++ src/effects/gradients/SkSweepGradient.cpp | 33 ++++++++----------------------- src/effects/gradients/SkSweepGradient.h | 2 ++ 9 files changed, 37 insertions(+), 27 deletions(-) diff --git a/include/core/SkShader.h b/include/core/SkShader.h index b253b6b..260306c 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -506,6 +506,8 @@ protected: return sk_ref_sp(const_cast(this)); } + virtual bool isRasterPipelineOnly() const { return false; } + private: virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*, const SkMatrix&, const SkPaint&, const SkMatrix* localM) const; @@ -516,6 +518,8 @@ private: friend class SkLocalMatrixShader; // sets fLocalMatrix in SkReadBuffer constructor friend class SkBitmapProcLegacyShader; // calls computeTotalInverse() friend class SkColorSpaceXformer; // calls makeColorSpace() + friend class SkBlitter; // calls isRasterPipelineOnly() + friend class SkComposeShader; // calls isRasterPipelineOnly() typedef SkFlattenable INHERITED; }; diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 3c607ac..f9e5d60 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -782,7 +782,7 @@ SkShader::ContextRec::DstType SkBlitter::PreferredShaderDest(const SkImageInfo& #endif } -static bool use_raster_pipeline_blitter(const SkPixmap& device, const SkPaint& paint) { +bool SkBlitter::UseRasterPipelineBlitter(const SkPixmap& device, const SkPaint& paint) { #if defined(SK_FORCE_RASTER_PIPELINE_BLITTER) return true; #else @@ -790,6 +790,12 @@ static bool use_raster_pipeline_blitter(const SkPixmap& device, const SkPaint& p if (device.colorSpace()) { return true; } + + // ... unless the shader is raster pipeline-only. + if (paint.getShader() && paint.getShader()->isRasterPipelineOnly()) { + return true; + } + return device.colorType() != kN32_SkColorType; #endif } @@ -859,7 +865,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, return alloc->make(device, *paint); } - if (use_raster_pipeline_blitter(device, *paint)) { + if (UseRasterPipelineBlitter(device, *paint)) { auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc); SkASSERT(blitter); return blitter; diff --git a/src/core/SkBlitter.h b/src/core/SkBlitter.h index 1fc4959..27552b9 100644 --- a/src/core/SkBlitter.h +++ b/src/core/SkBlitter.h @@ -150,6 +150,8 @@ public: static SkShader::ContextRec::DstType PreferredShaderDest(const SkImageInfo&); + static bool UseRasterPipelineBlitter(const SkPixmap&, const SkPaint&); + protected: SkAutoMalloc fBlitMemory; }; diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp index e328235..942c293 100644 --- a/src/core/SkComposeShader.cpp +++ b/src/core/SkComposeShader.cpp @@ -120,6 +120,10 @@ bool SkComposeShader::asACompose(ComposeRec* rec) const { return true; } +bool SkComposeShader::isRasterPipelineOnly() const { + return fShaderA->isRasterPipelineOnly() || fShaderB->isRasterPipelineOnly(); +} + bool SkComposeShader::onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc, const SkMatrix& ctm, const SkPaint& paint, const SkMatrix* localM) const { diff --git a/src/core/SkComposeShader.h b/src/core/SkComposeShader.h index a66743d..d3f8c9d 100644 --- a/src/core/SkComposeShader.h +++ b/src/core/SkComposeShader.h @@ -75,6 +75,8 @@ protected: bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*, const SkMatrix&, const SkPaint&, const SkMatrix* localM) const override; + bool isRasterPipelineOnly() const final; + private: sk_sp fShaderA; sk_sp fShaderB; diff --git a/src/core/SkLocalMatrixShader.h b/src/core/SkLocalMatrixShader.h index 97986a6..b00ee89 100644 --- a/src/core/SkLocalMatrixShader.h +++ b/src/core/SkLocalMatrixShader.h @@ -61,6 +61,10 @@ protected: } #endif + bool isRasterPipelineOnly() const final { + return fProxyShader->isRasterPipelineOnly(); + } + private: sk_sp fProxyShader; diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp index 6f03bd5..5eead36 100644 --- a/src/core/SkShader.cpp +++ b/src/core/SkShader.cpp @@ -103,6 +103,9 @@ SkShader::Context* SkShader::makeContext(const ContextRec& rec, SkArenaAlloc* al SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) : fShader(shader), fCTM(*rec.fMatrix) { + // We should never use a context for RP-only shaders. + SkASSERT(!shader.isRasterPipelineOnly()); + // Because the context parameters must be valid at this point, we know that the matrix is // invertible. SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &fTotalInverse)); diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index df571e9..66913c6 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -62,8 +62,15 @@ SkSweepGradient::SweepGradientContext::SweepGradientContext( const SkSweepGradient& shader, const ContextRec& rec) : INHERITED(shader, rec) {} -// returns angle in a circle [0..2PI) -> [0..255] +bool SkSweepGradient::isRasterPipelineOnly() const { #ifdef SK_LEGACY_SWEEP_GRADIENT + return false; +#else + return true; +#endif +} + +// returns angle in a circle [0..2PI) -> [0..255] static unsigned SkATan2_255(float y, float x) { // static const float g255Over2PI = 255 / (2 * SK_ScalarPI); static const float g255Over2PI = 40.584510488433314f; @@ -82,30 +89,6 @@ static unsigned SkATan2_255(float y, float x) { SkASSERT(ir >= 0 && ir <= 255); return ir; } -#else -static unsigned SkATan2_255(float y, float x) { - float yabs = sk_float_abs(y), - xabs = sk_float_abs(x); - float little, big; - std::tie(little, big) = std::minmax(yabs, xabs); - float a = little/big; - if (!std::isfinite(a)) { - return 0; - } - SkASSERT(a >=0 && a <= 1); - - float s = a * a; - float r = a*(40.57589784014689f - + s*(-13.222755844396332f + s*(6.314046289038564f - s*1.7989502668982151f))); - r = xabs < yabs ? 255/4.0f - r : r; - r = x < 0.0f ? 255/2.0f - r : r; - r = y < 0.0f ? 255 - r : r; - - int ir = (int)r; - SkASSERT(ir >= 0 && ir <= 255); - return ir; -} -#endif void SkSweepGradient::SweepGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) { diff --git a/src/effects/gradients/SkSweepGradient.h b/src/effects/gradients/SkSweepGradient.h index 5f12744..b7ed7e5 100644 --- a/src/effects/gradients/SkSweepGradient.h +++ b/src/effects/gradients/SkSweepGradient.h @@ -42,6 +42,8 @@ protected: SkMatrix* matrix, SkRasterPipeline* p) const final; + bool isRasterPipelineOnly() const final; + private: const SkPoint fCenter; -- 2.7.4