/*
 * 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/Recording.h"

#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/graphite/GraphiteTypes.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkPoint_impl.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkChecksum.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/graphite/CommandBuffer.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/RecordingPriv.h"
#include "src/gpu/graphite/Resource.h"
#include "src/gpu/graphite/RuntimeEffectDictionary.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/task/Task.h"
#include "src/gpu/graphite/task/TaskList.h"

#include <functional>
#include <unordered_map>
#include <unordered_set>
#include <utility>

namespace skgpu::graphite { class Context; }

using namespace skia_private;

namespace skgpu::graphite {

Recording::Recording(uint32_t uniqueID,
                     uint32_t recorderID,
                     std::unique_ptr<LazyProxyData> targetProxyData,
                     TArray<sk_sp<RefCntedCallback>>&& finishedProcs)
        : fUniqueID(uniqueID)
        , fRecorderID(recorderID)
        , fRootTaskList(new TaskList)
        , fTargetProxyData(std::move(targetProxyData))
        , fFinishedProcs(std::move(finishedProcs)) {}

Recording::~Recording() {
    // Any finished procs that haven't been passed to a CommandBuffer fail
    this->priv().setFailureResultForFinishedProcs();
}

std::size_t Recording::ProxyHash::operator()(const sk_sp<TextureProxy> &proxy) const {
    return SkGoodHash()(proxy.get());
}

Recording::LazyProxyData::LazyProxyData(const Caps* caps,
                                        SkISize dimensions,
                                        const TextureInfo& textureInfo) {
    auto onInstantiate = [this](ResourceProvider*) {
        SkASSERT(SkToBool(fTarget));
        return std::move(fTarget);
    };

    // If the texture info specifies that mipmapping is required, that implies that the final
    // surface used to instantiate this proxy will be mipmapped, and that the dimensions of that
    // surface are known already.
    fTargetProxy = textureInfo.mipmapped() == Mipmapped::kYes
                           ? TextureProxy::MakeLazy(caps,
                                                    dimensions,
                                                    textureInfo,
                                                    skgpu::Budgeted::kNo,
                                                    Volatile::kYes,
                                                    std::move(onInstantiate))
                           : TextureProxy::MakeFullyLazy(textureInfo,
                                                         skgpu::Budgeted::kNo,
                                                         Volatile::kYes,
                                                         std::move(onInstantiate));
}

Recording::LazyProxyData::~LazyProxyData() = default;

TextureProxy* Recording::LazyProxyData::lazyProxy() { return fTargetProxy.get(); }

sk_sp<TextureProxy> Recording::LazyProxyData::refLazyProxy() { return fTargetProxy; }

bool Recording::LazyProxyData::lazyInstantiate(ResourceProvider* resourceProvider,
                                               sk_sp<Texture> texture) {
    fTarget = std::move(texture);
    return fTargetProxy->lazyInstantiate(resourceProvider);
}

////////////////////////////////////////////////////////////////////////////////
bool RecordingPriv::hasNonVolatileLazyProxies() const {
    return !fRecording->fNonVolatileLazyProxies.empty();
}

bool RecordingPriv::instantiateNonVolatileLazyProxies(ResourceProvider* resourceProvider) {
    SkASSERT(this->hasNonVolatileLazyProxies());

    for (const auto& proxy : fRecording->fNonVolatileLazyProxies) {
        if (!proxy->lazyInstantiate(resourceProvider)) {
            return false;
        }
    }

    // Note: once all the lazy proxies have been instantiated, that's it - there are no more
    // chances to instantiate.
    fRecording->fNonVolatileLazyProxies.clear();
    return true;
}

bool RecordingPriv::hasVolatileLazyProxies() const {
    return !fRecording->fVolatileLazyProxies.empty();
}

bool RecordingPriv::instantiateVolatileLazyProxies(ResourceProvider* resourceProvider) {
    SkASSERT(this->hasVolatileLazyProxies());

    for (const auto& proxy : fRecording->fVolatileLazyProxies) {
        if (!proxy->lazyInstantiate(resourceProvider)) {
            return false;
        }
    }

    return true;
}

void RecordingPriv::deinstantiateVolatileLazyProxies() {
    if (!this->hasVolatileLazyProxies()) {
        return;
    }

    for (const auto& proxy : fRecording->fVolatileLazyProxies) {
        SkASSERT(proxy->isVolatile());
        proxy->deinstantiate();
    }
}

void RecordingPriv::setFailureResultForFinishedProcs() {
    for (int i = 0; i < fRecording->fFinishedProcs.size(); ++i) {
        fRecording->fFinishedProcs[i]->setFailureResult();
    }
    fRecording->fFinishedProcs.clear();
}

TextureProxy* RecordingPriv::deferredTargetProxy() {
    return fRecording->fTargetProxyData ? fRecording->fTargetProxyData->lazyProxy() : nullptr;
}

const Texture* RecordingPriv::setupDeferredTarget(ResourceProvider* resourceProvider,
                                                  Surface* targetSurface,
                                                  SkIVector targetTranslation,
                                                  SkIRect targetClip) {
    SkASSERT(targetSurface && fRecording->fTargetProxyData);

    TextureProxy* surfaceTexture = targetSurface->backingTextureProxy();
    SkASSERT(surfaceTexture->isInstantiated());

    const TextureProxy* targetProxy = fRecording->fTargetProxyData->lazyProxy();
    if (surfaceTexture->mipmapped() != targetProxy->mipmapped()) {
        SKGPU_LOG_E("Deferred canvas mipmap settings don't match instantiating target's.");
        return nullptr;
    }

    // If the deferred canvas's texture proxy is not fully lazy, that means we used it for draws
    // that require specific dimensions and no translation. The only time this happens is when a
    // client requests a mipmapped deferred canvas and we automatically insert commands to
    // regenerate mipmaps.
    if (!targetProxy->isFullyLazy()) {
        SkASSERT(targetProxy->mipmapped() == skgpu::Mipmapped::kYes);
        if (targetProxy->dimensions() != surfaceTexture->dimensions()) {
            SKGPU_LOG_E(
                    "Deferred canvas dimensions don't match instantiating target's dimensions.");
            return nullptr;
        }
        if (!targetTranslation.isZero()) {
            SKGPU_LOG_E(
                    "Replay translation is not allowed when replaying draws to a mipmapped "
                    "deferred canvas.");
            return nullptr;
        }
        if (!targetClip.isEmpty()) {
            SKGPU_LOG_E(
                    "Replay clip is not allowed when replaying draws to a mipmapped deferred "
                    "canvas.");
            return nullptr;
        }
    }

    if (!fRecording->fTargetProxyData->lazyInstantiate(resourceProvider,
                                                       surfaceTexture->refTexture())) {
        SKGPU_LOG_E("Could not instantiate deferred texture proxy.");
        return nullptr;
    }
    return surfaceTexture->texture();
}

bool RecordingPriv::prepareResources(ResourceProvider* resourceProvider,
                                     ScratchResourceManager* scratchManager,
                                     sk_sp<const RuntimeEffectDictionary> rteDict) {
    Task::Status status = fRecording->fRootTaskList->prepareResources(
            resourceProvider, scratchManager, rteDict);
    if (status == Task::Status::kSuccess) {
        fRecording->fRootTaskList->visitProxies([&](const TextureProxy* proxy) {
            if (proxy->isLazy()) {
                if (proxy->isVolatile()) {
                    fRecording->fVolatileLazyProxies.insert(sk_ref_sp(proxy));
                } else {
                    fRecording->fNonVolatileLazyProxies.insert(sk_ref_sp(proxy));
                }
            }
            return true;
        }, /*readsOnly=*/false);
    }

    return status != Task::Status::kFail;
}

