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

using namespace skgpu::graphite;

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

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

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

    VulkanTextureInfo textureInfo;
    textureInfo.fSampleCount = SampleCount::k1;
    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_202404) {
    auto recorder = context->makeRecorder();

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

    VulkanTextureInfo textureInfo;
    textureInfo.fSampleCount = SampleCount::k1;
    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.
}
