/*
 * 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 "dm/DMSrcSink.h"
#include "gm/verifiers/gmverifier.h"
#include "include/codec/SkAndroidCodec.h"
#include "include/codec/SkCodec.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkData.h"
#include "include/core/SkDeferredDisplayListRecorder.h"
#include "include/core/SkDocument.h"
#include "include/core/SkExecutor.h"
#include "include/core/SkImageGenerator.h"
#include "include/core/SkMallocPixelRef.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceCharacterization.h"
#include "include/docs/SkPDFDocument.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/ports/SkImageGeneratorCG.h"
#include "include/ports/SkImageGeneratorNDK.h"
#include "include/ports/SkImageGeneratorWIC.h"
#include "include/private/SkImageInfoPriv.h"
#include "include/private/SkTLogic.h"
#include "include/third_party/skcms/skcms.h"
#include "include/utils/SkNullCanvas.h"
#include "include/utils/SkPaintFilterCanvas.h"
#include "include/utils/SkRandom.h"
#include "modules/skottie/utils/SkottieUtils.h"
#include "src/codec/SkCodecImageGenerator.h"
#include "src/codec/SkSwizzler.h"
#include "src/core/SkAutoMalloc.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkOSFile.h"
#include "src/core/SkOpts.h"
#include "src/core/SkPictureCommon.h"
#include "src/core/SkPictureData.h"
#include "src/core/SkRecordDraw.h"
#include "src/core/SkRecorder.h"
#include "src/core/SkTaskGroup.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/utils/SkMultiPictureDocumentPriv.h"
#include "src/utils/SkOSPath.h"
#include "tools/DDLPromiseImageHelper.h"
#include "tools/DDLTileHelper.h"
#include "tools/Resources.h"
#include "tools/RuntimeBlendUtils.h"
#include "tools/debugger/DebugCanvas.h"
#include "tools/gpu/BackendSurfaceFactory.h"
#include "tools/gpu/MemoryCache.h"
#if defined(SK_BUILD_FOR_WIN)
    #include "include/docs/SkXPSDocument.h"
    #include "src/utils/win/SkAutoCoInitialize.h"
    #include "src/utils/win/SkHRESULT.h"
    #include "src/utils/win/SkTScopedComPtr.h"
    #include <XpsObjectModel.h>
#endif

#if defined(SK_ENABLE_SKOTTIE)
    #include "modules/skottie/include/Skottie.h"
    #include "modules/skresources/include/SkResources.h"
#endif

#if defined(SK_ENABLE_SKRIVE)
    #include "experimental/skrive/include/SkRive.h"
#endif

#if defined(SK_ENABLE_SVG)
    #include "include/svg/SkSVGCanvas.h"
    #include "modules/svg/include/SkSVGDOM.h"
    #include "modules/svg/include/SkSVGNode.h"
    #include "src/xml/SkXMLWriter.h"
#endif

#ifdef SK_GRAPHITE_ENABLED
#include "experimental/graphite/include/Context.h"
#include "experimental/graphite/include/Recorder.h"
#include "experimental/graphite/include/Recording.h"
#include "experimental/graphite/include/SkStuff.h"
// TODO: Remove this src include once we figure out public readPixels call for Graphite.
#include "experimental/graphite/src/Surface_Graphite.h"
#include "tools/graphite/ContextFactory.h"
#include "tools/graphite/GraphiteTestContext.h"
#endif

#if defined(SK_ENABLE_ANDROID_UTILS)
    #include "client_utils/android/BitmapRegionDecoder.h"
#endif
#include "tests/TestUtils.h"

#include <cmath>
#include <functional>

static DEFINE_bool(multiPage, false,
                   "For document-type backends, render the source into multiple pages");
static DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?");

DECLARE_int(gpuThreads);

using sk_gpu_test::GrContextFactory;
using sk_gpu_test::ContextInfo;

namespace DM {

GMSrc::GMSrc(skiagm::GMFactory factory) : fFactory(factory) {}

Result GMSrc::draw(GrDirectContext* context, SkCanvas* canvas) const {
    std::unique_ptr<skiagm::GM> gm(fFactory());
    SkString msg;

    skiagm::DrawResult gpuSetupResult = gm->gpuSetup(context, canvas, &msg);
    switch (gpuSetupResult) {
        case skiagm::DrawResult::kOk  : break;
        case skiagm::DrawResult::kFail: return Result(Result::Status::Fatal, msg);
        case skiagm::DrawResult::kSkip: return Result(Result::Status::Skip,  msg);
        default: SK_ABORT("");
    }

    skiagm::DrawResult drawResult = gm->draw(canvas, &msg);
    switch (drawResult) {
        case skiagm::DrawResult::kOk  : return Result(Result::Status::Ok,    msg);
        case skiagm::DrawResult::kFail: return Result(Result::Status::Fatal, msg);
        case skiagm::DrawResult::kSkip: return Result(Result::Status::Skip,  msg);
        default: SK_ABORT("");
    }

    // Note: we don't call "gpuTeardown" here because, when testing DDL recording, we want
    // the gpu-backed images to live past the lifetime of the GM.
}

SkISize GMSrc::size() const {
    std::unique_ptr<skiagm::GM> gm(fFactory());
    return gm->getISize();
}

Name GMSrc::name() const {
    std::unique_ptr<skiagm::GM> gm(fFactory());
    return gm->getName();
}

void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
    std::unique_ptr<skiagm::GM> gm(fFactory());
    gm->modifyGrContextOptions(options);
}

std::unique_ptr<skiagm::verifiers::VerifierList> GMSrc::getVerifiers() const {
    std::unique_ptr<skiagm::GM> gm(fFactory());
    return gm->getVerifiers();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

static SkString get_scaled_name(const Path& path, float scale) {
    return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
}

#ifdef SK_ENABLE_ANDROID_UTILS
BRDSrc::BRDSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType, uint32_t sampleSize)
    : fPath(path)
    , fMode(mode)
    , fDstColorType(dstColorType)
    , fSampleSize(sampleSize)
{}

bool BRDSrc::veto(SinkFlags flags) const {
    // No need to test to non-raster or indirect backends.
    return flags.type != SinkFlags::kRaster
        || flags.approach != SinkFlags::kDirect;
}

static std::unique_ptr<android::skia::BitmapRegionDecoder> create_brd(Path path) {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
    return android::skia::BitmapRegionDecoder::Make(encoded);
}

static inline void alpha8_to_gray8(SkBitmap* bitmap) {
    // Android requires kGray8 bitmaps to be tagged as kAlpha8.  Here we convert
    // them back to kGray8 so our test framework can draw them correctly.
    if (kAlpha_8_SkColorType == bitmap->info().colorType()) {
        SkImageInfo newInfo = bitmap->info().makeColorType(kGray_8_SkColorType)
                                            .makeAlphaType(kOpaque_SkAlphaType);
        *const_cast<SkImageInfo*>(&bitmap->info()) = newInfo;
    }
}

Result BRDSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    SkColorType colorType = canvas->imageInfo().colorType();
    if (kRGB_565_SkColorType == colorType &&
        CodecSrc::kGetFromCanvas_DstColorType != fDstColorType)
    {
        return Result::Skip("Testing non-565 to 565 is uninteresting.");
    }
    switch (fDstColorType) {
        case CodecSrc::kGetFromCanvas_DstColorType:
            break;
        case CodecSrc::kGrayscale_Always_DstColorType:
            colorType = kGray_8_SkColorType;
            break;
        default:
            SkASSERT(false);
            break;
    }

    auto brd = create_brd(fPath);
    if (nullptr == brd) {
        return Result::Skip("Could not create brd for %s.", fPath.c_str());
    }

    auto recommendedCT = brd->computeOutputColorType(colorType);
    if (kRGB_565_SkColorType == colorType && recommendedCT != colorType) {
        return Result::Skip("Skip decoding non-opaque to 565.");
    }
    colorType = recommendedCT;

    auto colorSpace = brd->computeOutputColorSpace(colorType, nullptr);

    const uint32_t width = brd->width();
    const uint32_t height = brd->height();
    // Visually inspecting very small output images is not necessary.
    if ((width / fSampleSize <= 10 || height / fSampleSize <= 10) && 1 != fSampleSize) {
        return Result::Skip("Scaling very small images is uninteresting.");
    }
    switch (fMode) {
        case kFullImage_Mode: {
            SkBitmap bitmap;
            if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, width, height),
                    fSampleSize, colorType, false, colorSpace)) {
                return Result::Fatal("Cannot decode (full) region.");
            }
            alpha8_to_gray8(&bitmap);

            canvas->drawImage(bitmap.asImage(), 0, 0);
            return Result::Ok();
        }
        case kDivisor_Mode: {
            const uint32_t divisor = 2;
            if (width < divisor || height < divisor) {
                return Result::Skip("Divisor is larger than image dimension.");
            }

            // Use a border to test subsets that extend outside the image.
            // We will not allow the border to be larger than the image dimensions.  Allowing
            // these large borders causes off by one errors that indicate a problem with the
            // test suite, not a problem with the implementation.
            const uint32_t maxBorder = std::min(width, height) / (fSampleSize * divisor);
            const uint32_t scaledBorder = std::min(5u, maxBorder);
            const uint32_t unscaledBorder = scaledBorder * fSampleSize;

            // We may need to clear the canvas to avoid uninitialized memory.
            // Assume we are scaling a 780x780 image with sampleSize = 8.
            // The output image should be 97x97.
            // Each subset will be 390x390.
            // Each scaled subset be 48x48.
            // Four scaled subsets will only fill a 96x96 image.
            // The bottom row and last column will not be touched.
            // This is an unfortunate result of our rounding rules when scaling.
            // Maybe we need to consider testing scaled subsets without trying to
            // combine them to match the full scaled image?  Or maybe this is the
            // best we can do?
            canvas->clear(0);

            for (uint32_t x = 0; x < divisor; x++) {
                for (uint32_t y = 0; y < divisor; y++) {
                    // Calculate the subset dimensions
                    uint32_t subsetWidth = width / divisor;
                    uint32_t subsetHeight = height / divisor;
                    const int left = x * subsetWidth;
                    const int top = y * subsetHeight;

                    // Increase the size of the last subset in each row or column, when the
                    // divisor does not divide evenly into the image dimensions
                    subsetWidth += (x + 1 == divisor) ? (width % divisor) : 0;
                    subsetHeight += (y + 1 == divisor) ? (height % divisor) : 0;

                    // Increase the size of the subset in order to have a border on each side
                    const int decodeLeft = left - unscaledBorder;
                    const int decodeTop = top - unscaledBorder;
                    const uint32_t decodeWidth = subsetWidth + unscaledBorder * 2;
                    const uint32_t decodeHeight = subsetHeight + unscaledBorder * 2;
                    SkBitmap bitmap;
                    if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(decodeLeft,
                            decodeTop, decodeWidth, decodeHeight), fSampleSize, colorType, false,
                            colorSpace)) {
                        return Result::Fatal("Cannot decode region.");
                    }

                    alpha8_to_gray8(&bitmap);
                    canvas->drawImageRect(bitmap.asImage().get(),
                            SkRect::MakeXYWH((SkScalar) scaledBorder, (SkScalar) scaledBorder,
                                    (SkScalar) (subsetWidth / fSampleSize),
                                    (SkScalar) (subsetHeight / fSampleSize)),
                            SkRect::MakeXYWH((SkScalar) (left / fSampleSize),
                                    (SkScalar) (top / fSampleSize),
                                    (SkScalar) (subsetWidth / fSampleSize),
                                    (SkScalar) (subsetHeight / fSampleSize)),
                            SkSamplingOptions(), nullptr,
                            SkCanvas::kStrict_SrcRectConstraint);
                }
            }
            return Result::Ok();
        }
        default:
            SkASSERT(false);
            return Result::Fatal("Error: Should not be reached.");
    }
}

SkISize BRDSrc::size() const {
    auto brd = create_brd(fPath);
    if (brd) {
        return {std::max(1, brd->width() / (int)fSampleSize),
                std::max(1, brd->height() / (int)fSampleSize)};
    }
    return {0, 0};
}

Name BRDSrc::name() const {
    // We will replicate the names used by CodecSrc so that images can
    // be compared in Gold.
    if (1 == fSampleSize) {
        return SkOSPath::Basename(fPath.c_str());
    }
    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
}

#endif // SK_ENABLE_ANDROID_UTILS

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

static bool serial_from_path_name(const SkString& path) {
    if (!FLAGS_RAW_threading) {
        static const char* const exts[] = {
            "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
            "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
        };
        const char* actualExt = strrchr(path.c_str(), '.');
        if (actualExt) {
            actualExt++;
            for (auto* ext : exts) {
                if (0 == strcmp(ext, actualExt)) {
                    return true;
                }
            }
        }
    }
    return false;
}

CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, SkAlphaType dstAlphaType,
                   float scale)
    : fPath(path)
    , fMode(mode)
    , fDstColorType(dstColorType)
    , fDstAlphaType(dstAlphaType)
    , fScale(scale)
    , fRunSerially(serial_from_path_name(path))
{}

bool CodecSrc::veto(SinkFlags flags) const {
    // Test to direct raster backends (8888 and 565).
    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
}

// Allows us to test decodes to non-native 8888.
static void swap_rb_if_necessary(SkBitmap& bitmap, CodecSrc::DstColorType dstColorType) {
    if (CodecSrc::kNonNative8888_Always_DstColorType != dstColorType) {
        return;
    }

    for (int y = 0; y < bitmap.height(); y++) {
        uint32_t* row = (uint32_t*) bitmap.getAddr(0, y);
        SkOpts::RGBA_to_BGRA(row, row, bitmap.width());
    }
}

static bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
                            CodecSrc::DstColorType dstColorType, SkAlphaType dstAlphaType) {
    switch (dstColorType) {
        case CodecSrc::kGrayscale_Always_DstColorType:
            if (kRGB_565_SkColorType == canvasColorType) {
                return false;
            }
            *decodeInfo = decodeInfo->makeColorType(kGray_8_SkColorType);
            break;
        case CodecSrc::kNonNative8888_Always_DstColorType:
            if (kRGB_565_SkColorType == canvasColorType
                    || kRGBA_F16_SkColorType == canvasColorType) {
                return false;
            }
#ifdef SK_PMCOLOR_IS_RGBA
            *decodeInfo = decodeInfo->makeColorType(kBGRA_8888_SkColorType);
#else
            *decodeInfo = decodeInfo->makeColorType(kRGBA_8888_SkColorType);
#endif
            break;
        default:
            if (kRGB_565_SkColorType == canvasColorType &&
                    kOpaque_SkAlphaType != decodeInfo->alphaType()) {
                return false;
            }

            *decodeInfo = decodeInfo->makeColorType(canvasColorType);
            break;
    }

    *decodeInfo = decodeInfo->makeAlphaType(dstAlphaType);
    return true;
}

static void draw_to_canvas(SkCanvas* canvas, const SkImageInfo& info, void* pixels, size_t rowBytes,
                           CodecSrc::DstColorType dstColorType,
                           SkScalar left = 0, SkScalar top = 0) {
    SkBitmap bitmap;
    bitmap.installPixels(info, pixels, rowBytes);
    swap_rb_if_necessary(bitmap, dstColorType);
    canvas->drawImage(bitmap.asImage(), left, top);
}

// For codec srcs, we want the "draw" step to be a memcpy.  Any interesting color space or
// color format conversions should be performed by the codec.  Sometimes the output of the
// decode will be in an interesting color space.  On our srgb and f16 backends, we need to
// "pretend" that the color space is standard sRGB to avoid triggering color conversion
// at draw time.
static void set_bitmap_color_space(SkImageInfo* info) {
    *info = info->makeColorSpace(SkColorSpace::MakeSRGB());
}

Result CodecSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    if (!encoded) {
        return Result::Fatal("Couldn't read %s.", fPath.c_str());
    }

    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
    if (nullptr == codec) {
        return Result::Fatal("Couldn't create codec for %s.", fPath.c_str());
    }

    SkImageInfo decodeInfo = codec->getInfo();
    if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
                         fDstAlphaType)) {
        return Result::Skip("Skipping uninteresting test.");
    }

    // Try to scale the image if it is desired
    SkISize size = codec->getScaledDimensions(fScale);

    std::unique_ptr<SkAndroidCodec> androidCodec;
    if (1.0f != fScale && fMode == kAnimated_Mode) {
        androidCodec = SkAndroidCodec::MakeFromData(encoded);
        size = androidCodec->getSampledDimensions(1 / fScale);
    }

    if (size == decodeInfo.dimensions() && 1.0f != fScale) {
        return Result::Skip("Test without scaling is uninteresting.");
    }

    // Visually inspecting very small output images is not necessary.  We will
    // cover these cases in unit testing.
    if ((size.width() <= 10 || size.height() <= 10) && 1.0f != fScale) {
        return Result::Skip("Scaling very small images is uninteresting.");
    }
    decodeInfo = decodeInfo.makeDimensions(size);

    const int bpp = decodeInfo.bytesPerPixel();
    const size_t rowBytes = size.width() * bpp;
    const size_t safeSize = decodeInfo.computeByteSize(rowBytes);
    SkAutoMalloc pixels(safeSize);

    SkCodec::Options options;
    if (kCodecZeroInit_Mode == fMode) {
        memset(pixels.get(), 0, size.height() * rowBytes);
        options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
    }

    SkImageInfo bitmapInfo = decodeInfo;
    set_bitmap_color_space(&bitmapInfo);
    if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
            kBGRA_8888_SkColorType == decodeInfo.colorType()) {
        bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
    }

    switch (fMode) {
        case kAnimated_Mode: {
            SkAndroidCodec::AndroidOptions androidOptions;
            if (fScale != 1.0f) {
                SkASSERT(androidCodec);
                androidOptions.fSampleSize = 1 / fScale;
                auto dims = androidCodec->getSampledDimensions(androidOptions.fSampleSize);
                decodeInfo = decodeInfo.makeDimensions(dims);
            }

            std::vector<SkCodec::FrameInfo> frameInfos = androidCodec
                    ? androidCodec->codec()->getFrameInfo() : codec->getFrameInfo();
            if (frameInfos.size() <= 1) {
                return Result::Fatal("%s is not an animated image.", fPath.c_str());
            }

            // As in CodecSrc::size(), compute a roughly square grid to draw the frames
            // into. "factor" is the number of frames to draw on one row. There will be
            // up to "factor" rows as well.
            const float root = sqrt((float) frameInfos.size());
            const int factor = sk_float_ceil2int(root);

            // Used to cache a frame that future frames will depend on.
            SkAutoMalloc priorFramePixels;
            int cachedFrame = SkCodec::kNoFrame;
            for (int i = 0; static_cast<size_t>(i) < frameInfos.size(); i++) {
                androidOptions.fFrameIndex = i;
                // Check for a prior frame
                const int reqFrame = frameInfos[i].fRequiredFrame;
                if (reqFrame != SkCodec::kNoFrame && reqFrame == cachedFrame
                        && priorFramePixels.get()) {
                    // Copy into pixels
                    memcpy(pixels.get(), priorFramePixels.get(), safeSize);
                    androidOptions.fPriorFrame = reqFrame;
                } else {
                    androidOptions.fPriorFrame = SkCodec::kNoFrame;
                }
                SkCodec::Result result = androidCodec
                        ? androidCodec->getAndroidPixels(decodeInfo, pixels.get(), rowBytes,
                                                         &androidOptions)
                        : codec->getPixels(decodeInfo, pixels.get(), rowBytes, &androidOptions);
                if (SkCodec::kInvalidInput == result && i > 0) {
                    // Some of our test images have truncated later frames. Treat that
                    // the same as incomplete.
                    result = SkCodec::kIncompleteInput;
                }
                switch (result) {
                    case SkCodec::kSuccess:
                    case SkCodec::kErrorInInput:
                    case SkCodec::kIncompleteInput: {
                        // If the next frame depends on this one, store it in priorFrame.
                        // It is possible that we may discard a frame that future frames depend on,
                        // but the codec will simply redecode the discarded frame.
                        // Do this before calling draw_to_canvas, which premultiplies in place. If
                        // we're decoding to unpremul, we want to pass the unmodified frame to the
                        // codec for decoding the next frame.
                        if (static_cast<size_t>(i+1) < frameInfos.size()
                                && frameInfos[i+1].fRequiredFrame == i) {
                            memcpy(priorFramePixels.reset(safeSize), pixels.get(), safeSize);
                            cachedFrame = i;
                        }

                        SkAutoCanvasRestore acr(canvas, true);
                        const int xTranslate = (i % factor) * decodeInfo.width();
                        const int yTranslate = (i / factor) * decodeInfo.height();
                        canvas->translate(SkIntToScalar(xTranslate), SkIntToScalar(yTranslate));
                        draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
                        if (result != SkCodec::kSuccess) {
                            return Result::Ok();
                        }
                        break;
                    }
                    case SkCodec::kInvalidConversion:
                        if (i > 0 && (decodeInfo.colorType() == kRGB_565_SkColorType)) {
                            return Result::Skip(
                                "Cannot decode frame %i to 565 (%s).", i, fPath.c_str());
                        }
                        [[fallthrough]];
                    default:
                        return Result::Fatal(
                            "Couldn't getPixels for frame %i in %s.", i, fPath.c_str());
                }
            }
            break;
        }
        case kCodecZeroInit_Mode:
        case kCodec_Mode: {
            switch (codec->getPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
                case SkCodec::kSuccess:
                    // We consider these to be valid, since we should still decode what is
                    // available.
                case SkCodec::kErrorInInput:
                case SkCodec::kIncompleteInput:
                    break;
                default:
                    // Everything else is considered a failure.
                    return Result::Fatal("Couldn't getPixels %s.", fPath.c_str());
            }

            draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
            break;
        }
        case kScanline_Mode: {
            void* dst = pixels.get();
            uint32_t height = decodeInfo.height();
            const bool useIncremental = [this]() {
                auto exts = { "png", "PNG", "gif", "GIF" };
                for (auto ext : exts) {
                    if (fPath.endsWith(ext)) {
                        return true;
                    }
                }
                return false;
            }();
            // ico may use the old scanline method or the new one, depending on whether it
            // internally holds a bmp or a png.
            const bool ico = fPath.endsWith("ico");
            bool useOldScanlineMethod = !useIncremental && !ico;
            if (useIncremental || ico) {
                if (SkCodec::kSuccess == codec->startIncrementalDecode(decodeInfo, dst,
                        rowBytes, &options)) {
                    int rowsDecoded;
                    auto result = codec->incrementalDecode(&rowsDecoded);
                    if (SkCodec::kIncompleteInput == result || SkCodec::kErrorInInput == result) {
                        codec->fillIncompleteImage(decodeInfo, dst, rowBytes,
                                                   SkCodec::kNo_ZeroInitialized, height,
                                                   rowsDecoded);
                    }
                } else {
                    if (useIncremental) {
                        // Error: These should support incremental decode.
                        return Result::Fatal("Could not start incremental decode");
                    }
                    // Otherwise, this is an ICO. Since incremental failed, it must contain a BMP,
                    // which should work via startScanlineDecode
                    useOldScanlineMethod = true;
                }
            }

            if (useOldScanlineMethod) {
                if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)) {
                    return Result::Fatal("Could not start scanline decoder");
                }

                // We do not need to check the return value.  On an incomplete
                // image, memory will be filled with a default value.
                codec->getScanlines(dst, height, rowBytes);
            }

            draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, fDstColorType);
            break;
        }
        case kStripe_Mode: {
            const int height = decodeInfo.height();
            // This value is chosen arbitrarily.  We exercise more cases by choosing a value that
            // does not align with image blocks.
            const int stripeHeight = 37;
            const int numStripes = (height + stripeHeight - 1) / stripeHeight;
            void* dst = pixels.get();

            // Decode odd stripes
            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &options)) {
                return Result::Fatal("Could not start scanline decoder");
            }

            // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
            // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
            // to run this test for image types that do not have this scanline ordering.
            // We only run this on Jpeg, which is always kTopDown.
            SkASSERT(SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder());

            for (int i = 0; i < numStripes; i += 2) {
                // Skip a stripe
                const int linesToSkip = std::min(stripeHeight, height - i * stripeHeight);
                codec->skipScanlines(linesToSkip);

                // Read a stripe
                const int startY = (i + 1) * stripeHeight;
                const int linesToRead = std::min(stripeHeight, height - startY);
                if (linesToRead > 0) {
                    codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
                                        rowBytes);
                }
            }

            // Decode even stripes
            const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
            if (SkCodec::kSuccess != startResult) {
                return Result::Fatal("Failed to restart scanline decoder with same parameters.");
            }
            for (int i = 0; i < numStripes; i += 2) {
                // Read a stripe
                const int startY = i * stripeHeight;
                const int linesToRead = std::min(stripeHeight, height - startY);
                codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
                                    rowBytes);

                // Skip a stripe
                const int linesToSkip = std::min(stripeHeight, height - (i + 1) * stripeHeight);
                if (linesToSkip > 0) {
                    codec->skipScanlines(linesToSkip);
                }
            }

            draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, fDstColorType);
            break;
        }
        case kCroppedScanline_Mode: {
            const int width = decodeInfo.width();
            const int height = decodeInfo.height();
            // This value is chosen because, as we move across the image, it will sometimes
            // align with the jpeg block sizes and it will sometimes not.  This allows us
            // to test interestingly different code paths in the implementation.
            const int tileSize = 36;
            SkIRect subset;
            for (int x = 0; x < width; x += tileSize) {
                subset = SkIRect::MakeXYWH(x, 0, std::min(tileSize, width - x), height);
                options.fSubset = &subset;
                if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &options)) {
                    return Result::Fatal("Could not start scanline decoder.");
                }

                codec->getScanlines(SkTAddOffset<void>(pixels.get(), x * bpp), height, rowBytes);
            }

            draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
            break;
        }
        case kSubset_Mode: {
            // Arbitrarily choose a divisor.
            int divisor = 2;
            // Total width/height of the image.
            const int W = codec->getInfo().width();
            const int H = codec->getInfo().height();
            if (divisor > W || divisor > H) {
                return Result::Skip("Cannot codec subset: divisor %d is too big "
                                    "for %s with dimensions (%d x %d)", divisor,
                                    fPath.c_str(), W, H);
            }
            // subset dimensions
            // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
            const int w = SkAlign2(W / divisor);
            const int h = SkAlign2(H / divisor);
            SkIRect subset;
            options.fSubset = &subset;
            SkBitmap subsetBm;
            // We will reuse pixel memory from bitmap.
            void* dst = pixels.get();
            // Keep track of left and top (for drawing subsetBm into canvas). We could use
            // fScale * x and fScale * y, but we want integers such that the next subset will start
            // where the last one ended. So we'll add decodeInfo.width() and height().
            int left = 0;
            for (int x = 0; x < W; x += w) {
                int top = 0;
                for (int y = 0; y < H; y+= h) {
                    // Do not make the subset go off the edge of the image.
                    const int preScaleW = std::min(w, W - x);
                    const int preScaleH = std::min(h, H - y);
                    subset.setXYWH(x, y, preScaleW, preScaleH);
                    // And scale
                    // FIXME: Should we have a version of getScaledDimensions that takes a subset
                    // into account?
                    const int scaledW = std::max(1, SkScalarRoundToInt(preScaleW * fScale));
                    const int scaledH = std::max(1, SkScalarRoundToInt(preScaleH * fScale));
                    decodeInfo = decodeInfo.makeWH(scaledW, scaledH);
                    SkImageInfo subsetBitmapInfo = bitmapInfo.makeWH(scaledW, scaledH);
                    size_t subsetRowBytes = subsetBitmapInfo.minRowBytes();
                    const SkCodec::Result result = codec->getPixels(decodeInfo, dst, subsetRowBytes,
                            &options);
                    switch (result) {
                        case SkCodec::kSuccess:
                        case SkCodec::kErrorInInput:
                        case SkCodec::kIncompleteInput:
                            break;
                        default:
                            return Result::Fatal("subset codec failed to decode (%d, %d, %d, %d) "
                                                 "from %s with dimensions (%d x %d)\t error %d",
                                                 x, y, decodeInfo.width(), decodeInfo.height(),
                                                 fPath.c_str(), W, H, result);
                    }
                    draw_to_canvas(canvas, subsetBitmapInfo, dst, subsetRowBytes, fDstColorType,
                                   SkIntToScalar(left), SkIntToScalar(top));

                    // translate by the scaled height.
                    top += decodeInfo.height();
                }
                // translate by the scaled width.
                left += decodeInfo.width();
            }
            return Result::Ok();
        }
        default:
            SkASSERT(false);
            return Result::Fatal("Invalid fMode");
    }
    return Result::Ok();
}

SkISize CodecSrc::size() const {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
    if (nullptr == codec) {
        return {0, 0};
    }

    if (fMode != kAnimated_Mode) {
        return codec->getScaledDimensions(fScale);
    }

    // We'll draw one of each frame, so make it big enough to hold them all
    // in a grid. The grid will be roughly square, with "factor" frames per
    // row and up to "factor" rows.
    const size_t count = codec->getFrameInfo().size();
    const float root = sqrt((float) count);
    const int factor = sk_float_ceil2int(root);

    auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
    auto imageSize = androidCodec->getSampledDimensions(1 / fScale);
    imageSize.fWidth  = imageSize.fWidth  * factor;
    imageSize.fHeight = imageSize.fHeight * sk_float_ceil2int((float) count / (float) factor);
    return imageSize;
}

Name CodecSrc::name() const {
    Name name = SkOSPath::Basename(fPath.c_str());
    if (fMode == kAnimated_Mode) {
        name.append("_animated");
    }
    if (1.0f == fScale) {
        return name;
    }
    return get_scaled_name(name.c_str(), fScale);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

AndroidCodecSrc::AndroidCodecSrc(Path path, CodecSrc::DstColorType dstColorType,
        SkAlphaType dstAlphaType, int sampleSize)
    : fPath(path)
    , fDstColorType(dstColorType)
    , fDstAlphaType(dstAlphaType)
    , fSampleSize(sampleSize)
    , fRunSerially(serial_from_path_name(path))
{}

bool AndroidCodecSrc::veto(SinkFlags flags) const {
    // No need to test decoding to non-raster or indirect backend.
    return flags.type != SinkFlags::kRaster
        || flags.approach != SinkFlags::kDirect;
}

Result AndroidCodecSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    if (!encoded) {
        return Result::Fatal("Couldn't read %s.", fPath.c_str());
    }
    std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromData(encoded));
    if (nullptr == codec) {
        return Result::Fatal("Couldn't create android codec for %s.", fPath.c_str());
    }

    SkImageInfo decodeInfo = codec->getInfo();
    if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
                         fDstAlphaType)) {
        return Result::Skip("Skipping uninteresting test.");
    }

    // Scale the image if it is desired.
    SkISize size = codec->getSampledDimensions(fSampleSize);

    // Visually inspecting very small output images is not necessary.  We will
    // cover these cases in unit testing.
    if ((size.width() <= 10 || size.height() <= 10) && 1 != fSampleSize) {
        return Result::Skip("Scaling very small images is uninteresting.");
    }
    decodeInfo = decodeInfo.makeDimensions(size);

    int bpp = decodeInfo.bytesPerPixel();
    size_t rowBytes = size.width() * bpp;
    SkAutoMalloc pixels(size.height() * rowBytes);

    SkBitmap bitmap;
    SkImageInfo bitmapInfo = decodeInfo;
    set_bitmap_color_space(&bitmapInfo);
    if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
            kBGRA_8888_SkColorType == decodeInfo.colorType()) {
        bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
    }

    // Create options for the codec.
    SkAndroidCodec::AndroidOptions options;
    options.fSampleSize = fSampleSize;

    switch (codec->getAndroidPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
        case SkCodec::kSuccess:
        case SkCodec::kErrorInInput:
        case SkCodec::kIncompleteInput:
            break;
        default:
            return Result::Fatal("Couldn't getPixels %s.", fPath.c_str());
    }
    draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
    return Result::Ok();
}

SkISize AndroidCodecSrc::size() const {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromData(encoded));
    if (nullptr == codec) {
        return {0, 0};
    }
    return codec->getSampledDimensions(fSampleSize);
}

Name AndroidCodecSrc::name() const {
    // We will replicate the names used by CodecSrc so that images can
    // be compared in Gold.
    if (1 == fSampleSize) {
        return SkOSPath::Basename(fPath.c_str());
    }
    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

ImageGenSrc::ImageGenSrc(Path path, Mode mode, SkAlphaType alphaType, bool isGpu)
    : fPath(path)
    , fMode(mode)
    , fDstAlphaType(alphaType)
    , fIsGpu(isGpu)
    , fRunSerially(serial_from_path_name(path))
{}

bool ImageGenSrc::veto(SinkFlags flags) const {
    if (fIsGpu) {
        // MSAA runs tend to run out of memory and tests the same code paths as regular gpu configs.
        return flags.type != SinkFlags::kGPU || flags.approach != SinkFlags::kDirect ||
               flags.multisampled == SinkFlags::kMultisampled;
    }

    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
}

Result ImageGenSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
        return Result::Skip("Uninteresting to test image generator to 565.");
    }

    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    if (!encoded) {
        return Result::Fatal("Couldn't read %s.", fPath.c_str());
    }

#if defined(SK_BUILD_FOR_WIN)
    // Initialize COM in order to test with WIC.
    SkAutoCoInitialize com;
    if (!com.succeeded()) {
        return Result::Fatal("Could not initialize COM.");
    }
#endif

    std::unique_ptr<SkImageGenerator> gen(nullptr);
    switch (fMode) {
        case kCodec_Mode:
            gen = SkCodecImageGenerator::MakeFromEncodedCodec(encoded);
            if (!gen) {
                return Result::Fatal("Could not create codec image generator.");
            }
            break;
        case kPlatform_Mode: {
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
            gen = SkImageGeneratorCG::MakeFromEncodedCG(encoded);
#elif defined(SK_BUILD_FOR_WIN)
            gen = SkImageGeneratorWIC::MakeFromEncodedWIC(encoded);
#elif defined(SK_ENABLE_NDK_IMAGES)
            gen = SkImageGeneratorNDK::MakeFromEncodedNDK(encoded);
#endif
            if (!gen) {
                return Result::Fatal("Could not create platform image generator.");
            }
            break;
        }
        default:
            SkASSERT(false);
            return Result::Fatal("Invalid image generator mode");
    }

    // Test deferred decoding path on GPU
    if (fIsGpu) {
        sk_sp<SkImage> image(SkImage::MakeFromGenerator(std::move(gen)));
        if (!image) {
            return Result::Fatal("Could not create image from codec image generator.");
        }
        canvas->drawImage(image, 0, 0);
        return Result::Ok();
    }

    // Test various color and alpha types on CPU
    SkImageInfo decodeInfo = gen->getInfo().makeAlphaType(fDstAlphaType);

    int bpp = decodeInfo.bytesPerPixel();
    size_t rowBytes = decodeInfo.width() * bpp;
    SkAutoMalloc pixels(decodeInfo.height() * rowBytes);
    if (!gen->getPixels(decodeInfo, pixels.get(), rowBytes)) {
        Result::Status status = Result::Status::Fatal;
#if defined(SK_BUILD_FOR_WIN)
        if (kPlatform_Mode == fMode) {
            // Do not issue a fatal error for WIC flakiness.
            status = Result::Status::Skip;
        }
#endif
        return Result(status, "Image generator could not getPixels() for %s\n", fPath.c_str());
    }

    set_bitmap_color_space(&decodeInfo);
    draw_to_canvas(canvas, decodeInfo, pixels.get(), rowBytes,
                   CodecSrc::kGetFromCanvas_DstColorType);
    return Result::Ok();
}

SkISize ImageGenSrc::size() const {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
    if (nullptr == codec) {
        return {0, 0};
    }
    return codec->getInfo().dimensions();
}

Name ImageGenSrc::name() const {
    return SkOSPath::Basename(fPath.c_str());
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

ColorCodecSrc::ColorCodecSrc(Path path, bool decode_to_dst) : fPath(path)
                                                            , fDecodeToDst(decode_to_dst) {}

bool ColorCodecSrc::veto(SinkFlags flags) const {
    // Test to direct raster backends (8888 and 565).
    return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
}

Result ColorCodecSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    if (!encoded) {
        return Result::Fatal("Couldn't read %s.", fPath.c_str());
    }

    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
    if (nullptr == codec) {
        return Result::Fatal("Couldn't create codec for %s.", fPath.c_str());
    }

    SkImageInfo info = codec->getInfo();
    if (fDecodeToDst) {
        SkImageInfo canvasInfo = canvas->imageInfo();
        if (!canvasInfo.colorSpace()) {
            // This will skip color conversion, and the resulting images will
            // look different from images they are compared against in Gold, but
            // that doesn't mean they are wrong. We have a test verifying that
            // passing a null SkColorSpace skips conversion, so skip this
            // misleading test.
            return Result::Skip("Skipping decoding without color transform.");
        }
        info = canvasInfo.makeDimensions(info.dimensions());
    }

    auto [image, result] = codec->getImage(info);
    switch (result) {
        case SkCodec::kSuccess:
        case SkCodec::kErrorInInput:
        case SkCodec::kIncompleteInput:
            canvas->drawImage(image, 0,0);
            return Result::Ok();
        case SkCodec::kInvalidConversion:
            // TODO(mtklein): why are there formats we can't decode to?
            return Result::Skip("SkCodec can't decode to this format.");
        default:
            return Result::Fatal("Couldn't getPixels %s. Error code %d", fPath.c_str(), result);
    }
}

SkISize ColorCodecSrc::size() const {
    sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
    if (nullptr == codec) {
        return {0, 0};
    }
    return {codec->getInfo().width(), codec->getInfo().height()};
}

Name ColorCodecSrc::name() const {
    return SkOSPath::Basename(fPath.c_str());
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

static DEFINE_int(skpViewportSize, 1000,
                  "Width & height of the viewport used to crop skp rendering.");

SKPSrc::SKPSrc(Path path) : fPath(path) { }

Result SKPSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(fPath.c_str());
    if (!stream) {
        return Result::Fatal("Couldn't read %s.", fPath.c_str());
    }
    sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
    if (!pic) {
        return Result::Fatal("Couldn't parse file %s.", fPath.c_str());
    }
    stream = nullptr;  // Might as well drop this when we're done with it.
    canvas->clipRect(SkRect::MakeWH(FLAGS_skpViewportSize, FLAGS_skpViewportSize));
    canvas->drawPicture(pic);
    return Result::Ok();
}

static SkRect get_cull_rect_for_skp(const char* path) {
    std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(path);
    if (!stream) {
        return SkRect::MakeEmpty();
    }
    SkPictInfo info;
    if (!SkPicture_StreamIsSKP(stream.get(), &info)) {
        return SkRect::MakeEmpty();
    }

    return info.fCullRect;
}

SkISize SKPSrc::size() const {
    SkRect viewport = get_cull_rect_for_skp(fPath.c_str());
    if (!viewport.intersect((SkRect::MakeWH(FLAGS_skpViewportSize, FLAGS_skpViewportSize)))) {
        return {0, 0};
    }
    return viewport.roundOut().size();
}

Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

BisectSrc::BisectSrc(Path path, const char* trail) : INHERITED(path), fTrail(trail) {}

Result BisectSrc::draw(GrDirectContext* context, SkCanvas* canvas) const {
    struct FoundPath {
        SkPath fPath;
        SkPaint fPaint;
        SkMatrix fViewMatrix;
    };

    // This subclass of SkCanvas just extracts all the SkPaths (drawn via drawPath) from an SKP.
    class PathFindingCanvas : public SkCanvas {
    public:
        PathFindingCanvas(int width, int height) : SkCanvas(width, height, nullptr) {}
        const SkTArray<FoundPath>& foundPaths() const { return fFoundPaths; }

    private:
        void onDrawPath(const SkPath& path, const SkPaint& paint) override {
            fFoundPaths.push_back() = {path, paint, this->getTotalMatrix()};
        }

        SkTArray<FoundPath> fFoundPaths;
    };

    PathFindingCanvas pathFinder(canvas->getBaseLayerSize().width(),
                                 canvas->getBaseLayerSize().height());
    Result result = this->INHERITED::draw(context, &pathFinder);
    if (!result.isOk()) {
        return result;
    }

    int start = 0, end = pathFinder.foundPaths().count();
    for (const char* ch = fTrail.c_str(); *ch; ++ch) {
        int midpt = (start + end) / 2;
        if ('l' == *ch) {
            start = midpt;
        } else if ('r' == *ch) {
            end = midpt;
        }
    }

    for (int i = start; i < end; ++i) {
        const FoundPath& path = pathFinder.foundPaths()[i];
        SkAutoCanvasRestore acr(canvas, true);
        canvas->concat(path.fViewMatrix);
        canvas->drawPath(path.fPath, path.fPaint);
    }

    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

#if defined(SK_ENABLE_SKOTTIE)
static DEFINE_bool(useLottieGlyphPaths, false,
                   "Prioritize embedded glyph paths over native fonts.");

SkottieSrc::SkottieSrc(Path path) : fPath(std::move(path)) {}

Result SkottieSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    auto resource_provider =
            skresources::DataURIResourceProviderProxy::Make(
                skresources::FileResourceProvider::Make(SkOSPath::Dirname(fPath.c_str()),
                                                        /*predecode=*/true),
                /*predecode=*/true);

    static constexpr char kInterceptPrefix[] = "__";
    auto precomp_interceptor =
            sk_make_sp<skottie_utils::ExternalAnimationPrecompInterceptor>(resource_provider,
                                                                           kInterceptPrefix);
    uint32_t flags = 0;
    if (FLAGS_useLottieGlyphPaths) {
        flags |= skottie::Animation::Builder::kPreferEmbeddedFonts;
    }

    auto animation = skottie::Animation::Builder(flags)
        .setResourceProvider(std::move(resource_provider))
        .setPrecompInterceptor(std::move(precomp_interceptor))
        .makeFromFile(fPath.c_str());
    if (!animation) {
        return Result::Fatal("Unable to parse file: %s", fPath.c_str());
    }

    canvas->drawColor(SK_ColorWHITE);

    const auto t_rate = 1.0f / (kTileCount * kTileCount - 1);

    // Draw the frames in a shuffled order to exercise non-linear
    // frame progression. The film strip will still be in order left-to-right,
    // top-down, just not drawn in that order.
    static constexpr int frameOrder[] = { 4, 0, 3, 1, 2 };
    static_assert(SK_ARRAY_COUNT(frameOrder) == kTileCount, "");

    for (int i = 0; i < kTileCount; ++i) {
        const SkScalar y = frameOrder[i] * kTileSize;

        for (int j = 0; j < kTileCount; ++j) {
            const SkScalar x = frameOrder[j] * kTileSize;
            SkRect dest = SkRect::MakeXYWH(x, y, kTileSize, kTileSize);

            const auto t = t_rate * (frameOrder[i] * kTileCount + frameOrder[j]);
            {
                SkAutoCanvasRestore acr(canvas, true);
                canvas->clipRect(dest, true);
                canvas->concat(SkMatrix::RectToRect(SkRect::MakeSize(animation->size()), dest,
                                                    SkMatrix::kCenter_ScaleToFit));
                animation->seek(t);
                animation->render(canvas);
            }
        }
    }

    return Result::Ok();
}

