Reland "Add a direct context arg to makeColorTypeAndColorSpace"

This reverts commit 779813a2394073f2f00029a7ef89e886d592eba1.

Reason for revert: Avoid null dereference in DDL test case

Original change's description:
> Revert "Add a direct context arg to makeColorTypeAndColorSpace"
>
> This reverts commit a56da9ee923c5f09ed9b97a83e250400b3c78deb.
>
> Reason for revert: UBSAN complains in Vulkan OOPRDDL mode
>
> Original change's description:
> > Add a direct context arg to makeColorTypeAndColorSpace
> >
> > This is part of a larger effort to de-power SkImage and force users to
> > specify the GPU context for all new images.
> >
> > Staging flag landed in Chrome CL 2296632.
> >
> > Bug: skia:10466
> > Change-Id: I6b7bbec10369f7d8ee884dd1bcc234d332c30a6c
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302290
> > Commit-Queue: Adlai Holler <adlai@google.com>
> > Reviewed-by: Brian Salomon <bsalomon@google.com>
> > Reviewed-by: Robert Phillips <robertphillips@google.com>
>
> TBR=bsalomon@google.com,robertphillips@google.com,adlai@google.com
>
> Change-Id: Ide36bed6966d3d92ad6b8d05f897d22d287b40b1
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:10466
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302824
> Reviewed-by: Adlai Holler <adlai@google.com>
> Commit-Queue: Adlai Holler <adlai@google.com>

Bug: skia:10466
Change-Id: I59de0bd2b33989b1af08e8af2f8a52542b6b5db0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302829
Commit-Queue: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/gm/drawimageset.cpp b/gm/drawimageset.cpp
index 870da11..515715a 100644
--- a/gm/drawimageset.cpp
+++ b/gm/drawimageset.cpp
@@ -293,7 +293,8 @@
 private:
     SkString onShortName() override { return SkString("draw_image_set_alpha_only"); }
     SkISize onISize() override { return {kM*kTileW, 2*kN*kTileH}; }
-    void onOnceBeforeDraw() override {
+
+    DrawResult onGpuSetup(GrDirectContext* direct, SkString*) override {
         static constexpr SkColor kColors[] = {SK_ColorBLUE, SK_ColorTRANSPARENT,
                                               SK_ColorRED,  SK_ColorTRANSPARENT};
         static constexpr SkColor kBGColor = SkColorSetARGB(128, 128, 128, 128);
@@ -308,11 +309,11 @@
                 fSet[i].fAlpha = (kM - x) / (float) kM;
                 if (y % 2 == 0) {
                     fSet[i].fImage = fSet[i].fImage->makeColorTypeAndColorSpace(
-                            kAlpha_8_SkColorType, alphaSpace);
+                            kAlpha_8_SkColorType, alphaSpace, direct);
                 }
             }
         }
-
+        return skiagm::DrawResult::kOk;
     }
 
     void onDraw(SkCanvas* canvas) override {
diff --git a/gm/makecolorspace.cpp b/gm/makecolorspace.cpp
index 54d8f4d..48cbbd0 100644
--- a/gm/makecolorspace.cpp
+++ b/gm/makecolorspace.cpp
@@ -17,6 +17,7 @@
 #include "include/core/SkRefCnt.h"
 #include "include/core/SkSize.h"
 #include "include/core/SkString.h"
+#include "include/gpu/GrDirectContext.h"
 #include "src/core/SkImagePriv.h"
 #include "tools/Resources.h"
 
@@ -34,8 +35,9 @@
     return SkImage::MakeFromBitmap(bitmap);
 }
 
