/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "include/gpu/graphite/Context.h"

#include "include/core/SkAlphaType.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/ContextOptions.h"
#include "include/gpu/graphite/GraphiteTypes.h"
#include "include/gpu/graphite/PrecompileContext.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "include/private/base/SingleOwner.h"
#include "include/private/base/SkAlign.h"
#include "include/private/base/SkMutex.h"
#include "include/private/base/SkOnce.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkEnumBitMask.h"
#include "src/base/SkRectMemcpy.h"
#include "src/capture/SkCapture.h"
#include "src/capture/SkCaptureManager.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkCPUContextImpl.h"
#include "src/core/SkCPURecorderImpl.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkImageInfoPriv.h"
#include "src/core/SkTraceEvent.h"
#include "src/core/SkYUVMath.h"
#include "src/gpu/AsyncReadTypes.h"
#include "src/gpu/GpuTypesPriv.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/graphite/AtlasProvider.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/BufferManager.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ClientMappedBufferManager.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/GlobalCache.h"
#include "src/gpu/graphite/Image_Graphite.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/QueueManager.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/ResourceTypes.h"
#include "src/gpu/graphite/RuntimeEffectDictionary.h"
#include "src/gpu/graphite/SharedContext.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/TextureProxyView.h"
#include "src/gpu/graphite/TextureUtils.h"
#include "src/gpu/graphite/task/CopyTask.h"
#include "src/gpu/graphite/task/SynchronizeToCpuTask.h"
#include "src/gpu/graphite/task/Task.h"
#include "src/image/SkSurface_Base.h"
#include "src/sksl/SkSLGraphiteModules.h"

#include <algorithm>
#include <array>
#include <atomic>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <forward_list>
#include <functional>
#include <memory>
#include <optional>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#if defined(GPU_TEST_UTILS)
#include "src/gpu/graphite/ContextOptionsPriv.h"
#endif

class SkTraceMemoryDump;

namespace skgpu::graphite { class Recording; }

