/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSurface.h"
#include "include/core/SkYUVAInfo.h"
#include "include/core/SkYUVAPixmaps.h"
#include "include/effects/SkGradientShader.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "src/base/SkScopeExit.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "tools/DecodeUtils.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
#include "tools/gpu/YUVUtils.h"

#if defined(SK_GRAPHITE)
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Image.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "tools/graphite/GraphiteTestContext.h"
#endif

#include <variant>

namespace {
/// We test reading from images and surfaces
enum class ReadSource {
    kImage,
    kSurface,
};

// We test reading to RGBA, YUV, and YUVA
enum class Type {
    kRGBA,
    kYUV,
    kYUVA
};

template <ReadSource> struct SourceS;
template <> struct SourceS<ReadSource::kImage>   { using Type = SkImage;   };
template <> struct SourceS<ReadSource::kSurface> { using Type = SkSurface; };

template <ReadSource RS> using Source = typename SourceS<RS>::Type;

// Converts a source image to either an SkImage or SkSurface, backed by GPU if canvas is. Returns
// kSkip or kFail if the image cannot be converted.
template <ReadSource RS>
std::variant<sk_sp<Source<RS>>, skiagm::DrawResult> convert_image_to_source(SkCanvas* canvas,
                                                                            sk_sp<SkImage> image,
                                                                            SkString* errorMsg);

template <>
std::variant<sk_sp<SkImage>, skiagm::DrawResult> convert_image_to_source<ReadSource::kImage>(
        SkCanvas* canvas,
        sk_sp<SkImage> image,
        SkString* errorMsg) {
#if defined(SK_GRAPHITE)
    if (auto recorder = canvas->recorder()) {
        image = SkImages::TextureFromImage(recorder, image);
        if (image) {
            return image;
        }
        *errorMsg = "Could not create Graphite image";
        return skiagm::DrawResult::kFail;
    }
#endif
    auto dContext = GrAsDirectContext(canvas->recordingContext());
    if (!dContext && canvas->recordingContext()) {
        *errorMsg = "Not supported in DDL mode";
        return skiagm::DrawResult::kSkip;
    }
    if (dContext) {
        image = SkImages::TextureFromImage(dContext, image);
        if (image) {
            return image;
        }
        // When testing abandoned GrContext we expect surface creation to fail.
        if (dContext && dContext->abandoned()) {
            return skiagm::DrawResult::kSkip;
        }
        *errorMsg = "Could not create Ganesh image";
        return skiagm::DrawResult::kFail;
    }
    return image;
}

template <>
std::variant<sk_sp<SkSurface>, skiagm::DrawResult> convert_image_to_source<ReadSource::kSurface>(
        SkCanvas* canvas,
        sk_sp<SkImage> image,
        SkString* errorMsg) {
    // Turn the image into a surface in order to call the read and rescale API
    auto surfInfo = image->imageInfo().makeDimensions(image->dimensions());
    auto surface = canvas->makeSurface(surfInfo);
    if (!surface && surfInfo.colorType() == kBGRA_8888_SkColorType) {
        surfInfo = surfInfo.makeColorType(kRGBA_8888_SkColorType);
        surface = canvas->makeSurface(surfInfo);
    }
    if (!surface) {
        *errorMsg = "Could not create surface for image.";
        // When testing abandoned GrContext we expect surface creation to fail.
        if (canvas->recordingContext() && canvas->recordingContext()->abandoned()) {
            return skiagm::DrawResult::kSkip;
        }
        return skiagm::DrawResult::kFail;
    }
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);
    surface->getCanvas()->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
    return surface;
}

class AsyncReadGMBase : public skiagm::GM {
public:
    AsyncReadGMBase(const char* name) : fName(name) {}

