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

#include "include/gpu/graphite/Recorder.h"
#include "src/core/SkMipmap.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/ScratchResourceManager.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureUtils.h"

namespace skgpu::graphite {

TextureProxy::TextureProxy(SkISize dimensions,
                           const TextureInfo& info,
                           std::string_view label,
                           skgpu::Budgeted budgeted)
        : fDimensions(dimensions)
        , fInfo(info)
        , fLabel(label)
        , fBudgeted(budgeted)
        , fVolatile(Volatile::kNo) {
    SkASSERT(fInfo.isValid());
}

TextureProxy::TextureProxy(sk_sp<Texture> texture)
        : fDimensions(texture->dimensions())
        , fInfo(texture->textureInfo())
        , fLabel(texture->getLabel())
        , fBudgeted(texture->budgeted())
        , fVolatile(Volatile::kNo)
        , fTexture(std::move(texture)) {
    SkASSERT(fInfo.isValid());
}

TextureProxy::TextureProxy(SkISize dimensions,
                           const TextureInfo& textureInfo,
                           skgpu::Budgeted budgeted,
                           Volatile isVolatile,
                           LazyInstantiateCallback&& callback)
        : fDimensions(dimensions)
        , fInfo(textureInfo)
        , fBudgeted(budgeted)
        , fVolatile(isVolatile)
        , fLazyInstantiateCallback(std::move(callback)) {
    SkASSERT(fInfo.isValid());
    SkASSERT(fLazyInstantiateCallback);
}

TextureProxy::~TextureProxy() {}

SkISize TextureProxy::dimensions() const {
    SkASSERT(!this->isFullyLazy() || this->isInstantiated());
    return this->isInstantiated() ? fTexture->dimensions() : fDimensions;
}

bool TextureProxy::isLazy() const {
    return SkToBool(fLazyInstantiateCallback);
}

bool TextureProxy::isFullyLazy() const {
    bool result = fDimensions.width() < 0;
    SkASSERT(result == (fDimensions.height() < 0));
    SkASSERT(!result || this->isLazy());
    return result;
}

bool TextureProxy::isVolatile() const {
    SkASSERT(fVolatile == Volatile::kNo || SkToBool(fLazyInstantiateCallback));

    return fVolatile == Volatile::kYes;
}

size_t TextureProxy::uninstantiatedGpuMemorySize() const {
    return ComputeSize(fDimensions, fInfo);
}

bool TextureProxy::instantiate(ResourceProvider* resourceProvider) {
    SkASSERT(!this->isLazy());

    if (fTexture) {
        return true;
    }

    // TODO(389908374): Once all tasks use the ScratchResourceManager, this can be updated to just
    // finding and creating a non-shareable AND non-budgeted texture.
    fTexture = resourceProvider->findOrCreateNonShareableTexture(
            fDimensions, fInfo, fLabel, fBudgeted);
    if (!fTexture) {
        return false;
    }
    SkDEBUGCODE(this->validateTexture(fTexture.get()));
    return true;
}

bool TextureProxy::lazyInstantiate(ResourceProvider* resourceProvider) {
    SkASSERT(this->isLazy());

    if (fTexture) {
        return true;
    }

    fTexture = fLazyInstantiateCallback(resourceProvider);
    if (!fTexture) {
        return false;
    }
    SkDEBUGCODE(this->validateTexture(fTexture.get()));
    return true;
}

bool TextureProxy::InstantiateIfNotLazy(ResourceProvider* resourceProvider,
                                        TextureProxy* textureProxy) {
    if (textureProxy->isLazy()) {
        return true;
    }

    return textureProxy->instantiate(resourceProvider);
}

bool TextureProxy::InstantiateIfNotLazy(ScratchResourceManager* scratchManager,
                                        TextureProxy* textureProxy) {
    if (textureProxy->isLazy() || textureProxy->isInstantiated()) {
        return true;
    }

    textureProxy->fTexture = scratchManager->getScratchTexture(textureProxy->dimensions(),
                                                               textureProxy->textureInfo(),
                                                               textureProxy->fLabel);
    if (!textureProxy->fTexture) {
        return false;
    }
    SkDEBUGCODE(textureProxy->validateTexture(textureProxy->fTexture.get()));
    return true;
}


void TextureProxy::deinstantiate() {
    SkASSERT(fVolatile == Volatile::kYes && SkToBool(fLazyInstantiateCallback));

    fTexture.reset();
}

sk_sp<Texture> TextureProxy::refTexture() const {
    return fTexture;
}

const Texture* TextureProxy::texture() const {
    return fTexture.get();
}

sk_sp<TextureProxy> TextureProxy::Make(const Caps* caps,
                                       ResourceProvider* resourceProvider,
                                       SkISize dimensions,
                                       const TextureInfo& textureInfo,
                                       std::string_view label,
                                       skgpu::Budgeted budgeted) {
    if (dimensions.width() < 1 || dimensions.height() < 1 ||
        dimensions.width() > caps->maxTextureSize() ||
        dimensions.height() > caps->maxTextureSize() ||
        !textureInfo.isValid()) {
        return nullptr;
    }

    sk_sp<TextureProxy> proxy {new TextureProxy(dimensions, textureInfo, label, budgeted)};
    if (budgeted == Budgeted::kNo) {
        // Instantiate immediately to avoid races later on if the client starts to use the wrapping
        // object on multiple threads.
        if (!proxy->instantiate(resourceProvider)) {
            return nullptr;
        }
    }
    return proxy;
}

sk_sp<TextureProxy> TextureProxy::MakeLazy(const Caps* caps,
                                           SkISize dimensions,
                                           const TextureInfo& textureInfo,
                                           skgpu::Budgeted budgeted,
                                           Volatile isVolatile,
                                           LazyInstantiateCallback&& callback) {
    SkASSERT(textureInfo.isValid());
    if (dimensions.width() < 1 || dimensions.height() < 1 ||
        dimensions.width() > caps->maxTextureSize() ||
        dimensions.height() > caps->maxTextureSize()) {
        return nullptr;
    }

    return sk_sp<TextureProxy>(new TextureProxy(dimensions,
                                                textureInfo,
                                                budgeted,
                                                isVolatile,
                                                std::move(callback)));
}

sk_sp<TextureProxy> TextureProxy::MakeFullyLazy(const TextureInfo& textureInfo,
                                                skgpu::Budgeted budgeted,
                                                Volatile isVolatile,
                                                LazyInstantiateCallback&& callback) {
    SkASSERT(textureInfo.isValid());

    return sk_sp<TextureProxy>(new TextureProxy(SkISize::Make(-1, -1),
                                                textureInfo,
                                                budgeted,
                                                isVolatile,
                                                std::move(callback)));
}

sk_sp<TextureProxy> TextureProxy::Wrap(sk_sp<Texture> texture) {
    return sk_sp<TextureProxy>(new TextureProxy(std::move(texture)));
}

#ifdef SK_DEBUG
void TextureProxy::validateTexture(const Texture* texture) {
    SkASSERT(this->isFullyLazy() || fDimensions == texture->dimensions());
    SkASSERTF(fInfo.canBeFulfilledBy(texture->textureInfo()),
              "proxy->fInfo[%s] incompatible with texture->fInfo[%s]",
              fInfo.toString().c_str(),
              texture->textureInfo().toString().c_str());
}
#endif

} // namespace skgpu::graphite
