Basic pipeline blend mode strength reductions:
authorMike Klein <mtklein@chromium.org>
Thu, 3 Nov 2016 16:22:01 +0000 (12:22 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 3 Nov 2016 17:15:15 +0000 (17:15 +0000)
  - when the shader is opaque, srcover becomes src
  - don't load dst when blitting in src mode with full coverage
  - fold coverage into src alpha when in srcover mode

It's not obvious that we can fold coverage into src alpha when using a 565 mask, so I've not attempted that.  What would we do about alpha?

Over all GMs this causes a single 1-bit difference in sRGB mode.  No 565 or f16 diffs.

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4349
CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Change-Id: Ib9161f498c4efa6b348ca74522166da64d09a7da
Reviewed-on: https://skia-review.googlesource.com/4349
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>

src/core/SkRasterPipeline.h
src/core/SkRasterPipelineBlitter.cpp
src/opts/SkRasterPipeline_opts.h

index 7107c688c214c0ce18afe38d23a6c60953024ef5..0a3cddbcb9dda91f88284e03652aa2a424968cff 100644 (file)
@@ -60,7 +60,7 @@
     M(load_s_565)  M(load_d_565)  M(store_565)                   \
     M(load_s_srgb) M(load_d_srgb) M(store_srgb)                  \
     M(load_s_f16)  M(load_d_f16)  M(store_f16)                   \
-    M(scale_u8)                                                  \
+    M(scale_u8) M(scale_constant_float)                          \
     M(lerp_u8) M(lerp_565) M(lerp_constant_float)                \
     M(dst)                                                       \
     M(dstatop) M(dstin) M(dstout) M(dstover)                     \
index f68006981f45962e75454d08196c057511e479fb..31c188e4f9afab98d53dad21ceae8162d3880876 100644 (file)
@@ -103,14 +103,19 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
     bool shaderIsOpaque = (paintColor >> 24) == 0xff;
 
     SkRasterPipeline shader, colorFilter;
-    if (paint.getShader()) {
-        shaderIsOpaque = paint.getShader()->isOpaque();
+    if (auto s = paint.getShader()) {
+        shaderIsOpaque = s->isOpaque();
     }
-    if ( paint.getColorFilter() &&
-        !paint.getColorFilter()->appendStages(&colorFilter, shaderIsOpaque)) {
-        return nullptr;
+    if (auto cf = paint.getColorFilter()) {
+        if (!cf->appendStages(&colorFilter, shaderIsOpaque)) {
+            return nullptr;
+        }
+        shaderIsOpaque = shaderIsOpaque && (cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
     }
 
+    if (shaderIsOpaque && blend == SkBlendMode::kSrcOver) {
+        blend = SkBlendMode::kSrc;
+    }
 
     SkColor4f color;
     if (dst.info().colorSpace()) {
@@ -179,9 +184,11 @@ void SkRasterPipelineBlitter::blitH(int x, int y, int w) {
     if (!fBlitH) {
         SkRasterPipeline p;
         p.extend(fShader);
-        this->append_load_d(&p);
-        this->append_blend(&p);
-        this->maybe_clamp(&p);
+        if (fBlend != SkBlendMode::kSrc) {
+            this->append_load_d(&p);
+            this->append_blend(&p);
+            this->maybe_clamp(&p);
+        }
         this->append_store(&p);
         fBlitH = p.compile();
     }
@@ -194,9 +201,15 @@ void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const
     if (!fBlitAntiH) {
         SkRasterPipeline p;
         p.extend(fShader);
-        this->append_load_d(&p);
-        this->append_blend(&p);
-        p.append(SkRasterPipeline::lerp_constant_float, &fConstantCoverage);
+        if (fBlend == SkBlendMode::kSrcOver) {
+            p.append(SkRasterPipeline::scale_constant_float, &fConstantCoverage);
+            this->append_load_d(&p);
+            this->append_blend(&p);
+        } else {
+            this->append_load_d(&p);
+            this->append_blend(&p);
+            p.append(SkRasterPipeline::lerp_constant_float, &fConstantCoverage);
+        }
         this->maybe_clamp(&p);
         this->append_store(&p);
         fBlitAntiH = p.compile();
@@ -222,9 +235,15 @@ void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
     if (mask.fFormat == SkMask::kA8_Format && !fBlitMaskA8) {
         SkRasterPipeline p;
         p.extend(fShader);
-        this->append_load_d(&p);
-        this->append_blend(&p);
-        p.append(SkRasterPipeline::lerp_u8, &fMaskPtr);
+        if (fBlend == SkBlendMode::kSrcOver) {
+            p.append(SkRasterPipeline::scale_u8, &fMaskPtr);
+            this->append_load_d(&p);
+            this->append_blend(&p);
+        } else {
+            this->append_load_d(&p);
+            this->append_blend(&p);
+            p.append(SkRasterPipeline::lerp_u8, &fMaskPtr);
+        }
         this->maybe_clamp(&p);
         this->append_store(&p);
         fBlitMaskA8 = p.compile();
index 9f15391918e2755f0b31ec8f0f8c5e90cb414356..950264efb18ddb930f7c8297e645c45c0ef76628 100644 (file)
@@ -235,6 +235,16 @@ STAGE(constant_color, true) {
     a = color->a();
 }
 
+// s' = sc for a constant c.
+STAGE(scale_constant_float, true) {
+    SkNf c = *(const float*)ctx;
+
+    r *= c;
+    g *= c;
+    b *= c;
+    a *= c;
+}
+
 // s' = d(1-c) + sc, for a constant c.
 STAGE(lerp_constant_float, true) {
     SkNf c = *(const float*)ctx;