    SkString getName() const override { return fName; }

protected:
    // Does a rescale and read using Graphite, Ganesh, or CPU and returns the result as a pixmap
    // image.
    template <ReadSource ReadSource>
    sk_sp<SkImage> readAndScaleRGBA(Source<ReadSource>* src,
                                    SkIRect srcRect,
                                    GrDirectContext* direct,
                                    skgpu::graphite::Recorder* recorder,
                                    const SkImageInfo& ii,
                                    SkImage::RescaleGamma rescaleGamma,
                                    SkImage::RescaleMode rescaleMode) {
        auto* asyncContext = new AsyncContext();
        if (recorder) {
#if defined(SK_GRAPHITE)
            skgpu::graphite::Context* graphiteContext = recorder->priv().context();
            if (!graphiteContext) {
                return nullptr;
            }
            // We need to flush the existing drawing commands before we try to read
            std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
            if (!recording) {
                return nullptr;
            }
            skgpu::graphite::InsertRecordingInfo recordingInfo;
            recordingInfo.fRecording = recording.get();
            if (!graphiteContext->insertRecording(recordingInfo)) {
                return nullptr;
            }

            graphiteContext->asyncRescaleAndReadPixels(src,
                                                       ii,
                                                       srcRect,
                                                       rescaleGamma,
                                                       rescaleMode,
                                                       AsyncCallback,
                                                       asyncContext);
            graphiteContext->submit();
            while (!asyncContext->fCalled) {
                graphiteContext->checkAsyncWorkCompletion();
                if (this->graphiteTestContext()) {
                    this->graphiteTestContext()->tick();
                }
            }
#endif
        } else {
            src->asyncRescaleAndReadPixels(ii,
                                           srcRect,
                                           rescaleGamma,
                                           rescaleMode,
                                           AsyncCallback,
                                           asyncContext);
            if (direct) {
                direct->submit();
            }
            while (!asyncContext->fCalled) {
                // Only GPU should actually be asynchronous.
                SkASSERT(direct);
                direct->checkAsyncWorkCompletion();
            }
        }
        if (!asyncContext->fResult) {
            return nullptr;
        }
        SkPixmap pixmap(ii, asyncContext->fResult->data(0), asyncContext->fResult->rowBytes(0));
        auto releasePixels = [](const void*, void* c) { delete static_cast<AsyncContext*>(c); };
        return SkImages::RasterFromPixmap(pixmap, releasePixels, asyncContext);
    }

