Adding color space to SkSpecialImage

Mostly means that GPU backed special images need to be supplied (and
store) a color space object.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2163343002

Review-Url: https://codereview.chromium.org/2163343002
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 8a1bc40..6210073 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -11,6 +11,7 @@
 #include "../private/SkTArray.h"
 #include "../private/SkTemplates.h"
 #include "../private/SkMutex.h"
+#include "SkColorSpace.h"
 #include "SkFilterQuality.h"
 #include "SkFlattenable.h"
 #include "SkMatrix.h"
@@ -131,7 +132,8 @@
 #if SK_SUPPORT_GPU
     static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context, 
                                             sk_sp<GrFragmentProcessor> fp,
-                                            const SkIRect& bounds);
+                                            const SkIRect& bounds,
+                                            sk_sp<SkColorSpace> colorSpace);
 #endif
 
     /**
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 9e21525..18ebcc8 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -275,7 +275,8 @@
 #if SK_SUPPORT_GPU
 sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context,
                                                 sk_sp<GrFragmentProcessor> fp,
-                                                const SkIRect& bounds) {
+                                                const SkIRect& bounds,
+                                                sk_sp<SkColorSpace> colorSpace) {
     GrPaint paint;
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
@@ -293,8 +294,9 @@
     GrFixedClip clip(dstIRect);
     drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
 
+    // TODO: Get the colorSpace from the drawContext (once it has one)
     return SkSpecialImage::MakeFromGpu(dstIRect, kNeedNewImageUniqueID_SpecialImage,
-                                       drawContext->asTexture());
+                                       drawContext->asTexture(), std::move(colorSpace));
 }
 #endif
 
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index 19194bd..ecde3d9 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -45,6 +45,8 @@
 
     virtual GrTexture* onPeekTexture() const { return nullptr; }
 
+    virtual SkColorSpace* onGetColorSpace() const = 0;
+
 #if SK_SUPPORT_GPU
     virtual sk_sp<GrTexture> onAsTextureRef(GrContext* context) const = 0;
 #endif
@@ -111,7 +113,8 @@
 
     return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(resultTex->width(), resultTex->height()),
                                        this->uniqueID(),
-                                       resultTex, &this->props(), at);
+                                       resultTex, sk_ref_sp(this->getColorSpace()), &this->props(),
+                                       at);
 #else
     return nullptr;
 #endif
@@ -144,6 +147,10 @@
     return nullptr;
 }
 
+SkColorSpace* SkSpecialImage::getColorSpace() const {
+    return as_SIB(this)->onGetColorSpace();
+}
+
 #if SK_SUPPORT_GPU
 sk_sp<GrTexture> SkSpecialImage::asTextureRef(GrContext* context) const {
     return as_SIB(this)->onAsTextureRef(context);
@@ -187,7 +194,8 @@
 
 #if SK_SUPPORT_GPU
     if (GrTexture* texture = as_IB(image)->peekTexture()) {
-        return MakeFromGpu(subset, image->uniqueID(), sk_ref_sp(texture), props);
+        return MakeFromGpu(subset, image->uniqueID(), sk_ref_sp(texture),
+                           sk_ref_sp(as_IB(image)->onImageInfo().colorSpace()), props);
     } else
 #endif
     {
@@ -230,6 +238,10 @@
         return true;
     }
 
+    SkColorSpace* onGetColorSpace() const override {
+        return fBitmap.colorSpace();
+    }
+
 #if SK_SUPPORT_GPU
     sk_sp<GrTexture> onAsTextureRef(GrContext* context) const override {
         if (context) {
@@ -311,10 +323,11 @@
 public:
     SkSpecialImage_Gpu(const SkIRect& subset,
                        uint32_t uniqueID, sk_sp<GrTexture> tex, SkAlphaType at,
-                       const SkSurfaceProps* props)
+                       sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
         : INHERITED(subset, uniqueID, props)
         , fTexture(std::move(tex))
         , fAlphaType(at)
+        , fColorSpace(std::move(colorSpace))
         , fAddedRasterVersionToCache(false) {
     }
 
@@ -334,10 +347,9 @@
         SkRect dst = SkRect::MakeXYWH(x, y,
                                       this->subset().width(), this->subset().height());
 
-        // TODO: Supply correct color space after we're storing it here
         auto img = sk_sp<SkImage>(new SkImage_Gpu(fTexture->width(), fTexture->height(),
                                                   this->uniqueID(), fAlphaType, fTexture.get(),
-                                                  nullptr, SkBudgeted::kNo));
+                                                  fColorSpace, SkBudgeted::kNo));
 
         canvas->drawImageRect(img, this->subset(),
                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
@@ -357,7 +369,8 @@
 
         SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
                                                 this->isOpaque() ? kOpaque_SkAlphaType
-                                                                 : kPremul_SkAlphaType);
+                                                                 : kPremul_SkAlphaType,
+                                                fColorSpace);
 
         if (!dst->tryAllocPixels(info)) {
             return false;
@@ -374,10 +387,14 @@
         return true;
     }
 
+    SkColorSpace* onGetColorSpace() const override {
+        return fColorSpace.get();
+    }
+
     bool getBitmapDeprecated(SkBitmap* result) const override {
         const SkImageInfo info = GrMakeInfoFromTexture(fTexture.get(),
                                                        this->width(), this->height(),
-                                                       this->isOpaque());
+                                                       this->isOpaque(), fColorSpace);
         if (!result->setInfo(info)) {
             return false;
         }
@@ -405,6 +422,7 @@
         return SkSpecialImage::MakeFromGpu(subset,
                                            this->uniqueID(),
                                            fTexture,
+                                           fColorSpace,
                                            &this->props(),
                                            fAlphaType);
     }
@@ -414,10 +432,10 @@
             fTexture->width() == subset.width() &&
             fTexture->height() == subset.height()) {
             // The existing GrTexture is already tight so reuse it in the SkImage
-            // TODO: Supply correct color space after we're storing it here
             return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
                                            kNeedNewImageUniqueID,
-                                           fAlphaType, fTexture.get(), nullptr, SkBudgeted::kYes);
+                                           fAlphaType, fTexture.get(), fColorSpace,
+                                           SkBudgeted::kYes);
         }
 
         GrContext* ctx = fTexture->getContext();
@@ -430,9 +448,8 @@
             return nullptr;
         }
         ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
-        // TODO: Supply correct color space after we're storing it here
         return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
-                                       fAlphaType, subTx.get(), nullptr, SkBudgeted::kYes);
+                                       fAlphaType, subTx.get(), fColorSpace, SkBudgeted::kYes);
     }
 
     sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
@@ -442,6 +459,7 @@
 private:
     sk_sp<GrTexture>        fTexture;
     const SkAlphaType       fAlphaType;
+    sk_sp<SkColorSpace>     fColorSpace;
     mutable SkAtomic<bool>  fAddedRasterVersionToCache;
 
     typedef SkSpecialImage_Base INHERITED;
@@ -450,10 +468,12 @@
 sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(const SkIRect& subset,
                                                   uint32_t uniqueID,
                                                   sk_sp<GrTexture> tex,
+                                                  sk_sp<SkColorSpace> colorSpace,
                                                   const SkSurfaceProps* props,
                                                   SkAlphaType at) {
     SkASSERT(rect_fits(subset, tex->width(), tex->height()));
-    return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at, props);
+    return sk_make_sp<SkSpecialImage_Gpu>(subset, uniqueID, std::move(tex), at,
+                                          std::move(colorSpace), props);
 }
 
 #endif
diff --git a/src/core/SkSpecialImage.h b/src/core/SkSpecialImage.h
index 9afd64f..3c29882 100644
--- a/src/core/SkSpecialImage.h
+++ b/src/core/SkSpecialImage.h
@@ -50,6 +50,7 @@
     int width() const { return fSubset.width(); }
     int height() const { return fSubset.height(); }
     const SkIRect& subset() const { return fSubset; }
+    SkColorSpace* getColorSpace() const;
 
     uint32_t uniqueID() const { return fUniqueID; }
     virtual bool isOpaque() const { return false; }
@@ -77,6 +78,7 @@
     static sk_sp<SkSpecialImage> MakeFromGpu(const SkIRect& subset,
                                              uint32_t uniqueID,
                                              sk_sp<GrTexture>,
+                                             sk_sp<SkColorSpace>,
                                              const SkSurfaceProps* = nullptr,
                                              SkAlphaType at = kPremul_SkAlphaType);
 #endif
diff --git a/src/core/SkSpecialSurface.cpp b/src/core/SkSpecialSurface.cpp
index 510926a..b339c27 100644
--- a/src/core/SkSpecialSurface.cpp
+++ b/src/core/SkSpecialSurface.cpp
@@ -137,9 +137,11 @@
     ~SkSpecialSurface_Gpu() override { }
 
     sk_sp<SkSpecialImage> onMakeImageSnapshot() override {
+        // TODO: Supply color space from fDrawContext, once it's present
         sk_sp<SkSpecialImage> tmp(SkSpecialImage::MakeFromGpu(this->subset(),
                                                               kNeedNewImageUniqueID_SpecialImage,
                                                               fDrawContext->asTexture(),
+                                                              nullptr,
                                                               &this->props()));
         fDrawContext = nullptr;
         return tmp;
diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp
index b484892..67ede53 100644
--- a/src/effects/SkAlphaThresholdFilter.cpp
+++ b/src/effects/SkAlphaThresholdFilter.cpp
@@ -180,7 +180,7 @@
             return nullptr;
         }
 
-        return DrawWithFP(context, std::move(fp), bounds);
+        return DrawWithFP(context, std::move(fp), bounds, sk_ref_sp(input->getColorSpace()));
     }
 #endif
 
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index 39b58b8..d98f105 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -132,9 +132,11 @@
             return nullptr;
         }
 
+        // TODO: Get the colorSpace from the drawContext (once it has one)
         return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(dstBounds.width(), dstBounds.height()),
                                            kNeedNewImageUniqueID_SpecialImage,
-                                           drawContext->asTexture(), &source->props());
+                                           drawContext->asTexture(),
+                                           sk_ref_sp(input->getColorSpace()), &source->props());
     }
 #endif
 
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 29ce3fe..392ac43 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -346,9 +346,11 @@
 
         offset->fX = bounds.left();
         offset->fY = bounds.top();
+        // TODO: Get the colorSpace from the drawContext (once it has one)
         return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                            kNeedNewImageUniqueID_SpecialImage,
-                                           drawContext->asTexture());
+                                           drawContext->asTexture(),
+                                           sk_ref_sp(source->getColorSpace()));
     }
 #endif
 
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 71503b5..7de86fb 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -453,9 +453,11 @@
     this->drawRect(drawContext.get(), inputTexture.get(), matrix, clip, bottomRight,
                    kBottomRight_BoundaryMode, pSrcBounds, offsetBounds);
 
+    // TODO: Get the colorSpace from the drawContext (once it has one)
     return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height()),
                                        kNeedNewImageUniqueID_SpecialImage,
-                                       drawContext->asTexture());
+                                       drawContext->asTexture(),
+                                       sk_ref_sp(source->getColorSpace()));
 }
 #endif
 
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index aebbad8..59be8fb 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -337,7 +337,7 @@
             return nullptr;
         }
 
-        return DrawWithFP(context, std::move(fp), bounds);
+        return DrawWithFP(context, std::move(fp), bounds, sk_ref_sp(input->getColorSpace()));
     }
 #endif
 
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index 67d155b..5e5f20b 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -328,7 +328,7 @@
             return nullptr;
         }
 
-        return DrawWithFP(context, std::move(fp), bounds);
+        return DrawWithFP(context, std::move(fp), bounds, sk_ref_sp(input->getColorSpace()));
     }
 #endif
 
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 4ac6568..5d4b58c 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -519,9 +519,11 @@
         srcTexture = dstDrawContext->asTexture();
     }
 
+    // TODO: Get the colorSpace from the drawContext (once it has one)
     return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(rect.width(), rect.height()),
                                        kNeedNewImageUniqueID_SpecialImage,
-                                       std::move(srcTexture), &input->props());
+                                       std::move(srcTexture), sk_ref_sp(input->getColorSpace()),
+                                       &input->props());
 }
 #endif
 
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 345e6e5..0102538 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -252,9 +252,11 @@
     matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
     drawContext->drawRect(GrNoClip(), paint, matrix, SkRect::Make(bounds));
 
+    // TODO: Get the colorSpace from the drawContext (once it has one)
     return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                        kNeedNewImageUniqueID_SpecialImage,
-                                       drawContext->asTexture());
+                                       drawContext->asTexture(),
+                                       sk_ref_sp(source->getColorSpace()));
 }
 
 #endif
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index b91a84a..f8033ec 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1240,7 +1240,8 @@
 
     sk_sp<SkSpecialImage> srcImg(SkSpecialImage::MakeFromGpu(srcRect,
                                                              bitmap.getGenerationID(),
-                                                             std::move(texture), 
+                                                             std::move(texture),
+                                                             sk_ref_sp(bitmap.colorSpace()),
                                                              &this->surfaceProps()));
 
     this->drawSpecial(draw, srcImg.get(), left, top, paint);
@@ -1406,7 +1407,8 @@
 
     return SkSpecialImage::MakeFromGpu(bitmap.bounds(),
                                        bitmap.getGenerationID(),
-                                       sk_ref_sp(texture), 
+                                       sk_ref_sp(texture),
+                                       sk_ref_sp(bitmap.colorSpace()),
                                        &this->surfaceProps());
 }
 
@@ -1417,7 +1419,8 @@
 
         return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(image->width(), image->height()),
                                            image->uniqueID(),
-                                           sk_ref_sp(texture), 
+                                           sk_ref_sp(texture),
+                                           sk_ref_sp(as_IB(image)->onImageInfo().colorSpace()),
                                            &this->surfaceProps());
     } else if (image->peekPixels(&pm)) {
         SkBitmap bm;
@@ -1451,7 +1454,8 @@
 
     return SkSpecialImage::MakeFromGpu(srcRect,
                                        kNeedNewImageUniqueID_SpecialImage,
-                                       std::move(texture), 
+                                       std::move(texture),
+                                       sk_ref_sp(ii.colorSpace()),
                                        &this->surfaceProps());
 }
 
diff --git a/tests/ImageFilterCacheTest.cpp b/tests/ImageFilterCacheTest.cpp
index 640debb..92858c1 100644
--- a/tests/ImageFilterCacheTest.cpp
+++ b/tests/ImageFilterCacheTest.cpp
@@ -222,13 +222,13 @@
 
     sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromGpu(full,
                                                               kNeedNewImageUniqueID_SpecialImage,
-                                                              srcTexture));
+                                                              srcTexture, nullptr));
 
     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
 
     sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromGpu(subset,
                                                                 kNeedNewImageUniqueID_SpecialImage,
-                                                                srcTexture));
+                                                                srcTexture, nullptr));
 
     test_find_existing(reporter, fullImg, subsetImg);
     test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
diff --git a/tests/SpecialImageTest.cpp b/tests/SpecialImageTest.cpp
index d7eb340..ba0eb58 100644
--- a/tests/SpecialImageTest.cpp
+++ b/tests/SpecialImageTest.cpp
@@ -187,6 +187,7 @@
     REPORTER_ASSERT(reporter, gpuBacked->uniqueID() == orig->uniqueID());
     REPORTER_ASSERT(reporter, gpuBacked->subset().width() == orig->subset().width() &&
                               gpuBacked->subset().height() == orig->subset().height());
+    REPORTER_ASSERT(reporter, gpuBacked->getColorSpace() == orig->getColorSpace());
 }
 
 // Test out the SkSpecialImage::makeTextureImage entry point
@@ -236,7 +237,7 @@
                                                                 SkIRect::MakeWH(kFullSize,
                                                                                 kFullSize),
                                                                 kNeedNewImageUniqueID_SpecialImage,
-                                                                std::move(texture)));
+                                                                std::move(texture), nullptr));
 
         {
             sk_sp<SkSpecialImage> fromGPU(gpuImage->makeTextureImage(context));
@@ -272,7 +273,7 @@
     sk_sp<SkSpecialImage> fullSImg(SkSpecialImage::MakeFromGpu(
                                                             SkIRect::MakeWH(kFullSize, kFullSize),
                                                             kNeedNewImageUniqueID_SpecialImage,
-                                                            texture));
+                                                            texture, nullptr));
 
     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
 
@@ -280,7 +281,7 @@
         sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromGpu(
                                                                subset,
                                                                kNeedNewImageUniqueID_SpecialImage,
-                                                               texture));
+                                                               texture, nullptr));
         test_image(subSImg1, reporter, context, true, kPad, kFullSize);
     }