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

#include "src/gpu/ganesh/GrResourceProvider.h"

#include "include/core/SkAlphaType.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkData.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/private/SingleOwner.h"
#include "include/private/SkTemplates.h"
#include "src/core/SkMathPriv.h"
#include "src/core/SkMipmap.h"
#include "src/gpu/BufferWriter.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/ganesh/GrAttachment.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDataUtils.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrGpuBuffer.h"
#include "src/gpu/ganesh/GrGpuResourcePriv.h"
#include "src/gpu/ganesh/GrImageInfo.h"
#include "src/gpu/ganesh/GrPixmap.h"
#include "src/gpu/ganesh/GrRenderTarget.h"
#include "src/gpu/ganesh/GrResourceCache.h"
#include "src/gpu/ganesh/GrSemaphore.h"
#include "src/gpu/ganesh/GrSurface.h"
#include "src/gpu/ganesh/GrTexture.h"

#include <algorithm>
#include <utility>

struct SkImageInfo;

using namespace skia_private;

#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(fSingleOwner)

GrResourceProvider::GrResourceProvider(GrGpu* gpu,
                                       GrResourceCache* cache,
                                       skgpu::SingleOwner* owner)
        : fCache(cache)
        , fGpu(gpu)
#ifdef SK_DEBUG
        , fSingleOwner(owner)
#endif
{
    fCaps = sk_ref_sp(fGpu->caps());
}

sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
                                                   const GrBackendFormat& format,
                                                   GrTextureType textureType,
                                                   GrColorType colorType,
                                                   GrRenderable renderable,
                                                   int renderTargetSampleCnt,
                                                   skgpu::Budgeted budgeted,
                                                   skgpu::Mipmapped mipmapped,
                                                   GrProtected isProtected,
                                                   const GrMipLevel texels[],
                                                   std::string_view label) {
    ASSERT_SINGLE_OWNER

    if (this->isAbandoned()) {
        return nullptr;
    }

    int numMipLevels = 1;
    if (mipmapped == skgpu::Mipmapped::kYes) {
        numMipLevels = SkMipmap::ComputeLevelCount(dimensions) + 1;
    }

    if (!fCaps->validateSurfaceParams(dimensions,
                                      format,
                                      renderable,
                                      renderTargetSampleCnt,
                                      mipmapped,
                                      textureType)) {
        return nullptr;
    }
    // Current rule is that you can provide no level data, just the base, or all the levels.
    bool hasPixels = texels[0].fPixels;
    auto scratch = this->getExactScratch(dimensions,
                                         format,
                                         textureType,
                                         renderable,
                                         renderTargetSampleCnt,
                                         budgeted,
                                         mipmapped,
                                         isProtected,
                                         label);
    if (scratch) {
        if (!hasPixels) {
            return scratch;
        }
        return this->writePixels(std::move(scratch), colorType, dimensions, texels, numMipLevels);
    }
    AutoSTArray<14, GrMipLevel> tmpTexels;
    AutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
    GrColorType tempColorType = GrColorType::kUnknown;
    if (hasPixels) {
        tempColorType = this->prepareLevels(format, colorType, dimensions, texels, numMipLevels,
                                            &tmpTexels, &tmpDatas);
        if (tempColorType == GrColorType::kUnknown) {
            return nullptr;
        }
    }
    return fGpu->createTexture(dimensions,
                               format,
                               textureType,
                               renderable,
                               renderTargetSampleCnt,
                               budgeted,
                               isProtected,
                               colorType,
                               tempColorType,
                               tmpTexels.get(),
                               numMipLevels,
                               label);
}

sk_sp<GrTexture> GrResourceProvider::getExactScratch(SkISize dimensions,
                                                     const GrBackendFormat& format,
                                                     GrTextureType textureType,
                                                     GrRenderable renderable,
                                                     int renderTargetSampleCnt,
                                                     skgpu::Budgeted budgeted,
                                                     skgpu::Mipmapped mipmapped,
                                                     GrProtected isProtected,
                                                     std::string_view label) {
    sk_sp<GrTexture> tex(this->findAndRefScratchTexture(dimensions,
                                                        format,
                                                        textureType,
                                                        renderable,
                                                        renderTargetSampleCnt,
                                                        mipmapped,
                                                        isProtected,
                                                        label));
    if (tex && skgpu::Budgeted::kNo == budgeted) {
        tex->resourcePriv().makeUnbudgeted();
    }

    return tex;
}

sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
                                                   const GrBackendFormat& format,
                                                   GrTextureType textureType,
                                                   GrColorType colorType,
                                                   GrRenderable renderable,
                                                   int renderTargetSampleCnt,
                                                   skgpu::Budgeted budgeted,
                                                   SkBackingFit fit,
                                                   GrProtected isProtected,
                                                   const GrMipLevel& mipLevel,
                                                   std::string_view label) {
    ASSERT_SINGLE_OWNER

    if (!mipLevel.fPixels) {
        return nullptr;
    }

    if (SkBackingFit::kApprox == fit) {
        if (this->isAbandoned()) {
            return nullptr;
        }
        if (!fCaps->validateSurfaceParams(dimensions,
                                          format,
                                          renderable,
                                          renderTargetSampleCnt,
                                          skgpu::Mipmapped::kNo,
                                          textureType)) {
            return nullptr;
        }

        auto tex = this->createApproxTexture(dimensions,
                                             format,
                                             textureType,
                                             renderable,
                                             renderTargetSampleCnt,
                                             isProtected,
                                             label);
        if (!tex) {
            return nullptr;
        }
        return this->writePixels(std::move(tex), colorType, dimensions, &mipLevel, 1);
    } else {
        return this->createTexture(dimensions,
                                   format,
                                   textureType,
                                   colorType,
                                   renderable,
                                   renderTargetSampleCnt,
                                   budgeted,
                                   skgpu::Mipmapped::kNo,
                                   isProtected,
                                   &mipLevel,
                                   label);
    }
}

sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(SkISize dimensions,
                                                             const GrBackendFormat& format,
                                                             skgpu::Budgeted budgeted,
                                                             skgpu::Mipmapped mipmapped,
                                                             GrProtected isProtected,
                                                             SkData* data,
                                                             std::string_view label) {
    ASSERT_SINGLE_OWNER
    if (this->isAbandoned()) {
        return nullptr;
    }
    return fGpu->createCompressedTexture(dimensions,
                                         format,
                                         budgeted,
                                         mipmapped,
                                         isProtected,
                                         data->data(),
                                         data->size());
}

sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
                                                   const GrBackendFormat& format,
                                                   GrTextureType textureType,
                                                   GrRenderable renderable,
                                                   int renderTargetSampleCnt,
                                                   skgpu::Mipmapped mipmapped,
                                                   skgpu::Budgeted budgeted,
                                                   GrProtected isProtected,
                                                   std::string_view label) {
    ASSERT_SINGLE_OWNER
    if (this->isAbandoned()) {
        return nullptr;
    }

    if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
                                      mipmapped, textureType)) {
        return nullptr;
    }

    // Currently we don't recycle compressed textures as scratch. Additionally all compressed
    // textures should be created through the createCompressedTexture function.
    SkASSERT(!this->caps()->isFormatCompressed(format));

    // TODO: Support skgpu::Mipmapped::kYes in scratch texture lookup here.
    sk_sp<GrTexture> tex =
            this->getExactScratch(dimensions,
                                  format,
                                  textureType,
                                  renderable,
                                  renderTargetSampleCnt,
                                  budgeted,
                                  mipmapped,
                                  isProtected,
                                  label);
    if (tex) {
        return tex;
    }

    return fGpu->createTexture(dimensions,
                               format,
                               textureType,
                               renderable,
                               renderTargetSampleCnt,
                               mipmapped,
                               budgeted,
                               isProtected,
                               label);
}