SkISize SkottieSrc::size() const {
    return SkISize::Make(kTargetSize, kTargetSize);
}

Name SkottieSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }

bool SkottieSrc::veto(SinkFlags flags) const {
    // No need to test to non-(raster||gpu||vector) or indirect backends.
    bool type_ok = flags.type == SinkFlags::kRaster
                || flags.type == SinkFlags::kGPU
                || flags.type == SinkFlags::kVector;

    return !type_ok || flags.approach != SinkFlags::kDirect;
}
#endif

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if defined(SK_ENABLE_SKRIVE)
SkRiveSrc::SkRiveSrc(Path path) : fPath(std::move(path)) {}

Result SkRiveSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    auto fileStream = SkFILEStream::Make(fPath.c_str());
    if (!fileStream) {
        return Result::Fatal("Unable to open file: %s", fPath.c_str());
    }

    const auto skrive = skrive::SkRive::Builder().make(std::move(fileStream));
    if (!skrive) {
        return Result::Fatal("Unable to parse file: %s", fPath.c_str());
    }

    auto bounds = SkRect::MakeEmpty();

    for (const auto& ab : skrive->artboards()) {
        const auto& pos  = ab->getTranslation();
        const auto& size = ab->getSize();

        bounds.join(SkRect::MakeXYWH(pos.x, pos.y, size.x, size.y));
    }

    canvas->drawColor(SK_ColorWHITE);

    if (!bounds.isEmpty()) {
        // TODO: tiled frames when we add animation support
        SkAutoCanvasRestore acr(canvas, true);
        canvas->concat(SkMatrix::RectToRect(bounds, SkRect::MakeWH(kTargetSize, kTargetSize),
                                            SkMatrix::kCenter_ScaleToFit));
        for (const auto& ab : skrive->artboards()) {
            ab->render(canvas);
        }
    }

    return Result::Ok();
}