namespace skgpu::graphite {

#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(this->singleOwner())

Context::ContextID Context::ContextID::Next() {
    static std::atomic<uint32_t> nextID{1};
    uint32_t id;
    do {
        id = nextID.fetch_add(1, std::memory_order_relaxed);
    } while (id == SK_InvalidUniqueID);
    return ContextID(id);
}

//--------------------------------------------------------------------------------------------------
Context::Context(sk_sp<SharedContext> sharedContext,
                 std::unique_ptr<QueueManager> queueManager,
                 const ContextOptions& options)
        : fSharedContext(std::move(sharedContext))
        , fQueueManager(std::move(queueManager))
        , fContextID(ContextID::Next()) {
    // We need to move the Graphite SkSL code into the central SkSL data loader at least once
    // (but preferrably only once) before we try to use it. We assume that there's no way to
    // use the SkSL code without making a context, so we initialize it here.
    static SkOnce once;
    once([] { SkSL::Loader::SetGraphiteModuleData(SkSL::Loader::GetGraphiteModules()); });

    // We have to create this outside the initializer list because we need to pass in the Context's
    // SingleOwner object and it is declared last
    fResourceProvider = fSharedContext->makeResourceProvider(&fSingleOwner,
                                                             SK_InvalidGenID,
                                                             options.fGpuBudgetInBytes);
    fMappedBufferManager = std::make_unique<ClientMappedBufferManager>(this->contextID());
#if defined(GPU_TEST_UTILS)
    if (options.fOptionsPriv) {
        fStoreContextRefInRecorder = options.fOptionsPriv->fStoreContextRefInRecorder;
    }
#endif

    fSharedContext->globalCache()->setPipelineCallback(options.fPipelineCallbackContext,
                                                       options.fPipelineCachingCallback,
                                                       options.fPipelineCallback);

    fCPUContext = std::make_unique<skcpu::ContextImpl>();
    if (options.fEnableCapture) {
        fSharedContext->setCaptureManager(sk_make_sp<SkCaptureManager>());
    }

    fPersistentPipelineStorage = options.fPersistentPipelineStorage;
}

Context::~Context() {
#if defined(GPU_TEST_UTILS)
    SkAutoMutexExclusive lock(fTestingLock);
    for (auto& recorder : fTrackedRecorders) {
        recorder->priv().setContext(nullptr);
    }
#endif
}

Context::PixelTransferResult::PixelTransferResult() = default;
Context::PixelTransferResult::PixelTransferResult(const PixelTransferResult&) = default;
Context::PixelTransferResult::PixelTransferResult(PixelTransferResult&&) = default;
Context::PixelTransferResult& Context::PixelTransferResult::operator=(const PixelTransferResult&) = default;
Context::PixelTransferResult::~PixelTransferResult() = default;

bool Context::finishInitialization() {
    SkASSERT(!fSharedContext->rendererProvider()); // Can only initialize once

    if (!fSharedContext->globalCache()->initializeDynamicSamplers(fResourceProvider.get(),
                                                                  fSharedContext->caps())) {
        return false;
    }

    StaticBufferManager bufferManager{fResourceProvider.get(), fSharedContext->caps()};
    std::unique_ptr<RendererProvider> renderers{
            new RendererProvider(fSharedContext->caps(), &bufferManager)};

    auto result = bufferManager.finalize(this, fQueueManager.get(), fSharedContext->globalCache());
    if (result == StaticBufferManager::FinishResult::kFailure) {
        // If something went wrong filling out the static vertex buffers, any Renderer that would
        // use it will draw incorrectly, so it's better to fail the Context creation.
        return false;
    }
    if (result == StaticBufferManager::FinishResult::kSuccess &&
        !fQueueManager->submitToGpu(/*submitInfo=*/{})) {
        SKGPU_LOG_W("Failed to submit initial command buffer for Context creation.\n");
        return false;
    } // else result was kNoWork so skip submitting to the GPU
    fSharedContext->setRendererProvider(std::move(renderers));
    return true;
}

BackendApi Context::backend() const { return fSharedContext->backend(); }

std::unique_ptr<Recorder> Context::makeRecorder(const RecorderOptions& options) {
    ASSERT_SINGLE_OWNER

    // This is a client-owned Recorder so pass a null context so it creates its own ResourceProvider
    auto recorder = std::unique_ptr<Recorder>(new Recorder(fSharedContext, options, nullptr));
#if defined(GPU_TEST_UTILS)
    if (fStoreContextRefInRecorder) {
        recorder->priv().setContext(this);
    }
#endif
    return recorder;
}

std::unique_ptr<skcpu::Recorder> Context::makeCPURecorder() {
    ASSERT_SINGLE_OWNER

    return std::make_unique<skcpu::RecorderImpl>(fCPUContext.get());
}

std::unique_ptr<PrecompileContext> Context::makePrecompileContext() {
    ASSERT_SINGLE_OWNER

    return std::unique_ptr<PrecompileContext>(new PrecompileContext(fSharedContext));
}

std::unique_ptr<Recorder> Context::makeInternalRecorder() const {
    ASSERT_SINGLE_OWNER

    // Unlike makeRecorder(), this Recorder is meant to be short-lived and go away before a Context
    // public API function returns to the caller. As such it shares the Context's resource provider
    // (no separate budget) and does not get tracked. The internal drawing performed with an
    // internal recorder should not require a client image provider.
    //
    // Explicitly overrides fRequiresOrderedRecordings to false so that these Recorders do not
    // inherit any global policy from the ContextOptions. Since they will only produce one Recording
    // there's no need to require subsequent recordings be ordered.
    RecorderOptions options = {};
    options.fRequireOrderedRecordings = false;
    return std::unique_ptr<Recorder>(new Recorder(fSharedContext, options, this));
}

InsertStatus Context::insertRecording(const InsertRecordingInfo& info) {
    ASSERT_SINGLE_OWNER

    return fQueueManager->addRecording(info, this);
}

bool Context::submit(SubmitInfo submitInfo) {
    ASSERT_SINGLE_OWNER

    if (submitInfo.fSync == SyncToCpu::kYes && !fSharedContext->caps()->allowCpuSync()) {
        SKGPU_LOG_E("SyncToCpu::kYes not supported with ContextOptions::fNeverYieldToWebGPU. "
                    "The parameter is ignored and no synchronization will occur.");
        submitInfo.fSync = SyncToCpu::kNo;
    }
    bool success = fQueueManager->submitToGpu(submitInfo);
    this->checkForFinishedWork(submitInfo.fSync);
    return success;
}

bool Context::hasUnfinishedGpuWork() const { return fQueueManager->hasUnfinishedGpuWork(); }

template <typename SrcPixels>
struct Context::AsyncParams {
    const SrcPixels* fSrcImage;
    SkIRect          fSrcRect;
    SkImageInfo      fDstImageInfo;

    SkImage::ReadPixelsCallback* fCallback;
    SkImage::ReadPixelsContext   fCallbackContext;

    template <typename S>
    AsyncParams<S> withNewSource(const S* newPixels, const SkIRect& newSrcRect) const {
        return AsyncParams<S>{newPixels, newSrcRect,
                                fDstImageInfo, fCallback, fCallbackContext};
    }

    void fail() const {
        (*fCallback)(fCallbackContext, nullptr);
    }

