/*
 * 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/SkCombinationBuilder.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/SkSerialProcs.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/SkTLazy.h"
#include "src/core/SkTaskGroup.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/utils/SkJSONWriter.h"
#include "src/utils/SkMultiPictureDocumentPriv.h"
#include "src/utils/SkOSPath.h"
#include "src/utils/SkTestCanvas.h"
#include "tools/DDLPromiseImageHelper.h"
#include "tools/DDLTileHelper.h"
#include "tools/Resources.h"
#include "tools/RuntimeBlendUtils.h"
#include "tools/UrlDataManager.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_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 "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Recording.h"
#include "include/gpu/graphite/SkStuff.h"
// TODO: Remove this src include once we figure out public readPixels call for Graphite.
#include "src/gpu/graphite/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,
                SkStringPrintf("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* dContext, SkCanvas* canvas) const {

    struct DeserializationContext {
        GrDirectContext*           fDirectContext = nullptr;
#ifdef SK_GRAPHITE_ENABLED
        skgpu::graphite::Recorder* fRecorder = nullptr;
#endif
    } ctx {
        dContext,
#ifdef SK_GRAPHITE_ENABLED
        canvas->recorder()
#endif
    };

    SkDeserialProcs procs;
    procs.fImageProc = [](const void* data, size_t size, void* ctx) -> sk_sp<SkImage> {
        sk_sp<SkData> tmpData = SkData::MakeWithoutCopy(data, size);
        sk_sp<SkImage> image = SkImage::MakeFromEncoded(std::move(tmpData));
        image = image->makeRasterImage(); // force decoding

        if (image) {
            DeserializationContext* context = reinterpret_cast<DeserializationContext*>(ctx);

            if (context->fDirectContext) {
                image = image->makeTextureImage(context->fDirectContext);
            }
#ifdef SK_GRAPHITE_ENABLED
            else if (context->fRecorder) {
                image = image->makeTextureImage(context->fRecorder);
            }
#endif
        }

        return image;
    };
    procs.fImageCtx = &ctx;

    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(), &procs));
    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_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(Result::Status::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,
                       std::function<SkCanvas*(SkCanvas*)> wrapCanvas) 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();
    }

    auto canvas = surface->getCanvas();
    if (wrapCanvas != nullptr) {
        canvas = wrapCanvas(canvas);
    }

    Result result = src.draw(direct, canvas);
    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();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GPUSlugSink::GPUSlugSink(const SkCommandLineConfigGpu* config, const GrContextOptions& options)
        : GPUSink(config, options) {}

Result GPUSlugSink::draw(const Src& src, SkBitmap* dst, SkWStream* write, SkString* log) const {
    GrContextOptions grOptions = this->baseContextOptions();
    // Force padded atlas entries for slug drawing.
    grOptions.fSupportBilerpFromGlyphAtlas |= true;

    SkTLazy<SkTestCanvas<SkSlugTestKey>> testCanvas;

    return onDraw(src, dst, write, log, grOptions, nullptr,
        [&](SkCanvas* canvas){
            testCanvas.init(canvas);
            return testCanvas.get();
        });
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
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

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

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.");
    }

    std::unique_ptr<skgpu::graphite::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. Once we have a better 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::graphite::Surface*>(surface.get())->onReadPixels(context,
                                                                                 recorder.get(),
                                                                                 pm,
                                                                                 0,
                                                                                 0)) {
            return Result::Fatal("Could not readback from surface.");
        }
    }

    std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
    if (!recording) {
        return Result::Fatal("Could not create a recording.");
    }

    skgpu::graphite::InsertRecordingInfo info;
    info.fRecording = recording.get();
    context->insertRecording(info);
    context->submit(skgpu::graphite::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 (std::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
