// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VK_IMAGE_VIEW_HPP_
#define VK_IMAGE_VIEW_HPP_

#include "VkFormat.hpp"
#include "VkImage.hpp"
#include "VkObject.hpp"

#include "System/Debug.hpp"

#include <atomic>

namespace vk {

class SamplerYcbcrConversion;

// Uniquely identifies state used by sampling routine generation.
// ID space shared by image views and buffer views.
union Identifier
{
	// Image view identifier
	Identifier(const Image *image, VkImageViewType type, VkFormat format, VkComponentMapping mapping);

	// Buffer view identifier
	Identifier(VkFormat format);

	operator uint32_t() const
	{
		static_assert(sizeof(Identifier) == sizeof(uint32_t), "Identifier must be 32-bit");
		return id;
	}

	uint32_t id = 0;

	struct
	{
		uint32_t imageViewType : 3;
		uint32_t format : 8;
		uint32_t r : 3;
		uint32_t g : 3;
		uint32_t b : 3;
		uint32_t a : 3;
	};
};

class ImageView : public Object<ImageView, VkImageView>
{
public:
	// Image usage:
	// RAW: Use the base image as is
	// SAMPLING: Image used for texture sampling
	enum Usage
	{
		RAW,
		SAMPLING
	};

	ImageView(const VkImageViewCreateInfo *pCreateInfo, void *mem, const vk::SamplerYcbcrConversion *ycbcrConversion);
	void destroy(const VkAllocationCallbacks *pAllocator);

	static size_t ComputeRequiredAllocationSize(const VkImageViewCreateInfo *pCreateInfo);

	void clear(const VkClearValue &clearValues, VkImageAspectFlags aspectMask, const VkRect2D &renderArea);
	void clear(const VkClearValue &clearValue, VkImageAspectFlags aspectMask, const VkClearRect &renderArea);
	void clearWithLayerMask(const VkClearValue &clearValue, VkImageAspectFlags aspectMask, const VkRect2D &renderArea, uint32_t layerMask);
	void resolve(ImageView *resolveAttachment);
	void resolve(ImageView *resolveAttachment, int layer);
	void resolveWithLayerMask(ImageView *resolveAttachment, uint32_t layerMask);

	VkImageViewType getType() const { return viewType; }
	Format getFormat(Usage usage = RAW) const;
	Format getFormat(VkImageAspectFlagBits aspect) const { return image->getFormat(aspect); }
	int rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
	int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
	int getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
	int layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage = RAW) const;
	VkExtent3D getMipLevelExtent(uint32_t mipLevel) const;

	int getSampleCount() const
	{
		switch(image->getSampleCountFlagBits())
		{
			case VK_SAMPLE_COUNT_1_BIT: return 1;
			case VK_SAMPLE_COUNT_4_BIT: return 4;
			default:
				UNSUPPORTED("Sample count flags %d", image->getSampleCountFlagBits());
				return 1;
		}
	}

	void *getOffsetPointer(const VkOffset3D &offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer, Usage usage = RAW) const;
	bool hasDepthAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; }
	bool hasStencilAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; }

	// This function is only called from the renderer, so use the USING_STORAGE flag,
	// as it is required in order to write to an image from a shader
	void contentsChanged() { image->contentsChanged(subresourceRange, Image::USING_STORAGE); }

	void prepareForSampling() { image->prepareForSampling(subresourceRange); }

	const VkComponentMapping &getComponentMapping() const { return components; }
	const VkImageSubresourceRange &getSubresourceRange() const { return subresourceRange; }
	size_t getSizeInBytes() const { return image->getSizeInBytes(subresourceRange); }

private:
	bool imageTypesMatch(VkImageType imageType) const;
	const Image *getImage(Usage usage) const;

	Image *const image = nullptr;
	const VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
	const Format format = VK_FORMAT_UNDEFINED;
	const VkComponentMapping components = {};
	const VkImageSubresourceRange subresourceRange = {};

	const vk::SamplerYcbcrConversion *ycbcrConversion = nullptr;

public:
	const Identifier id;
};

// TODO(b/132437008): Also used by SamplerYcbcrConversion. Move somewhere centrally?
inline VkComponentMapping ResolveIdentityMapping(VkComponentMapping m)
{
	return {
		(m.r == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_R : m.r,
		(m.g == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_G : m.g,
		(m.b == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_B : m.b,
		(m.a == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_A : m.a,
	};
}

static inline ImageView *Cast(VkImageView object)
{
	return ImageView::Cast(object);
}

}  // namespace vk

#endif  // VK_IMAGE_VIEW_HPP_