    // Does a YUV[A] rescale and read using Graphite or Ganesh (no CPU support) and returns the
    // result as a YUVA planar texture image.
    template <ReadSource ReadSource>
    sk_sp<SkImage> readAndScaleYUVA(Source<ReadSource>* src,
                                    SkIRect srcRect,
                                    SkISize resultSize,
                                    bool readAlpha,
                                    GrDirectContext* direct,
                                    skgpu::graphite::Recorder* recorder,
                                    SkYUVColorSpace yuvCS,
                                    SkImage::RescaleGamma rescaleGamma,
                                    SkImage::RescaleMode rescaleMode,
                                    SkScopeExit* cleanup) {
        SkASSERT(!(resultSize.width() & 0b1) && !(resultSize.height() & 0b1));

        SkISize uvSize = {resultSize.width() / 2, resultSize.height() / 2};
        SkImageInfo yaII = SkImageInfo::Make(resultSize, kGray_8_SkColorType, kPremul_SkAlphaType);
        SkImageInfo uvII = SkImageInfo::Make(uvSize,     kGray_8_SkColorType, kPremul_SkAlphaType);

        AsyncContext asyncContext;
        if (recorder) {
#if defined(SK_GRAPHITE)
            skgpu::graphite::Context* graphiteContext = recorder->priv().context();
            if (!graphiteContext) {
                return nullptr;
            }
            // We need to flush the existing drawing commands before we try to read
            std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
            if (!recording) {
                return nullptr;
            }
            skgpu::graphite::InsertRecordingInfo recordingInfo;
            recordingInfo.fRecording = recording.get();
            if (!graphiteContext->insertRecording(recordingInfo)) {
                return nullptr;
            }

            if (readAlpha) {
                graphiteContext->asyncRescaleAndReadPixelsYUVA420(src,
                                                                  yuvCS,
                                                                  SkColorSpace::MakeSRGB(),
                                                                  srcRect,
                                                                  resultSize,
                                                                  rescaleGamma,
                                                                  rescaleMode,
                                                                  AsyncCallback,
                                                                  &asyncContext);
            } else {
                graphiteContext->asyncRescaleAndReadPixelsYUV420(src,
                                                                 yuvCS,
                                                                 SkColorSpace::MakeSRGB(),
                                                                 srcRect,
                                                                 resultSize,
                                                                 rescaleGamma,
                                                                 rescaleMode,
                                                                 AsyncCallback,
                                                                 &asyncContext);
            }
            graphiteContext->submit();
            while (!asyncContext.fCalled) {
                graphiteContext->checkAsyncWorkCompletion();
                if (this->graphiteTestContext()) {
                    this->graphiteTestContext()->tick();
                }
            }
#endif
        } else {
            if (readAlpha) {
                src->asyncRescaleAndReadPixelsYUVA420(yuvCS,
                                                      SkColorSpace::MakeSRGB(),
                                                      srcRect,
                                                      resultSize,
                                                      rescaleGamma,
                                                      rescaleMode,
                                                      AsyncCallback,
                                                      &asyncContext);
            } else {
                src->asyncRescaleAndReadPixelsYUV420(yuvCS,
                                                     SkColorSpace::MakeSRGB(),
                                                     srcRect,
                                                     resultSize,
                                                     rescaleGamma,
                                                     rescaleMode,
                                                     AsyncCallback,
                                                     &asyncContext);
            }
            if (direct) {
                direct->submit();
            }
            while (!asyncContext.fCalled) {
                // Only GPU should actually be asynchronous.
                SkASSERT(direct);
                direct->checkAsyncWorkCompletion();
            }
        }
        if (!asyncContext.fResult) {
            return nullptr;
        }
        auto planeConfig = readAlpha ? SkYUVAInfo::PlaneConfig::kY_U_V_A :
                                       SkYUVAInfo::PlaneConfig::kY_U_V;
        SkYUVAInfo yuvaInfo(resultSize,
                            planeConfig,
                            SkYUVAInfo::Subsampling::k420,
                            yuvCS);
        SkPixmap yuvPMs[4] = {
                {yaII, asyncContext.fResult->data(0), asyncContext.fResult->rowBytes(0)},
                {uvII, asyncContext.fResult->data(1), asyncContext.fResult->rowBytes(1)},
                {uvII, asyncContext.fResult->data(2), asyncContext.fResult->rowBytes(2)},
                {},
        };
        if (readAlpha) {
            yuvPMs[3] = {yaII, asyncContext.fResult->data(3), asyncContext.fResult->rowBytes(3)};
        }
        auto pixmaps = SkYUVAPixmaps::FromExternalPixmaps(yuvaInfo, yuvPMs);
        SkASSERT(pixmaps.isValid());
        auto lazyYUVImage = sk_gpu_test::LazyYUVImage::Make(pixmaps);
        SkASSERT(lazyYUVImage);
#if defined(SK_GRAPHITE)
        if (recorder) {
            return lazyYUVImage->refImage(recorder, sk_gpu_test::LazyYUVImage::Type::kFromTextures);
        } else
#endif
        {
            return lazyYUVImage->refImage(direct, sk_gpu_test::LazyYUVImage::Type::kFromTextures);
        }
    }