    bool validate() const {
        if (!fSrcImage) {
            return false;
        }
        // SkImage::isProtected() -> bool, TextureProxy::isProtected() -> Protected enum.
        // The explicit cast makes this function work for both template instantiations since
        // the Protected enum is backed by a bool.
        if ((bool) fSrcImage->isProtected()) {
            return false;
        }
        if (!SkIRect::MakeSize(fSrcImage->dimensions()).contains(fSrcRect)) {
            return false;
        }
        if (!SkImageInfoIsValid(fDstImageInfo)) {
            return false;
        }
        return true;
    }
};

template <typename ReadFn, typename... ExtraArgs>
void Context::asyncRescaleAndReadImpl(ReadFn Context::* asyncRead,
                                      SkImage::RescaleGamma rescaleGamma,
                                      SkImage::RescaleMode rescaleMode,
                                      const AsyncParams<SkImage>& params,
                                      ExtraArgs... extraParams) {
    if (!params.validate()) {
        return params.fail();
    }

    if (params.fSrcRect.size() == params.fDstImageInfo.dimensions()) {
        // No need to rescale so do a direct readback
        return (this->*asyncRead)(/*recorder=*/nullptr, params, extraParams...);
    }

    // Make a recorder to collect the rescale drawing commands and the copy commands
    std::unique_ptr<Recorder> recorder = this->makeInternalRecorder();
    sk_sp<SkImage> scaledImage = RescaleImage(recorder.get(),
                                              params.fSrcImage,
                                              params.fSrcRect,
                                              params.fDstImageInfo,
                                              rescaleGamma,
                                              rescaleMode);
    if (!scaledImage) {
        SKGPU_LOG_W("AsyncRead failed because rescaling failed");
        return params.fail();
    }
    (this->*asyncRead)(std::move(recorder),
                       params.withNewSource(scaledImage.get(), params.fDstImageInfo.bounds()),
                       extraParams...);
}

void Context::asyncRescaleAndReadPixels(const SkImage* src,
                                        const SkImageInfo& dstImageInfo,
                                        const SkIRect& srcRect,
                                        SkImage::RescaleGamma rescaleGamma,
                                        SkImage::RescaleMode rescaleMode,
                                        SkImage::ReadPixelsCallback callback,
                                        SkImage::ReadPixelsContext callbackContext) {
    this->asyncRescaleAndReadImpl(&Context::asyncReadPixels,
                                  rescaleGamma, rescaleMode,
                                  {src, srcRect, dstImageInfo, callback, callbackContext});
}

void Context::asyncRescaleAndReadPixels(const SkSurface* src,
                                        const SkImageInfo& dstImageInfo,
                                        const SkIRect& srcRect,
                                        SkImage::RescaleGamma rescaleGamma,
                                        SkImage::RescaleMode rescaleMode,
                                        SkImage::ReadPixelsCallback callback,
                                        SkImage::ReadPixelsContext callbackContext) {
    sk_sp<SkImage> surfaceImage = SkSurfaces::AsImage(sk_ref_sp(src));
    if (!surfaceImage) {
        // The source surface is not texturable, so the only supported readback is if there's
        // no rescaling
        if (src && asConstSB(src)->isGraphiteBacked() &&
            srcRect.size() == dstImageInfo.dimensions()) {
            TextureProxy* proxy = static_cast<const Surface*>(src)->backingTextureProxy();
            return this->asyncReadTexture(/*recorder=*/nullptr,
                                          {proxy, srcRect, dstImageInfo, callback, callbackContext},
                                          src->imageInfo().colorInfo());
        }
        // else fall through and let asyncRescaleAndReadPixels() invoke the callback when it detects
        // the null image.
    }
    this->asyncRescaleAndReadPixels(surfaceImage.get(),
                                    dstImageInfo,
                                    srcRect,
                                    rescaleGamma,
                                    rescaleMode,
                                    callback,
                                    callbackContext);
}

void Context::asyncReadPixels(std::unique_ptr<Recorder> recorder,
                              const AsyncParams<SkImage>& params) {
    TRACE_EVENT2("skia.gpu", TRACE_FUNC,
                 "width", params.fSrcRect.width(),
                 "height", params.fSrcRect.height());
    SkASSERT(params.validate());    // all paths to here are already validated
    SkASSERT(params.fSrcRect.size() == params.fDstImageInfo.dimensions());

    const Caps* caps = fSharedContext->caps();
    TextureProxyView view = AsView(params.fSrcImage);
    if (!view || !caps->supportsReadPixels(view.proxy()->textureInfo())) {
        // This is either a YUVA image (null view) or the texture can't be read directly, so
        // perform a draw into a compatible texture format and/or flatten any YUVA planes to RGBA.
        if (!recorder) {
            recorder = this->makeInternalRecorder();
        }
        sk_sp<SkImage> flattened = CopyAsDraw(recorder.get(),
                                              /*drawContext=*/nullptr,
                                              params.fSrcImage,
                                              params.fSrcRect,
                                              params.fDstImageInfo.colorInfo(),
                                              Budgeted::kYes,
                                              Mipmapped::kNo,
                                              SkBackingFit::kApprox,
                                              "AsyncReadPixelsFallbackTexture");
        if (!flattened) {
            SKGPU_LOG_W("AsyncRead failed because copy-as-drawing into a readable format failed");
            return params.fail();
        }
        // Use the original fSrcRect and not flattened's size since it's approx-fit.
        return this->asyncReadPixels(std::move(recorder),
                                     params.withNewSource(flattened.get(),
                                     SkIRect::MakeSize(params.fSrcRect.size())));
    }

    // Can copy directly from the image's texture
    this->asyncReadTexture(std::move(recorder), params.withNewSource(view.proxy(), params.fSrcRect),
                           params.fSrcImage->imageInfo().colorInfo());
}

void Context::asyncReadTexture(std::unique_ptr<Recorder> recorder,
                               const AsyncParams<TextureProxy>& params,
                               const SkColorInfo& srcColorInfo) {
    SkASSERT(params.fSrcRect.size() == params.fDstImageInfo.dimensions());

    // We can get here directly from surface or testing-only read pixels, so re-validate
    if (!params.validate()) {
        return params.fail();
    }
    PixelTransferResult transferResult = this->transferPixels(recorder.get(),
                                                              params.fSrcImage,
                                                              srcColorInfo,
                                                              params.fDstImageInfo.colorInfo(),
                                                              params.fSrcRect);

    if (!transferResult.fTransferBuffer) {
        // TODO: try to do a synchronous readPixels instead
        return params.fail();
    }

    this->finalizeAsyncReadPixels(std::move(recorder),
                                  {&transferResult, 1},
                                  params.fCallback,
                                  params.fCallbackContext);
}

void Context::asyncRescaleAndReadPixelsYUV420(const SkImage* src,
                                              SkYUVColorSpace yuvColorSpace,
                                              sk_sp<SkColorSpace> dstColorSpace,
                                              const SkIRect& srcRect,
                                              const SkISize& dstSize,
                                              SkImage::RescaleGamma rescaleGamma,
                                              SkImage::RescaleMode rescaleMode,
                                              SkImage::ReadPixelsCallback callback,
                                              SkImage::ReadPixelsContext callbackContext) {
    // Use kOpaque alpha type to signal that we don't read back the alpha channel
    SkImageInfo dstImageInfo = SkImageInfo::Make(dstSize,
                                                 kRGBA_8888_SkColorType,
                                                 kOpaque_SkAlphaType,
                                                 std::move(dstColorSpace));
    this->asyncRescaleAndReadImpl(&Context::asyncReadPixelsYUV420,
                                  rescaleGamma, rescaleMode,
                                  {src, srcRect, dstImageInfo, callback, callbackContext},
                                  yuvColorSpace);
}

void Context::asyncRescaleAndReadPixelsYUV420(const SkSurface* src,
                                              SkYUVColorSpace yuvColorSpace,
                                              sk_sp<SkColorSpace> dstColorSpace,
                                              const SkIRect& srcRect,
                                              const SkISize& dstSize,
                                              SkImage::RescaleGamma rescaleGamma,
                                              SkImage::RescaleMode rescaleMode,
                                              SkImage::ReadPixelsCallback callback,
                                              SkImage::ReadPixelsContext callbackContext) {
    // YUV[A] readback requires the surface to be texturable since the plane conversion is performed
    // by draws. If AsImage() returns null, the image version of asyncRescaleAndReadback will
    // automatically fail.
    // TODO: Is it worth performing an extra copy from 'surface' into a texture in order to succeed?
    sk_sp<SkImage> surfaceImage = SkSurfaces::AsImage(sk_ref_sp(src));
    this->asyncRescaleAndReadPixelsYUV420(surfaceImage.get(),
                                          yuvColorSpace,
                                          dstColorSpace,
                                          srcRect,
                                          dstSize,
                                          rescaleGamma,
                                          rescaleMode,
                                          callback,
                                          callbackContext);
}

void Context::asyncRescaleAndReadPixelsYUVA420(const SkImage* src,
                                               SkYUVColorSpace yuvColorSpace,
                                               sk_sp<SkColorSpace> dstColorSpace,
                                               const SkIRect& srcRect,
                                               const SkISize& dstSize,
                                               SkImage::RescaleGamma rescaleGamma,
                                               SkImage::RescaleMode rescaleMode,
                                               SkImage::ReadPixelsCallback callback,
                                               SkImage::ReadPixelsContext callbackContext) {
    SkImageInfo dstImageInfo = SkImageInfo::Make(dstSize,
                                                 kRGBA_8888_SkColorType,
                                                 kPremul_SkAlphaType,
                                                 std::move(dstColorSpace));
    this->asyncRescaleAndReadImpl(&Context::asyncReadPixelsYUV420,
                                  rescaleGamma, rescaleMode,
                                  {src, srcRect, dstImageInfo, callback, callbackContext},
                                  yuvColorSpace);
}

void Context::asyncRescaleAndReadPixelsYUVA420(const SkSurface* src,
                                               SkYUVColorSpace yuvColorSpace,
                                               sk_sp<SkColorSpace> dstColorSpace,
                                               const SkIRect& srcRect,
                                               const SkISize& dstSize,
                                               SkImage::RescaleGamma rescaleGamma,
                                               SkImage::RescaleMode rescaleMode,
                                               SkImage::ReadPixelsCallback callback,
                                               SkImage::ReadPixelsContext callbackContext) {
    sk_sp<SkImage> surfaceImage = SkSurfaces::AsImage(sk_ref_sp(src));
    this->asyncRescaleAndReadPixelsYUVA420(surfaceImage.get(),
                                           yuvColorSpace,
                                           dstColorSpace,
                                           srcRect,
                                           dstSize,
                                           rescaleGamma,
                                           rescaleMode,
                                           callback,
                                           callbackContext);
}

void Context::asyncReadPixelsYUV420(std::unique_ptr<Recorder> recorder,
                                    const AsyncParams<SkImage>& params,
                                    SkYUVColorSpace yuvColorSpace) {
    TRACE_EVENT2("skia.gpu", TRACE_FUNC,
                 "width", params.fSrcRect.width(),
                 "height", params.fSrcRect.height());
    // This is only called by asyncRescaleAndReadImpl which already validates its parameters
    SkASSERT(params.validate());
    SkASSERT(params.fSrcRect.size() == params.fDstImageInfo.dimensions());

    // The planes are always extracted via drawing, so create the Recorder if there isn't one yet.
    if (!recorder) {
        recorder = this->makeInternalRecorder();
    }

    // copyPlane renders the source image into an A8 image and sets up a transfer stored in 'result'
    auto copyPlane = [&](SkImageInfo planeInfo,
                         std::string_view label,
                         float rgb2yuv[20],
                         const SkMatrix& texMatrix,
                         PixelTransferResult* result) {
        sk_sp<Surface> dstSurface = Surface::MakeScratch(recorder.get(),
                                                         planeInfo,
                                                         label,
                                                         Budgeted::kYes,
                                                         Mipmapped::kNo,
                                                         SkBackingFit::kApprox);
        if (!dstSurface) {
            return false;
        }

        // Render the plane defined by rgb2yuv from srcImage into dstSurface
        SkPaint paint;
        const SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kNone);
        sk_sp<SkShader> imgShader = params.fSrcImage->makeShader(
                SkTileMode::kClamp, SkTileMode::kClamp, sampling, texMatrix);
        paint.setShader(std::move(imgShader));
        paint.setBlendMode(SkBlendMode::kSrc);

        if (rgb2yuv) {
            // NOTE: The dstSurface's color space is set to the requested RGB dstColorSpace, so
            // the rendered image is automatically converted to that RGB color space before the
            // RGB->YUV color filter is evaluated, putting the plane data into the alpha channel.
            paint.setColorFilter(SkColorFilters::Matrix(rgb2yuv));
        }

        SkCanvas* canvas = dstSurface->getCanvas();
        canvas->drawPaint(paint);

        // Manually flush the surface before transferPixels() is called to ensure the rendering
        // operations run before the CopyTextureToBuffer task.
        Flush(dstSurface);
        // Must use planeInfo.bounds() for srcRect since dstSurface is kApprox-fit.
        *result = this->transferPixels(recorder.get(),
                                       dstSurface->backingTextureProxy(),
                                       dstSurface->imageInfo().colorInfo(),
                                       planeInfo.colorInfo(),
                                       planeInfo.bounds());
        return SkToBool(result->fTransferBuffer);
    };