SkISize SkRiveSrc::size() const {
    return SkISize::Make(kTargetSize, kTargetSize);
}

Name SkRiveSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }

bool SkRiveSrc::veto(SinkFlags flags) const {
    // No need to test to non-(raster||gpu||vector) or indirect backends.
    bool type_ok = flags.type == SinkFlags::kRaster
                || flags.type == SinkFlags::kGPU
                || flags.type == SinkFlags::kVector;

    return !type_ok || flags.approach != SinkFlags::kDirect;
}
#endif

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if defined(SK_ENABLE_SVG)
// Used when the image doesn't have an intrinsic size.
static const SkSize kDefaultSVGSize = {1000, 1000};

// Used to force-scale tiny fixed-size images.
static const SkSize kMinimumSVGSize = {128, 128};

SVGSrc::SVGSrc(Path path)
    : fName(SkOSPath::Basename(path.c_str()))
    , fScale(1) {

    auto stream = SkStream::MakeFromFile(path.c_str());
    if (!stream) {
        return;
    }

    auto rp = skresources::DataURIResourceProviderProxy::Make(
                  skresources::FileResourceProvider::Make(SkOSPath::Dirname(path.c_str()),
                                                          /*predecode=*/true),
                  /*predecode=*/true);
    fDom = SkSVGDOM::Builder().setResourceProvider(std::move(rp))
                              .make(*stream);
    if (!fDom) {
        return;
    }

    const SkSize& sz = fDom->containerSize();
    if (sz.isEmpty()) {
        // no intrinsic size
        fDom->setContainerSize(kDefaultSVGSize);
    } else {
        fScale = std::max(1.f, std::max(kMinimumSVGSize.width()  / sz.width(),
                                    kMinimumSVGSize.height() / sz.height()));
    }
}

