Adding an SkColorSpace to SkImage_Gpu

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

Review-Url: https://codereview.chromium.org/2165703003
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
index fb3e5c6..e8cd5e0 100644
--- a/gm/image_pict.cpp
+++ b/gm/image_pict.cpp
@@ -332,6 +332,7 @@
         // No API to draw a GrTexture directly, so we cheat and create a private image subclass
         SkAutoTUnref<SkImage> image(new SkImage_Gpu(cache->info().width(), cache->info().height(),
                                                     cache->uniqueID(), kPremul_SkAlphaType, texture,
+                                                    sk_ref_sp(cache->info().colorSpace()),
                                                     SkBudgeted::kNo));
         canvas->drawImage(image, x, y);
 #endif
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 6021590..fd20e5e 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -73,7 +73,7 @@
      *
      *  If a subset is specified, it must be contained within the generator's bounds.
      */
-    static sk_sp<SkImage> MakeFromGenerator(SkImageGenerator*, const SkIRect* subset = NULL);
+    static sk_sp<SkImage> MakeFromGenerator(SkImageGenerator*, const SkIRect* subset = nullptr);
 
     /**
      *  Construct a new SkImage based on the specified encoded data. Returns NULL on failure,
@@ -81,7 +81,7 @@
      *
      *  If a subset is specified, it must be contained within the encoded data's bounds.
      */
-    static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = NULL);
+    static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);
 
     /**
      *  Create a new image from the specified descriptor. Note - the caller is responsible for
@@ -90,12 +90,12 @@
      *  Will return NULL if the specified descriptor is unsupported.
      */
     static sk_sp<SkImage> MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc) {
-        return MakeFromTexture(ctx, desc, kPremul_SkAlphaType, NULL, NULL);
+        return MakeFromTexture(ctx, desc, kPremul_SkAlphaType, nullptr, nullptr, nullptr);
     }
 
     static sk_sp<SkImage> MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& de,
                                           SkAlphaType at) {
-        return MakeFromTexture(ctx, de, at, NULL, NULL);
+        return MakeFromTexture(ctx, de, at, nullptr, nullptr, nullptr);
     }
 
     typedef void (*TextureReleaseProc)(ReleaseContext);
@@ -107,8 +107,21 @@
      *
      *  Will return NULL if the specified descriptor is unsupported.
      */
+    static sk_sp<SkImage> MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
+                                          SkAlphaType at, TextureReleaseProc trp,
+                                          ReleaseContext rc) {
+        return MakeFromTexture(ctx, desc, at, nullptr, trp, rc);
+    }
+
+    /**
+    *  Create a new image from the specified descriptor. The underlying platform texture must stay
+    *  valid and unaltered until the specified release-proc is invoked, indicating that Skia
+    *  no longer is holding a reference to it.
+    *
+    *  Will return NULL if the specified descriptor is unsupported.
+    */
     static sk_sp<SkImage> MakeFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
-                                          TextureReleaseProc, ReleaseContext);
+                                          sk_sp<SkColorSpace>, TextureReleaseProc, ReleaseContext);
 
     /**
      *  Create a new image from the specified descriptor. Note - Skia will delete or recycle the
@@ -117,7 +130,8 @@
      *  Will return NULL if the specified descriptor is unsupported.
      */
     static sk_sp<SkImage> MakeFromAdoptedTexture(GrContext*, const GrBackendTextureDesc&,
-                                                 SkAlphaType = kPremul_SkAlphaType);
+                                                 SkAlphaType = kPremul_SkAlphaType,
+                                                 sk_sp<SkColorSpace> = nullptr);
 
     /**
      *  Create a new image by copying the pixels from the specified y, u, v textures. The data
@@ -127,7 +141,8 @@
     static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext*, SkYUVColorSpace,
                                                   const GrBackendObject yuvTextureHandles[3],
                                                   const SkISize yuvSizes[3],
-                                                  GrSurfaceOrigin);
+                                                  GrSurfaceOrigin,
+                                                  sk_sp<SkColorSpace> = nullptr);
 
     /**
      *  Create a new image by copying the pixels from the specified y and uv textures. The data
@@ -136,7 +151,8 @@
      */
     static sk_sp<SkImage> MakeFromNV12TexturesCopy(GrContext*, SkYUVColorSpace,
                                                    const GrBackendObject nv12TextureHandles[2],
-                                                   const SkISize nv12Sizes[2], GrSurfaceOrigin);
+                                                   const SkISize nv12Sizes[2], GrSurfaceOrigin,
+                                                   sk_sp<SkColorSpace> = nullptr);
 
     static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture>, const SkISize& dimensions,
                                           const SkMatrix*, const SkPaint*);