    // Set up draws and transfers. This interleaves the drawing to a plane and the copy to the
    // transfer buffer, which will allow the scratch A8 surface to be reused for each plane.
    // TODO: Use one transfer buffer for all three planes to reduce map/unmap cost?
    const bool readAlpha = params.fDstImageInfo.colorInfo().alphaType() != kOpaque_SkAlphaType;
    SkImageInfo yaInfo = params.fDstImageInfo.makeColorType(kAlpha_8_SkColorType)
                                             .makeAlphaType(kPremul_SkAlphaType);
    SkImageInfo uvInfo = yaInfo.makeWH(yaInfo.width()/2, yaInfo.height()/2);
    PixelTransferResult transfers[4];

    float baseM[20];
    SkColorMatrix_RGB2YUV(yuvColorSpace, baseM);
    SkMatrix texMatrix = SkMatrix::Translate(-params.fSrcRect.fLeft, -params.fSrcRect.fTop);

    // This matrix generates (r,g,b,a) = (0, 0, 0, y)
    float yM[20];
    std::fill_n(yM, 15, 0.f);
    std::copy_n(baseM + 0, 5, yM + 15);
    if (!copyPlane(yaInfo, "AsyncReadPixelsYPlane", yM, texMatrix, &transfers[0])) {
        return params.fail();
    }