Result SVGSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
    if (!fDom) {
        return Result::Fatal("Unable to parse file: %s", fName.c_str());
    }

    SkAutoCanvasRestore acr(canvas, true);
    canvas->scale(fScale, fScale);
    canvas->drawColor(SK_ColorWHITE);
    fDom->render(canvas);

    return Result::Ok();
}

SkISize SVGSrc::size() const {
    if (!fDom) {
        return {0, 0};
    }

    return SkSize{fDom->containerSize().width() * fScale, fDom->containerSize().height() * fScale}
            .toRound();
}

Name SVGSrc::name() const { return fName; }

bool SVGSrc::veto(SinkFlags flags) const {
    // No need to test to non-(raster||gpu||vector) or indirect backends.
    bool type_ok = flags.type == SinkFlags::kRaster
                || flags.type == SinkFlags::kGPU
                || flags.type == SinkFlags::kVector;

    return !type_ok || flags.approach != SinkFlags::kDirect;
}

#endif // defined(SK_ENABLE_SVG)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

MSKPSrc::MSKPSrc(Path path) : fPath(path) {
    std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fPath.c_str());
    int count = SkMultiPictureDocumentReadPageCount(stream.get());
    if (count > 0) {
        fPages.reset(count);
        (void)SkMultiPictureDocumentReadPageSizes(stream.get(), &fPages[0], fPages.count());
    }
}

