/*
 * Copyright 2022 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/Resource.h"

#include "include/core/SkTraceMemoryDump.h"
#include "src/gpu/graphite/ResourceCache.h"

namespace skgpu::graphite {

namespace {
uint32_t create_unique_id() {
    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 id;
}
} // namespace anonymous

Resource::Resource(const SharedContext* sharedContext,
                   Ownership ownership,
                   size_t gpuMemorySize,
                   bool reusableRequiresPurgeable,
                   bool requiresPrepareForReturnToCache)
        : fRefs(RefIncrement(RefType::kUsage)) // Start with 1 usage ref and no others
        , fReusableRefMask(
            (reusableRequiresPurgeable ? PurgeableMask()
                                       : RefMask(RefType::kUsage)) | RefMask(RefType::kReturnQueue))
        , fSharedContext(sharedContext)
        , fUniqueID(create_unique_id())
        , fOwnership(ownership)
        , fRequiresPrepareForReturnToCache(requiresPrepareForReturnToCache)
        , fGpuMemorySize(gpuMemorySize) {
    // At initialization time, a Resource should not be considered budgeted because it does not yet
    // belong to a ResourceCache (which manages a budget). Wrapped resources and owned-but-uncached
    // resources will never be added to a cache and can therefore depend on this default value (as
    // opposed to a resource having its budget and shareable state set via registerWithCache()).
    SkASSERT(fBudgeted == Budgeted::kNo);
    SkASSERT(fShareable == Shareable::kNo);
    SkASSERT(this->isUniquelyHeld());
}

Resource::~Resource() {
    // The cache should have released or destroyed this resource.
    SkASSERT(this->wasDestroyed());
}

void Resource::registerWithCache(sk_sp<ResourceCache> returnCache,
                                 const GraphiteResourceKey& key,
                                 Budgeted initialBudgetedState,
                                 Shareable initialShareableState) {
    // ResourceCache should be registered before the Resource escapes the ResourceProvider, e.g. it
    // has a single usage ref and no others.
    SkASSERT(this->isUniquelyHeld());
    SkASSERT(!fReturnCache);
    SkASSERT(returnCache);

    fKey = key;
    fReturnCache = std::move(returnCache);

    this->addRef<RefType::kCache>();

    this->setBudgeted(initialBudgetedState);
    this->setShareable(initialShareableState);
}

bool Resource::returnToCache() const {
    // No resource should have been destroyed if there was still any sort of ref on it.
    SkASSERT(!this->wasDestroyed());

    // Not all resources are registered with the cache, but returnToCache() should only be called
    // when they have been registered.
    SkASSERT(fReturnCache);
    // In order to be returned, the Resource's "return queue" ref bit must be set. Its cache ref
    // may not be set if the cache has been shut down (but `fReturnCache` remains valid and just
    // returns false to reject the resource return).
    SkASSERT(this->hasReturnQueueRef());
    return fReturnCache->returnResource(const_cast<Resource*>(this));
}

void Resource::internalDispose() {
    SkASSERT(fSharedContext);
    this->invokeReleaseProc();
    this->freeGpuData();
    fSharedContext = nullptr;
    // TODO: If we ever support freeing all the backend objects without deleting the object, we'll
    // need to add a hasAnyRefs() check here.
    delete this;
}

void Resource::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump,
                                    bool inPurgeableQueue) const {
    if (this->ownership() == Ownership::kWrapped && !traceMemoryDump->shouldDumpWrappedObjects()) {
        return;
    }

    if (this->budgeted() == skgpu::Budgeted::kNo &&
        !traceMemoryDump->shouldDumpUnbudgetedObjects()) {
        return;
    }

    size_t size = this->gpuMemorySize();

    // Dump zero-sized objects (e.g. Samplers, pipelines, etc) per traceMemoryDump implementation.
    // Always dump memoryless textures.
    if (size == 0 && !traceMemoryDump->shouldDumpSizelessObjects() &&
        this->asTexture() == nullptr) {
        return;
    }

    SkString resourceName("skia/gpu_resources/resource_");
    resourceName.appendU32(this->uniqueID().asUInt());

    traceMemoryDump->dumpNumericValue(resourceName.c_str(), "size", "bytes", size);
    traceMemoryDump->dumpStringValue(resourceName.c_str(), "type", this->getResourceType());
    traceMemoryDump->dumpStringValue(resourceName.c_str(), "label", this->getLabel().c_str());
    if (inPurgeableQueue) {
        traceMemoryDump->dumpNumericValue(resourceName.c_str(), "purgeable_size", "bytes", size);
    }
    if (traceMemoryDump->shouldDumpWrappedObjects()) {
        traceMemoryDump->dumpWrappedState(resourceName.c_str(),
                                          this->ownership() == Ownership::kWrapped);
    }
    if (traceMemoryDump->shouldDumpUnbudgetedObjects()) {
        traceMemoryDump->dumpBudgetedState(resourceName.c_str(),
                                           this->budgeted() == skgpu::Budgeted::kYes);
    }

    this->onDumpMemoryStatistics(traceMemoryDump, resourceName.c_str());

    // TODO: implement this to report real gpu id backing the resource. Will be virtual implemented
    // by backend specific resource subclasses.
    //this->setMemoryBacking(traceMemoryDump, resourceName);
}

} // namespace skgpu::graphite