    // Draws a 3x2 grid of rescales. The columns are none, low, and high filter quality. The rows
    // are rescale in src gamma and rescale in linear gamma.
    template <ReadSource ReadSource>
    skiagm::DrawResult drawRescaleGrid(SkCanvas* canvas,
                                       Source<ReadSource>* src,
                                       SkIRect srcRect,
                                       SkISize readSize,
                                       Type type,
                                       SkString* errorMsg,
                                       int pad = 0) {
        SkASSERT(canvas->imageInfo().colorType() != kUnknown_SkColorType);

        auto direct = GrAsDirectContext(canvas->recordingContext());
        auto recorder = canvas->recorder();
        SkASSERT(direct || !canvas->recordingContext());

        SkYUVColorSpace yuvColorSpace = kRec601_SkYUVColorSpace;
        canvas->save();
        for (auto gamma : {SkImage::RescaleGamma::kSrc, SkImage::RescaleGamma::kLinear}) {
            canvas->save();
            for (auto mode : {SkImage::RescaleMode::kNearest,
                              SkImage::RescaleMode::kRepeatedLinear,
                              SkImage::RescaleMode::kRepeatedCubic}) {
                SkScopeExit cleanup;
                sk_sp<SkImage> result;
                switch (type) {
                    case Type::kRGBA: {
                        const auto ii = canvas->imageInfo().makeDimensions(readSize);
                        result = readAndScaleRGBA<ReadSource>(src,
                                                              srcRect,
                                                              direct,
                                                              recorder,
                                                              ii,
                                                              gamma,
                                                              mode);
                        if (!result) {
                            errorMsg->printf("async read call failed.");
                            return skiagm::DrawResult::kFail;
                        }
                        break;
                    }
                    case Type::kYUV:
                    case Type::kYUVA:
                        result = readAndScaleYUVA<ReadSource>(src,
                                                              srcRect,
                                                              readSize,
                                                              /*readAlpha=*/type == Type::kYUVA,
                                                              direct,
                                                              recorder,
                                                              yuvColorSpace,
                                                              gamma,
                                                              mode,
                                                              &cleanup);
                        if (!result) {
                            errorMsg->printf("YUV[A]420 async call failed. Allowed for now.");
                            return skiagm::DrawResult::kSkip;
                        }
                        int nextCS = static_cast<int>(yuvColorSpace + 1) %
                                     (kLastEnum_SkYUVColorSpace + 1);
                        yuvColorSpace = static_cast<SkYUVColorSpace>(nextCS);
                        break;
                }
                canvas->drawImage(result, 0, 0);
                canvas->translate(readSize.width() + pad, 0);
            }
            canvas->restore();
            canvas->translate(0, readSize.height() + pad);
        }
        canvas->restore();
        return skiagm::DrawResult::kOk;
    }

private:
    struct AsyncContext {
        bool fCalled = false;
        std::unique_ptr<const SkImage::AsyncReadResult> fResult;
    };

    // Making this a lambda in the test functions caused:
    //   "error: cannot compile this forwarded non-trivially copyable parameter yet"
    // on x86/Win/Clang bot, referring to 'result'.
    static void AsyncCallback(void* c, std::unique_ptr<const SkImage::AsyncReadResult> result) {
        auto context = static_cast<AsyncContext*>(c);
        context->fResult = std::move(result);
        context->fCalled = true;
    }

    SkString fName;
};

template <ReadSource ReadSource, Type Type>
class AsyncRescaleAndReadGridGM : public AsyncReadGMBase {
public:
    AsyncRescaleAndReadGridGM(const char* name,
                              const char* imageFile,
                              SkIRect srcRect,
                              SkISize readSize)
            : AsyncReadGMBase(name)
            , fImageFile(imageFile)
            , fSrcRect(srcRect)
            , fReadSize(readSize) {}

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        ToolUtils::draw_checkerboard(canvas, SK_ColorDKGRAY, SK_ColorLTGRAY, 25);
        auto image = ToolUtils::GetResourceAsImage(fImageFile.c_str());
        if (!image) {
            errorMsg->printf("Could not load image file %s.", fImageFile.c_str());
            return skiagm::DrawResult::kFail;
        }
        if (canvas->imageInfo().colorType() == kUnknown_SkColorType) {
            *errorMsg = "Not supported on recording/vector backends.";
            return skiagm::DrawResult::kSkip;
        }

