/*
 * 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 "src/gpu/graphite/ResourceProvider.h"

#include "include/core/SkSamplingOptions.h"
#include "include/core/SkTileMode.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/CommandBuffer.h"
#include "src/gpu/graphite/ComputePipeline.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/GlobalCache.h"
#include "src/gpu/graphite/GraphicsPipeline.h"
#include "src/gpu/graphite/GraphicsPipelineHandle.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/PipelineCreationTask.h"
#include "src/gpu/graphite/PipelineManager.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/ResourceCache.h"
#include "src/gpu/graphite/RuntimeEffectDictionary.h"
#include "src/gpu/graphite/Sampler.h"
#include "src/gpu/graphite/SharedContext.h"
#include "src/gpu/graphite/Texture.h"
#include "src/sksl/SkSLCompiler.h"

namespace skgpu::graphite {

ResourceProvider::ResourceProvider(SharedContext* sharedContext,
                                   SingleOwner* singleOwner,
                                   uint32_t recorderID,
                                   size_t resourceBudget)
        : fSharedContext(sharedContext)
        , fResourceCache(ResourceCache::Make(singleOwner, recorderID, resourceBudget)) {}

ResourceProvider::~ResourceProvider() {
    fResourceCache->shutdown();
}

GraphicsPipelineHandle ResourceProvider::createGraphicsPipelineHandle(
        const GraphicsPipelineDesc& pipelineDesc,
        const RenderPassDesc& renderPassDesc,
        SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags) {

    PipelineManager* pipelineManager = fSharedContext->pipelineManager();

    return pipelineManager->createHandle(fSharedContext,
                                         pipelineDesc,
                                         renderPassDesc,
                                         pipelineCreationFlags);
}

void ResourceProvider::startPipelineCreationTask(sk_sp<const RuntimeEffectDictionary> runtimeDict,
                                                 const GraphicsPipelineHandle& handle) {
    PipelineManager* pipelineManager = fSharedContext->pipelineManager();

    pipelineManager->startPipelineCreationTask(fSharedContext,
                                               std::move(runtimeDict),
                                               handle);
}

sk_sp<GraphicsPipeline> ResourceProvider::resolveHandle(const GraphicsPipelineHandle& handle) {
    PipelineManager* pipelineManager = fSharedContext->pipelineManager();

    return pipelineManager->resolveHandle(handle);
}

sk_sp<ComputePipeline> ResourceProvider::findOrCreateComputePipeline(
        const ComputePipelineDesc& pipelineDesc) {
    auto globalCache = fSharedContext->globalCache();
    UniqueKey pipelineKey = fSharedContext->caps()->makeComputePipelineKey(pipelineDesc);
    sk_sp<ComputePipeline> pipeline = globalCache->findComputePipeline(pipelineKey);
    if (!pipeline) {
        pipeline = this->createComputePipeline(pipelineDesc);
        if (pipeline) {
            pipeline = globalCache->addComputePipeline(pipelineKey, std::move(pipeline));
        }
    }
    return pipeline;
}

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

sk_sp<Texture> ResourceProvider::findOrCreateShareableTexture(SkISize dimensions,
                                                              const TextureInfo& info,
                                                              std::string_view label) {
    return this->findOrCreateTexture(dimensions,
                                     info,
                                     std::move(label),
                                     Budgeted::kYes,
                                     Shareable::kYes);
}

sk_sp<Texture> ResourceProvider::findOrCreateNonShareableTexture(SkISize dimensions,
                                                                 const TextureInfo& info,
                                                                 std::string_view label,
                                                                 Budgeted budgeted) {
    return this->findOrCreateTexture(dimensions,
                                     info,
                                     std::move(label),
                                     budgeted,
                                     Shareable::kNo);
}

sk_sp<Texture> ResourceProvider::findOrCreateScratchTexture(
        SkISize dimensions,
        const TextureInfo& info,
        std::string_view label,
        const ResourceCache::ScratchResourceSet& unavailable) {
    return this->findOrCreateTexture(dimensions,
                                     info,
                                     std::move(label),
                                     Budgeted::kYes,
                                     Shareable::kScratch,
                                     &unavailable);
}

sk_sp<Texture> ResourceProvider::findOrCreateTexture(
        SkISize dimensions,
        const TextureInfo& info,
        std::string_view label,
        Budgeted budgeted,
        Shareable shareable,
        const ResourceCache::ScratchResourceSet* unavailable) {
    // If the resource is shareable it should be budgeted since it shouldn't be backing any client
    // owned object.
    SkASSERT(shareable == Shareable::kNo || budgeted == Budgeted::kYes);
    SkASSERT(shareable != Shareable::kScratch || SkToBool(unavailable));

    static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();

    if (!info.isValid()) {
        // Checking for a valid TextureInfo here allows callers to consolidate error checking for
        // both TextureInfo and Texture creation to checking for a null returned Texture.
        return nullptr;
    }

    GraphiteResourceKey key;
    fSharedContext->caps()->buildKeyForTexture(dimensions, info, kType, &key);

    if (Resource* resource =
                fResourceCache->findAndRefResource(key, budgeted, shareable, unavailable)) {
        // Shareable resource labels should only be set upon creation.
        if (shareable == Shareable::kYes) {
            SkASSERT(resource->getLabel() == label);
        } else {
            resource->setLabel(std::move(label));
        }
        return sk_sp<Texture>(static_cast<Texture*>(resource));
    }

    auto tex = this->createTexture(dimensions, info);
    if (!tex) {
        return nullptr;
    }

    tex->setLabel(std::move(label));
    fResourceCache->insertResource(tex.get(), key, budgeted, shareable);

    return tex;
}

sk_sp<Texture> ResourceProvider::createWrappedTexture(const BackendTexture& backendTexture,
                                                      std::string_view label) {
    sk_sp<Texture> texture = this->onCreateWrappedTexture(backendTexture);
    if (texture) {
        texture->setLabel(std::move(label));
        SkASSERT(texture->ownership() == Ownership::kWrapped);
    }
    return texture;
}

sk_sp<Sampler> ResourceProvider::findOrCreateCompatibleSampler(const SamplerDesc& samplerDesc) {
    static constexpr Budgeted kBudgeted = Budgeted::kYes;
    static constexpr Shareable kShareable = Shareable::kYes;
    static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();

    GraphiteResourceKey key;
    {
        // The size of the returned span accurately captures the quantity of uint32s needed whether
        // the sampler is immutable or not. Each backend will already have encoded any specific
        // immutable sampler details into the SamplerDesc, so there is no need to delegate to Caps
        // to create a specific key.
        const SkSpan<const uint32_t>& samplerData = samplerDesc.asSpan();
        GraphiteResourceKey::Builder builder(&key, kType, samplerData.size());

        for (size_t i = 0; i < samplerData.size(); i++) {
            builder[i] = samplerData[i];
        }
    }

    if (Resource* resource = fResourceCache->findAndRefResource(key, kBudgeted, kShareable)) {
        return sk_sp<Sampler>(static_cast<Sampler*>(resource));
    }

    sk_sp<Sampler> sampler = this->createSampler(samplerDesc);
    if (!sampler) {
        return nullptr;
    }

    fResourceCache->insertResource(sampler.get(), key, kBudgeted, kShareable);
    return sampler;
}

sk_sp<Buffer> ResourceProvider::findOrCreateNonShareableBuffer(size_t size,
                                                               BufferType type,
                                                               AccessPattern accessPattern,
                                                               std::string_view label) {
    return this->findOrCreateBuffer(size, type, accessPattern, label, Shareable::kNo);
}

sk_sp<Buffer> ResourceProvider::findOrCreateScratchBuffer(
        size_t size,
        BufferType type,
        AccessPattern access,
        std::string_view label,
        const ResourceCache::ScratchResourceSet& unvailable) {
    // Scratch buffers must be GPU only, mapped access makes it too difficult to scope their
    // reads and writes within the actual command buffer execution.
    SkASSERT(access != AccessPattern::kHostVisible);
    return this->findOrCreateBuffer(size, type, access, label, Shareable::kScratch, &unvailable);
}

sk_sp<Buffer> ResourceProvider::findOrCreateBuffer(
        size_t size,
        BufferType type,
        AccessPattern accessPattern,
        std::string_view label,
        Shareable shareable,
        const ResourceCache::ScratchResourceSet* unavailable) {
    static constexpr Budgeted kBudgeted = Budgeted::kYes;
    static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();

    GraphiteResourceKey key;
    {
        // For the key we need ((sizeof(size_t) + (sizeof(uint32_t) - 1)) / (sizeof(uint32_t))
        // uint32_t's for the size and one uint32_t for the rest.
        static_assert(sizeof(uint32_t) == 4);
        static const int kSizeKeyNum32DataCnt = (sizeof(size_t) + 3) / 4;
        static const int kKeyNum32DataCnt =  kSizeKeyNum32DataCnt + 1;

        SkASSERT(static_cast<uint32_t>(type) < (1u << 4));
        SkASSERT(static_cast<uint32_t>(accessPattern) < (1u << 2));

        GraphiteResourceKey::Builder builder(&key, kType, kKeyNum32DataCnt);
        builder[0] = (static_cast<uint32_t>(type) << 0) |
                     (static_cast<uint32_t>(accessPattern) << 4);
        size_t szKey = size;
        for (int i = 0; i < kSizeKeyNum32DataCnt; ++i) {
            builder[i + 1] = (uint32_t) szKey;

            // If size_t is 4 bytes, we cannot do a shift of 32 or else we get a warning/error that
            // shift amount is >= width of the type.
            if constexpr(kSizeKeyNum32DataCnt > 1) {
                szKey = szKey >> 32;
            }
        }
    }

    if (Resource* resource =
            fResourceCache->findAndRefResource(key, kBudgeted, shareable, unavailable)) {
        // Shareable resource labels should only be set upon creation.
        if (shareable == Shareable::kYes) {
            SkASSERT(resource->getLabel() == label);
        } else {
            resource->setLabel(std::move(label));
        }
        return sk_sp<Buffer>(static_cast<Buffer*>(resource));
    }
    auto buffer = this->createBuffer(size, type, accessPattern);
    if (!buffer) {
        return nullptr;
    }

    buffer->setLabel(std::move(label));
    fResourceCache->insertResource(buffer.get(), key, kBudgeted, shareable);
    return buffer;
}

namespace {
bool dimensions_are_valid(const int maxTextureSize, const SkISize& dimensions) {
    if (dimensions.isEmpty() ||
        dimensions.width()  > maxTextureSize ||
        dimensions.height() > maxTextureSize) {
        SKGPU_LOG_W("Call to createBackendTexture has requested dimensions (%d, %d) larger than the"
                    " supported gpu max texture size: %d. Or the dimensions are empty.",
                    dimensions.fWidth, dimensions.fHeight, maxTextureSize);
        return false;
    }
    return true;
}
}

BackendTexture ResourceProvider::createBackendTexture(SkISize dimensions, const TextureInfo& info) {
    if (!dimensions_are_valid(fSharedContext->caps()->maxTextureSize(), dimensions)) {
        return {};
    }
    return this->onCreateBackendTexture(dimensions, info);
}

#ifdef SK_BUILD_FOR_ANDROID
BackendTexture ResourceProvider::createBackendTexture(AHardwareBuffer* hardwareBuffer,
                                                      bool isRenderable,
                                                      bool isProtectedContent,
                                                      SkISize dimensions,
                                                      bool fromAndroidWindow) const {
    if (!dimensions_are_valid(fSharedContext->caps()->maxTextureSize(), dimensions)) {
        return {};
    }
    return this->onCreateBackendTexture(hardwareBuffer,
                                        isRenderable,
                                        isProtectedContent,
                                        dimensions,
                                        fromAndroidWindow);
}

BackendTexture ResourceProvider::onCreateBackendTexture(AHardwareBuffer*,
                                                        bool isRenderable,
                                                        bool isProtectedContent,
                                                        SkISize dimensions,
                                                        bool fromAndroidWindow) const {
    return {};
}
#endif

void ResourceProvider::deleteBackendTexture(const BackendTexture& texture) {
    this->onDeleteBackendTexture(texture);
}

void ResourceProvider::freeGpuResources() {
    this->onFreeGpuResources();

    // TODO: Are there Resources that are ref'd by the ResourceProvider or its subclasses that need
    // be released? If we ever find that we're holding things directly on the ResourceProviders we
    // call down into the subclasses to allow them to release things.

    fResourceCache->purgeResources();
}

void ResourceProvider::purgeResourcesNotUsedSince(StdSteadyClock::time_point purgeTime) {
    this->onPurgeResourcesNotUsedSince(purgeTime);
    fResourceCache->purgeResourcesNotUsedSince(purgeTime);
}

const Caps* ResourceProvider::caps() const {
    return fSharedContext->caps();
}

}  // namespace skgpu::graphite
