/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 The Khronos Group Inc.
 * Copyright (c) 2015 Imagination Technologies Ltd.
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Reference renderer.
 *//*--------------------------------------------------------------------*/

#include "vktPipelineReferenceRenderer.hpp"
#include "vktPipelineClearUtil.hpp"
#include "rrShadingContext.hpp"
#include "rrVertexAttrib.hpp"

namespace vkt
{
namespace pipeline
{

using namespace vk;

rr::BlendFunc mapVkBlendFactor (VkBlendFactor blend)
{
	switch (blend)
	{
		case VK_BLEND_FACTOR_ZERO:						return rr::BLENDFUNC_ZERO;
		case VK_BLEND_FACTOR_ONE:						return rr::BLENDFUNC_ONE;
		case VK_BLEND_FACTOR_SRC_COLOR:					return rr::BLENDFUNC_SRC_COLOR;
		case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:		return rr::BLENDFUNC_ONE_MINUS_SRC_COLOR;
		case VK_BLEND_FACTOR_DST_COLOR:					return rr::BLENDFUNC_DST_COLOR;
		case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:		return rr::BLENDFUNC_ONE_MINUS_DST_COLOR;
		case VK_BLEND_FACTOR_SRC_ALPHA:					return rr::BLENDFUNC_SRC_ALPHA;
		case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:		return rr::BLENDFUNC_ONE_MINUS_SRC_ALPHA;
		case VK_BLEND_FACTOR_DST_ALPHA:					return rr::BLENDFUNC_DST_ALPHA;
		case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:		return rr::BLENDFUNC_ONE_MINUS_DST_ALPHA;
		case VK_BLEND_FACTOR_CONSTANT_COLOR:			return rr::BLENDFUNC_CONSTANT_COLOR;
		case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:	return rr::BLENDFUNC_ONE_MINUS_CONSTANT_COLOR;
		case VK_BLEND_FACTOR_CONSTANT_ALPHA:			return rr::BLENDFUNC_CONSTANT_ALPHA;
		case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:	return rr::BLENDFUNC_ONE_MINUS_CONSTANT_ALPHA;
		case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:		return rr::BLENDFUNC_SRC_ALPHA_SATURATE;
		case VK_BLEND_FACTOR_SRC1_COLOR:				return rr::BLENDFUNC_SRC1_COLOR;
		case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:		return rr::BLENDFUNC_ONE_MINUS_SRC1_COLOR;
		case VK_BLEND_FACTOR_SRC1_ALPHA:				return rr::BLENDFUNC_SRC1_ALPHA;
		case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:		return rr::BLENDFUNC_ONE_MINUS_SRC1_ALPHA;
		default:
			DE_ASSERT(false);
	}
	return rr::BLENDFUNC_LAST;
}

rr::BlendEquation mapVkBlendOp (VkBlendOp blendOp)
{
	switch (blendOp)
	{
		case VK_BLEND_OP_ADD:					return rr::BLENDEQUATION_ADD;
		case VK_BLEND_OP_SUBTRACT:				return rr::BLENDEQUATION_SUBTRACT;
		case VK_BLEND_OP_REVERSE_SUBTRACT:		return rr::BLENDEQUATION_REVERSE_SUBTRACT;
		case VK_BLEND_OP_MIN:					return rr::BLENDEQUATION_MIN;
		case VK_BLEND_OP_MAX:					return rr::BLENDEQUATION_MAX;
		default:
			DE_ASSERT(false);
	}
	return rr::BLENDEQUATION_LAST;
}

tcu::BVec4 mapVkColorComponentFlags (VkColorComponentFlags flags)
{
	return tcu::BVec4((flags & VK_COLOR_COMPONENT_R_BIT) != 0,
					  (flags & VK_COLOR_COMPONENT_G_BIT) != 0,
					  (flags & VK_COLOR_COMPONENT_B_BIT) != 0,
					  (flags & VK_COLOR_COMPONENT_A_BIT) != 0);
}

rr::TestFunc mapVkCompareOp (VkCompareOp compareFunc)
{
	switch (compareFunc)
	{
		case VK_COMPARE_OP_NEVER:				return rr::TESTFUNC_NEVER;
		case VK_COMPARE_OP_LESS:				return rr::TESTFUNC_LESS;
		case VK_COMPARE_OP_EQUAL:				return rr::TESTFUNC_EQUAL;
		case VK_COMPARE_OP_LESS_OR_EQUAL:		return rr::TESTFUNC_LEQUAL;
		case VK_COMPARE_OP_GREATER:				return rr::TESTFUNC_GREATER;
		case VK_COMPARE_OP_NOT_EQUAL:			return rr::TESTFUNC_NOTEQUAL;
		case VK_COMPARE_OP_GREATER_OR_EQUAL:	return rr::TESTFUNC_GEQUAL;
		case VK_COMPARE_OP_ALWAYS:				return rr::TESTFUNC_ALWAYS;
		default:
			DE_ASSERT(false);
	}
	return rr::TESTFUNC_LAST;
}

rr::PrimitiveType mapVkPrimitiveTopology (VkPrimitiveTopology primitiveTopology)
{
	switch (primitiveTopology)
	{
		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:						return rr::PRIMITIVETYPE_POINTS;
		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:						return rr::PRIMITIVETYPE_LINES;
		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:						return rr::PRIMITIVETYPE_LINE_STRIP;
		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:					return rr::PRIMITIVETYPE_TRIANGLES;
		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:					return rr::PRIMITIVETYPE_TRIANGLE_FAN;
		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:					return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINES_ADJACENCY;
		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
		default:
			DE_ASSERT(false);
	}
	return rr::PRIMITIVETYPE_LAST;
}

rr::StencilOp mapVkStencilOp (vk::VkStencilOp stencilOp)
{
	switch (stencilOp)
	{
		case VK_STENCIL_OP_KEEP:					return rr::STENCILOP_KEEP;
		case VK_STENCIL_OP_ZERO:					return rr::STENCILOP_ZERO;
		case VK_STENCIL_OP_REPLACE:					return rr::STENCILOP_REPLACE;
		case VK_STENCIL_OP_INCREMENT_AND_CLAMP:		return rr::STENCILOP_INCR;
		case VK_STENCIL_OP_DECREMENT_AND_CLAMP:		return rr::STENCILOP_DECR;
		case VK_STENCIL_OP_INVERT:					return rr::STENCILOP_INVERT;
		case VK_STENCIL_OP_INCREMENT_AND_WRAP:		return rr::STENCILOP_INCR_WRAP;
		case VK_STENCIL_OP_DECREMENT_AND_WRAP:		return rr::STENCILOP_DECR_WRAP;
		default:
			DE_ASSERT(false);
	}
	return rr::STENCILOP_LAST;
}

tcu::Vec4 swizzle (const tcu::Vec4& color, const tcu::UVec4& swizzle)
{
	const float channelValues[] =
	{
		0.0f,
		1.0f,
		color.x(),
		color.y(),
		color.z(),
		color.w()
	};

	return tcu::Vec4(channelValues[swizzle.x()],
					 channelValues[swizzle.y()],
					 channelValues[swizzle.z()],
					 channelValues[swizzle.w()]);
}

ReferenceRenderer::ReferenceRenderer(int						surfaceWidth,
									 int						surfaceHeight,
									 int						numSamples,
									 const tcu::TextureFormat&	colorFormat,
									 const tcu::TextureFormat&	depthStencilFormat,
									 const rr::Program* const	program)
	: m_surfaceWidth		(surfaceWidth)
	, m_surfaceHeight		(surfaceHeight)
	, m_numSamples			(numSamples)
	, m_colorFormat			(colorFormat)
	, m_depthStencilFormat	(depthStencilFormat)
	, m_program				(program)
{
	const tcu::TextureChannelClass	formatClass				= tcu::getTextureChannelClass(colorFormat.type);
	const bool						hasDepthStencil			= (m_depthStencilFormat.order != tcu::TextureFormat::CHANNELORDER_LAST);
	const bool						hasDepthBufferOnly		= (m_depthStencilFormat.order == tcu::TextureFormat::D);
	const bool						hasStencilBufferOnly	= (m_depthStencilFormat.order == tcu::TextureFormat::S);
	const int						actualSamples			= (formatClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || formatClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)? 1: m_numSamples;

	m_colorBuffer.setStorage(m_colorFormat, actualSamples, m_surfaceWidth, m_surfaceHeight);
	m_resolveColorBuffer.setStorage(m_colorFormat, m_surfaceWidth, m_surfaceHeight);

	if (formatClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
	{
		tcu::clear(m_colorBuffer.getAccess(), defaultClearColorInt(m_colorFormat));
		tcu::clear(m_resolveColorBuffer.getAccess(), defaultClearColorInt(m_colorFormat));
	}
	else if (formatClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
	{
		tcu::clear(m_colorBuffer.getAccess(), defaultClearColorUint(m_colorFormat));
		tcu::clear(m_resolveColorBuffer.getAccess(), defaultClearColorUint(m_colorFormat));
	}
	else
	{
		tcu::Vec4 clearColor = defaultClearColor(m_colorFormat);

		if (isSRGB(m_colorFormat))
			clearColor = tcu::linearToSRGB(clearColor);

		tcu::clear(m_colorBuffer.getAccess(), clearColor);
		tcu::clear(m_resolveColorBuffer.getAccess(), clearColor);
	}

	if (hasDepthStencil)
	{
		if (hasDepthBufferOnly)
		{
			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
			tcu::clearDepth(m_depthStencilBuffer.getAccess(), defaultClearDepth());

			m_resolveDepthStencilBuffer.setStorage(m_depthStencilFormat, surfaceWidth, surfaceHeight);
			tcu::clearDepth(m_resolveDepthStencilBuffer.getAccess(), defaultClearDepth());

			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
		}
		else if (hasStencilBufferOnly)
		{
			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
			tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());

			m_resolveDepthStencilBuffer.setStorage(m_depthStencilFormat, surfaceWidth, surfaceHeight);
			tcu::clearStencil(m_resolveDepthStencilBuffer.getAccess(), defaultClearStencil());

			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
												  rr::MultisamplePixelBufferAccess(),
												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
		}
		else
		{
			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);

			tcu::clearDepth(m_depthStencilBuffer.getAccess(), defaultClearDepth());
			tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());

			m_resolveDepthStencilBuffer.setStorage(m_depthStencilFormat, surfaceWidth, surfaceHeight);
			tcu::clearDepth(m_resolveDepthStencilBuffer.getAccess(), defaultClearDepth());

			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()),
												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
		}
	}
	else
	{
		m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()));
	}
}

