Always use raster pipeline for SkSweepGradient
authorFlorin Malita <fmalita@chromium.org>
Mon, 15 May 2017 19:06:39 +0000 (15:06 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Tue, 16 May 2017 02:01:03 +0000 (02:01 +0000)
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 <reed@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>

include/core/SkShader.h
src/core/SkBlitter.cpp
src/core/SkBlitter.h
src/core/SkComposeShader.cpp
src/core/SkComposeShader.h
src/core/SkLocalMatrixShader.h
src/core/SkShader.cpp
src/effects/gradients/SkSweepGradient.cpp
src/effects/gradients/SkSweepGradient.h

index b253b6b..260306c 100644 (file)
@@ -506,6 +506,8 @@ protected:
         return sk_ref_sp(const_cast<SkShader*>(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;
 };
index 3c607ac..f9e5d60 100644 (file)
@@ -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<SkA8_Coverage_Blitter>(device, *paint);
     }
 
-    if (use_raster_pipeline_blitter(device, *paint)) {
+    if (UseRasterPipelineBlitter(device, *paint)) {
         auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
         SkASSERT(blitter);
         return blitter;
index 1fc4959..27552b9 100644 (file)
@@ -150,6 +150,8 @@ public:
 
     static SkShader::ContextRec::DstType PreferredShaderDest(const SkImageInfo&);
 
+    static bool UseRasterPipelineBlitter(const SkPixmap&, const SkPaint&);
+
 protected:
     SkAutoMalloc fBlitMemory;
 };
index e328235..942c293 100644 (file)
@@ -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 {
index a66743d..d3f8c9d 100644 (file)
@@ -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<SkShader>     fShaderA;
     sk_sp<SkShader>     fShaderB;
index 97986a6..b00ee89 100644 (file)
@@ -61,6 +61,10 @@ protected:
     }
 #endif
 
+    bool isRasterPipelineOnly() const final {
+        return fProxyShader->isRasterPipelineOnly();
+    }
+
 private:
     sk_sp<SkShader> fProxyShader;
 
index 6f03bd5..5eead36 100644 (file)
@@ -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));
index df571e9..66913c6 100644 (file)
@@ -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) {
index 5f12744..b7ed7e5 100644 (file)
@@ -42,6 +42,8 @@ protected:
                                      SkMatrix* matrix,
                                      SkRasterPipeline* p) const final;
 
+    bool isRasterPipelineOnly() const final;
+
 private:
     const SkPoint fCenter;