/*
 * 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 "include/gpu/vk/VulkanMutableTextureState.h"

#include "include/gpu/GpuTypes.h"
#include "include/gpu/MutableTextureState.h"
#include "include/private/base/SkAssert.h"
#include "src/gpu/MutableTextureStatePriv.h"
#include "src/gpu/vk/VulkanMutableTextureStatePriv.h"

namespace skgpu::MutableTextureStates {

class VulkanMutableTextureState : public MutableTextureStateData {
public:
    VulkanMutableTextureState(VkImageLayout layout, uint32_t queueFamilyIndex)
            : fLayout(layout)
            , fQueueFamilyIndex(queueFamilyIndex) {}

#if defined(SK_DEBUG)
    BackendApi type() const override { return BackendApi::kVulkan; }
#endif

    void copyTo(AnyStateData& formatData) const override {
        formatData.emplace<VulkanMutableTextureState>(fLayout, fQueueFamilyIndex);
    }

    VkImageLayout fLayout;
    uint32_t      fQueueFamilyIndex;
};

MutableTextureState MakeVulkan(VkImageLayout layout, uint32_t queueFamilyIndex) {
    return MutableTextureStatePriv::MakeMutableTextureState(
            BackendApi::kVulkan,
            VulkanMutableTextureState(layout, queueFamilyIndex));
}

static const VulkanMutableTextureState* get_and_cast_data(const MutableTextureState& mts) {
    auto data = skgpu::MutableTextureStatePriv::GetStateData(mts);
    SkASSERT(!data || data->type() == BackendApi::kVulkan);
    return static_cast<const VulkanMutableTextureState*>(data);
}

static const VulkanMutableTextureState* get_and_cast_data(const MutableTextureState* mts) {
    auto data = skgpu::MutableTextureStatePriv::GetStateData(mts);
    SkASSERT(!data || data->type() == BackendApi::kVulkan);
    return static_cast<const VulkanMutableTextureState*>(data);
}

static VulkanMutableTextureState* get_and_cast_data(MutableTextureState* mts) {
    auto data = skgpu::MutableTextureStatePriv::GetStateData(mts);
    SkASSERT(!data || data->type() == BackendApi::kVulkan);
    return static_cast<VulkanMutableTextureState*>(data);
}

VkImageLayout GetVkImageLayout(const MutableTextureState& state) {
    SkASSERT(state.backend() == BackendApi::kVulkan);
    return get_and_cast_data(state)->fLayout;
}

VkImageLayout GetVkImageLayout(const MutableTextureState* state) {
    SkASSERT(state);
    SkASSERT(state->backend() == BackendApi::kVulkan);
    return get_and_cast_data(state)->fLayout;
}

void SetVkImageLayout(MutableTextureState* state, VkImageLayout layout) {
    SkASSERT(state->backend() == BackendApi::kVulkan);
    get_and_cast_data(state)->fLayout = layout;
}

uint32_t GetVkQueueFamilyIndex(const MutableTextureState& state) {
    SkASSERT(state.backend() == BackendApi::kVulkan);
    return get_and_cast_data(state)->fQueueFamilyIndex;
}

uint32_t GetVkQueueFamilyIndex(const MutableTextureState* state) {
    SkASSERT(state);
    SkASSERT(state->backend() == BackendApi::kVulkan);
    return get_and_cast_data(state)->fQueueFamilyIndex;
}

void SetVkQueueFamilyIndex(MutableTextureState* state, uint32_t queueFamilyIndex) {
    SkASSERT(state->backend() == BackendApi::kVulkan);
    get_and_cast_data(state)->fQueueFamilyIndex = queueFamilyIndex;
}

}  // namespace skgpu::MutableTextureStates


#if defined(SK_VULKAN) && !defined(SK_DISABLE_LEGACY_VULKAN_MUTABLE_TEXTURE_STATE)
namespace skgpu {
MutableTextureState::MutableTextureState(VkImageLayout layout, uint32_t queueFamilyIndex)
            : MutableTextureState(BackendApi::kVulkan,
                                  skgpu::MutableTextureStates::VulkanMutableTextureState(layout, queueFamilyIndex)) {}

VkImageLayout MutableTextureState::getVkImageLayout() const {
    return skgpu::MutableTextureStates::GetVkImageLayout(this);
}

uint32_t MutableTextureState::getQueueFamilyIndex() const {
    return skgpu::MutableTextureStates::GetVkQueueFamilyIndex(this);
}

}  // namespace skgpu
#endif