ReferenceRenderer::~ReferenceRenderer (void)
{
	delete m_renderTarget;
}

void ReferenceRenderer::colorClear(const tcu::Vec4& color)
{
	tcu::clear(m_colorBuffer.getAccess(), color);
	tcu::clear(m_resolveColorBuffer.getAccess(), color);
}

void ReferenceRenderer::draw (const rr::RenderState&			renderState,
							  const rr::PrimitiveType			primitive,
							  const std::vector<Vertex4RGBA>&	vertexBuffer)
{
	const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);

	std::vector<tcu::Vec4> positions;
	std::vector<tcu::Vec4> colors;

	for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
	{
		const Vertex4RGBA& v = vertexBuffer[vertexNdx];
		positions.push_back(v.position);
		colors.push_back(v.color);
	}

	rr::VertexAttrib vertexAttribs[2];

	// Position attribute
	vertexAttribs[0].type		= rr::VERTEXATTRIBTYPE_FLOAT;
	vertexAttribs[0].size		= 4;
	vertexAttribs[0].pointer	= positions.data();
	// UV attribute
	vertexAttribs[1].type		= rr::VERTEXATTRIBTYPE_FLOAT;
	vertexAttribs[1].size		= 4;
	vertexAttribs[1].pointer	= colors.data();

	rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);

	m_renderer.draw(drawQuadCommand);
}