@@ -421,14 +437,14 @@
     static SkImage* NewFromRaster(const Info&, const void* pixels, size_t rowBytes,
                                   RasterReleaseProc, ReleaseContext);
     static SkImage* NewFromBitmap(const SkBitmap&);
-    static SkImage* NewFromGenerator(SkImageGenerator*, const SkIRect* subset = NULL);
-    static SkImage* NewFromEncoded(SkData* encoded, const SkIRect* subset = NULL);
+    static SkImage* NewFromGenerator(SkImageGenerator*, const SkIRect* subset = nullptr);
+    static SkImage* NewFromEncoded(SkData* encoded, const SkIRect* subset = nullptr);
     static SkImage* NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc) {
-        return NewFromTexture(ctx, desc, kPremul_SkAlphaType, NULL, NULL);
+        return NewFromTexture(ctx, desc, kPremul_SkAlphaType, nullptr, nullptr);
     }
 
     static SkImage* NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& de, SkAlphaType at) {
-        return NewFromTexture(ctx, de, at, NULL, NULL);
+        return NewFromTexture(ctx, de, at, nullptr, nullptr);
     }
     static SkImage* NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
                                    TextureReleaseProc, ReleaseContext);
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 881c015..31d53a7 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -86,6 +86,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque);
+SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque,
+                                  sk_sp<SkColorSpace> colorSpace = nullptr);
 
 #endif
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index a4ffa19..4a3e46e 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -449,9 +449,10 @@
         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(),
-                                                  SkBudgeted::kNo));
+                                                  nullptr, SkBudgeted::kNo));
 
         canvas->drawImageRect(img, this->subset(),
                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
@@ -528,9 +529,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(), SkBudgeted::kYes);
+                                           fAlphaType, fTexture.get(), nullptr, SkBudgeted::kYes);
         }
 
         GrContext* ctx = fTexture->getContext();
@@ -543,8 +545,9 @@
             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(), SkBudgeted::kYes);
+                                       fAlphaType, subTx.get(), nullptr, SkBudgeted::kYes);
     }
 
     sk_sp<SkSurface> onMakeTightSurface(const SkImageInfo& info) const override {
diff --git a/src/gpu/GrTextureParamsAdjuster.h b/src/gpu/GrTextureParamsAdjuster.h
index 7513eb4..eee761f 100644
--- a/src/gpu/GrTextureParamsAdjuster.h
+++ b/src/gpu/GrTextureParamsAdjuster.h
@@ -72,6 +72,7 @@
     int width() const { return fWidth; }
     int height() const { return fHeight; }
     bool isAlphaOnly() const { return fIsAlphaOnly; }
+    virtual SkColorSpace* getColorSpace() = 0;
 
 protected:
     GrTextureProducer(int width, int height, bool isAlphaOnly)
@@ -108,8 +109,6 @@
     */
     virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0;
 
-    virtual SkColorSpace* getColorSpace() = 0;
-
 private:
     const int   fWidth;
     const int   fHeight;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 2694718..3b3783a 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -742,7 +742,8 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) {
+SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque,
+                                  sk_sp<SkColorSpace> colorSpace) {
 #ifdef SK_DEBUG
     const GrSurfaceDesc& desc = tex->desc();
     SkASSERT(w <= desc.fWidth);
@@ -754,7 +755,7 @@
     if (!GrPixelConfigToColorAndColorSpace(config, &ct, nullptr)) {
         ct = kUnknown_SkColorType;
     }
-    return SkImageInfo::Make(w, h, ct, at);
+    return SkImageInfo::Make(w, h, ct, at, std::move(colorSpace));
 }
 
 
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index e6d66a1..8e46407 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -304,7 +304,8 @@
         }
         const SkImageInfo info = bm.info();
         return sk_make_sp<SkImage_Gpu>(info.width(), info.height(), bm.getGenerationID(),
-                                       info.alphaType(), tex, SkBudgeted::kNo);
+                                       info.alphaType(), tex, sk_ref_sp(info.colorSpace()),
+                                       SkBudgeted::kNo);
     }
 #endif
 
@@ -396,7 +397,7 @@
 }
 
 sk_sp<SkImage> SkImage::MakeFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
-                                        TextureReleaseProc, ReleaseContext) {
+                                        sk_sp<SkColorSpace>, TextureReleaseProc, ReleaseContext) {
     return nullptr;
 }
 
@@ -412,14 +413,15 @@
 }
 
 sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext*, const GrBackendTextureDesc&,