int MSKPSrc::pageCount() const { return fPages.count(); }

SkISize MSKPSrc::size() const { return this->size(0); }
SkISize MSKPSrc::size(int i) const {
    return i >= 0 && i < fPages.count() ? fPages[i].fSize.toCeil() : SkISize{0, 0};
}

Result MSKPSrc::draw(GrDirectContext* context, SkCanvas* c) const {
    return this->draw(0, context, c);
}
Result MSKPSrc::draw(int i, GrDirectContext*, SkCanvas* canvas) const {
    if (this->pageCount() == 0) {
        return Result::Fatal("Unable to parse MultiPictureDocument file: %s", fPath.c_str());
    }
    if (i >= fPages.count() || i < 0) {
        return Result::Fatal("MultiPictureDocument page number out of range: %d", i);
    }
    SkPicture* page = fPages[i].fPicture.get();
    if (!page) {
        std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fPath.c_str());
        if (!stream) {
            return Result::Fatal("Unable to open file: %s", fPath.c_str());
        }
        if (!SkMultiPictureDocumentRead(stream.get(), &fPages[0], fPages.count())) {
            return Result::Fatal("SkMultiPictureDocument reader failed on page %d: %s", i,
                                 fPath.c_str());
        }
        page = fPages[i].fPicture.get();
    }
    canvas->drawPicture(page);
    return Result::Ok();
}

Name MSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

Result NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
    return src.draw(nullptr, SkMakeNullCanvas().get());
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

static Result compare_bitmaps(const SkBitmap& reference, const SkBitmap& bitmap) {
    // The dimensions are a property of the Src only, and so should be identical.
    SkASSERT(reference.computeByteSize() == bitmap.computeByteSize());
    if (reference.computeByteSize() != bitmap.computeByteSize()) {
        return Result::Fatal("Dimensions don't match reference");
    }
    // All SkBitmaps in DM are tight, so this comparison is easy.
    if (0 != memcmp(reference.getPixels(), bitmap.getPixels(), reference.computeByteSize())) {
        SkString encoded;
        SkString errString("Pixels don't match reference");
        if (BipmapToBase64DataURI(reference, &encoded)) {
            errString.append("\nExpected: ");
            errString.append(encoded);
        } else {
            errString.append("\nExpected image failed to encode: ");
            errString.append(encoded);
        }
        if (BipmapToBase64DataURI(bitmap, &encoded)) {
            errString.append("\nActual: ");
            errString.append(encoded);
        } else {
            errString.append("\nActual image failed to encode: ");
            errString.append(encoded);
        }
        return Result::Fatal(errString);
    }
    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

static DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
static DEFINE_bool(preAbandonGpuContext, false,
                   "Test abandoning the GrContext before running the test.");
static DEFINE_bool(abandonGpuContext, false,
                   "Test abandoning the GrContext after running each test.");
static DEFINE_bool(releaseAndAbandonGpuContext, false,
                   "Test releasing all gpu resources and abandoning the GrContext "
                   "after running each test");
static DEFINE_bool(drawOpClip, false, "Clip each GrDrawOp to its device bounds for testing.");
static DEFINE_bool(programBinaryCache, true, "Use in-memory program binary cache");

GPUSink::GPUSink(const SkCommandLineConfigGpu* config,
                 const GrContextOptions& grCtxOptions)
        : fContextType(config->getContextType())
        , fContextOverrides(config->getContextOverrides())
        , fSurfType(config->getSurfType())
        , fSampleCount(config->getSamples())
        , fSurfaceFlags(config->getSurfaceFlags())
        , fColorType(config->getColorType())
        , fAlphaType(config->getAlphaType())
        , fBaseContextOptions(grCtxOptions) {
    if (FLAGS_programBinaryCache) {
        fBaseContextOptions.fPersistentCache = &fMemoryCache;
    }
}

Result GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream* dstStream, SkString* log) const {
    return this->onDraw(src, dst, dstStream, log, fBaseContextOptions);
}