    // No matrix, straight copy of alpha channel
    SkASSERT(baseM[15] == 0 &&
             baseM[16] == 0 &&
             baseM[17] == 0 &&
             baseM[18] == 1 &&
             baseM[19] == 0);
    if (readAlpha &&
        !copyPlane(yaInfo, "AsyncReadPixelsAPlane", nullptr, texMatrix, &transfers[3])) {
        return params.fail();
    }

    // The UV planes are at half resolution compared to Y and A in 4:2:0
    texMatrix.postScale(0.5f, 0.5f);

    // This matrix generates (r,g,b,a) = (0, 0, 0, u)
    float uM[20];
    std::fill_n(uM, 15, 0.f);
    std::copy_n(baseM + 5, 5, uM + 15);
    if (!copyPlane(uvInfo, "AsyncReadPixelsUPlane", uM, texMatrix, &transfers[1])) {
        return params.fail();
    }

    // This matrix generates (r,g,b,a) = (0, 0, 0, v)
    float vM[20];
    std::fill_n(vM, 15, 0.f);
    std::copy_n(baseM + 10, 5, vM + 15);
    if (!copyPlane(uvInfo, "AsyncReadPixelsVPlane", vM, texMatrix, &transfers[2])) {
        return params.fail();
    }

    this->finalizeAsyncReadPixels(std::move(recorder),
                                  {transfers, readAlpha ? 4u : 3u},
                                  params.fCallback,
                                  params.fCallbackContext);
}

