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

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Image.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureProxy.h"

namespace skgpu::graphite {

DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphiteTextureProxyTest, reporter, context) {
    const Caps* caps = context->priv().caps();
    constexpr SkISize kValidSize = SkISize::Make(1, 1);
    constexpr SkISize kInvalidSize = SkISize::MakeEmpty();
    constexpr SkColorType kValidColorType = kRGBA_8888_SkColorType;
    constexpr SkColorType kInvalidColorType = kUnknown_SkColorType;

    std::unique_ptr<Recorder> recorder = context->makeRecorder();
    ResourceProvider* resourceProvider = recorder->priv().resourceProvider();
    const TextureInfo textureInfo = caps->getDefaultSampledTextureInfo(
            kValidColorType, Mipmapped::kNo, Protected::kNo, Renderable::kNo);
    const BackendTexture backendTexture = recorder->createBackendTexture(kValidSize, textureInfo);
    sk_sp<Texture> texture = resourceProvider->createWrappedTexture(backendTexture);

    auto nullCallback = [](ResourceProvider*) -> sk_sp<Texture> { return nullptr; };
    auto callback = [texture](ResourceProvider*) -> sk_sp<Texture> { return texture; };

    // Assign to assignableTexture before instantiating with this callback.
    sk_sp<Texture> assignableTexture;
    auto assignableCallback = [&assignableTexture](ResourceProvider*) -> sk_sp<Texture> {
        return assignableTexture;
    };

    // Invalid parameters.
    sk_sp<TextureProxy> textureProxy;
    textureProxy = TextureProxy::Make(caps,
                                      kInvalidSize,
                                      kValidColorType,
                                      Mipmapped::kNo,
                                      Protected::kNo,
                                      Renderable::kNo,
                                      skgpu::Budgeted::kNo);
    REPORTER_ASSERT(reporter, textureProxy == nullptr);
    textureProxy = TextureProxy::Make(caps,
                                      kValidSize,
                                      kInvalidColorType,
                                      Mipmapped::kNo,
                                      Protected::kNo,
                                      Renderable::kNo,
                                      skgpu::Budgeted::kNo);
    REPORTER_ASSERT(reporter, textureProxy == nullptr);

    // Non-lazy TextureProxy, successful instantiation.
    textureProxy = TextureProxy::Make(caps,
                                      kValidSize,
                                      kValidColorType,
                                      Mipmapped::kNo,
                                      Protected::kNo,
                                      Renderable::kNo,
                                      skgpu::Budgeted::kNo);
    REPORTER_ASSERT(reporter, !textureProxy->isLazy());
    REPORTER_ASSERT(reporter, !textureProxy->isFullyLazy());
    REPORTER_ASSERT(reporter, !textureProxy->isVolatile());
    REPORTER_ASSERT(reporter, !textureProxy->isInstantiated());
    REPORTER_ASSERT(reporter, textureProxy->dimensions() == kValidSize);

    bool instantiateSuccess = textureProxy->instantiate(resourceProvider);
    REPORTER_ASSERT(reporter, instantiateSuccess);
    REPORTER_ASSERT(reporter, textureProxy->isInstantiated());
    REPORTER_ASSERT(reporter, textureProxy->dimensions() == kValidSize);
    const Texture* createdTexture = textureProxy->texture();

    instantiateSuccess = textureProxy->instantiate(resourceProvider);
    REPORTER_ASSERT(reporter, instantiateSuccess);
    REPORTER_ASSERT(reporter, textureProxy->texture() == createdTexture);

    // Lazy, non-volatile TextureProxy, unsuccessful instantiation.
    textureProxy = TextureProxy::MakeLazy(
            caps, kValidSize, textureInfo, skgpu::Budgeted::kNo, Volatile::kNo, nullCallback);
    REPORTER_ASSERT(reporter, textureProxy->isLazy());
    REPORTER_ASSERT(reporter, !textureProxy->isFullyLazy());
    REPORTER_ASSERT(reporter, !textureProxy->isVolatile());

    instantiateSuccess = textureProxy->lazyInstantiate(resourceProvider);
    REPORTER_ASSERT(reporter, !instantiateSuccess);
    REPORTER_ASSERT(reporter, !textureProxy->isInstantiated());

    // Lazy, non-volatile TextureProxy, successful instantiation.
    textureProxy = TextureProxy::MakeLazy(
            caps, kValidSize, textureInfo, skgpu::Budgeted::kNo, Volatile::kNo, callback);

    instantiateSuccess = textureProxy->lazyInstantiate(resourceProvider);
    REPORTER_ASSERT(reporter, instantiateSuccess);
    REPORTER_ASSERT(reporter, textureProxy->texture() == texture.get());

    // Lazy, volatile TextureProxy, unsuccessful instantiation.
    textureProxy = TextureProxy::MakeLazy(
            caps, kValidSize, textureInfo, skgpu::Budgeted::kNo, Volatile::kYes, nullCallback);
    REPORTER_ASSERT(reporter, textureProxy->isLazy());
    REPORTER_ASSERT(reporter, !textureProxy->isFullyLazy());
    REPORTER_ASSERT(reporter, textureProxy->isVolatile());

    instantiateSuccess = textureProxy->lazyInstantiate(resourceProvider);
    REPORTER_ASSERT(reporter, !instantiateSuccess);
    REPORTER_ASSERT(reporter, !textureProxy->isInstantiated());

    // Lazy, volatile TextureProxy, successful instantiation.
    textureProxy = TextureProxy::MakeLazy(
            caps, kValidSize, textureInfo, skgpu::Budgeted::kNo, Volatile::kYes, callback);

    instantiateSuccess = textureProxy->lazyInstantiate(resourceProvider);
    REPORTER_ASSERT(reporter, instantiateSuccess);
    REPORTER_ASSERT(reporter, textureProxy->texture() == texture.get());

    textureProxy->deinstantiate();
    REPORTER_ASSERT(reporter, !textureProxy->isInstantiated());

    // Fully-lazy TextureProxy.
    textureProxy = TextureProxy::MakeFullyLazy(
            textureInfo, skgpu::Budgeted::kNo, Volatile::kYes, assignableCallback);
    REPORTER_ASSERT(reporter, textureProxy->isLazy());
    REPORTER_ASSERT(reporter, textureProxy->isFullyLazy());
    REPORTER_ASSERT(reporter, textureProxy->isVolatile());

    assignableTexture = texture;
    instantiateSuccess = textureProxy->lazyInstantiate(resourceProvider);
    REPORTER_ASSERT(reporter, instantiateSuccess);
    REPORTER_ASSERT(reporter, textureProxy->isInstantiated());
    REPORTER_ASSERT(reporter, textureProxy->isFullyLazy());
    REPORTER_ASSERT(reporter, textureProxy->dimensions() == kValidSize);

    textureProxy->deinstantiate();
    REPORTER_ASSERT(reporter, !textureProxy->isInstantiated());
    REPORTER_ASSERT(reporter, textureProxy->isFullyLazy());

    constexpr SkISize kLargerSize = SkISize::Make(2, 2);
    const BackendTexture largerBackendTexture =
            recorder->createBackendTexture(kLargerSize, textureInfo);
    assignableTexture = resourceProvider->createWrappedTexture(largerBackendTexture);
    instantiateSuccess = textureProxy->lazyInstantiate(resourceProvider);
    REPORTER_ASSERT(reporter, instantiateSuccess);
    REPORTER_ASSERT(reporter, textureProxy->dimensions() == kLargerSize);

    // InstantiateIfNotLazy tests.
    textureProxy = TextureProxy::Make(caps,
                                      kValidSize,
                                      kValidColorType,
                                      Mipmapped::kNo,
                                      Protected::kNo,
                                      Renderable::kNo,
                                      skgpu::Budgeted::kNo);
    instantiateSuccess = TextureProxy::InstantiateIfNotLazy(resourceProvider, textureProxy.get());
    REPORTER_ASSERT(reporter, instantiateSuccess);

    textureProxy = TextureProxy::MakeLazy(
            caps, kValidSize, textureInfo, skgpu::Budgeted::kNo, Volatile::kNo, nullCallback);
    instantiateSuccess = TextureProxy::InstantiateIfNotLazy(resourceProvider, textureProxy.get());
    REPORTER_ASSERT(reporter, instantiateSuccess);
}

DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphiteTextureTooLargeTest, reporter, context) {
    std::unique_ptr<Recorder> recorder = context->makeRecorder();
    const Caps* caps = context->priv().caps();

    // Try to create a texture that is too large for the backend.
    SkBitmap bitmap;
    SkISize dimensions = SkISize::Make(caps->maxTextureSize() + 1, 1);
    bitmap.allocPixels(SkImageInfo::Make(
            dimensions, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kPremul_SkAlphaType));
    sk_sp<SkImage> rasterImage = SkImages::RasterFromBitmap(bitmap);
    sk_sp<SkImage> graphiteImage =
            SkImages::TextureFromImage(recorder.get(), rasterImage.get(), /*requiredProps=*/{});

    // Image creation should have failed.
    REPORTER_ASSERT(reporter, !graphiteImage);

    // Snapping should still succeed, no texture upload should actually be attempted.
    REPORTER_ASSERT(reporter, recorder->snap());
}

DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphiteLazyTextureInvalidDimensions, reporter, context) {
    class FulfillContext {
    public:
        FulfillContext(BackendTexture backendTexture) : fBackendTexture(backendTexture) {}

        static std::tuple<BackendTexture, void*> Fulfill(void* ctx) {
            FulfillContext* self = reinterpret_cast<FulfillContext*>(ctx);
            return {self->fBackendTexture, nullptr};
        }

        BackendTexture fBackendTexture;
    };

    std::unique_ptr<Recorder> recorder = context->makeRecorder();
    const Caps* caps = context->priv().caps();

    // Try to create textures with invalid dimensions.
    SkISize largeDimensions = SkISize::Make(caps->maxTextureSize() + 1, 1);
    SkISize negativeDimensions = SkISize::Make(-1, -1);

    for (const SkISize& dimensions : {largeDimensions, negativeDimensions}) {
        SkImageInfo imageInfo = SkImageInfo::Make(
                dimensions, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kPremul_SkAlphaType);
        TextureInfo textureInfo = caps->getDefaultSampledTextureInfo(
                imageInfo.colorInfo().colorType(), Mipmapped::kNo, Protected::kNo, Renderable::kNo);

        // The created BackendTexture should be invalid, so an invalid texture would be used to
        // fulfill the promise image created later, if we were to attempt to draw it.
        BackendTexture backendTexture =
                recorder->createBackendTexture(imageInfo.dimensions(), textureInfo);
        FulfillContext fulfillContext(backendTexture);
        REPORTER_ASSERT(reporter, !backendTexture.isValid());

        // Drawing should still succeed, as no image draw should actually be attempted with this
        // texture.
        SkImageInfo surfaceImageInfo = SkImageInfo::Make(
                1, 1, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kPremul_SkAlphaType);
        sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(recorder.get(), surfaceImageInfo);
        sk_sp<SkImage> promiseImage = SkImages::PromiseTextureFrom(recorder.get(),
                                                                   imageInfo.dimensions(),
                                                                   textureInfo,
                                                                   imageInfo.colorInfo(),
                                                                   Volatile::kNo,
                                                                   FulfillContext::Fulfill,
                                                                   nullptr,
                                                                   nullptr,
                                                                   &fulfillContext);
        surface->getCanvas()->drawImage(promiseImage, 0.0f, 0.0f);
        std::unique_ptr<Recording> recording = recorder->snap();
        REPORTER_ASSERT(reporter, context->insertRecording({recording.get()}));
    }
}

}  // namespace skgpu::graphite
