Add SkPictureShader::makeColorSpace()
authorMatt Sarett <msarett@google.com>
Fri, 21 Apr 2017 19:12:34 +0000 (15:12 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Fri, 21 Apr 2017 19:40:53 +0000 (19:40 +0000)
Also adds an SkColorSpace to the BitmapShader
cache key (that should have been there already).

This fixes 3 gms in gbr-8888 config.

Bug: skia:
Change-Id: If47dfcdbd99b4caaeee4eddbe5ff1cd042ea9d02
Reviewed-on: https://skia-review.googlesource.com/13976
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>

src/core/SkPictureShader.cpp
src/core/SkPictureShader.h

index 3e36ffb..a92cf04 100644 (file)
@@ -11,6 +11,7 @@
 #include "SkBitmap.h"
 #include "SkBitmapProcShader.h"
 #include "SkCanvas.h"
+#include "SkColorSpaceXformCanvas.h"
 #include "SkImage.h"
 #include "SkImageShader.h"
 #include "SkMatrixUtils.h"
@@ -36,13 +37,15 @@ public:
                     SkShader::TileMode tmx,
                     SkShader::TileMode tmy,
                     const SkSize& scale,
-                    const SkMatrix& localMatrix)
+                    const SkMatrix& localMatrix,
+                    SkTransferFunctionBehavior blendBehavior)
         : fColorSpace(std::move(colorSpace))
         , fPictureID(pictureID)
         , fTile(tile)
         , fTmx(tmx)
         , fTmy(tmy)
-        , fScale(scale) {
+        , fScale(scale)
+        , fBlendBehavior(blendBehavior) {
 
         for (int i = 0; i < 9; ++i) {
             fLocalMatrixStorage[i] = localMatrix[i];
@@ -53,19 +56,21 @@ public:
                                       sizeof(fTile) +
                                       sizeof(fTmx) + sizeof(fTmy) +
                                       sizeof(fScale) +
-                                      sizeof(fLocalMatrixStorage);
+                                      sizeof(fLocalMatrixStorage) +
+                                      sizeof(fBlendBehavior);
         // This better be packed.
         SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - (uint32_t*)&fColorSpace) == keySize);
         this->init(&gBitmapSkaderKeyNamespaceLabel, 0, keySize);
     }
 
 private:
-    sk_sp<SkColorSpace> fColorSpace;
-    uint32_t            fPictureID;
-    SkRect              fTile;
-    SkShader::TileMode  fTmx, fTmy;
-    SkSize              fScale;
-    SkScalar            fLocalMatrixStorage[9];
+    sk_sp<SkColorSpace>        fColorSpace;
+    uint32_t                   fPictureID;
+    SkRect                     fTile;
+    SkShader::TileMode         fTmx, fTmy;
+    SkSize                     fScale;
+    SkScalar                   fLocalMatrixStorage[9];
+    SkTransferFunctionBehavior fBlendBehavior;
 
     SkDEBUGCODE(uint32_t fEndOfStruct;)
 };
@@ -102,20 +107,23 @@ struct BitmapShaderRec : public SkResourceCache::Rec {
 } // namespace
 
 SkPictureShader::SkPictureShader(sk_sp<SkPicture> picture, TileMode tmx, TileMode tmy,
-                                 const SkMatrix* localMatrix, const SkRect* tile)
+                                 const SkMatrix* localMatrix, const SkRect* tile,
+                                 sk_sp<SkColorSpace> colorSpace)
     : INHERITED(localMatrix)
     , fPicture(std::move(picture))
     , fTile(tile ? *tile : fPicture->cullRect())
     , fTmx(tmx)
-    , fTmy(tmy) {
-}
+    , fTmy(tmy)
+    , fColorSpace(std::move(colorSpace))
+{}
 
 sk_sp<SkShader> SkPictureShader::Make(sk_sp<SkPicture> picture, TileMode tmx, TileMode tmy,
                                       const SkMatrix* localMatrix, const SkRect* tile) {
     if (!picture || picture->cullRect().isEmpty() || (tile && tile->isEmpty())) {
         return SkShader::MakeEmptyShader();
     }
-    return sk_sp<SkShader>(new SkPictureShader(std::move(picture), tmx, tmy, localMatrix, tile));
+    return sk_sp<SkShader>(new SkPictureShader(std::move(picture), tmx, tmy, localMatrix, tile,
+                                               nullptr));
 }
 
 sk_sp<SkFlattenable> SkPictureShader::CreateProc(SkReadBuffer& buffer) {
@@ -219,14 +227,23 @@ sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, con
     const SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fTile.width(),
                                           SkIntToScalar(tileSize.height()) / fTile.height());
 
+    // |fColorSpace| will only be set when using an SkColorSpaceXformCanvas to do pre-draw xforms.
+    // This canvas is strictly for legacy mode.  A non-null |dstColorSpace| indicates that we
+    // should perform color correct rendering and xform at draw time.
+    SkASSERT(!fColorSpace || !dstColorSpace);
+    sk_sp<SkColorSpace> keyCS = dstColorSpace ? sk_ref_sp(dstColorSpace) : fColorSpace;
+    SkTransferFunctionBehavior blendBehavior = dstColorSpace ? SkTransferFunctionBehavior::kRespect
+                                                             : SkTransferFunctionBehavior::kIgnore;
+
     sk_sp<SkShader> tileShader;
-    BitmapShaderKey key(sk_ref_sp(dstColorSpace),
+    BitmapShaderKey key(std::move(keyCS),
                         fPicture->uniqueID(),
                         fTile,
                         fTmx,
                         fTmy,
                         tileScale,
-                        this->getLocalMatrix());
+                        this->getLocalMatrix(),
+                        blendBehavior);
 
     if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) {
         SkMatrix tileMatrix;
@@ -240,6 +257,10 @@ sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, con
             return nullptr;
         }
 
+        if (fColorSpace) {
+            tileImage = tileImage->makeColorSpace(fColorSpace, SkTransferFunctionBehavior::kIgnore);
+        }
+
         SkMatrix shaderMatrix = this->getLocalMatrix();
         shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
         tileShader = tileImage->makeShader(fTmx, fTmy, &shaderMatrix);
@@ -276,6 +297,11 @@ const {
     return ctx;
 }
 
+sk_sp<SkShader> SkPictureShader::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+    return sk_sp<SkPictureShader>(new SkPictureShader(fPicture, fTmx, fTmy, &this->getLocalMatrix(),
+                                                      &fTile, xformer->dst()));
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////
 
 SkPictureShader::PictureShaderContext::PictureShaderContext(
index 9807cd9..10b1f93 100644 (file)
@@ -38,9 +38,11 @@ protected:
     bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
                         const SkMatrix&, const SkPaint&, const SkMatrix*) const override;
     Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
+    sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
 
 private:
-    SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*);
+    SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*,
+                    sk_sp<SkColorSpace>);
 
     sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix,
                                     SkColorSpace* dstColorSpace,
@@ -67,6 +69,10 @@ private:
         typedef SkShader::Context INHERITED;
     };
 
+    // Should never be set by a public constructor.  This is only used when onMakeColorSpace()
+    // forces a deferred color space xform.
+    sk_sp<SkColorSpace>   fColorSpace;
+
     typedef SkShader INHERITED;
 };