void Context::finalizeAsyncReadPixels(std::unique_ptr<Recorder> recorder,
                                      SkSpan<PixelTransferResult> transferResults,
                                      SkImage::ReadPixelsCallback callback,
                                      SkImage::ReadPixelsContext callbackContext) {
    // If the async readback work required a Recorder, insert the recording with all of the
    // accumulated work (which includes any copies). Otherwise, for pure copy readbacks,
    // transferPixels() already added the tasks directly to the QueueManager.
    if (recorder) {
        std::unique_ptr<Recording> recording = recorder->snap();
        if (!recording) {
            callback(callbackContext, nullptr);
            return;
        }
        InsertRecordingInfo recordingInfo;
        recordingInfo.fRecording = recording.get();
        if (!this->insertRecording(recordingInfo)) {
            callback(callbackContext, nullptr);
            return;
        }
    }

    // Set up FinishContext and add transfer commands to queue
    struct AsyncReadFinishContext {
        SkImage::ReadPixelsCallback* fClientCallback;
        SkImage::ReadPixelsContext fClientContext;
        ClientMappedBufferManager* fMappedBufferManager;
        std::array<PixelTransferResult, 4> fTransferResults;
    };

    auto finishContext = std::make_unique<AsyncReadFinishContext>();
    finishContext->fClientCallback      = callback;
    finishContext->fClientContext       = callbackContext;
    finishContext->fMappedBufferManager = fMappedBufferManager.get();

    SkASSERT(transferResults.size() <= std::size(finishContext->fTransferResults));
    skia_private::STArray<4, sk_sp<Buffer>> buffersToAsyncMap;
    for (size_t i = 0; i < transferResults.size(); ++i) {
        finishContext->fTransferResults[i] = std::move(transferResults[i]);
        if (fSharedContext->caps()->bufferMapsAreAsync()) {
            buffersToAsyncMap.push_back(finishContext->fTransferResults[i].fTransferBuffer);
        }
    }

    InsertFinishInfo info;
    info.fFinishedContext = finishContext.release();
    info.fFinishedProc = [](GpuFinishedContext c, CallbackResult status) {
        std::unique_ptr<const AsyncReadFinishContext> context(
                reinterpret_cast<const AsyncReadFinishContext*>(c));
        using AsyncReadResult = skgpu::TAsyncReadResult<Buffer, ContextID, PixelTransferResult>;

        ClientMappedBufferManager* manager = context->fMappedBufferManager;
        std::unique_ptr<AsyncReadResult> result;
        if (status == CallbackResult::kSuccess) {
            result = std::make_unique<AsyncReadResult>(manager->ownerID());
        }
        for (const auto& r : context->fTransferResults) {
            if (!r.fTransferBuffer) {
                break;
            }
            if (result && !result->addTransferResult(r, r.fSize, r.fRowBytes, manager)) {
                result.reset();
            }
            // If we didn't get this buffer into the mapped buffer manager then make sure it gets
            // unmapped if it has a pending or completed async map.
            if (!result && r.fTransferBuffer->isUnmappable()) {
                r.fTransferBuffer->unmap();
            }
        }
        (*context->fClientCallback)(context->fClientContext, std::move(result));
    };

    // If addFinishInfo() fails, it invokes the finish callback automatically, which handles all the
    // required clean up for us, just log an error message. The buffers will never be mapped and
    // thus don't need an unmap.
    if (!fQueueManager->addFinishInfo(info, fResourceProvider.get(), buffersToAsyncMap)) {
        SKGPU_LOG_E("Failed to register finish callbacks for asyncReadPixels.");
        return;
    }
}

