Move Ganesh Skp texture code into GrImageUtils

This is a follow-up to http://review.skia.org/673717 which
makes SkPictureImageGenerator Ganesh-agnostic (and moves it
to src/image/ so it can be closer to its friends).

Change-Id: I61e0e8d5e026fd782da9651c4d90be51daee0734
Bug: skia:13983
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/678656
Commit-Queue: Kevin Lubick <kjlubick@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/core.gni b/gn/core.gni
index 0930db0..a24a9fc 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -597,9 +597,13 @@
   "$_src/image/SkImage_Lazy.cpp",
   "$_src/image/SkImage_Lazy.h",
   "$_src/image/SkImage_LazyFactories.cpp",
+  "$_src/image/SkImage_Picture.cpp",
+  "$_src/image/SkImage_Picture.h",
   "$_src/image/SkImage_Raster.cpp",
   "$_src/image/SkImage_Raster.h",
   "$_src/image/SkImage_RasterFactories.cpp",
+  "$_src/image/SkPictureImageGenerator.cpp",
+  "$_src/image/SkPictureImageGenerator.h",
   "$_src/image/SkRescaleAndReadPixels.cpp",
   "$_src/image/SkRescaleAndReadPixels.h",
   "$_src/image/SkSurface.cpp",
@@ -726,7 +730,6 @@
   "$_src/core/SkPictureData.h",
   "$_src/core/SkPictureFlat.cpp",
   "$_src/core/SkPictureFlat.h",
-  "$_src/core/SkPictureImageGenerator.cpp",
   "$_src/core/SkPicturePlayback.cpp",
   "$_src/core/SkPicturePlayback.h",
   "$_src/core/SkPictureRecord.cpp",
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 8f7d4a4..1dc696d 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -1021,7 +1021,7 @@
         example: https://fiddle.skia.org/c/@Image_isLazyGenerated_a
         example: https://fiddle.skia.org/c/@Image_isLazyGenerated_b
     */