-                                               SkAlphaType) {
+                                               SkAlphaType, sk_sp<SkColorSpace>) {
     return nullptr;
 }
 
 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace space,
                                                 const GrBackendObject yuvTextureHandles[3],
                                                 const SkISize yuvSizes[3],
-                                                GrSurfaceOrigin origin) {
+                                                GrSurfaceOrigin origin,
+                                                sk_sp<SkColorSpace> imageColorSpace) {
     return nullptr;
 }
 
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index de67d6c..b3604b9 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -20,11 +20,12 @@
 #include "SkPixelRef.h"
 
 SkImage_Gpu::SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType at, GrTexture* tex,
-                         SkBudgeted budgeted)
+                         sk_sp<SkColorSpace> colorSpace, SkBudgeted budgeted)
     : INHERITED(w, h, uniqueID)
     , fTexture(SkRef(tex))
     , fAlphaType(at)
     , fBudgeted(budgeted)
+    , fColorSpace(std::move(colorSpace))
     , fAddedRasterVersionToCache(false)
 {
     SkASSERT(tex->width() == w);
@@ -43,8 +44,9 @@
     }
 }
 
-static SkImageInfo make_info(int w, int h, bool isOpaque) {
-    return SkImageInfo::MakeN32(w, h, isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+static SkImageInfo make_info(int w, int h, bool isOpaque, sk_sp<SkColorSpace> colorSpace) {
+    return SkImageInfo::MakeN32(w, h, isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
+                                std::move(colorSpace));
 }
 
 bool SkImage_Gpu::getROPixels(SkBitmap* dst, CachingHint chint) const {
@@ -55,7 +57,8 @@
         return true;
     }
 
-    if (!dst->tryAllocPixels(make_info(this->width(), this->height(), this->isOpaque()))) {
+    if (!dst->tryAllocPixels(make_info(this->width(), this->height(), this->isOpaque(),
+                                       this->fColorSpace))) {
         return false;
     }
     if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig,
@@ -72,7 +75,7 @@
 }
 
 bool SkImage_Gpu::asBitmapForImageFilters(SkBitmap* bitmap) const {
-    bitmap->setInfo(make_info(this->width(), this->height(), this->isOpaque()));
+    bitmap->setInfo(make_info(this->width(), this->height(), this->isOpaque(), fColorSpace));
     bitmap->setPixelRef(new SkGrPixelRef(bitmap->info(), fTexture))->unref();
     bitmap->pixelRef()->setImmutableWithID(this->uniqueID());
     return true;
@@ -147,13 +150,14 @@
     }
     ctx->copySurface(subTx.get(), fTexture, subset, SkIPoint::Make(0, 0));
     return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
-                                   fAlphaType, subTx.get(), fBudgeted);
+                                   fAlphaType, subTx.get(), fColorSpace, fBudgeted);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx, const GrBackendTextureDesc& desc,
-                                                 SkAlphaType at, GrWrapOwnership ownership,
+                                                 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
+                                                 GrWrapOwnership ownership,
                                                  SkImage::TextureReleaseProc releaseProc,
                                                  SkImage::ReleaseContext releaseCtx) {
     if (desc.fWidth <= 0 || desc.fHeight <= 0) {
@@ -169,25 +173,28 @@
 
     const SkBudgeted budgeted = SkBudgeted::kNo;
     return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
-                                   at, tex, budgeted);
+                                   at, tex, colorSpace, budgeted);
 }
 
 sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
-                                        SkAlphaType at, TextureReleaseProc releaseP,
-                                        ReleaseContext releaseC) {
-    return new_wrapped_texture_common(ctx, desc, at, kBorrow_GrWrapOwnership, releaseP, releaseC);
+                                        SkAlphaType at, sk_sp<SkColorSpace> cs,
+                                        TextureReleaseProc releaseP, ReleaseContext releaseC) {
+    return new_wrapped_texture_common(ctx, desc, at, std::move(cs), kBorrow_GrWrapOwnership,
+                                      releaseP, releaseC);
 }
 
 sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
-                                               SkAlphaType at) {
-    return new_wrapped_texture_common(ctx, desc, at, kAdopt_GrWrapOwnership, nullptr, nullptr);
+                                               SkAlphaType at, sk_sp<SkColorSpace> cs) {
+    return new_wrapped_texture_common(ctx, desc, at, std::move(cs), kAdopt_GrWrapOwnership,
+                                      nullptr, nullptr);
 }
 
 static sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpace colorSpace,
                                                   bool nv12,
                                                   const GrBackendObject yuvTextureHandles[],
                                                   const SkISize yuvSizes[],