Context::PixelTransferResult Context::transferPixels(Recorder* recorder,
                                                     const TextureProxy* srcProxy,
                                                     const SkColorInfo& srcColorInfo,
                                                     const SkColorInfo& dstColorInfo,
                                                     const SkIRect& srcRect) {
    SkASSERT(SkIRect::MakeSize(srcProxy->dimensions()).contains(srcRect));
    SkASSERT(SkColorInfoIsValid(dstColorInfo));

    const Caps* caps = fSharedContext->caps();
    if (!srcProxy || !caps->supportsReadPixels(srcProxy->textureInfo())) {
        return {};
    }

    const SkColorType srcColorType = srcColorInfo.colorType();
    SkColorType supportedColorType;
    bool isRGB888Format;
    std::tie(supportedColorType, isRGB888Format) =
            caps->supportedReadPixelsColorType(srcColorType,
                                               srcProxy->textureInfo(),
                                               dstColorInfo.colorType());
    if (supportedColorType == kUnknown_SkColorType) {
        return {};
    }

    // Fail if read color type does not have all of dstCT's color channels and those missing color
    // channels are in the src.
    uint32_t dstChannels = SkColorTypeChannelFlags(dstColorInfo.colorType());
    uint32_t legalReadChannels = SkColorTypeChannelFlags(supportedColorType);
    uint32_t srcChannels = SkColorTypeChannelFlags(srcColorType);
    if ((~legalReadChannels & dstChannels) & srcChannels) {
        return {};
    }

    int bpp = isRGB888Format ? 3 : SkColorTypeBytesPerPixel(supportedColorType);
    size_t rowBytes = caps->getAlignedTextureDataRowBytes(bpp * srcRect.width());
    size_t size = SkAlignTo(rowBytes * srcRect.height(), caps->requiredTransferBufferAlignment());
    sk_sp<Buffer> buffer = fResourceProvider->findOrCreateNonShareableBuffer(
            size, BufferType::kXferGpuToCpu, AccessPattern::kHostVisible, "TransferToCpu");
    if (!buffer) {
        return {};
    }

    // Set up copy task. Since we always use a new buffer the offset can be 0 and we don't need to
    // worry about aligning it to the required transfer buffer alignment.
    sk_sp<CopyTextureToBufferTask> copyTask = CopyTextureToBufferTask::Make(sk_ref_sp(srcProxy),
                                                                            srcRect,
                                                                            buffer,
                                                                            /*bufferOffset=*/0,
                                                                            rowBytes);
    const bool addTasksDirectly = !SkToBool(recorder);
    Protected contextIsProtected = fSharedContext->isProtected();
    if (!copyTask || (addTasksDirectly && !fQueueManager->addTask(copyTask.get(),
                                                                  this,
                                                                  contextIsProtected))) {
        return {};
    } else if (!addTasksDirectly) {
        // Add the task to the Recorder instead of the QueueManager if that's been required for
        // collecting tasks to prepare the copied textures.
        recorder->priv().add(std::move(copyTask));
    }
    sk_sp<SynchronizeToCpuTask> syncTask = SynchronizeToCpuTask::Make(buffer);
    if (!syncTask || (addTasksDirectly && !fQueueManager->addTask(syncTask.get(),
                                                                  this,
                                                                  contextIsProtected))) {
        return {};
    } else if (!addTasksDirectly) {
        recorder->priv().add(std::move(syncTask));
    }

    PixelTransferResult result;
    result.fTransferBuffer = std::move(buffer);
    result.fSize = srcRect.size();
    // srcColorInfo describes the texture; readColorInfo describes the result of the copy-to-buffer,
    // which may be different; dstColorInfo is what we have to transform it into when invoking the
    // async callbacks.
    SkColorInfo readColorInfo = srcColorInfo.makeColorType(supportedColorType);
    if (readColorInfo != dstColorInfo || isRGB888Format) {
        SkISize dims = srcRect.size();
        SkImageInfo srcInfo = SkImageInfo::Make(dims, readColorInfo);
        SkImageInfo dstInfo = SkImageInfo::Make(dims, dstColorInfo);
        result.fRowBytes = dstInfo.minRowBytes();
        result.fPixelConverter = [dstInfo, srcInfo, rowBytes, isRGB888Format](
                void* dst, const void* src) {
            SkAutoPixmapStorage temp;
            size_t srcRowBytes = rowBytes;
            if (isRGB888Format) {
                temp.alloc(srcInfo);
                size_t tRowBytes = temp.rowBytes();
                auto* sRow = reinterpret_cast<const char*>(src);
                auto* tRow = reinterpret_cast<char*>(temp.writable_addr());
                for (int y = 0; y < srcInfo.height(); ++y, sRow += srcRowBytes, tRow += tRowBytes) {
                    for (int x = 0; x < srcInfo.width(); ++x) {
                        auto s = sRow + x*3;
                        auto t = tRow + x*sizeof(uint32_t);
                        memcpy(t, s, 3);
                        t[3] = static_cast<char>(0xFF);
                    }
                }
                src = temp.addr();
                srcRowBytes = tRowBytes;
            }
            SkAssertResult(SkConvertPixels(dstInfo, dst, dstInfo.minRowBytes(),
                                           srcInfo, src, srcRowBytes));
        };
    } else {
        result.fRowBytes = rowBytes;
    }

    return result;
}

void Context::checkForFinishedWork(SyncToCpu syncToCpu) {
    ASSERT_SINGLE_OWNER

    fQueueManager->checkForFinishedWork(syncToCpu);
    fMappedBufferManager->process();
    // Process the return queue periodically to make sure it doesn't get too big
    fResourceProvider->forceProcessReturnedResources();
    fSharedContext->forceProcessReturnedResources();
}

void Context::checkAsyncWorkCompletion() {
    this->checkForFinishedWork(SyncToCpu::kNo);
}

void Context::deleteBackendTexture(const BackendTexture& texture) {
    ASSERT_SINGLE_OWNER

    if (!texture.isValid() || texture.backend() != this->backend()) {
        return;
    }
    fResourceProvider->deleteBackendTexture(texture);
}

void Context::freeGpuResources() {
    ASSERT_SINGLE_OWNER

    this->checkAsyncWorkCompletion();

    fResourceProvider->freeGpuResources();
    fSharedContext->freeGpuResources();
}

void Context::performDeferredCleanup(std::chrono::milliseconds msNotUsed) {
    ASSERT_SINGLE_OWNER

    this->checkAsyncWorkCompletion();

    auto purgeTime = skgpu::StdSteadyClock::now() - msNotUsed;
    fResourceProvider->purgeResourcesNotUsedSince(purgeTime);
    fSharedContext->purgeResourcesNotUsedSince(purgeTime);
}

size_t Context::currentBudgetedBytes() const {
    ASSERT_SINGLE_OWNER
    SkASSERT(fSharedContext->getResourceCacheCurrentBudgetedBytes() == 0);
    return fResourceProvider->getResourceCacheCurrentBudgetedBytes();
}

size_t Context::currentPurgeableBytes() const {
    ASSERT_SINGLE_OWNER
    SkASSERT(fSharedContext->getResourceCacheCurrentPurgeableBytes() == 0);
    return fResourceProvider->getResourceCacheCurrentPurgeableBytes();
}

size_t Context::maxBudgetedBytes() const {
    ASSERT_SINGLE_OWNER
    SkASSERT(fSharedContext->getResourceCacheLimit() == SharedContext::kThreadedSafeResourceBudget);
    return fResourceProvider->getResourceCacheLimit();
}

