/*
 * Copyright 2023 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/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/vk/VulkanGraphiteTypesPriv.h"

using namespace skgpu::graphite;

namespace {
const SkISize kSize = {16, 16};
}

DEF_GRAPHITE_TEST_FOR_VULKAN_CONTEXT(VulkanBackendTextureSimpleCreationTest, reporter, context,
                                     CtsEnforcement::kApiLevel_V) {
    auto recorder = context->makeRecorder();

    bool isProtected = context->priv().caps()->protectedSupport();

    VulkanTextureInfo textureInfo;
    textureInfo.fSampleCount = 1;
    textureInfo.fMipmapped = skgpu::Mipmapped::kNo;
    textureInfo.fFlags = isProtected ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
    textureInfo.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
    textureInfo.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
    textureInfo.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
    textureInfo.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;

    auto beTexture = recorder->createBackendTexture(kSize, TextureInfos::MakeVulkan(textureInfo));
    REPORTER_ASSERT(reporter, beTexture.isValid());
    recorder->deleteBackendTexture(beTexture);

    // It should also pass if we set the usage to be a render target
    textureInfo.fImageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    beTexture = recorder->createBackendTexture(kSize, TextureInfos::MakeVulkan(textureInfo));
    REPORTER_ASSERT(reporter, beTexture.isValid());
    recorder->deleteBackendTexture(beTexture);
}

// Test that copying BackendTexture variables works.
DEF_GRAPHITE_TEST_FOR_VULKAN_CONTEXT(VulkanBackendTextureCopyVariableTest, reporter, context,
                                     CtsEnforcement::kApiLevel_V) {
    auto recorder = context->makeRecorder();

    bool isProtected = context->priv().caps()->protectedSupport();

    VulkanTextureInfo textureInfo;
    textureInfo.fSampleCount = 1;
    textureInfo.fMipmapped = skgpu::Mipmapped::kNo;
    textureInfo.fFlags = isProtected ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
    textureInfo.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
    textureInfo.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
    textureInfo.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
    textureInfo.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;

    BackendTexture beTexture =
            recorder->createBackendTexture(kSize, TextureInfos::MakeVulkan(textureInfo));
    REPORTER_ASSERT(reporter, beTexture.isValid());

    BackendTexture beTexture2;
    REPORTER_ASSERT(reporter, beTexture2 != beTexture);
    REPORTER_ASSERT(reporter, BackendTextures::GetVkImage(beTexture2) == VK_NULL_HANDLE);
    REPORTER_ASSERT(reporter,
                    BackendTextures::GetVkImageLayout(beTexture2) == VK_IMAGE_LAYOUT_UNDEFINED);

    beTexture2 = beTexture;
    REPORTER_ASSERT(reporter, beTexture2 == beTexture);
    REPORTER_ASSERT(
            reporter,
            BackendTextures::GetVkImage(beTexture2) == BackendTextures::GetVkImage(beTexture));
    REPORTER_ASSERT(reporter,
                    BackendTextures::GetVkImageLayout(beTexture2) ==
                            BackendTextures::GetVkImageLayout(beTexture));
    REPORTER_ASSERT(reporter,
                    BackendTextures::GetVkQueueFamilyIndex(beTexture2) ==
                            BackendTextures::GetVkQueueFamilyIndex(beTexture));

    recorder->deleteBackendTexture(beTexture);
    // The backend memory of beTexture2 == that of beTexture, so only call delete once.
}