void ReferenceRenderer::draw (const rr::RenderState&			renderState,
							  const rr::PrimitiveType			primitive,
							  const std::vector<Vertex4Tex4>&	vertexBuffer)
{
	const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);

	std::vector<tcu::Vec4> positions;
	std::vector<tcu::Vec4> texCoords;

	for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
	{
		const Vertex4Tex4& v = vertexBuffer[vertexNdx];
		positions.push_back(v.position);
		texCoords.push_back(v.texCoord);
	}

	rr::VertexAttrib vertexAttribs[2];

	// Position attribute
	vertexAttribs[0].type		= rr::VERTEXATTRIBTYPE_FLOAT;
	vertexAttribs[0].size		= 4;
	vertexAttribs[0].pointer	= positions.data();
	// UV attribute
	vertexAttribs[1].type		= rr::VERTEXATTRIBTYPE_FLOAT;
	vertexAttribs[1].size		= 4;
	vertexAttribs[1].pointer	= texCoords.data();

	rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);

	m_renderer.draw(drawQuadCommand);
}

tcu::PixelBufferAccess ReferenceRenderer::getAccess (void)
{
	rr::MultisampleConstPixelBufferAccess multiSampleAccess = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess());
	rr::resolveMultisampleColorBuffer(m_resolveColorBuffer.getAccess(), multiSampleAccess);

	return m_resolveColorBuffer.getAccess();
}

tcu::PixelBufferAccess ReferenceRenderer::getDepthStencilAccess (void)
{
	rr::MultisampleConstPixelBufferAccess multiSampleAccess = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess());
	rr::resolveMultisampleColorBuffer(m_resolveDepthStencilBuffer.getAccess(), multiSampleAccess);

	return m_resolveDepthStencilBuffer.getAccess();
}

const rr::ViewportState ReferenceRenderer::getViewportState (void) const
{
	return rr::ViewportState(rr::WindowRectangle(0, 0, m_surfaceWidth, m_surfaceHeight));
}

} // pipeline
} // vkt