sk_sp<GrTexture> GrResourceProvider::createApproxTexture(SkISize dimensions,
                                                         const GrBackendFormat& format,
                                                         GrTextureType textureType,
                                                         GrRenderable renderable,
                                                         int renderTargetSampleCnt,
                                                         GrProtected isProtected,
                                                         std::string_view label) {
    ASSERT_SINGLE_OWNER

    if (this->isAbandoned()) {
        return nullptr;
    }

    // Currently we don't recycle compressed textures as scratch. Additionally all compressed
    // textures should be created through the createCompressedTexture function.
    SkASSERT(!this->caps()->isFormatCompressed(format));

    if (!fCaps->validateSurfaceParams(dimensions,
                                      format,
                                      renderable,
                                      renderTargetSampleCnt,
                                      skgpu::Mipmapped::kNo,
                                      textureType)) {
        return nullptr;
    }

    auto copyDimensions = skgpu::GetApproxSize(dimensions);

    if (auto tex = this->findAndRefScratchTexture(copyDimensions,
                                                  format,
                                                  textureType,
                                                  renderable,
                                                  renderTargetSampleCnt,
                                                  skgpu::Mipmapped::kNo,
                                                  isProtected,
                                                  label)) {
        return tex;
    }

    return fGpu->createTexture(copyDimensions,
                               format,
                               textureType,
                               renderable,
                               renderTargetSampleCnt,
                               skgpu::Mipmapped::kNo,
                               skgpu::Budgeted::kYes,
                               isProtected,
                               label);
}

sk_sp<GrTexture> GrResourceProvider::findAndRefScratchTexture(const skgpu::ScratchKey& key,
                                                              std::string_view label) {
    ASSERT_SINGLE_OWNER
    SkASSERT(!this->isAbandoned());
    SkASSERT(key.isValid());

    if (GrGpuResource* resource = fCache->findAndRefScratchResource(key)) {
        fGpu->stats()->incNumScratchTexturesReused();
        GrSurface* surface = static_cast<GrSurface*>(resource);
        resource->setLabel(label);
        return sk_sp<GrTexture>(surface->asTexture());
    }
    return nullptr;
}

sk_sp<GrTexture> GrResourceProvider::findAndRefScratchTexture(SkISize dimensions,
                                                              const GrBackendFormat& format,
                                                              GrTextureType textureType,
                                                              GrRenderable renderable,
                                                              int renderTargetSampleCnt,
                                                              skgpu::Mipmapped mipmapped,
                                                              GrProtected isProtected,
                                                              std::string_view label) {
    ASSERT_SINGLE_OWNER
    SkASSERT(!this->isAbandoned());
    SkASSERT(!this->caps()->isFormatCompressed(format));
    SkASSERT(fCaps->validateSurfaceParams(dimensions,
                                          format,
                                          renderable,
                                          renderTargetSampleCnt,
                                          skgpu::Mipmapped::kNo,
                                          textureType));

    // We could make initial clears work with scratch textures but it is a rare case so we just opt
    // to fall back to making a new texture.
    if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
        skgpu::ScratchKey key;
        GrTexture::ComputeScratchKey(*this->caps(), format, dimensions, renderable,
                                     renderTargetSampleCnt, mipmapped, isProtected, &key);
        return this->findAndRefScratchTexture(key, label);
    }

    return nullptr;
}

sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
                                                        GrWrapOwnership ownership,
                                                        GrWrapCacheable cacheable,
                                                        GrIOType ioType) {
    ASSERT_SINGLE_OWNER
    if (this->isAbandoned()) {
        return nullptr;
    }
    return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
}

sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
                                                                  GrWrapOwnership ownership,
                                                                  GrWrapCacheable cacheable) {
    ASSERT_SINGLE_OWNER
    if (this->isAbandoned()) {
        return nullptr;
    }

    return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
}


sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
                                                                  int sampleCnt,
                                                                  GrWrapOwnership ownership,
                                                                  GrWrapCacheable cacheable) {
    ASSERT_SINGLE_OWNER
    if (this->isAbandoned()) {
        return nullptr;
    }
    return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
}

sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
        const GrBackendRenderTarget& backendRT) {
    ASSERT_SINGLE_OWNER
    return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
}

sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
        const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
    ASSERT_SINGLE_OWNER
    return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
                                                                                     vkInfo);

}

void GrResourceProvider::assignUniqueKeyToResource(const skgpu::UniqueKey& key,
                                                   GrGpuResource* resource) {
    ASSERT_SINGLE_OWNER
    if (this->isAbandoned() || !resource) {
        return;
    }
    resource->resourcePriv().setUniqueKey(key);
}

sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const skgpu::UniqueKey& key) {
    ASSERT_SINGLE_OWNER
    return this->isAbandoned() ? nullptr
                               : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
}

sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
                                                                    size_t size,
                                                                    const void* staticData,
                                                                    const skgpu::UniqueKey& key) {
    if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
        return buffer;
    }

    auto buffer = this->createBuffer(staticData, size, intendedType, kStatic_GrAccessPattern);
    if (!buffer) {
        return nullptr;
    }

    // We shouldn't bin and/or cache static buffers.
    SkASSERT(buffer->size() == size);
    SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());

    buffer->resourcePriv().setUniqueKey(key);

    return buffer;
}

sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(
        GrGpuBufferType intendedType,
        size_t size,
        const skgpu::UniqueKey& uniqueKey,
        InitializeBufferFn initializeBufferFn) {
    if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(uniqueKey)) {
        return buffer;
    }

    auto buffer = this->createBuffer(size,
                                     intendedType,
                                     kStatic_GrAccessPattern,
                                     ZeroInit::kNo);
    if (!buffer) {
        return nullptr;
    }

    // We shouldn't bin and/or cache static buffers.
    SkASSERT(buffer->size() == size);
    SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());

    buffer->resourcePriv().setUniqueKey(uniqueKey);

    // Map the buffer. Use a staging buffer on the heap if mapping isn't supported.
    skgpu::VertexWriter vertexWriter = {buffer->map(), size};
    AutoTMalloc<char> stagingBuffer;
    if (!vertexWriter) {
        SkASSERT(!buffer->isMapped());
        vertexWriter = skgpu::VertexWriter{stagingBuffer.reset(size), size};
    }

    initializeBufferFn(std::move(vertexWriter), size);

    if (buffer->isMapped()) {
        buffer->unmap();
    } else {
        buffer->updateData(stagingBuffer, /*offset=*/0, size, /*preserve=*/false);
    }

    return buffer;
}

sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(
        const uint16_t* pattern,
        int patternSize,
        int reps,
        int vertCount,
        const skgpu::UniqueKey* key) {
    size_t bufferSize = patternSize * reps * sizeof(uint16_t);

    sk_sp<GrGpuBuffer> buffer = this->createBuffer(bufferSize,
                                                   GrGpuBufferType::kIndex,
                                                   kStatic_GrAccessPattern,
                                                   ZeroInit::kNo);
    if (!buffer) {
        return nullptr;
    }
    uint16_t* data = (uint16_t*) buffer->map();
    AutoTArray<uint16_t> temp;
    if (!data) {
        temp.reset(reps * patternSize);
        data = temp.get();
    }
    for (int i = 0; i < reps; ++i) {
        int baseIdx = i * patternSize;
        uint16_t baseVert = (uint16_t)(i * vertCount);
        for (int j = 0; j < patternSize; ++j) {
            data[baseIdx+j] = baseVert + pattern[j];
        }
    }
    if (temp.get()) {
        if (!buffer->updateData(data, /*offset=*/0, bufferSize, /*preserve=*/false)) {
            return nullptr;
        }
    } else {
        buffer->unmap();
    }
    if (key) {
        SkASSERT(key->isValid());
        this->assignUniqueKeyToResource(*key, buffer.get());
    }
    return buffer;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
static constexpr int kMaxNumNonAAQuads = 1 << 12;  // max possible: (1 << 14) - 1;
static const int kVertsPerNonAAQuad = 4;
static const int kIndicesPerNonAAQuad = 6;

sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
    static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535);  // indices fit in a uint16_t

    static const uint16_t kNonAAQuadIndexPattern[] = {
        0, 1, 2, 2, 1, 3
    };

    static_assert(std::size(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);

    return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
                                            kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
}

int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }

///////////////////////////////////////////////////////////////////////////////////////////////////
static constexpr int kMaxNumAAQuads = 1 << 9;  // max possible: (1 << 13) - 1;
static const int kVertsPerAAQuad = 8;
static const int kIndicesPerAAQuad = 30;

sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
    static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535);  // indices fit in a uint16_t

    // clang-format off
    static const uint16_t kAAQuadIndexPattern[] = {
        0, 1, 2, 1, 3, 2,
        0, 4, 1, 4, 5, 1,
        0, 6, 4, 0, 2, 6,
        2, 3, 6, 3, 7, 6,
        1, 5, 3, 3, 5, 7,
    };
    // clang-format on

    static_assert(std::size(kAAQuadIndexPattern) == kIndicesPerAAQuad);

    return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
                                            kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
}

int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }

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

sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size,
                                                    GrGpuBufferType intendedType,
                                                    GrAccessPattern accessPattern,
                                                    ZeroInit zeroInit) {
    if (this->isAbandoned()) {
        return nullptr;
    }
    if (kDynamic_GrAccessPattern != accessPattern) {
        if (this->caps()->buffersAreInitiallyZero()) {
            zeroInit = ZeroInit::kNo;
        }
        sk_sp<GrGpuBuffer> buffer = this->gpu()->createBuffer(size, intendedType, accessPattern);
        if (buffer && zeroInit == ZeroInit::kYes && !buffer->clearToZero()) {
            return nullptr;
        }
        return buffer;
    }
    // bin by pow2+midpoint with a reasonable min
    static const size_t MIN_SIZE = 1 << 12;
    static const size_t MIN_UNIFORM_SIZE = 1 << 7;
    size_t allocSize = intendedType == GrGpuBufferType::kUniform ? std::max(size, MIN_UNIFORM_SIZE)
                                                                 : std::max(size, MIN_SIZE);
    size_t ceilPow2 = SkNextSizePow2(allocSize);
    size_t floorPow2 = ceilPow2 >> 1;
    size_t mid = floorPow2 + (floorPow2 >> 1);
    allocSize = (allocSize <= mid) ? mid : ceilPow2;

    skgpu::ScratchKey key;
    GrGpuBuffer::ComputeScratchKeyForDynamicBuffer(allocSize, intendedType, &key);
    auto buffer =
            sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
                    key)));
    if (!buffer) {
        if (this->caps()->buffersAreInitiallyZero()) {
            zeroInit = ZeroInit::kNo;
        }
        buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
    }
    if (buffer && zeroInit == ZeroInit::kYes && !buffer->clearToZero()) {
        return nullptr;
    }
    return buffer;
}

sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(const void* data,
                                                    size_t size,
                                                    GrGpuBufferType type,
                                                    GrAccessPattern pattern) {
    SkASSERT(data);
    auto buffer = this->createBuffer(size, type, pattern, ZeroInit::kNo);
    if (!buffer) {
        return nullptr;
    }
    if (!buffer->updateData(data, /*offset=*/0, size, /*preserve=*/false)) {
        return nullptr;
    }
    return buffer;
}

static int num_stencil_samples(const GrRenderTarget* rt, bool useMSAASurface, const GrCaps& caps) {
    int numSamples = rt->numSamples();
    if (numSamples == 1 && useMSAASurface) {  // Are we using dynamic msaa?
        numSamples = caps.internalMultisampleCount(rt->backendFormat());
        SkASSERT(numSamples > 1);  // Caller must ensure dmsaa is supported before trying to use it.
    }
    return numSamples;
}

bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, bool useMSAASurface) {
    SkASSERT(rt);
    SkASSERT(!this->caps()->avoidStencilBuffers());

    GrAttachment* stencil = rt->getStencilAttachment(useMSAASurface);
    if (stencil) {
        SkASSERT(stencil->numSamples() == num_stencil_samples(rt, useMSAASurface, *this->caps()));
        return true;
    }

    if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment(useMSAASurface)) {
        skgpu::UniqueKey sbKey;

#if 0
        if (this->caps()->oversizedStencilSupport()) {
            width  = SkNextPow2(width);
            height = SkNextPow2(height);
        }
#endif
        GrBackendFormat stencilFormat = this->gpu()->getPreferredStencilFormat(rt->backendFormat());
        if (!stencilFormat.isValid()) {
            return false;
        }
        GrProtected isProtected = rt->isProtected() ? GrProtected::kYes : GrProtected::kNo;
        int numStencilSamples = num_stencil_samples(rt, useMSAASurface, *this->caps());
        GrAttachment::ComputeSharedAttachmentUniqueKey(*this->caps(),
                                                       stencilFormat,
                                                       rt->dimensions(),
                                                       GrAttachment::UsageFlags::kStencilAttachment,
                                                       numStencilSamples,
                                                       skgpu::Mipmapped::kNo,
                                                       isProtected,
                                                       GrMemoryless::kNo,
                                                       &sbKey);
        auto keyedStencil = this->findByUniqueKey<GrAttachment>(sbKey);
        if (!keyedStencil) {
            // Need to try and create a new stencil
            keyedStencil = this->gpu()->makeStencilAttachment(rt->backendFormat(), rt->dimensions(),
                                                              numStencilSamples);
            if (!keyedStencil) {
                return false;
            }
            this->assignUniqueKeyToResource(sbKey, keyedStencil.get());
        }
        rt->attachStencilAttachment(std::move(keyedStencil), useMSAASurface);
    }
    stencil = rt->getStencilAttachment(useMSAASurface);
    SkASSERT(!stencil ||
             stencil->numSamples() == num_stencil_samples(rt, useMSAASurface, *this->caps()));
    return stencil != nullptr;
}

sk_sp<GrAttachment> GrResourceProvider::getDiscardableMSAAAttachment(SkISize dimensions,
                                                                     const GrBackendFormat& format,
                                                                     int sampleCnt,
                                                                     GrProtected isProtected,
                                                                     GrMemoryless memoryless) {
    ASSERT_SINGLE_OWNER

    SkASSERT(sampleCnt > 1);

    if (this->isAbandoned()) {
        return nullptr;
    }

    if (!fCaps->validateSurfaceParams(dimensions,
                                      format,
                                      GrRenderable::kYes,
                                      sampleCnt,
                                      skgpu::Mipmapped::kNo,
                                      GrTextureType::kNone)) {
        return nullptr;
    }

    skgpu::UniqueKey key;
    GrAttachment::ComputeSharedAttachmentUniqueKey(*this->caps(),
                                                   format,
                                                   dimensions,
                                                   GrAttachment::UsageFlags::kColorAttachment,
                                                   sampleCnt,
                                                   skgpu::Mipmapped::kNo,
                                                   isProtected,
                                                   memoryless,
                                                   &key);
    auto msaaAttachment = this->findByUniqueKey<GrAttachment>(key);
    if (msaaAttachment) {
        return msaaAttachment;
    }
    msaaAttachment = this->makeMSAAAttachment(dimensions, format, sampleCnt, isProtected,
                                              memoryless);
    if (msaaAttachment) {
        this->assignUniqueKeyToResource(key, msaaAttachment.get());
    }
    return msaaAttachment;
}

sk_sp<GrAttachment> GrResourceProvider::makeMSAAAttachment(SkISize dimensions,
                                                           const GrBackendFormat& format,
                                                           int sampleCnt,
                                                           GrProtected isProtected,
                                                           GrMemoryless memoryless) {
    ASSERT_SINGLE_OWNER

    SkASSERT(sampleCnt > 1);

    if (this->isAbandoned()) {
        return nullptr;
    }

    if (!fCaps->validateSurfaceParams(dimensions,
                                      format,
                                      GrRenderable::kYes,
                                      sampleCnt,
                                      skgpu::Mipmapped::kNo,
                                      GrTextureType::kNone)) {
        return nullptr;
    }

    auto scratch = this->refScratchMSAAAttachment(dimensions,
                                                  format,
                                                  sampleCnt,
                                                  isProtected,
                                                  memoryless,
                                                  /*label=*/"MakeMSAAAttachment");
    if (scratch) {
        return scratch;
    }

    return fGpu->makeMSAAAttachment(dimensions, format, sampleCnt, isProtected, memoryless);
}