        auto sourceOrResult = convert_image_to_source<ReadSource>(canvas, image, errorMsg);
        if (auto dr = std::get_if<skiagm::DrawResult>(&sourceOrResult)) {
            return *dr;
        }

        using Src = sk_sp<Source<ReadSource>>;
        return drawRescaleGrid<ReadSource>(canvas,
                                           std::get<Src>(sourceOrResult).get(),
                                           fSrcRect,
                                           fReadSize,
                                           Type,
                                           errorMsg);
    }

    SkISize getISize() override { return {3 * fReadSize.width(), 2 * fReadSize.height()}; }

private:
    SkString fImageFile;
    SkIRect fSrcRect;
    SkISize fReadSize;
};
}  // anonymous namespace

#define DEF_RESCALE_AND_READ_GRID_GM(IMAGE_FILE, TAG, SRC_RECT, W, H, SOURCE, TYPE) \
    DEF_GM(return new (AsyncRescaleAndReadGridGM<SOURCE, TYPE>)(                    \
                          "async_rescale_and_read_" #TAG, #IMAGE_FILE, SRC_RECT, SkISize{W, H});)

DEF_RESCALE_AND_READ_GRID_GM(images/yellow_rose.webp,
                             yuv420_rose,
                             SkIRect::MakeXYWH(50, 5, 200, 150),
                             410,
                             376,
                             ReadSource::kSurface,
                             Type::kYUVA)

DEF_RESCALE_AND_READ_GRID_GM(images/yellow_rose.webp,
                             yuv420_rose_down,
                             SkIRect::MakeXYWH(50, 5, 200, 150),
                             106,
                             60,
                             ReadSource::kImage,
                             Type::kYUV)

DEF_RESCALE_AND_READ_GRID_GM(images/yellow_rose.webp,
                             rose,
                             SkIRect::MakeXYWH(100, 20, 100, 100),
                             410,
                             410,
                             ReadSource::kSurface,
                             Type::kRGBA)

DEF_RESCALE_AND_READ_GRID_GM(images/dog.jpg,
                             dog_down,
                             SkIRect::MakeXYWH(0, 10, 180, 150),
                             45,
                             45,
                             ReadSource::kSurface,
                             Type::kRGBA)

DEF_RESCALE_AND_READ_GRID_GM(images/dog.jpg,
                             dog_up,
                             SkIRect::MakeWH(180, 180),
                             800,
                             400,
                             ReadSource::kImage,
                             Type::kRGBA)

DEF_RESCALE_AND_READ_GRID_GM(images/text.png,
                             text_down,
                             SkIRect::MakeWH(637, 105),
                             (int)(0.7 * 637),
                             (int)(0.7 * 105),
                             ReadSource::kImage,
                             Type::kRGBA)

DEF_RESCALE_AND_READ_GRID_GM(images/text.png,
                             text_up,
                             SkIRect::MakeWH(637, 105),
                             (int)(1.2 * 637),
                             (int)(1.2 * 105),
                             ReadSource::kSurface,
                             Type::kRGBA)

DEF_RESCALE_AND_READ_GRID_GM(images/text.png,
                             text_up_large,
                             SkIRect::MakeXYWH(300, 0, 300, 105),
                             (int)(2.4 * 300),
                             (int)(2.4 * 105),
                             ReadSource::kImage,
                             Type::kRGBA)

namespace {
class AyncYUVNoScaleGM : public AsyncReadGMBase {
public:
    AyncYUVNoScaleGM() : AsyncReadGMBase("async_yuv_no_scale") {}
    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        auto surface = canvas->getSurface();
        if (!surface) {
            *errorMsg = "Not supported on recording/vector backends.";
            return skiagm::DrawResult::kSkip;
        }

        auto dContext = GrAsDirectContext(surface->recordingContext());
        if (!dContext && surface->recordingContext()) {
            *errorMsg = "Not supported in DDL mode";
            return skiagm::DrawResult::kSkip;
        }

        auto image = ToolUtils::GetResourceAsImage("images/yellow_rose.webp");
        if (!image) {
            return skiagm::DrawResult::kFail;
        }
        SkPaint paint;
        canvas->drawImage(image.get(), 0, 0);

        skgpu::graphite::Recorder* recorder = canvas->recorder();
        SkScopeExit scopeExit;
        auto yuvImage = readAndScaleYUVA<ReadSource::kSurface>(surface,
                                                               SkIRect::MakeWH(400, 300),
                                                               SkISize{400, 300},
                                                               /*readAlpha=*/false,
                                                               dContext,
                                                               recorder,
                                                               kRec601_SkYUVColorSpace,
                                                               SkImage::RescaleGamma::kSrc,
                                                               SkImage::RescaleMode::kNearest,
                                                               &scopeExit);

        canvas->clear(SK_ColorWHITE);
        canvas->drawImage(yuvImage.get(), 0, 0);

        return skiagm::DrawResult::kOk;
    }
    SkISize getISize() override { return {400, 300}; }
};
}  // namespace

DEF_GM(return new AyncYUVNoScaleGM();)

namespace {
class AsyncRescaleAndReadNoBleedGM : public AsyncReadGMBase {
public:
    AsyncRescaleAndReadNoBleedGM() : AsyncReadGMBase("async_rescale_and_read_no_bleed") {}

    SkISize getISize() override { return {60, 60}; }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        if (canvas->imageInfo().colorType() == kUnknown_SkColorType) {
            *errorMsg = "Not supported on recording/vector backends.";
            return skiagm::DrawResult::kSkip;
        }

        auto dContext = GrAsDirectContext(canvas->recordingContext());
        if (!dContext && canvas->recordingContext()) {
            *errorMsg = "Not supported in DDL mode";
            return skiagm::DrawResult::kSkip;
        }

        static constexpr int kBorder = 5;
        static constexpr int kInner = 5;
        const auto srcRect = SkIRect::MakeXYWH(kBorder, kBorder, kInner, kInner);
        auto surfaceII = SkImageInfo::Make(kInner + 2 * kBorder,
                                           kInner + 2 * kBorder,
                                           kRGBA_8888_SkColorType,
                                           kPremul_SkAlphaType,
                                           SkColorSpace::MakeSRGB());
        auto surface = canvas->makeSurface(surfaceII);
        if (!surface) {
            *errorMsg = "Could not create surface for image.";
            // When testing abandoned GrContext we expect surface creation to fail.
            if (canvas->recordingContext() && canvas->recordingContext()->abandoned()) {
                return skiagm::DrawResult::kSkip;
            }
            return skiagm::DrawResult::kFail;
        }
        surface->getCanvas()->clear(SK_ColorRED);
        surface->getCanvas()->save();
        surface->getCanvas()->clipRect(SkRect::Make(srcRect), SkClipOp::kIntersect, false);
        surface->getCanvas()->clear(SK_ColorBLUE);
        surface->getCanvas()->restore();
        static constexpr int kPad = 2;
        canvas->translate(kPad, kPad);
        skiagm::DrawResult result;
        SkISize downSize = {static_cast<int>(kInner / 2), static_cast<int>(kInner / 2)};
        result = drawRescaleGrid<ReadSource::kSurface>(canvas,
                                                       surface.get(),
                                                       srcRect,
                                                       downSize,
                                                       Type::kRGBA,
                                                       errorMsg,
                                                       kPad);
        if (result != skiagm::DrawResult::kOk) {
            return result;
        }
        canvas->translate(0, 4 * downSize.height());
        SkISize upSize = {static_cast<int>(kInner * 3.5), static_cast<int>(kInner * 4.6)};
        result = drawRescaleGrid<ReadSource::kSurface>(canvas,
                                                       surface.get(),
                                                       srcRect,
                                                       upSize,
                                                       Type::kRGBA,
                                                       errorMsg,
                                                       kPad);
        if (result != skiagm::DrawResult::kOk) {
            return result;
        }
        return skiagm::DrawResult::kOk;
    }
};
}  // namespace