-sk_sp<SkImage> make_color_space(sk_sp<SkImage> orig, sk_sp<SkColorSpace> colorSpace) {
-    sk_sp<SkImage> xform = orig->makeColorSpace(colorSpace);
+sk_sp<SkImage> make_color_space(
+        sk_sp<SkImage> orig, sk_sp<SkColorSpace> colorSpace, GrDirectContext* direct) {
+    sk_sp<SkImage> xform = orig->makeColorSpace(colorSpace, direct);
 
     // Assign an sRGB color space on the xformed image, so we can see the effects of the xform
     // when we draw.
@@ -58,23 +60,24 @@
         *errorMsg = "Failed to load images. Did you forget to set the resourcePath?";
         return skiagm::DrawResult::kFail;
     }
+    auto direct = GrAsDirectContext(canvas->recordingContext());
     canvas->drawImage(opaqueImage, 0.0f, 0.0f);
-    canvas->drawImage(make_color_space(opaqueImage, wideGamut), 128.0f, 0.0f);
-    canvas->drawImage(make_color_space(opaqueImage, wideGamutLinear), 256.0f, 0.0f);
+    canvas->drawImage(make_color_space(opaqueImage, wideGamut, direct), 128.0f, 0.0f);
+    canvas->drawImage(make_color_space(opaqueImage, wideGamutLinear, direct), 256.0f, 0.0f);
     canvas->drawImage(premulImage, 0.0f, 128.0f);
-    canvas->drawImage(make_color_space(premulImage, wideGamut), 128.0f, 128.0f);
-    canvas->drawImage(make_color_space(premulImage, wideGamutLinear), 256.0f, 128.0f);
+    canvas->drawImage(make_color_space(premulImage, wideGamut, direct), 128.0f, 128.0f);
+    canvas->drawImage(make_color_space(premulImage, wideGamutLinear, direct), 256.0f, 128.0f);
     canvas->translate(0.0f, 256.0f);
 
     // Raster images
     opaqueImage = make_raster_image("images/mandrill_128.png");
     premulImage = make_raster_image("images/color_wheel.png");
     canvas->drawImage(opaqueImage, 0.0f, 0.0f);
-    canvas->drawImage(make_color_space(opaqueImage, wideGamut), 128.0f, 0.0f);
-    canvas->drawImage(make_color_space(opaqueImage, wideGamutLinear), 256.0f, 0.0f);
+    canvas->drawImage(make_color_space(opaqueImage, wideGamut, direct), 128.0f, 0.0f);
+    canvas->drawImage(make_color_space(opaqueImage, wideGamutLinear, direct), 256.0f, 0.0f);
     canvas->drawImage(premulImage, 0.0f, 128.0f);
-    canvas->drawImage(make_color_space(premulImage, wideGamut), 128.0f, 128.0f);
-    canvas->drawImage(make_color_space(premulImage, wideGamutLinear), 256.0f, 128.0f);
+    canvas->drawImage(make_color_space(premulImage, wideGamut, direct), 128.0f, 128.0f);
+    canvas->drawImage(make_color_space(premulImage, wideGamutLinear, direct), 256.0f, 128.0f);
     return skiagm::DrawResult::kOk;
 }
 
@@ -86,6 +89,7 @@
     auto rec2020 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kRec2020);
 
     // Use the lazy images on the first iteration, and concrete (raster/GPU) images on the second
+    auto direct = GrAsDirectContext(canvas->recordingContext());
     for (bool lazy : {true, false}) {
         for (int j = 0; j < 2; ++j) {
             const SkImage* image = images[j].get();
@@ -103,7 +107,8 @@
 
             // 565 in a wide color space (should be visibly quantized). Fails with the color_wheel,
             // because of the codec issues mentioned above.
-            auto image565 = image->makeColorTypeAndColorSpace(kRGB_565_SkColorType, rec2020);
+            auto image565 = image->makeColorTypeAndColorSpace(kRGB_565_SkColorType,
+                                                              rec2020, direct);
             if (!lazy || image565->makeRasterImage()) {
                 canvas->drawImage(image565, 128, 0);
             }
@@ -111,14 +116,13 @@
             // Grayscale in the original color space. This fails in even more cases, due to the
             // above opaque issue, and because Ganesh doesn't support drawing to gray, at all.
             auto imageGray = image->makeColorTypeAndColorSpace(kGray_8_SkColorType,
-                                                               image->refColorSpace());
+                                                               image->refColorSpace(),
+                                                               direct);
             if (!lazy || imageGray->makeRasterImage()) {
                 canvas->drawImage(imageGray, 256, 0);
             }
 
-            images[j] = canvas->getGrContext()
-                    ? image->makeTextureImage(canvas->getGrContext())
-                    : image->makeRasterImage();
+            images[j] = direct ? image->makeTextureImage(direct) : image->makeRasterImage();
 
             canvas->translate(0, 128);
         }