bool RecordingPriv::addCommands(Context* context,
                                CommandBuffer* commandBuffer,
                                const Texture* replayTarget,
                                SkIVector targetTranslation,
                                SkIRect targetClip) {
    for (size_t i = 0; i < fRecording->fExtraResourceRefs.size(); ++i) {
        commandBuffer->trackCommandBufferResource(fRecording->fExtraResourceRefs[i]);
    }

    // There's no need to differentiate kSuccess and kDiscard at the root list level; if every task
    // is discarded, the Recording will automatically be a no-op on replay while still correctly
    // notifying any finish procs the client may have added.
    if (fRecording->fRootTaskList->addCommands(
                context, commandBuffer, {replayTarget, targetTranslation, targetClip}) ==
        Task::Status::kFail) {
        return false;
    }
    for (int i = 0; i < fRecording->fFinishedProcs.size(); ++i) {
        commandBuffer->addFinishedProc(std::move(fRecording->fFinishedProcs[i]));
    }
    fRecording->fFinishedProcs.clear();

    return true;
}

void RecordingPriv::addResourceRef(sk_sp<Resource> resource) {
    fRecording->fExtraResourceRefs.push_back(std::move(resource));
}

#if defined(GPU_TEST_UTILS)
bool RecordingPriv::isTargetProxyInstantiated() const {
    return fRecording->fTargetProxyData->lazyProxy()->isInstantiated();
}

int RecordingPriv::numVolatilePromiseImages() const {
    return fRecording->fVolatileLazyProxies.size();
}

int RecordingPriv::numNonVolatilePromiseImages() const {
    return fRecording->fNonVolatileLazyProxies.size();
}

bool RecordingPriv::hasTasks() const {
    return fRecording->fRootTaskList->hasTasks();
}
#endif

} // namespace skgpu::graphite