-                                                  GrSurfaceOrigin origin) {
+                                                  GrSurfaceOrigin origin,
+                                                  sk_sp<SkColorSpace> imageColorSpace) {
     const SkBudgeted budgeted = SkBudgeted::kYes;
 
     if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 || yuvSizes[1].fWidth <= 0 ||
@@ -262,21 +269,25 @@
     drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect);
     ctx->flushSurfaceWrites(drawContext->accessRenderTarget());
     return sk_make_sp<SkImage_Gpu>(width, height, kNeedNewImageUniqueID,
-                                   kOpaque_SkAlphaType,
-                                   drawContext->asTexture().get(), budgeted);
+                                   kOpaque_SkAlphaType, drawContext->asTexture().get(),
+                                   std::move(imageColorSpace), budgeted);
 }
 
 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
                                                 const GrBackendObject yuvTextureHandles[3],
-                                                const SkISize yuvSizes[3], GrSurfaceOrigin origin) {
-    return make_from_yuv_textures_copy(ctx, colorSpace, false, yuvTextureHandles, yuvSizes, origin);
+                                                const SkISize yuvSizes[3], GrSurfaceOrigin origin,
+                                                sk_sp<SkColorSpace> imageColorSpace) {
+    return make_from_yuv_textures_copy(ctx, colorSpace, false, yuvTextureHandles, yuvSizes, origin,
+                                       std::move(imageColorSpace));
 }
 
 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
                                                  const GrBackendObject yuvTextureHandles[2],
                                                  const SkISize yuvSizes[2],
-                                                 GrSurfaceOrigin origin) {
-    return make_from_yuv_textures_copy(ctx, colorSpace, true, yuvTextureHandles, yuvSizes, origin);
+                                                 GrSurfaceOrigin origin,
+                                                 sk_sp<SkColorSpace> imageColorSpace) {
+    return make_from_yuv_textures_copy(ctx, colorSpace, true, yuvTextureHandles, yuvSizes, origin,
+                                       std::move(imageColorSpace));
 }
 
 static sk_sp<SkImage> create_image_from_maker(GrTextureMaker* maker, SkAlphaType at, uint32_t id) {
@@ -286,7 +297,7 @@
         return nullptr;
     }
     return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), id, at, texture,
-                                   SkBudgeted::kNo);
+                                   sk_ref_sp(maker->getColorSpace()), SkBudgeted::kNo);
 }
 
 sk_sp<SkImage> SkImage::makeTextureImage(GrContext *context) const {
@@ -346,7 +357,8 @@
         return nullptr;
     }
     return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID,
-                                   pixmap.alphaType(), texture, budgeted);
+                                   pixmap.alphaType(), texture,
+                                   sk_ref_sp(pixmap.info().colorSpace()), budgeted);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -544,5 +556,6 @@
         return nullptr;
     }
     return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID,
-                                   info.alphaType(), texture, budgeted);
+                                   info.alphaType(), texture, sk_ref_sp(info.colorSpace()),
+                                   budgeted);
 }
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index 3cef934..6206416 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -23,11 +23,13 @@
      *  An "image" can be a subset/window into a larger texture, so we explicit take the
      *  width and height.
      */
-    SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType, GrTexture*, SkBudgeted);
+    SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType, GrTexture*, sk_sp<SkColorSpace>,
+                SkBudgeted);
     ~SkImage_Gpu() override;
 
     SkImageInfo onImageInfo() const override {
-        return GrMakeInfoFromTexture(fTexture, fTexture->width(), fTexture->height(), isOpaque());
+        return GrMakeInfoFromTexture(fTexture, fTexture->width(), fTexture->height(), isOpaque(),
+                                     fColorSpace);
     }
 
     void applyBudgetDecision() const {
@@ -58,6 +60,7 @@
     SkAutoTUnref<GrTexture>     fTexture;
     const SkAlphaType           fAlphaType;
     const SkBudgeted            fBudgeted;
+    sk_sp<SkColorSpace>         fColorSpace;
     mutable SkAtomic<bool>      fAddedRasterVersionToCache;
 
 
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 5d1555f..fa37814 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -100,7 +100,8 @@
     sk_sp<SkImage> image;
     if (tex) {
         image = sk_make_sp<SkImage_Gpu>(info.width(), info.height(), kNeedNewImageUniqueID,
-                                        info.alphaType(), tex, budgeted);
+                                        info.alphaType(), tex, sk_ref_sp(info.colorSpace()),
+                                        budgeted);
     }
     return image;
 }