@@ -150,7 +154,8 @@
     // Lazy images
     canvas->drawImage(image, 0.0f, 0.0f);
     canvas->drawImage(image->reinterpretColorSpace(spin), 128.0f, 0.0f);
-    canvas->drawImage(image->makeColorSpace(spin)->reinterpretColorSpace(srgb), 256.0f, 0.0f);
+    canvas->drawImage(image->makeColorSpace(spin, nullptr)->reinterpretColorSpace(srgb),
+                      256.0f, 0.0f);
 
     canvas->translate(0.0f, 128.0f);
 
@@ -158,18 +163,21 @@
     image = image->makeRasterImage();
     canvas->drawImage(image, 0.0f, 0.0f);
     canvas->drawImage(image->reinterpretColorSpace(spin), 128.0f, 0.0f);
-    canvas->drawImage(image->makeColorSpace(spin)->reinterpretColorSpace(srgb), 256.0f, 0.0f);
+    canvas->drawImage(image->makeColorSpace(spin, nullptr)->reinterpretColorSpace(srgb),
+                      256.0f, 0.0f);
 
     canvas->translate(0.0f, 128.0f);
 
     // GPU images
-    if (auto gpuImage = image->makeTextureImage(canvas->getGrContext())) {
+    auto direct = GrAsDirectContext(canvas->recordingContext());
+    if (auto gpuImage = image->makeTextureImage(direct)) {
         image = gpuImage;
     }
 
     canvas->drawImage(image, 0.0f, 0.0f);
     canvas->drawImage(image->reinterpretColorSpace(spin), 128.0f, 0.0f);
-    canvas->drawImage(image->makeColorSpace(spin)->reinterpretColorSpace(srgb), 256.0f, 0.0f);
+    canvas->drawImage(image->makeColorSpace(spin, direct)->reinterpretColorSpace(srgb),
+                      256.0f, 0.0f);
 
     return skiagm::DrawResult::kOk;
 }
diff --git a/gm/wacky_yuv_formats.cpp b/gm/wacky_yuv_formats.cpp
index 829aef9..cc2ecf0 100644
--- a/gm/wacky_yuv_formats.cpp
+++ b/gm/wacky_yuv_formats.cpp
@@ -1405,6 +1405,7 @@
             cellHeight *= 1.5f;
         }
 
+        auto direct = GrAsDirectContext(canvas->recordingContext());
         SkRect origSrcRect = SkRect::MakeWH(fOriginalBMs[0].width(), fOriginalBMs[0].height());
 
         SkRect srcRect = SkRect::MakeWH(fOriginalBMs[0].width(), fOriginalBMs[0].height());
@@ -1456,7 +1457,7 @@
                         // doesn't make a whole lot of sense. The colorSpace conversion will
                         // operate on the YUV components rather than the RGB components.
                         sk_sp<SkImage> csImage =
