/*
 * 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;
}

bool TextureProxy::isProtected() const {
    return fInfo.isProtected() == Protected::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,
                                               std::move(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