-    bool isLazyGenerated() const;
+    virtual bool isLazyGenerated() const = 0;
 
     /** Creates SkImage in target SkColorSpace.
         Returns nullptr if SkImage could not be created.
diff --git a/public.bzl b/public.bzl
index c73f52f..5b4e056 100644
--- a/public.bzl
+++ b/public.bzl
@@ -547,7 +547,6 @@
     "src/core/SkPictureData.h",
     "src/core/SkPictureFlat.cpp",
     "src/core/SkPictureFlat.h",
-    "src/core/SkPictureImageGenerator.cpp",
     "src/core/SkPicturePlayback.cpp",
     "src/core/SkPicturePlayback.h",
     "src/core/SkPicturePriv.h",
@@ -1232,9 +1231,13 @@
     "src/image/SkImage_Lazy.cpp",
     "src/image/SkImage_Lazy.h",
     "src/image/SkImage_LazyFactories.cpp",
+    "src/image/SkImage_Picture.cpp",
+    "src/image/SkImage_Picture.h",
     "src/image/SkImage_Raster.cpp",
     "src/image/SkImage_Raster.h",
     "src/image/SkImage_RasterFactories.cpp",
+    "src/image/SkPictureImageGenerator.cpp",
+    "src/image/SkPictureImageGenerator.h",
     "src/image/SkRescaleAndReadPixels.cpp",
     "src/image/SkRescaleAndReadPixels.h",
     "src/image/SkSurface.cpp",
diff --git a/src/core/BUILD.bazel b/src/core/BUILD.bazel
index 5539fc6..c9a60f2 100644
--- a/src/core/BUILD.bazel
+++ b/src/core/BUILD.bazel
@@ -394,7 +394,6 @@
     "SkPictureData.h",
     "SkPictureFlat.cpp",
     "SkPictureFlat.h",
-    "SkPictureImageGenerator.cpp",
     "SkPicturePlayback.cpp",
     "SkPicturePlayback.h",
     "SkPictureRecord.cpp",
diff --git a/src/core/SkPictureImageGenerator.cpp b/src/core/SkPictureImageGenerator.cpp
deleted file mode 100644
index 4177cbf..0000000
--- a/src/core/SkPictureImageGenerator.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "include/core/SkCanvas.h"
-#include "include/core/SkColorSpace.h"
-#include "include/core/SkImageGenerator.h"
-#include "include/core/SkMatrix.h"
-#include "include/core/SkPaint.h"
-#include "include/core/SkPicture.h"
-#include "include/core/SkSurface.h"
-#include "src/base/SkTLazy.h"
-#include "src/image/SkImageGeneratorPriv.h"
-#include "src/image/SkImage_Base.h"
-
-#if defined(SK_GANESH)
-#include "include/gpu/ganesh/GrTextureGenerator.h"
-#include "src/gpu/ganesh/GrTextureProxy.h"
-#include "src/gpu/ganesh/image/GrImageUtils.h"
-#endif
-
-
-#if defined(SK_GANESH)
-using BASE_CLASS = GrTextureGenerator;
-#else
-using BASE_CLASS = SkImageGenerator;
-#endif
-
-class SkPictureImageGenerator : public BASE_CLASS {
-public:
-    SkPictureImageGenerator(const SkImageInfo&, sk_sp<SkPicture>, const SkMatrix*,
-                            const SkPaint*, const SkSurfaceProps&);
-
-protected:
-    bool onGetPixels(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&) override;
-
-#if defined(SK_GANESH)
-    GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
-                                         GrMipmapped, GrImageTexGenPolicy) override;
-#endif
-
-#if defined(SK_GRAPHITE)
-    sk_sp<SkImage> onMakeTextureImage(skgpu::graphite::Recorder*,
-                                      const SkImageInfo&,
-                                      skgpu::Mipmapped) override;
-#endif
-
-private:
-    sk_sp<SkPicture> fPicture;
-    SkMatrix         fMatrix;
-    SkTLazy<SkPaint> fPaint;
-    SkSurfaceProps   fProps;
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-namespace SkImageGenerators {
-std::unique_ptr<SkImageGenerator> MakeFromPicture(
-        const SkISize& size,
-        sk_sp<SkPicture> picture,
-        const SkMatrix* matrix,
-        const SkPaint* paint,
-        SkImages::BitDepth bitDepth,
-        sk_sp<SkColorSpace> colorSpace) {
-    return MakeFromPicture(size, picture, matrix, paint, bitDepth, colorSpace, {});
-}
-
-std::unique_ptr<SkImageGenerator> MakeFromPicture(const SkISize& size,
-                                                  sk_sp<SkPicture> picture,
-                                                  const SkMatrix* matrix,
-                                                  const SkPaint* paint,
-                                                  SkImages::BitDepth bitDepth,
-                                                  sk_sp<SkColorSpace> colorSpace,
-                                                  SkSurfaceProps props) {
-    if (!picture || !colorSpace || size.isEmpty()) {
-        return nullptr;
-    }
-
-    SkColorType colorType = kN32_SkColorType;
-    if (SkImages::BitDepth::kF16 == bitDepth) {
-        colorType = kRGBA_F16_SkColorType;
-    }
-
-    SkImageInfo info =
-            SkImageInfo::Make(size, colorType, kPremul_SkAlphaType, std::move(colorSpace));
-    return std::unique_ptr<SkImageGenerator>(
-        new SkPictureImageGenerator(info, std::move(picture), matrix, paint, props));
-}
-} // SkImageGenerators
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture> picture,
-                                                 const SkMatrix* matrix, const SkPaint* paint,
-                                                 const SkSurfaceProps& props)
-        : BASE_CLASS(info)
-        , fPicture(std::move(picture))
-        , fProps(props) {
-
-    if (matrix) {
-        fMatrix = *matrix;
-    } else {
-        fMatrix.reset();
-    }
-
-    if (paint) {
-        fPaint.set(*paint);
-    }
-}
-
-bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
-                                          const Options& opts) {
-    std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, rowBytes, &fProps);
-    if (!canvas) {
-        return false;
-    }
-    canvas->clear(0);
-    canvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
-    return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#if defined(SK_GANESH)
-#include "include/gpu/GrRecordingContext.h"
-#include "src/gpu/ganesh/GrRecordingContextPriv.h"
-#include "src/gpu/ganesh/SkGr.h"
-
-GrSurfaceProxyView SkPictureImageGenerator::onGenerateTexture(GrRecordingContext* ctx,
-                                                              const SkImageInfo& info,
-                                                              GrMipmapped mipmapped,
-                                                              GrImageTexGenPolicy texGenPolicy) {
-    SkASSERT(ctx);
-
-    skgpu::Budgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
-                                       ? skgpu::Budgeted::kNo
-                                       : skgpu::Budgeted::kYes;
-    auto surface = SkSurface::MakeRenderTarget(ctx, budgeted, info, 0, kTopLeft_GrSurfaceOrigin,
-                                               &fProps, mipmapped == GrMipmapped::kYes);
-    if (!surface) {
-        return {};
-    }
-
-    surface->getCanvas()->clear(SkColors::kTransparent);
-    surface->getCanvas()->drawPicture(fPicture.get(), &fMatrix, fPaint.getMaybeNull());
-    sk_sp<SkImage> image(surface->makeImageSnapshot());
-    if (!image) {
-        return {};
-    }
-
-    auto [view, ct] = skgpu::ganesh::AsView(ctx, image, mipmapped);
-    SkASSERT(view);
-    SkASSERT(mipmapped == GrMipmapped::kNo ||
-             view.asTextureProxy()->mipmapped() == GrMipmapped::kYes);
-    return view;
-}
-
-#endif // defined(SK_GANESH)
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#if defined(SK_GRAPHITE)
-#include "src/gpu/graphite/Log.h"
-
-sk_sp<SkImage> SkPictureImageGenerator::onMakeTextureImage(skgpu::graphite::Recorder* recorder,
-                                                           const SkImageInfo& info,
-                                                           skgpu::Mipmapped mipmapped) {
-    using namespace skgpu::graphite;
-
-    sk_sp<SkSurface> surface = SkSurface::MakeGraphite(recorder, info, mipmapped);
-    if (!surface) {
-        SKGPU_LOG_E("Failed to create Surface");
-        return nullptr;
-    }
-
-    surface->getCanvas()->clear(SkColors::kTransparent);
-    surface->getCanvas()->drawPicture(fPicture.get(), &fMatrix, fPaint.getMaybeNull());
-    return surface->asImage();
-}
-
-#endif // SK_GRAPHITE
diff --git a/src/gpu/ganesh/image/GrImageUtils.cpp b/src/gpu/ganesh/image/GrImageUtils.cpp
index c6e758d..0702f65 100644
--- a/src/gpu/ganesh/image/GrImageUtils.cpp
+++ b/src/gpu/ganesh/image/GrImageUtils.cpp
@@ -9,6 +9,8 @@
 
 #include "include/core/SkAlphaType.h"
 #include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColor.h"
 #include "include/core/SkColorSpace.h"
 #include "include/core/SkImage.h"
 #include "include/core/SkImageInfo.h"
@@ -16,6 +18,7 @@
 #include "include/core/SkRect.h"
 #include "include/core/SkSamplingOptions.h"
 #include "include/core/SkSize.h"
+#include "include/core/SkSurface.h"
 #include "include/core/SkTypes.h"
 #include "include/core/SkYUVAInfo.h"
 #include "include/core/SkYUVAPixmaps.h"
@@ -53,6 +56,7 @@
 #include "src/gpu/ganesh/image/SkImage_RasterPinnable.h"
 #include "src/image/SkImage_Base.h"
 #include "src/image/SkImage_Lazy.h"
+#include "src/image/SkImage_Picture.h"
 #include "src/image/SkImage_Raster.h"
 
 #include <string_view>
@@ -219,6 +223,41 @@
     return sfc->readSurfaceView();
 }
 
+static GrSurfaceProxyView generate_picture_texture(GrRecordingContext* ctx,
+                                                   const SkImage_Picture* img,
+                                                   GrMipmapped mipmapped,
+                                                   GrImageTexGenPolicy texGenPolicy) {
+    SkASSERT(ctx);
+    SkASSERT(img);
+
+    auto sharedGenerator = img->generator();
+    SkAutoMutexExclusive mutex(sharedGenerator->fMutex);
+
+    skgpu::Budgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
+                                       ? skgpu::Budgeted::kNo
+                                       : skgpu::Budgeted::kYes;
+    auto surface = SkSurface::MakeRenderTarget(ctx, budgeted, img->imageInfo(), 0,
+                                               kTopLeft_GrSurfaceOrigin,
+                                               img->props(), mipmapped == GrMipmapped::kYes);
+    if (!surface) {
+        return {};
+    }
+
+    surface->getCanvas()->clear(SkColors::kTransparent);
+    surface->getCanvas()->drawPicture(img->picture(), img->matrix(), img->paint());
+    sk_sp<SkImage> image(surface->makeImageSnapshot());
+    if (!image) {
+        return {};
+    }
+
+    auto [view, ct] = AsView(ctx, image, mipmapped);
+    SkASSERT(view);
+    SkASSERT(mipmapped == GrMipmapped::kNo ||
+             view.asTextureProxy()->mipmapped() == GrMipmapped::kYes);
+    return view;
+}
+
+
 // Returns the texture proxy. We will always cache the generated texture on success.
 // We have 4 ways to try to return a texture (in sorted order)
 //
@@ -292,7 +331,15 @@
 
     // 2. Ask the generator to natively create one (if it knows how)
     {
-        if (img->generator()->isTextureGenerator()) {
+        if (img->type() == SkImage_Base::Type::kLazyPicture) {
+            if (auto view = generate_picture_texture(rContext,
+                                                     static_cast<const SkImage_Picture*>(img),
+                                                     mipmapped,
+                                                     texGenPolicy)) {
+                installKey(view);
+                return view;
+            }
+        } else if (img->generator()->isTextureGenerator()) {
             auto sharedGenerator = img->generator();
             SkAutoMutexExclusive mutex(sharedGenerator->fMutex);
             auto textureGen = static_cast<GrTextureGenerator*>(sharedGenerator->fGenerator.get());
diff --git a/src/image/BUILD.bazel b/src/image/BUILD.bazel
index 93dcad9..7e29553 100644
--- a/src/image/BUILD.bazel
+++ b/src/image/BUILD.bazel
@@ -12,9 +12,13 @@
     "SkImage_Lazy.cpp",
     "SkImage_Lazy.h",
     "SkImage_LazyFactories.cpp",
+    "SkImage_Picture.cpp",
+    "SkImage_Picture.h",
     "SkImage_Raster.cpp",
     "SkImage_Raster.h",
     "SkImage_RasterFactories.cpp",
+    "SkPictureImageGenerator.cpp",
+    "SkPictureImageGenerator.h",
     "SkRescaleAndReadPixels.cpp",
     "SkRescaleAndReadPixels.h",
     "SkSurface.cpp",
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index ee231e4..5c37cc3 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -312,10 +312,6 @@
     return result->asImage();
 }
 
-bool SkImage::isLazyGenerated() const {
-    return as_IB(this)->onIsLazyGenerated();
-}
-
 bool SkImage::isAlphaOnly() const { return SkColorTypeIsAlphaOnly(fInfo.colorType()); }
 
 sk_sp<SkImage> SkImage::makeColorSpace(sk_sp<SkColorSpace> target, GrDirectContext* direct) const {
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index 923cd0a..b94ed99 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -129,6 +129,7 @@
         kRaster,
         kRasterPinnable,
         kLazy,
+        kLazyPicture,
         kGanesh,
         kGaneshYUVA,
         kGraphite,
@@ -138,7 +139,9 @@
     virtual Type type() const = 0;
 
     // True for picture-backed and codec-backed
-    bool onIsLazyGenerated() const { return this->type() == Type::kLazy; }
+    bool isLazyGenerated() const override {
+        return this->type() == Type::kLazy || this->type() == Type::kLazyPicture;
+    }
 
     bool isRasterBacked() const {
         return this->type() == Type::kRaster || this->type() == Type::kRasterPinnable;
diff --git a/src/image/SkImage_Lazy.h b/src/image/SkImage_Lazy.h
index 4ae2e67..561e98e 100644
--- a/src/image/SkImage_Lazy.h
+++ b/src/image/SkImage_Lazy.h
@@ -83,7 +83,6 @@
 
     // Be careful with this. You need to acquire the mutex, as the generator might be shared
     // among several images.
-    //std::unique_ptr<SkImageGenerator> generator() const;
     sk_sp<SharedGenerator> generator() const;
 protected:
     virtual bool readPixelsProxy(GrDirectContext*, const SkPixmap&) const { return false; }
diff --git a/src/image/SkImage_LazyFactories.cpp b/src/image/SkImage_LazyFactories.cpp
index bbb4fcf..526e9c8 100644
--- a/src/image/SkImage_LazyFactories.cpp
+++ b/src/image/SkImage_LazyFactories.cpp
@@ -12,8 +12,7 @@
 #include "include/core/SkPicture.h"
 #include "include/core/SkRefCnt.h"
 #include "include/core/SkSurfaceProps.h"
-
-#include "src/image/SkImageGeneratorPriv.h"
+#include "src/image/SkImage_Picture.h"
 
 #include <optional>
 #include <utility>
@@ -39,8 +38,8 @@
                                    const SkPaint* paint,
                                    BitDepth bitDepth,
                                    sk_sp<SkColorSpace> colorSpace) {
-    return DeferredFromPicture(std::move(picture), dimensions, matrix, paint, bitDepth,
-                               std::move(colorSpace), {});
+    return SkImage_Picture::Make(std::move(picture), dimensions, matrix, paint, bitDepth,
+                                 std::move(colorSpace), {});
 }
 
 sk_sp<SkImage> DeferredFromPicture(sk_sp<SkPicture> picture,
@@ -50,8 +49,8 @@
                                    BitDepth bitDepth,
                                    sk_sp<SkColorSpace> colorSpace,
                                    SkSurfaceProps props) {
-    return DeferredFromGenerator(SkImageGenerators::MakeFromPicture(
-            dimensions, std::move(picture), matrix, paint, bitDepth, std::move(colorSpace), props));
+    return SkImage_Picture::Make(std::move(picture), dimensions, matrix, paint, bitDepth,
+                                 std::move(colorSpace), props);
 }
 
 }  // namespace SkImages
diff --git a/src/image/SkImage_Picture.cpp b/src/image/SkImage_Picture.cpp
new file mode 100644
index 0000000..5c80bb4
--- /dev/null
+++ b/src/image/SkImage_Picture.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/image/SkImage_Picture.h"
+
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkImageGenerator.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkSurfaceProps.h"
+#include "src/base/SkTLazy.h"
+#include "src/image/SkImageGeneratorPriv.h"
+#include "src/image/SkImage_Lazy.h"
+#include "src/image/SkPictureImageGenerator.h"
+
+#include <memory>
+#include <utility>
+
+class SkMatrix;
+class SkPaint;
+struct SkISize;
+
+sk_sp<SkImage> SkImage_Picture::Make(sk_sp<SkPicture> picture, const SkISize& dimensions,
+                                     const SkMatrix* matrix, const SkPaint* paint,
+                                     SkImages::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace,
+                                     SkSurfaceProps props) {
+    auto gen = SkImageGenerators::MakeFromPicture(dimensions, std::move(picture), matrix, paint,
+                                                  bitDepth, std::move(colorSpace), props);
+
+    SkImage_Lazy::Validator validator(
+            SharedGenerator::Make(std::move(gen)), nullptr, nullptr);
+
+    return validator ? sk_make_sp<SkImage_Picture>(&validator) : nullptr;
+}
+
+SkPictureImageGenerator* SkImage_Picture::gen() const {
+    return static_cast<SkPictureImageGenerator*>(this->generator()->fGenerator.get());
+}
+
+SkPicture* SkImage_Picture::picture() const {
+    return this->gen()->fPicture.get();
+}
+
+SkMatrix* SkImage_Picture::matrix() const {
+    return &this->gen()->fMatrix;
+}
+
+SkPaint* SkImage_Picture::paint() const {
+    return this->gen()->fPaint.getMaybeNull();
+}
+
+SkSurfaceProps* SkImage_Picture::props() const {
+    return &this->gen()->fProps;
+}
diff --git a/src/image/SkImage_Picture.h b/src/image/SkImage_Picture.h
new file mode 100644
index 0000000..cb2eefe
--- /dev/null
+++ b/src/image/SkImage_Picture.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkImage_Picture_DEFINED
+#define SkImage_Picture_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "src/image/SkImage_Base.h"
+#include "src/image/SkImage_Lazy.h"
+
+class SkColorSpace;
+class SkImage;
+class SkMatrix;
+class SkPaint;
+class SkPicture;
+class SkPictureImageGenerator;
+class SkSurfaceProps;
+struct SkISize;
+
+namespace SkImages { enum class BitDepth; }
+
+class SkImage_Picture : public SkImage_Lazy {
+public:
+    static sk_sp<SkImage> Make(sk_sp<SkPicture> picture, const SkISize& dimensions,
+                               const SkMatrix* matrix, const SkPaint* paint,
+                               SkImages::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace,
+                               SkSurfaceProps props);
+
+    SkImage_Picture(Validator* validator) : SkImage_Lazy(validator) {}
+
+     SkImage_Base::Type type() const override { return SkImage_Base::Type::kLazyPicture; }
+
+     // These are not necessarily thread-safe. Be sure to grab the mutex from the shared
+     // generator before accessing them.
+     SkPicture* picture() const;
+     SkMatrix* matrix() const;
+     SkPaint* paint() const;
+     SkSurfaceProps* props() const;
+
+private:
+    SkPictureImageGenerator* gen() const;
+};
+
+#endif
diff --git a/src/image/SkPictureImageGenerator.cpp b/src/image/SkPictureImageGenerator.cpp
new file mode 100644
index 0000000..864fad9
--- /dev/null
+++ b/src/image/SkPictureImageGenerator.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/image/SkPictureImageGenerator.h"
+
+#include "include/core/SkAlphaType.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkColorType.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkImageGenerator.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkSize.h"
+#include "src/base/SkTLazy.h"
+#include "src/image/SkImageGeneratorPriv.h"
+
+#include <memory>
+#include <utility>
+
+namespace SkImageGenerators {
+std::unique_ptr<SkImageGenerator> MakeFromPicture(
+        const SkISize& size,
+        sk_sp<SkPicture> picture,
+        const SkMatrix* matrix,
+        const SkPaint* paint,
+        SkImages::BitDepth bitDepth,
+        sk_sp<SkColorSpace> colorSpace) {
+    return MakeFromPicture(size, picture, matrix, paint, bitDepth, colorSpace, {});
+}
+
+std::unique_ptr<SkImageGenerator> MakeFromPicture(const SkISize& size,
+                                                  sk_sp<SkPicture> picture,
+                                                  const SkMatrix* matrix,
+                                                  const SkPaint* paint,
+                                                  SkImages::BitDepth bitDepth,
+                                                  sk_sp<SkColorSpace> colorSpace,
+                                                  SkSurfaceProps props) {
+    if (!picture || !colorSpace || size.isEmpty()) {
+        return nullptr;
+    }
+
+    SkColorType colorType = kN32_SkColorType;
+    if (SkImages::BitDepth::kF16 == bitDepth) {
+        colorType = kRGBA_F16_SkColorType;
+    }
+
+    SkImageInfo info =
+            SkImageInfo::Make(size, colorType, kPremul_SkAlphaType, std::move(colorSpace));
+    return std::unique_ptr<SkImageGenerator>(
+        new SkPictureImageGenerator(info, std::move(picture), matrix, paint, props));
+}
+} // SkImageGenerators
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture> picture,
+                                                 const SkMatrix* matrix, const SkPaint* paint,
+                                                 const SkSurfaceProps& props)
+        : SkImageGenerator(info)
+        , fPicture(std::move(picture))
+        , fProps(props) {
+
+    if (matrix) {
+        fMatrix = *matrix;
+    } else {
+        fMatrix.reset();
+    }
+
+    if (paint) {
+        fPaint.set(*paint);
+    }
+}
+
+bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+                                          const Options& opts) {
+    std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, rowBytes, &fProps);
+    if (!canvas) {
+        return false;
+    }
+    canvas->clear(0);
+    canvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
+    return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if defined(SK_GRAPHITE)
+#include "include/core/SkSurface.h"
+#include "src/gpu/graphite/Log.h"
+
+sk_sp<SkImage> SkPictureImageGenerator::onMakeTextureImage(skgpu::graphite::Recorder* recorder,
+                                                           const SkImageInfo& info,
+                                                           skgpu::Mipmapped mipmapped) {
+    using namespace skgpu::graphite;
+
+    sk_sp<SkSurface> surface = SkSurface::MakeGraphite(recorder, info, mipmapped);
+    if (!surface) {
+        SKGPU_LOG_E("Failed to create Surface");
+        return nullptr;
+    }
+
+    surface->getCanvas()->clear(SkColors::kTransparent);
+    surface->getCanvas()->drawPicture(fPicture.get(), &fMatrix, fPaint.getMaybeNull());
+    return surface->asImage();
+}
+
+#endif // SK_GRAPHITE
diff --git a/src/image/SkPictureImageGenerator.h b/src/image/SkPictureImageGenerator.h
new file mode 100644
index 0000000..6f5e7c0
--- /dev/null
+++ b/src/image/SkPictureImageGenerator.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPictureImageGenerator_DEFINED
+#define SkPictureImageGenerator_DEFINED
+
+#include "include/core/SkImageGenerator.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurfaceProps.h"
+#include "src/base/SkTLazy.h"
+
+#include <cstddef>
+
+struct SkImageInfo;
+
+class SkPictureImageGenerator : public SkImageGenerator {
+public:
+    SkPictureImageGenerator(const SkImageInfo&, sk_sp<SkPicture>, const SkMatrix*,
+                            const SkPaint*, const SkSurfaceProps&);
+
+protected:
+    bool onGetPixels(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&) override;
+
+#if defined(SK_GRAPHITE)
+    sk_sp<SkImage> onMakeTextureImage(skgpu::graphite::Recorder*,
+                                      const SkImageInfo&,
+                                      skgpu::Mipmapped) override;
+#endif
+
+private:
+    sk_sp<SkPicture> fPicture;
+    SkMatrix         fMatrix;
+    SkTLazy<SkPaint> fPaint;
+    SkSurfaceProps   fProps;
+
+    friend class SkImage_Picture;
+};
+
+#endif