-                            fImages[opaque][cs][format]->makeColorSpace(fTargetColorSpace);
+                            fImages[opaque][cs][format]->makeColorSpace(fTargetColorSpace, direct);
                         canvas->drawImageRect(csImage, srcRect, dstRect, &paint, constraint);
                     } else {
                         canvas->drawImageRect(fImages[opaque][cs][format], srcRect, dstRect,
@@ -1615,43 +1616,53 @@
         fImages[0][0] = fImages[0][1] = fImages[1][0] = fImages[1][1] = nullptr;
     }
 
-    void onDraw(GrRecordingContext* context, GrRenderTargetContext*, SkCanvas* canvas) override {
+    DrawResult onDraw(GrRecordingContext* recording, GrRenderTargetContext*,
+                      SkCanvas* canvas, SkString* msg) override {
         SkASSERT(fImages[0][0] && fImages[0][1] && fImages[1][0] && fImages[1][1]);
 
-        auto direct = context->asDirectContext();
+        auto direct = GrAsDirectContext(recording);
+        if (recording && !direct) {
+            *msg = "YUV ColorSpace image creation requires a direct context.";
+            return DrawResult::kSkip;
+        }
+
         int x = kPad;
         for (int tagged : { 0, 1 }) {
             for (int opaque : { 0, 1 }) {
                 int y = kPad;
 
                 auto raster = SkImage::MakeFromBitmap(fOriginalBMs[opaque])
-                    ->makeColorSpace(fTargetColorSpace);
+                    ->makeColorSpace(fTargetColorSpace, nullptr);
                 canvas->drawImage(raster, x, y);
                 y += kTileWidthHeight + kPad;
 
                 if (fImages[opaque][tagged]) {
-                    auto yuv = fImages[opaque][tagged]->makeColorSpace(fTargetColorSpace);
+                    auto yuv = fImages[opaque][tagged]->makeColorSpace(fTargetColorSpace, direct);
+                    SkASSERT(yuv);
                     SkASSERT(SkColorSpace::Equals(yuv->colorSpace(), fTargetColorSpace.get()));
                     canvas->drawImage(yuv, x, y);
                     y += kTileWidthHeight + kPad;
 
                     SkIRect bounds = SkIRect::MakeWH(kTileWidthHeight / 2, kTileWidthHeight / 2);
                     auto subset = yuv->makeSubset(bounds, direct);
+                    SkASSERT(subset);
                     canvas->drawImage(subset, x, y);
                     y += kTileWidthHeight + kPad;
 
                     auto nonTexture = yuv->makeNonTextureImage();
+                    SkASSERT(nonTexture);
                     canvas->drawImage(nonTexture, x, y);
                     y += kTileWidthHeight + kPad;
 
                     SkBitmap readBack;
                     readBack.allocPixels(yuv->imageInfo());
-                    yuv->readPixels(readBack.pixmap(), 0, 0);
+                    SkAssertResult(yuv->readPixels(readBack.pixmap(), 0, 0));
                     canvas->drawBitmap(readBack, x, y);
                 }
                 x += kTileWidthHeight + kPad;
             }
         }
+        return DrawResult::kOk;
     }
 
 private:
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 3ae1ab5..f1a7e77 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -1364,12 +1364,17 @@
         Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
         If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
 
+        If this image is texture-backed, the context parameter is required and must match the
+        context of the source image.
+
         @param target  SkColorSpace describing color range of returned SkImage
+        @param direct  The GrDirectContext in play, if it exists
         @return        created SkImage in target SkColorSpace
 
         example: https://fiddle.skia.org/c/@Image_makeColorSpace
     */
-    sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target) const;
+    sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target,
+                                  GrDirectContext* direct = nullptr) const;
 
     /** Experimental.
         Creates SkImage in target SkColorType and SkColorSpace.
@@ -1377,12 +1382,17 @@
 
         Returns original SkImage if it is in target SkColorType and SkColorSpace.
 
+        If this image is texture-backed, the context parameter is required and must match the
+        context of the source image.
+
         @param targetColorType  SkColorType of returned SkImage
         @param targetColorSpace SkColorSpace of returned SkImage
+        @param direct           The GrDirectContext in play, if it exists
         @return                 created SkImage in target SkColorType and SkColorSpace
     */
     sk_sp<SkImage> makeColorTypeAndColorSpace(SkColorType targetColorType,
-                                              sk_sp<SkColorSpace> targetColorSpace) const;
+                                              sk_sp<SkColorSpace> targetColorSpace,
+                                              GrDirectContext* direct = nullptr) const;
 
     /** Creates a new SkImage identical to this one, but with a different SkColorSpace.
         This does not convert the underlying pixel data, so the resulting image will draw
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 8e4bbcf..8d32892 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -189,6 +189,7 @@
         direct = GrAsDirectContext(myContext);
     }
 #endif
+    // This check is also performed in the subclass, but we do it here for the short-circuit below.
     if (myContext && !myContext->priv().matches(direct)) {
         return nullptr;
     }
@@ -433,37 +434,30 @@
 
 bool SkImage::isAlphaOnly() const { return SkColorTypeIsAlphaOnly(fInfo.colorType()); }
 
-sk_sp<SkImage> SkImage::makeColorSpace(sk_sp<SkColorSpace> target) const {
-    if (!target) {
-        return nullptr;
-    }
-
-    // No need to create a new image if:
-    // (1) The color spaces are equal.
-    // (2) The color type is kAlpha8.
-    SkColorSpace* colorSpace = this->colorSpace();
-    if (!colorSpace) {
-        colorSpace = sk_srgb_singleton();
-    }
-    if (SkColorSpace::Equals(colorSpace, target.get()) || this->isAlphaOnly()) {
-        return sk_ref_sp(const_cast<SkImage*>(this));
-    }
-
-    // CONTEXT TODO: propagate the context parameter to the top-level API
-#if SK_SUPPORT_GPU
-    return as_IB(this)->onMakeColorTypeAndColorSpace(as_IB(this)->context(),
-#else
-    return as_IB(this)->onMakeColorTypeAndColorSpace(nullptr,
-#endif
-                                                     this->colorType(), std::move(target));
+sk_sp<SkImage> SkImage::makeColorSpace(sk_sp<SkColorSpace> target, GrDirectContext* direct) const {
+    return this->makeColorTypeAndColorSpace(this->colorType(), std::move(target), direct);
 }
 
 sk_sp<SkImage> SkImage::makeColorTypeAndColorSpace(SkColorType targetColorType,
-                                                   sk_sp<SkColorSpace> targetColorSpace) const {
+                                                   sk_sp<SkColorSpace> targetColorSpace,
+                                                   GrDirectContext* direct) const {
     if (kUnknown_SkColorType == targetColorType || !targetColorSpace) {
         return nullptr;
     }
 
+#if SK_SUPPORT_GPU
+    auto myContext = as_IB(this)->context();
+#ifdef SK_IMAGE_MAKE_COLOR_TYPE_AND_SPACE_USE_SOURCE_CONTEXT
+    if (!direct) {
+        direct = GrAsDirectContext(myContext);
+    }
+#endif
+    // This check is also performed in the subclass, but we do it here for the short-circuit below.
+    if (myContext && !myContext->priv().matches(direct)) {
+        return nullptr;
+    }
+#endif
+
     SkColorType colorType = this->colorType();
     SkColorSpace* colorSpace = this->colorSpace();
     if (!colorSpace) {
@@ -474,13 +468,8 @@
         return sk_ref_sp(const_cast<SkImage*>(this));
     }
 
-    // CONTEXT TODO: propagate the context parameter to the top-level API
-#if SK_SUPPORT_GPU
-    return as_IB(this)->onMakeColorTypeAndColorSpace(as_IB(this)->context(),
-#else
-    return as_IB(this)->onMakeColorTypeAndColorSpace(nullptr,
-#endif
-                                                     targetColorType, std::move(targetColorSpace));
+    return as_IB(this)->onMakeColorTypeAndColorSpace(targetColorType,
+                                                     std::move(targetColorSpace), direct);
 }
 
 sk_sp<SkImage> SkImage::reinterpretColorSpace(sk_sp<SkColorSpace> target) const {
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index 4046d0e..c782632 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -130,8 +130,8 @@
     virtual bool onPinAsTexture(GrContext*) const { return false; }
     virtual void onUnpinAsTexture(GrContext*) const {}
 
-    virtual sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
-                                                        SkColorType, sk_sp<SkColorSpace>) const = 0;
+    virtual sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
+                                                        GrDirectContext*) const = 0;
 
     virtual sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const = 0;
 
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 1f71435..58f9130 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -80,21 +80,21 @@
     return context->priv().flushSurfaces(p, 1, info);
 }
 
-sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
-                                                         SkColorType targetCT,
-                                                         sk_sp<SkColorSpace> targetCS) const {
-    if (!context || !fContext->priv().matches(context)) {
+sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(SkColorType targetCT,
+                                                         sk_sp<SkColorSpace> targetCS,
+                                                         GrDirectContext* direct) const {
+    if (!fContext->priv().matches(direct)) {
         return nullptr;
     }
 
     auto renderTargetContext = GrRenderTargetContext::MakeWithFallback(
-            context, SkColorTypeToGrColorType(targetCT), nullptr, SkBackingFit::kExact,
+            direct, SkColorTypeToGrColorType(targetCT), nullptr, SkBackingFit::kExact,
             this->dimensions());
     if (!renderTargetContext) {
         return nullptr;
     }
 
-    auto texFP = GrTextureEffect::Make(*this->view(context), this->alphaType());
+    auto texFP = GrTextureEffect::Make(*this->view(direct), this->alphaType());
     auto colorFP = GrColorSpaceXformEffect::Make(std::move(texFP),
                                                  this->colorSpace(), this->alphaType(),
                                                  targetCS.get(), this->alphaType());
@@ -112,7 +112,7 @@
 
     targetCT = GrColorTypeToSkColorType(renderTargetContext->colorInfo().colorType());
     // MDB: this call is okay bc we know 'renderTargetContext' was exact
-    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
+    return sk_make_sp<SkImage_Gpu>(sk_ref_sp(direct), kNeedNewImageUniqueID,
                                    renderTargetContext->readSurfaceView(), targetCT,
                                    this->alphaType(), std::move(targetCS));
 }
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index 821f106..347b848 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -45,8 +45,8 @@
         return true;
     }
 
-    sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
-                                                SkColorType, sk_sp<SkColorSpace>) const final;
+    sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
+                                                GrDirectContext*) const final;
 
     sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const final;
 
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 2006347..c38267e 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -136,7 +136,7 @@
 
 sk_sp<SkImage> SkImage_GpuBase::onMakeSubset(const SkIRect& subset,
                                              GrDirectContext* direct) const {
-    if (!direct || !fContext->priv().matches(direct)) {
+    if (!fContext->priv().matches(direct)) {
         return nullptr;
     }
 
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index 0374f33..34dbc98 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -10,7 +10,7 @@
 #include <type_traits>
 
 #include "include/core/SkYUVASizeInfo.h"
-#include "include/gpu/GrContext.h"
+#include "include/gpu/GrDirectContext.h"
 #include "include/gpu/GrRecordingContext.h"
 #include "src/core/SkAutoPixmapStorage.h"
 #include "src/core/SkMipmap.h"
@@ -63,8 +63,10 @@
 }
 
 // For onMakeColorSpace()
-SkImage_GpuYUVA::SkImage_GpuYUVA(const SkImage_GpuYUVA* image, sk_sp<SkColorSpace> targetCS)
-        : INHERITED(image->fContext, image->dimensions(), kNeedNewImageUniqueID, kAssumedColorType,
+SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrContext> context, const SkImage_GpuYUVA* image,
+                                 sk_sp<SkColorSpace> targetCS)
+        : INHERITED(std::move(context), image->dimensions(), kNeedNewImageUniqueID,
+                    kAssumedColorType,
                     // If an alpha channel is present we always switch to kPremul. This is because,
                     // although the planar data is always un-premul, the final interleaved RGB image
                     // is/would-be premul.
@@ -209,7 +211,7 @@
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
 sk_sp<SkImage> SkImage_GpuYUVA::onMakeColorTypeAndColorSpace(
-        GrRecordingContext*, SkColorType, sk_sp<SkColorSpace> targetCS) const {
+        SkColorType, sk_sp<SkColorSpace> targetCS, GrDirectContext* direct) const {
     // We explicitly ignore color type changes, for now.
 
     // we may need a mutex here but for now we expect usage to be in a single thread
@@ -217,7 +219,7 @@
         SkColorSpace::Equals(targetCS.get(), fOnMakeColorSpaceTarget.get())) {
         return fOnMakeColorSpaceResult;
     }
-    sk_sp<SkImage> result = sk_sp<SkImage>(new SkImage_GpuYUVA(this, targetCS));
+    sk_sp<SkImage> result = sk_sp<SkImage>(new SkImage_GpuYUVA(sk_ref_sp(direct), this, targetCS));
     if (result) {
         fOnMakeColorSpaceTarget = targetCS;
         fOnMakeColorSpaceResult = result;
diff --git a/src/image/SkImage_GpuYUVA.h b/src/image/SkImage_GpuYUVA.h
index a5fec95..17f146b 100644
--- a/src/image/SkImage_GpuYUVA.h
+++ b/src/image/SkImage_GpuYUVA.h
@@ -47,8 +47,8 @@
         return true;
     }
 
-    sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
-                                                SkColorType, sk_sp<SkColorSpace>) const final;
+    sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
+                                                GrDirectContext*) const final;
 
     sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const final;
 
@@ -86,7 +86,7 @@
                                                  PromiseImageApiVersion);
 
 private:
-    SkImage_GpuYUVA(const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);
+    SkImage_GpuYUVA(sk_sp<GrContext>, const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);
 
     void flattenToRGB(GrRecordingContext*) const;
 
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 687250a..51a128a 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -249,9 +249,9 @@
     return validator ? sk_sp<SkImage>(new SkImage_Lazy(&validator)) : nullptr;
 }
 
-sk_sp<SkImage> SkImage_Lazy::onMakeColorTypeAndColorSpace(GrRecordingContext*,
-                                                          SkColorType targetCT,
-                                                          sk_sp<SkColorSpace> targetCS) const {
+sk_sp<SkImage> SkImage_Lazy::onMakeColorTypeAndColorSpace(SkColorType targetCT,
+                                                          sk_sp<SkColorSpace> targetCS,
+                                                          GrDirectContext*) const {
     SkAutoMutexExclusive autoAquire(fOnMakeColorTypeAndSpaceMutex);
     if (fOnMakeColorTypeAndSpaceResult &&
         targetCT == fOnMakeColorTypeAndSpaceResult->colorType() &&
diff --git a/src/image/SkImage_Lazy.h b/src/image/SkImage_Lazy.h
index 6d1a04a..6fb030f 100644
--- a/src/image/SkImage_Lazy.h
+++ b/src/image/SkImage_Lazy.h
@@ -51,8 +51,8 @@
     sk_sp<SkImage> onMakeSubset(const SkIRect&, GrDirectContext*) const override;
     bool getROPixels(SkBitmap*, CachingHint) const override;
     bool onIsLazyGenerated() const override { return true; }
-    sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
-                                                SkColorType, sk_sp<SkColorSpace>) const override;
+    sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
+                                                GrDirectContext*) const override;
     sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const final;
 
     bool onIsValid(GrRecordingContext*) const override;
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 4783470..92d6377 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -102,8 +102,8 @@
         SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
     }
 
-    sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
-                                                SkColorType, sk_sp<SkColorSpace>) const override;
+    sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
+                                                GrDirectContext*) const override;
 
     sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const override;
 
@@ -384,9 +384,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(GrRecordingContext*,
-                                                            SkColorType targetCT,
-                                                            sk_sp<SkColorSpace> targetCS) const {
+sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(SkColorType targetCT,
+                                                            sk_sp<SkColorSpace> targetCS,
+                                                            GrDirectContext*) const {
     SkPixmap src;
     SkAssertResult(fBitmap.peekPixels(&src));
 
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index e90af19..9f9e433 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1175,7 +1175,7 @@
     *srgbBitmap.getAddr32(0, 0) = SkSwizzle_RGBA_to_PMColor(0xFF604020);
     srgbBitmap.setImmutable();
     sk_sp<SkImage> srgbImage = SkImage::MakeFromBitmap(srgbBitmap);
-    sk_sp<SkImage> p3Image = srgbImage->makeColorSpace(p3);
+    sk_sp<SkImage> p3Image = srgbImage->makeColorSpace(p3, nullptr);
     SkBitmap p3Bitmap;
     bool success = p3Image->asLegacyBitmap(&p3Bitmap);
 
@@ -1186,7 +1186,7 @@
     REPORTER_ASSERT(r, almost_equal(0x40, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
     REPORTER_ASSERT(r, almost_equal(0x5E, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
 
-    sk_sp<SkImage> adobeImage = srgbImage->makeColorSpace(adobeGamut);
+    sk_sp<SkImage> adobeImage = srgbImage->makeColorSpace(adobeGamut, nullptr);
     SkBitmap adobeBitmap;
     success = adobeImage->asLegacyBitmap(&adobeBitmap);
     REPORTER_ASSERT(r, success);
@@ -1195,7 +1195,7 @@
     REPORTER_ASSERT(r, almost_equal(0x4C, SkGetPackedB32(*adobeBitmap.getAddr32(0, 0))));
 
     srgbImage = GetResourceAsImage("images/1x1.png");
-    p3Image = srgbImage->makeColorSpace(p3);
+    p3Image = srgbImage->makeColorSpace(p3, nullptr);
     success = p3Image->asLegacyBitmap(&p3Bitmap);
     REPORTER_ASSERT(r, success);
     REPORTER_ASSERT(r, almost_equal(0x8B, SkGetPackedR32(*p3Bitmap.getAddr32(0, 0))));