sk_sp<SkSurface> GPUSink::createDstSurface(GrDirectContext* context, SkISize size) const {
    sk_sp<SkSurface> surface;

    SkImageInfo info = SkImageInfo::Make(size, fColorType, fAlphaType, fColorSpace);
    SkSurfaceProps props(fSurfaceFlags, kRGB_H_SkPixelGeometry);

    switch (fSurfType) {
        case SkCommandLineConfigGpu::SurfType::kDefault:
            surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, fSampleCount,
                                                  &props);
            break;
        case SkCommandLineConfigGpu::SurfType::kBackendTexture:
            surface = sk_gpu_test::MakeBackendTextureSurface(context,
                                                             info,
                                                             kTopLeft_GrSurfaceOrigin,
                                                             fSampleCount,
                                                             GrMipmapped::kNo,
                                                             GrProtected::kNo,
                                                             &props);
            break;
        case SkCommandLineConfigGpu::SurfType::kBackendRenderTarget:
            surface = sk_gpu_test::MakeBackendRenderTargetSurface(context,
                                                                  info,
                                                                  kBottomLeft_GrSurfaceOrigin,
                                                                  fSampleCount,
                                                                  GrProtected::kNo,
                                                                  &props);
            break;
    }

    return surface;
}

bool GPUSink::readBack(SkSurface* surface, SkBitmap* dst) const {
    SkCanvas* canvas = surface->getCanvas();
    SkISize size = surface->imageInfo().dimensions();

    SkImageInfo info = SkImageInfo::Make(size, fColorType, fAlphaType, fColorSpace);
    dst->allocPixels(info);
    return canvas->readPixels(*dst, 0, 0);
}

Result GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
                       const GrContextOptions& baseOptions,
                       std::function<void(GrDirectContext*)> initContext) const {
    GrContextOptions grOptions = baseOptions;

    // We don't expect the src to mess with the persistent cache or the executor.
    SkDEBUGCODE(auto cache = grOptions.fPersistentCache);
    SkDEBUGCODE(auto exec = grOptions.fExecutor);
    src.modifyGrContextOptions(&grOptions);
    SkASSERT(cache == grOptions.fPersistentCache);
    SkASSERT(exec == grOptions.fExecutor);

    GrContextFactory factory(grOptions);
    auto direct = factory.getContextInfo(fContextType, fContextOverrides).directContext();
    if (initContext) {
        initContext(direct);
    }

    const int maxDimension = direct->priv().caps()->maxTextureSize();
    if (maxDimension < std::max(src.size().width(), src.size().height())) {
        return Result::Skip("Src too large to create a texture.\n");
    }

    sk_sp<SkSurface> surface = this->createDstSurface(direct, src.size());
    if (!surface) {
        return Result::Fatal("Could not create a surface.");
    }
    if (FLAGS_preAbandonGpuContext) {
        factory.abandonContexts();
    }

    Result result = src.draw(direct, surface->getCanvas());
    if (!result.isOk()) {
        return result;
    }
    surface->flushAndSubmit();
    if (FLAGS_gpuStats) {
        direct->priv().dumpCacheStats(log);
        direct->priv().dumpGpuStats(log);
        direct->priv().dumpContextStats(log);
    }

    this->readBack(surface.get(), dst);

    if (FLAGS_abandonGpuContext) {
        factory.abandonContexts();
    } else if (FLAGS_releaseAndAbandonGpuContext) {
        factory.releaseResourcesAndAbandonContexts();
    }

    if (grOptions.fPersistentCache) {
        direct->storeVkPipelineCacheData();
    }
    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

GPUThreadTestingSink::GPUThreadTestingSink(const SkCommandLineConfigGpu* config,
                                           const GrContextOptions& grCtxOptions)
        : INHERITED(config, grCtxOptions)
        , fExecutor(SkExecutor::MakeFIFOThreadPool(FLAGS_gpuThreads)) {
    SkASSERT(fExecutor);
}

Result GPUThreadTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream,
                                 SkString* log) const {
    // Draw twice, once with worker threads, and once without. Verify that we get the same result.
    // Also, force us to only use the software path renderer, so we really stress-test the threaded
    // version of that code.
    GrContextOptions contextOptions = this->baseContextOptions();
    contextOptions.fGpuPathRenderers = GpuPathRenderers::kNone;
    contextOptions.fExecutor = fExecutor.get();

    Result result = this->onDraw(src, dst, wStream, log, contextOptions);
    if (!result.isOk() || !dst) {
        return result;
    }

    SkBitmap reference;
    SkString refLog;
    SkDynamicMemoryWStream refStream;
    contextOptions.fExecutor = nullptr;
    Result refResult = this->onDraw(src, &reference, &refStream, &refLog, contextOptions);
    if (!refResult.isOk()) {
        return refResult;
    }

    return compare_bitmaps(reference, *dst);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

GPUPersistentCacheTestingSink::GPUPersistentCacheTestingSink(const SkCommandLineConfigGpu* config,
                                                             const GrContextOptions& grCtxOptions)
    : INHERITED(config, grCtxOptions)
    , fCacheType(config->getTestPersistentCache()) {}

Result GPUPersistentCacheTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream,
                                           SkString* log) const {
    // Draw twice, once with a cold cache, and again with a warm cache. Verify that we get the same
    // result.
    sk_gpu_test::MemoryCache memoryCache;
    GrContextOptions contextOptions = this->baseContextOptions();
    contextOptions.fPersistentCache = &memoryCache;
    if (fCacheType == 2) {
        contextOptions.fShaderCacheStrategy = GrContextOptions::ShaderCacheStrategy::kBackendSource;
    }

    Result result = this->onDraw(src, dst, wStream, log, contextOptions);
    if (!result.isOk() || !dst) {
        return result;
    }

    SkBitmap reference;
    SkString refLog;
    SkDynamicMemoryWStream refStream;
    memoryCache.resetCacheStats();
    Result refResult = this->onDraw(src, &reference, &refStream, &refLog, contextOptions);
    if (!refResult.isOk()) {
        return refResult;
    }
    SkASSERT(!memoryCache.numCacheMisses());
    SkASSERT(!memoryCache.numCacheStores());

    return compare_bitmaps(reference, *dst);
}


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

GPUPrecompileTestingSink::GPUPrecompileTestingSink(const SkCommandLineConfigGpu* config,
                                                   const GrContextOptions& grCtxOptions)
    : INHERITED(config, grCtxOptions) {}