void Context::setMaxBudgetedBytes(size_t bytes) {
    ASSERT_SINGLE_OWNER
    return fResourceProvider->setResourceCacheLimit(bytes);
}

void Context::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
    ASSERT_SINGLE_OWNER
    fResourceProvider->dumpMemoryStatistics(traceMemoryDump);
    fSharedContext->dumpMemoryStatistics(traceMemoryDump);
    // TODO: What is the graphite equivalent for the text blob cache and how do we print out its
    // used bytes here (see Ganesh implementation).
}

bool Context::isDeviceLost() const {
    return fSharedContext->isDeviceLost();
}

int Context::maxTextureSize() const {
    return fSharedContext->caps()->maxTextureSize();
}

bool Context::supportsProtectedContent() const {
    return fSharedContext->isProtected() == Protected::kYes;
}

GpuStatsFlags Context::supportedGpuStats() const {
    return fSharedContext->caps()->supportedGpuStats();
}

void Context::syncPipelineData(size_t maxSize) {
    ASSERT_SINGLE_OWNER

    if (fPersistentPipelineStorage) {
        fSharedContext->syncPipelineData(fPersistentPipelineStorage, maxSize);
    }
}

void Context::startCapture() {
    if (fSharedContext->captureManager()) {
        fSharedContext->captureManager()->toggleCapture(true);
    }
}

sk_sp<SkCapture> Context::endCapture() {
    if (fSharedContext->captureManager()) {
        fSharedContext->captureManager()->toggleCapture(false);
        return fSharedContext->captureManager()->getLastCapture();
    }
    return nullptr;
}

///////////////////////////////////////////////////////////////////////////////////

#if defined(GPU_TEST_UTILS)
void Context::deregisterRecorder(const Recorder* recorder) {
    SkAutoMutexExclusive lock(fTestingLock);
    for (auto it = fTrackedRecorders.begin();
         it != fTrackedRecorders.end();
         it++) {
        if (*it == recorder) {
            fTrackedRecorders.erase(it);
            return;
        }
    }
}

bool ContextPriv::readPixels(const SkPixmap& pm,
                             const TextureProxy* textureProxy,
                             const SkImageInfo& srcImageInfo,
                             int srcX, int srcY) {
    auto rect = SkIRect::MakeXYWH(srcX, srcY, pm.width(), pm.height());
    struct AsyncContext {
        bool fCalled = false;
        std::unique_ptr<const SkImage::AsyncReadResult> fResult;
    } asyncContext;

    auto asyncCallback = [](void* c, std::unique_ptr<const SkImage::AsyncReadResult> out) {
        auto context = static_cast<AsyncContext*>(c);
        context->fResult = std::move(out);
        context->fCalled = true;
    };

    const SkColorInfo& srcColorInfo = srcImageInfo.colorInfo();

    // This is roughly equivalent to the logic taken in asyncRescaleAndRead(SkSurface) to either
    // try the image-based readback (with copy-as-draw fallbacks) or read the texture directly
    // if it supports reading.
    if (!fContext->fSharedContext->caps()->supportsReadPixels(textureProxy->textureInfo())) {
        // Since this is a synchronous testing-only API, callers should have flushed any pending
        // work that modifies this texture proxy already. This means we don't have to worry about
        // re-wrapping the proxy in a new Image (that wouldn't tbe connected to any Device, etc.).
        sk_sp<SkImage> image{new Image(TextureProxyView(sk_ref_sp(textureProxy)), srcColorInfo)};
        Context::AsyncParams<SkImage> params {image.get(), rect, pm.info(),
                                              asyncCallback, &asyncContext};
        if (!params.validate()) {
            params.fail();
        } else {
            fContext->asyncReadPixels(/*recorder=*/nullptr, params);
        }
    } else {
        fContext->asyncReadTexture(/*recorder=*/nullptr,
                                   {textureProxy, rect, pm.info(), asyncCallback, &asyncContext},
                                   srcImageInfo.colorInfo());
    }

    if (fContext->fSharedContext->caps()->allowCpuSync()) {
        fContext->submit(SyncToCpu::kYes);
    } else {
        fContext->submit(SyncToCpu::kNo);
        if (fContext->fSharedContext->backend() == BackendApi::kDawn) {
            while (!asyncContext.fCalled) {
                fContext->fSharedContext->deviceTick(fContext);
            }
        } else {
            SK_ABORT("Only Dawn supports non-syncing contexts.");
        }
    }
    SkASSERT(asyncContext.fCalled);
    if (!asyncContext.fResult) {
        return false;
    }
    SkRectMemcpy(pm.writable_addr(), pm.rowBytes(), asyncContext.fResult->data(0),
                 asyncContext.fResult->rowBytes(0), pm.info().minRowBytes(),
                 pm.height());
    return true;
}
#endif // GPU_TEST_UTILS

///////////////////////////////////////////////////////////////////////////////////

std::unique_ptr<Context> ContextCtorAccessor::MakeContext(
        sk_sp<SharedContext> sharedContext,
        std::unique_ptr<QueueManager> queueManager,
        const ContextOptions& options) {
    auto context = std::unique_ptr<Context>(new Context(std::move(sharedContext),
                                                        std::move(queueManager),
                                                        options));
    if (context && context->finishInitialization()) {
        return context;
    } else {
        return nullptr;
    }
}

} // namespace skgpu::graphite