sk_sp<GrAttachment> GrResourceProvider::refScratchMSAAAttachment(SkISize dimensions,
                                                                 const GrBackendFormat& format,
                                                                 int sampleCnt,
                                                                 GrProtected isProtected,
                                                                 GrMemoryless memoryless,
                                                                 std::string_view label) {
    ASSERT_SINGLE_OWNER
    SkASSERT(!this->isAbandoned());
    SkASSERT(!this->caps()->isFormatCompressed(format));
    SkASSERT(fCaps->validateSurfaceParams(dimensions,
                                          format,
                                          GrRenderable::kYes,
                                          sampleCnt,
                                          skgpu::Mipmapped::kNo,
                                          GrTextureType::kNone));

    skgpu::ScratchKey key;
    GrAttachment::ComputeScratchKey(*this->caps(),
                                    format,
                                    dimensions,
                                    GrAttachment::UsageFlags::kColorAttachment,
                                    sampleCnt,
                                    skgpu::Mipmapped::kNo,
                                    isProtected,
                                    memoryless,
                                    &key);
    GrGpuResource* resource = fCache->findAndRefScratchResource(key);
    if (resource) {
        fGpu->stats()->incNumScratchMSAAAttachmentsReused();
        GrAttachment* attachment = static_cast<GrAttachment*>(resource);
        resource->setLabel(label);
        return sk_sp<GrAttachment>(attachment);
    }

    return nullptr;
}

[[nodiscard]] std::unique_ptr<GrSemaphore> GrResourceProvider::makeSemaphore(bool isOwned) {
    return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
}

std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
        const GrBackendSemaphore& semaphore,
        GrSemaphoreWrapType wrapType,
        GrWrapOwnership ownership) {
    ASSERT_SINGLE_OWNER
    return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
                                                                      wrapType,
                                                                      ownership);
}

// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
static bool prepare_level(const GrMipLevel& inLevel,
                          SkISize dimensions,
                          bool rowBytesSupport,
                          GrColorType origColorType,
                          GrColorType allowedColorType,
                          GrMipLevel* outLevel,
                          std::unique_ptr<char[]>* data) {
    if (!inLevel.fPixels) {
        outLevel->fPixels = nullptr;
        outLevel->fRowBytes = 0;
        return true;
    }
    size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
    size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
    if (actualRB < minRB) {
        return false;
    }
    if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
        outLevel->fRowBytes = actualRB;
        outLevel->fPixels = inLevel.fPixels;
        return true;
    }
    auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
    data->reset(new char[tempRB * dimensions.fHeight]);
    outLevel->fPixels = data->get();
    outLevel->fRowBytes = tempRB;
    GrImageInfo srcInfo(   origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
    GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
    return GrConvertPixels( GrPixmap(dstInfo,     data->get(),   tempRB),
                           GrCPixmap(srcInfo, inLevel.fPixels, actualRB));
}

GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
                                              GrColorType colorType,
                                              SkISize baseSize,
                                              const GrMipLevel texels[],
                                              int mipLevelCount,
                                              TempLevels* tempLevels,
                                              TempLevelDatas* tempLevelDatas) const {
    SkASSERT(mipLevelCount && texels && texels[0].fPixels);

    auto allowedColorType =
            this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
    if (allowedColorType == GrColorType::kUnknown) {
        return GrColorType::kUnknown;
    }
    bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
    tempLevels->reset(mipLevelCount);
    tempLevelDatas->reset(mipLevelCount);
    auto size = baseSize;
    for (int i = 0; i < mipLevelCount; ++i) {
        if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
                           &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
            return GrColorType::kUnknown;
        }
        size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
    }
    return allowedColorType;
}

sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
                                                 GrColorType colorType,
                                                 SkISize baseSize,
                                                 const GrMipLevel texels[],
                                                 int mipLevelCount) const {
    SkASSERT(!this->isAbandoned());
    SkASSERT(texture);
    SkASSERT(colorType != GrColorType::kUnknown);
    SkASSERT(mipLevelCount && texels && texels[0].fPixels);

    AutoSTArray<14, GrMipLevel> tmpTexels;
    AutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
    auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
                                             mipLevelCount, &tmpTexels, &tmpDatas);
    if (tempColorType == GrColorType::kUnknown) {
        return nullptr;
    }
    SkAssertResult(fGpu->writePixels(texture.get(),
                                     SkIRect::MakeSize(baseSize),
                                     colorType,
                                     tempColorType,
                                     tmpTexels.get(),
                                     mipLevelCount));
    return texture;
}