Result GPUPrecompileTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream,
                                      SkString* log) const {
    // Three step process:
    // 1) Draw once with an SkSL cache, and store off the shader blobs.
    // 2) For the second context, pre-compile the shaders to warm the cache.
    // 3) Draw with the second context, ensuring that we get the same result, and no cache misses.
    sk_gpu_test::MemoryCache memoryCache;
    GrContextOptions contextOptions = this->baseContextOptions();
    contextOptions.fPersistentCache = &memoryCache;
    contextOptions.fShaderCacheStrategy = GrContextOptions::ShaderCacheStrategy::kSkSL;

    Result result = this->onDraw(src, dst, wStream, log, contextOptions);
    if (!result.isOk() || !dst) {
        return result;
    }

    auto precompileShaders = [&memoryCache](GrDirectContext* dContext) {
        memoryCache.foreach([dContext](sk_sp<const SkData> key,
                                       sk_sp<SkData> data,
                                       const SkString& /*description*/,
                                       int /*count*/) {
            SkAssertResult(dContext->precompileShader(*key, *data));
        });
    };

    sk_gpu_test::MemoryCache replayCache;
    GrContextOptions replayOptions = this->baseContextOptions();
    // Ensure that the runtime cache is large enough to hold all of the shaders we pre-compile
    replayOptions.fRuntimeProgramCacheSize = memoryCache.numCacheMisses();
    replayOptions.fPersistentCache = &replayCache;

    SkBitmap reference;
    SkString refLog;
    SkDynamicMemoryWStream refStream;
    Result refResult = this->onDraw(src, &reference, &refStream, &refLog, replayOptions,
                                    precompileShaders);
    if (!refResult.isOk()) {
        return refResult;
    }
    SkASSERT(!replayCache.numCacheMisses());

    return compare_bitmaps(reference, *dst);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GPUOOPRSink::GPUOOPRSink(const SkCommandLineConfigGpu* config, const GrContextOptions& ctxOptions)
        : INHERITED(config, ctxOptions) {
}

Result GPUOOPRSink::ooprDraw(const Src& src,
                             sk_sp<SkSurface> dstSurface,
                             GrDirectContext* context) const {
    SkSurfaceCharacterization dstCharacterization;
    SkAssertResult(dstSurface->characterize(&dstCharacterization));

    SkDeferredDisplayListRecorder recorder(dstCharacterization);

    Result result = src.draw(context, recorder.getCanvas());
    if (!result.isOk()) {
        return result;
    }

    auto ddl = recorder.detach();

    SkDeferredDisplayList::ProgramIterator iter(context, ddl.get());
    for (; !iter.done(); iter.next()) {
        iter.compile();
    }

    SkAssertResult(dstSurface->draw(std::move(ddl)));

    return Result::Ok();
}

Result GPUOOPRSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
    GrContextOptions contextOptions = this->baseContextOptions();
    src.modifyGrContextOptions(&contextOptions);
    contextOptions.fPersistentCache = nullptr;
    contextOptions.fExecutor = nullptr;

    GrContextFactory factory(contextOptions);

    ContextInfo ctxInfo = factory.getContextInfo(this->contextType(), this->contextOverrides());
    auto context = ctxInfo.directContext();
    if (!context) {
        return Result::Fatal("Could not create context.");
    }

    SkASSERT(context->priv().getGpu());

    sk_sp<SkSurface> surface = this->createDstSurface(context, src.size());
    if (!surface) {
        return Result::Fatal("Could not create a surface.");
    }

    Result result = this->ooprDraw(src, surface, context);
    if (!result.isOk()) {
        return result;
    }

    if (FLAGS_gpuStats) {
        context->priv().dumpCacheStats(log);
        context->priv().dumpGpuStats(log);
        context->priv().dumpContextStats(log);
    }

    if (!this->readBack(surface.get(), dst)) {
        return Result::Fatal("Could not readback from surface.");
    }

    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GPUDDLSink::GPUDDLSink(const SkCommandLineConfigGpu* config, const GrContextOptions& ctxOptions)
        : INHERITED(config, ctxOptions)
        , fRecordingExecutor(SkExecutor::MakeLIFOThreadPool(1))
        , fGPUExecutor(SkExecutor::MakeFIFOThreadPool(1, false)) {
}

Result GPUDDLSink::ddlDraw(const Src& src,
                           sk_sp<SkSurface> dstSurface,
                           SkTaskGroup* recordingTaskGroup,
                           SkTaskGroup* gpuTaskGroup,
                           sk_gpu_test::TestContext* gpuTestCtx,
                           GrDirectContext* dContext) const {

    // We have to do this here bc characterization can hit the SkGpuDevice's thread guard (i.e.,
    // leaving it until the DDLTileHelper ctor will result in multiple threads trying to use the
    // same context (this thread and the gpuThread - which will be uploading textures)).
    SkSurfaceCharacterization dstCharacterization;
    SkAssertResult(dstSurface->characterize(&dstCharacterization));

    auto size = src.size();
    SkPictureRecorder recorder;
    Result result = src.draw(dContext, recorder.beginRecording(SkIntToScalar(size.width()),
                                                               SkIntToScalar(size.height())));
    if (!result.isOk()) {
        return result;
    }
    sk_sp<SkPicture> inputPicture(recorder.finishRecordingAsPicture());

    // this is our ultimate final drawing area/rect
    SkIRect viewport = SkIRect::MakeWH(size.fWidth, size.fHeight);

    SkYUVAPixmapInfo::SupportedDataTypes supportedYUVADataTypes(*dContext);
    DDLPromiseImageHelper promiseImageHelper(supportedYUVADataTypes);
    sk_sp<SkPicture> newSKP = promiseImageHelper.recreateSKP(dContext, inputPicture.get());
    if (!newSKP) {
        return Result::Fatal("GPUDDLSink: Couldn't recreate the SKP");
    }

    // 'gpuTestCtx/gpuThreadCtx' is being shifted to the gpuThread. Leave the main (this)
    // thread w/o a context.
    gpuTestCtx->makeNotCurrent();

    // Job one for the GPU thread is to make 'gpuTestCtx' current!
    gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeCurrent(); });

    // TODO: move the image upload to the utility thread
    promiseImageHelper.uploadAllToGPU(gpuTaskGroup, dContext);

    // Care must be taken when using 'gpuThreadCtx' bc it moves between the gpu-thread and this
    // one. About all it can be consistently used for is GrCaps access and 'defaultBackendFormat'
    // calls.
    constexpr int kNumDivisions = 3;
    DDLTileHelper tiles(dContext, dstCharacterization, viewport,
                        kNumDivisions, kNumDivisions,
                        /* addRandomPaddingToDst */ false);

    tiles.createBackendTextures(gpuTaskGroup, dContext);

    tiles.kickOffThreadedWork(recordingTaskGroup, gpuTaskGroup, dContext, newSKP.get());

    // We have to wait for the recording threads to schedule all their work on the gpu thread
    // before we can schedule the composition draw and the flush. Note that the gpu thread
    // is not blocked at this point and this thread is borrowing recording work.
    recordingTaskGroup->wait();

    // Note: at this point the recording thread(s) are stalled out w/ nothing to do.

    // The recording threads have already scheduled the drawing of each tile's DDL on the gpu
    // thread. The composition DDL must be scheduled last bc it relies on the result of all
    // the tiles' rendering. Additionally, bc we're aliasing the tiles' backend textures,
    // there is nothing in the DAG to automatically force the required order.
    gpuTaskGroup->add([dstSurface, ddl = tiles.composeDDL()]() {
                          dstSurface->draw(ddl);
                      });

    // This should be the only explicit flush for the entire DDL draw.
    gpuTaskGroup->add([dContext]() {
                                           // We need to ensure all the GPU work is finished so
                                           // the following 'deleteAllFromGPU' call will work
                                           // on Vulkan.
                                           // TODO: switch over to using the promiseImage callbacks
                                           // to free the backendTextures. This is complicated a
                                           // bit by which thread possesses the direct context.
                                           dContext->flush();
                                           dContext->submit(true);
                                       });

    // The backend textures are created on the gpuThread by the 'uploadAllToGPU' call.
    // It is simpler to also delete them at this point on the gpuThread.
    promiseImageHelper.deleteAllFromGPU(gpuTaskGroup, dContext);

    tiles.deleteBackendTextures(gpuTaskGroup, dContext);

    // A flush has already been scheduled on the gpu thread along with the clean up of the backend
    // textures so it is safe to schedule making 'gpuTestCtx' not current on the gpuThread.
    gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeNotCurrent(); });

    // All the work is scheduled on the gpu thread, we just need to wait
    gpuTaskGroup->wait();

    return Result::Ok();
}

Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
    GrContextOptions contextOptions = this->baseContextOptions();
    src.modifyGrContextOptions(&contextOptions);
    contextOptions.fPersistentCache = nullptr;
    contextOptions.fExecutor = nullptr;

    GrContextFactory factory(contextOptions);

    // This captures the context destined to be the main gpu context
    ContextInfo mainCtxInfo = factory.getContextInfo(this->contextType(), this->contextOverrides());
    sk_gpu_test::TestContext* mainTestCtx = mainCtxInfo.testContext();
    auto mainCtx = mainCtxInfo.directContext();
    if (!mainCtx) {
        return Result::Fatal("Could not create context.");
    }

    SkASSERT(mainCtx->priv().getGpu());

    // TODO: make use of 'otherCtx' for uploads & compilation
#if 0
    // This captures the context destined to be the utility context. It is in a share group
    // with the main context
    ContextInfo otherCtxInfo = factory.getSharedContextInfo(mainCtx);
    sk_gpu_test::TestContext* otherTestCtx = otherCtxInfo.testContext();
    auto otherCtx = otherCtxInfo.directContext();
    if (!otherCtx) {
        return Result::Fatal("Cound not create shared context.");
    }

    SkASSERT(otherCtx->priv().getGpu());
#endif

    SkTaskGroup recordingTaskGroup(*fRecordingExecutor);
    SkTaskGroup gpuTaskGroup(*fGPUExecutor);

    // Make sure 'mainCtx' is current
    mainTestCtx->makeCurrent();

    sk_sp<SkSurface> surface = this->createDstSurface(mainCtx, src.size());
    if (!surface) {
        return Result::Fatal("Could not create a surface.");
    }

    Result result = this->ddlDraw(src, surface, &recordingTaskGroup, &gpuTaskGroup,
                                  mainTestCtx, mainCtx);
    if (!result.isOk()) {
        return result;
    }

    // 'ddlDraw' will have made 'mainCtx' not current on the gpuThread
    mainTestCtx->makeCurrent();

    if (FLAGS_gpuStats) {
        mainCtx->priv().dumpCacheStats(log);
        mainCtx->priv().dumpGpuStats(log);
        mainCtx->priv().dumpContextStats(log);

#if 0
        otherCtx->priv().dumpCacheStats(log);
        otherCtx->priv().dumpGpuStats(log);
        otherCtx->priv().dumpContextStats(log);
#endif
    }

    if (!this->readBack(surface.get(), dst)) {
        return Result::Fatal("Could not readback from surface.");
    }

    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static Result draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
    if (src.size().isEmpty()) {
        return Result::Fatal("Source has empty dimensions");
    }
    SkASSERT(doc);
    int pageCount = src.pageCount();
    for (int i = 0; i < pageCount; ++i) {
        int width = src.size(i).width(), height = src.size(i).height();
        SkCanvas* canvas =
                doc->beginPage(SkIntToScalar(width), SkIntToScalar(height));
        if (!canvas) {
            return Result::Fatal("SkDocument::beginPage(w,h) returned nullptr");
        }
        Result result = src.draw(i, nullptr, canvas);
        if (!result.isOk()) {
            return result;
        }
        doc->endPage();
    }
    doc->close();
    dst->flush();
    return Result::Ok();
}

Result PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
    SkPDF::Metadata metadata;
    metadata.fTitle = src.name();
    metadata.fSubject = "rendering correctness test";
    metadata.fCreator = "Skia/DM";
    metadata.fRasterDPI = fRasterDpi;
    metadata.fPDFA = fPDFA;
#if SK_PDF_TEST_EXECUTOR
    std::unique_ptr<SkExecutor> executor = SkExecutor::MakeFIFOThreadPool();
    metadata.fExecutor = executor.get();
#endif
    auto doc = SkPDF::MakeDocument(dst, metadata);
    if (!doc) {
        return Result::Fatal("SkPDF::MakeDocument() returned nullptr");
    }
    return draw_skdocument(src, doc.get(), dst);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

XPSSink::XPSSink() {}

#if defined(SK_SUPPORT_XPS)
static SkTScopedComPtr<IXpsOMObjectFactory> make_xps_factory() {
    IXpsOMObjectFactory* factory;
    HRN(CoCreateInstance(CLSID_XpsOMObjectFactory,
                         nullptr,
                         CLSCTX_INPROC_SERVER,
                         IID_PPV_ARGS(&factory)));
    return SkTScopedComPtr<IXpsOMObjectFactory>(factory);
}

Result XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
    SkAutoCoInitialize com;
    if (!com.succeeded()) {
        return Result::Fatal("Could not initialize COM.");
    }
    SkTScopedComPtr<IXpsOMObjectFactory> factory = make_xps_factory();
    if (!factory) {
        return Result::Fatal("Failed to create XPS Factory.");
    }
    auto doc = SkXPS::MakeDocument(dst, factory.get());
    if (!doc) {
        return Result::Fatal("SkXPS::MakeDocument() returned nullptr");
    }
    return draw_skdocument(src, doc.get(), dst);
}
#else
Result XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
    return Result::Fatal("XPS not supported on this platform.");
}
#endif

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

SKPSink::SKPSink() {}

Result SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
    auto size = SkSize::Make(src.size());
    SkPictureRecorder recorder;
    Result result = src.draw(nullptr, recorder.beginRecording(size.width(), size.height()));
    if (!result.isOk()) {
        return result;
    }
    recorder.finishRecordingAsPicture()->serialize(dst);
    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

Result DebugSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
    DebugCanvas debugCanvas(src.size().width(), src.size().height());
    Result result = src.draw(nullptr, &debugCanvas);
    if (!result.isOk()) {
        return result;
    }
    std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
    UrlDataManager dataManager(SkString("data"));
    SkJSONWriter writer(dst, SkJSONWriter::Mode::kPretty);
    writer.beginObject(); // root
    debugCanvas.toJSON(writer, dataManager, nullCanvas.get());
    writer.endObject(); // root
    writer.flush();
    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