DEF_GM(return new AsyncRescaleAndReadNoBleedGM();)

namespace {
class AsyncRescaleAndReadAlphaTypeGM : public AsyncReadGMBase {
public:
    AsyncRescaleAndReadAlphaTypeGM() : AsyncReadGMBase("async_rescale_and_read_alpha_type") {}

    SkISize getISize() override { return {512, 512}; }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        auto dContext = GrAsDirectContext(canvas->recordingContext());
        if (!dContext && canvas->recordingContext()) {
            *errorMsg = "Not supported in DDL mode";
            return skiagm::DrawResult::kSkip;
        }

        if (canvas->recorder()) {
            *errorMsg = "Reading to unpremul not supported in Graphite.";
            return skiagm::DrawResult::kSkip;
        }

        auto upmII = SkImageInfo::Make(200, 200, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType);

        auto pmII = upmII.makeAlphaType(kPremul_SkAlphaType);

        auto upmSurf = SkSurfaces::Raster(upmII);
        auto pmSurf = SkSurfaces::Raster(pmII);

        SkColor4f colors[] = {
                {.3f, .3f, .3f, .3f},
                {1.f, .2f, .6f, .9f},
                {0.f, .1f, 1.f, .1f},
                {.7f, .8f, .2f, .7f},
        };
        auto shader = SkGradientShader::MakeRadial({100, 100},
                                                   230,
                                                   colors,
                                                   nullptr,
                                                   nullptr,
                                                   std::size(colors),
                                                   SkTileMode::kRepeat);
        SkPaint paint;
        paint.setShader(std::move(shader));

        upmSurf->getCanvas()->drawPaint(paint);
        pmSurf ->getCanvas()->drawPaint(paint);

        auto pmImg  =  pmSurf->makeImageSnapshot();
        auto upmImg = upmSurf->makeImageSnapshot();

        auto imageOrResult = convert_image_to_source<ReadSource::kImage>(canvas,
                                                                         std::move(pmImg),
                                                                         errorMsg);
        if (const auto* dr = std::get_if<skiagm::DrawResult>(&imageOrResult)) {
            return *dr;
        }
        pmImg = std::move(std::get<sk_sp<SkImage>>(imageOrResult));

        imageOrResult = convert_image_to_source<ReadSource::kImage>(canvas,
                                                                    std::move(upmImg),
                                                                    errorMsg);
        if (const auto* dr = std::get_if<skiagm::DrawResult>(&imageOrResult)) {
            return *dr;
        }
        upmImg = std::move(std::get<sk_sp<SkImage>>(imageOrResult));

        int size = 256;

        ToolUtils::draw_checkerboard(canvas, SK_ColorWHITE, SK_ColorBLACK, 32);

        for (const auto& img : {pmImg, upmImg}) {
            canvas->save();
            for (auto readAT : {kPremul_SkAlphaType, kUnpremul_SkAlphaType}) {
                auto readInfo = img->imageInfo().makeAlphaType(readAT).makeWH(size, size);
                auto result =
                        readAndScaleRGBA<ReadSource::kImage>(img.get(),
                                                             SkIRect::MakeSize(img->dimensions()),
                                                             dContext,
                                                             canvas->recorder(),
                                                             readInfo,
                                                             SkImage::RescaleGamma::kSrc,
                                                             SkImage::RescaleMode::kRepeatedCubic);
                if (!result) {
                    *errorMsg = "async readback failed";
                    return skiagm::DrawResult::kFail;
                }
                canvas->drawImage(result, 0, 0);
                canvas->translate(size, 0);
            }
            canvas->restore();
            canvas->translate(0, size);
        }
        return skiagm::DrawResult::kOk;
    }
};
}  // namespace

DEF_GM(return new AsyncRescaleAndReadAlphaTypeGM();)