SVGSink::SVGSink(int pageIndex) : fPageIndex(pageIndex) {}

Result SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
#if defined(SK_ENABLE_SVG)
    if (src.pageCount() > 1) {
        int pageCount = src.pageCount();
        if (fPageIndex > pageCount - 1) {
            return Result::Fatal("Page index %d too high for document with only %d pages.",
                                 fPageIndex, pageCount);
        }
    }
    return src.draw(fPageIndex, nullptr,
                    SkSVGCanvas::Make(SkRect::MakeWH(SkIntToScalar(src.size().width()),
                                                     SkIntToScalar(src.size().height())),
                                      dst)
                            .get());
#else
    (void)fPageIndex;
    return Result::Fatal("SVG sink is disabled.");
#endif // SK_ENABLE_SVG
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

RasterSink::RasterSink(SkColorType colorType)
    : fColorType(colorType) {}

Result RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
    const SkISize size = src.size();
    // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
    SkAlphaType alphaType = kPremul_SkAlphaType;
    (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);

    dst->allocPixelsFlags(SkImageInfo::Make(size, fColorType, alphaType, fColorSpace),
                          SkBitmap::kZeroPixels_AllocFlag);

    SkCanvas canvas(*dst, SkSurfaceProps(0, kRGB_H_SkPixelGeometry));
    return src.draw(nullptr, &canvas);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

#ifdef SK_GRAPHITE_ENABLED

namespace {

// For the sprint Graphite only handles:
//    solid colors with src or srcOver
//    repeated or clamped linear gradients with src or srcOver
void precompile(skgpu::Context* context) {
    using ShaderType = skgpu::ShaderCombo::ShaderType;

    skgpu::PaintCombo c1 { { skgpu::ShaderCombo({ ShaderType::kSolidColor },
                                                { SkTileMode::kRepeat }) },
                           { SkBlendMode::kSrcOver, SkBlendMode::kSrc } };
    context->preCompile(c1);

    skgpu::PaintCombo c2 { { skgpu::ShaderCombo({ ShaderType::kLinearGradient },
                                                { SkTileMode::kRepeat, SkTileMode::kClamp }) },
                           { SkBlendMode::kSrcOver, SkBlendMode::kSrc } };
    context->preCompile(c2);
}

} // anonymous namespace

GraphiteSink::GraphiteSink(const SkCommandLineConfigGraphite* config)
        : fContextType(config->getContextType())
        , fColorType(config->getColorType())
        , fAlphaType(config->getAlphaType())
        , fTestPrecompile(config->getTestPrecompile()) {
}

Result GraphiteSink::draw(const Src& src,
                          SkBitmap* dst,
                          SkWStream* dstStream,
                          SkString* log) const {
    SkImageInfo ii = SkImageInfo::Make(src.size(), fColorType, fAlphaType);

    skiatest::graphite::ContextFactory factory;
    auto [_, context] = factory.getContextInfo(fContextType);
    if (!context) {
        return Result::Fatal("Could not create a context.");
    }

    if (fTestPrecompile) {
        precompile(context.get());
    }

    std::unique_ptr<skgpu::Recorder> recorder = context->makeRecorder();
    if (!recorder) {
        return Result::Fatal("Could not create a recorder.");
    }

    dst->allocPixels(ii);

    {
        sk_sp<SkSurface> surface = MakeGraphite(recorder.get(), ii);
        if (!surface) {
            return Result::Fatal("Could not create a surface.");
        }
        Result result = src.draw(/* dContext */ nullptr, surface->getCanvas());
        if (!result.isOk()) {
            return result;
        }

        // For now we cast and call directly into Surface_Graphite. Once we have a been idea of
        // what the public API for synchronous graphite readPixels we can update this call to use
        // that instead.
        SkPixmap pm;
        if (!dst->peekPixels(&pm) ||
            !static_cast<skgpu::Surface_Graphite*>(surface.get())->onReadPixels(context.get(),
                                                                                pm,
                                                                                0,
                                                                                0)) {
            return Result::Fatal("Could not readback from surface.");
        }
    }

    std::unique_ptr<skgpu::Recording> recording = recorder->snap();

    context->insertRecording(std::move(recording));
    context->submit(skgpu::SyncToCpu::kYes);

    return Result::Ok();
}
#endif

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

// Handy for front-patching a Src.  Do whatever up-front work you need, then call draw_to_canvas(),
// passing the Sink draw() arguments, a size, and a function draws into an SkCanvas.
// Several examples below.

using DrawToCanvasFn = std::function<DM::Result(GrDirectContext*, SkCanvas*)>;

static Result draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream,
                             SkString* log, SkISize size, const DrawToCanvasFn& draw) {
    class ProxySrc : public Src {
    public:
        ProxySrc(SkISize size, const DrawToCanvasFn& draw) : fSize(size), fDraw(draw) {}
        Result draw(GrDirectContext* context, SkCanvas* canvas) const override {
            return fDraw(context, canvas);
        }
        Name    name() const override { return "ProxySrc"; }
        SkISize size() const override { return fSize; }
    private:
        SkISize               fSize;
        const DrawToCanvasFn& fDraw;
    };
    return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

static DEFINE_bool(check, true, "If true, have most Via- modes fail if they affect the output.");

// Is *bitmap identical to what you get drawing src into sink?
static Result check_against_reference(const SkBitmap* bitmap, const Src& src, Sink* sink) {
    // We can only check raster outputs.
    // (Non-raster outputs like .pdf, .skp, .svg may differ but still draw identically.)
    if (FLAGS_check && bitmap) {
        SkBitmap reference;
        SkString log;
        SkDynamicMemoryWStream wStream;
        Result result = sink->draw(src, &reference, &wStream, &log);
        // If we can draw into this Sink via some pipeline, we should be able to draw directly.
        SkASSERT(result.isOk());
        if (!result.isOk()) {
            return result;
        }
        return compare_bitmaps(reference, *bitmap);
    }
    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
    SkRect bounds = SkRect::MakeIWH(srcW, srcH);
    matrix->mapRect(&bounds);
    matrix->postTranslate(-bounds.x(), -bounds.y());
    return {SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height())};
}

ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}

Result ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
    SkMatrix matrix = fMatrix;
    SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
    return draw_to_canvas(fSink.get(), bitmap, stream, log, size,
                          [&](GrDirectContext* context, SkCanvas* canvas) {
                              canvas->concat(matrix);
                              return src.draw(context, canvas);
                          });
}

// Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
// This should be pixel-preserving.
ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}

Result ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
    Result result = fSink->draw(src, bitmap, stream, log);
    if (!result.isOk()) {
        return result;
    }

    SkMatrix inverse;
    if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
        return Result::Fatal("Cannot upright --matrix.");
    }
    SkMatrix upright = SkMatrix::I();
    upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
    upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
    upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
    upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));

    SkBitmap uprighted;
    SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
    uprighted.allocPixels(bitmap->info().makeDimensions(size));

    SkCanvas canvas(uprighted);
    canvas.concat(upright);
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);
    canvas.drawImage(bitmap->asImage(), 0, 0, SkSamplingOptions(), &paint);

    *bitmap = uprighted;
    return Result::Ok();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

Result ViaSerialization::draw(
        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
    // Record our Src into a picture.
    auto size = src.size();
    SkPictureRecorder recorder;
    Result result = src.draw(nullptr, recorder.beginRecording(SkIntToScalar(size.width()),
                                                              SkIntToScalar(size.height())));
    if (!result.isOk()) {
        return result;
    }
    sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());

    // Serialize it and then deserialize it.
    sk_sp<SkPicture> deserialized(SkPicture::MakeFromData(pic->serialize().get()));

    result = draw_to_canvas(fSink.get(), bitmap, stream, log, size,
                            [&](GrDirectContext*, SkCanvas* canvas) {
                                canvas->drawPicture(deserialized);
                                return Result::Ok();
                            });
    if (!result.isOk()) {
        return result;
    }

    return check_against_reference(bitmap, src, fSink.get());
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

Result ViaPicture::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
    auto size = src.size();
    Result result = draw_to_canvas(fSink.get(), bitmap, stream, log, size,
                                   [&](GrDirectContext* context, SkCanvas* canvas) {
        SkPictureRecorder recorder;
        sk_sp<SkPicture> pic;
        Result result = src.draw(context, recorder.beginRecording(SkIntToScalar(size.width()),
                                                                  SkIntToScalar(size.height())));
        if (!result.isOk()) {
            return result;
        }
        pic = recorder.finishRecordingAsPicture();
        canvas->drawPicture(pic);
        return result;
    });
    if (!result.isOk()) {
        return result;
    }

    return check_against_reference(bitmap, src, fSink.get());
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

Result ViaRuntimeBlend::draw(const Src& src,
                             SkBitmap* bitmap,
                             SkWStream* stream,
                             SkString* log) const {
    class RuntimeBlendFilterCanvas : public SkPaintFilterCanvas {
    public:
        RuntimeBlendFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { }

    protected:
        bool onFilter(SkPaint& paint) const override {
            if (skstd::optional<SkBlendMode> mode = paint.asBlendMode()) {
                paint.setBlender(GetRuntimeBlendForBlendMode(*mode));
            }
            return true;
        }

    private:
        using INHERITED = SkPaintFilterCanvas;
    };

    return draw_to_canvas(fSink.get(), bitmap, stream, log, src.size(),
                          [&](GrDirectContext* context, SkCanvas* canvas) {
        RuntimeBlendFilterCanvas runtimeBlendCanvas{canvas};
        return src.draw(context, &runtimeBlendCanvas);
    });
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

#ifdef TEST_VIA_SVG
#include "include/svg/SkSVGCanvas.h"
#include "modules/svg/include/SkSVGDOM.h"
#include "src/xml/SkXMLWriter.h"

Result ViaSVG::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
    auto size = src.size();
    return draw_to_canvas(fSink.get(), bitmap, stream, log, size,
                          [&](GrDirectContext*, SkCanvas* canvas) -> Result {
        SkDynamicMemoryWStream wstream;
        SkXMLStreamWriter writer(&wstream);
        Result result = src.draw(SkSVGCanvas::Make(SkRect::Make(size), &writer).get());
        if (!result.isOk()) {
            return result;
        }
        std::unique_ptr<SkStream> rstream(wstream.detachAsStream());
        auto dom = SkSVGDOM::MakeFromStream(*rstream);
        if (dom) {
            dom->setContainerSize(SkSize::Make(size));
            dom->render(canvas);
        }
        return Result::Ok();
    });
}
#endif

}  // namespace DM
