/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 * Copyright (c) 2014 The Android Open Source Project
 *
 * 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 Scissor tests
 *//*--------------------------------------------------------------------*/

#include "vktFragmentOperationsScissorTests.hpp"
#include "vktFragmentOperationsScissorMultiViewportTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktFragmentOperationsMakeUtil.hpp"

#include "vkDefs.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkPrograms.hpp"
#include "vkImageUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"

#include "tcuTestLog.hpp"
#include "tcuVector.hpp"
#include "tcuImageCompare.hpp"

#include "deUniquePtr.hpp"
#include "deRandom.hpp"

namespace vkt
{
namespace FragmentOperations
{
using namespace vk;
using de::UniquePtr;
using de::MovePtr;
using tcu::Vec4;
using tcu::Vec2;
using tcu::IVec2;
using tcu::IVec4;

namespace
{

//! What primitives will be drawn by the test case.
enum TestPrimitive
{
	TEST_PRIMITIVE_POINTS,			//!< Many points.
	TEST_PRIMITIVE_LINES,			//!< Many short lines.
	TEST_PRIMITIVE_TRIANGLES,		//!< Many small triangles.
	TEST_PRIMITIVE_BIG_LINE,		//!< One line crossing the whole render area.
	TEST_PRIMITIVE_BIG_TRIANGLE,	//!< One triangle covering the whole render area.
};

struct VertexData
{
	Vec4	position;
	Vec4	color;
};

//! Parameters used by the test case.
struct CaseDef
{
	Vec4			renderArea;		//!< (ox, oy, w, h), where origin (0,0) is the top-left corner of the viewport. Width and height are in range [0, 1].
	Vec4			scissorArea;	//!< scissored area (ox, oy, w, h)
	TestPrimitive	primitive;
};

template<typename T>
inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
{
	return vec.size() * sizeof(vec[0]);
}

VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const IVec2& size, VkImageUsageFlags usage)
{
	const VkImageCreateInfo imageParams =
	{
		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
		DE_NULL,										// const void*				pNext;
		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
		format,											// VkFormat					format;
		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
		1u,												// deUint32					mipLevels;
		1u,												// deUint32					arrayLayers;
		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
		usage,											// VkImageUsageFlags		usage;
		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
		0u,												// deUint32					queueFamilyIndexCount;
		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
	};
	return imageParams;
}

Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
									   const VkDevice				device,
									   const VkPipelineLayout		pipelineLayout,
									   const VkRenderPass			renderPass,
									   const VkShaderModule			vertexModule,
									   const VkShaderModule			fragmentModule,
									   const IVec2					renderSize,
									   const IVec4					scissorArea,	//!< (ox, oy, w, h)
									   const VkPrimitiveTopology	topology)
{
	const VkVertexInputBindingDescription vertexInputBindingDescription =
	{
		0u,								// uint32_t				binding;
		sizeof(VertexData),				// uint32_t				stride;
		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
	};

	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
	{
		{
			0u,								// uint32_t		location;
			0u,								// uint32_t		binding;
			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
			0u,								// uint32_t		offset;
		},
		{
			1u,								// uint32_t		location;
			0u,								// uint32_t		binding;
			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
			sizeof(Vec4),					// uint32_t		offset;
		},
	};

	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType;
		DE_NULL,													// const void*                                 pNext;
		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags       flags;
		1u,															// uint32_t                                    vertexBindingDescriptionCount;
		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),		// uint32_t                                    vertexAttributeDescriptionCount;
		vertexInputAttributeDescriptions,							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
	};

	const VkRect2D			scissor		=
	{
		makeOffset2D(scissorArea.x(), scissorArea.y()),
		makeExtent2D(scissorArea.z(), scissorArea.w())
	};

	const std::vector<VkViewport>	viewports	(1, makeViewport(renderSize));
	const std::vector<VkRect2D>		scissors	(1, scissor);

	return vk::makeGraphicsPipeline(vk,						// const DeviceInterface&                        vk
									device,					// const VkDevice                                device
									pipelineLayout,			// const VkPipelineLayout                        pipelineLayout
									vertexModule,			// const VkShaderModule                          vertexShaderModule
									DE_NULL,				// const VkShaderModule                          tessellationControlModule
									DE_NULL,				// const VkShaderModule                          tessellationEvalModule
									DE_NULL,				// const VkShaderModule                          geometryShaderModule
									fragmentModule,			// const VkShaderModule                          fragmentShaderModule
									renderPass,				// const VkRenderPass                            renderPass
									viewports,				// const std::vector<VkViewport>&                viewports
									scissors,				// const std::vector<VkRect2D>&                  scissors
									topology,				// const VkPrimitiveTopology                     topology
									0u,						// const deUint32                                subpass
									0u,						// const deUint32                                patchControlPoints
									&vertexInputStateInfo);	// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
}

inline VertexData makeVertex (const float x, const float y, const Vec4& color)
{
	const VertexData data = { Vec4(x, y, 0.0f, 1.0f), color };
	return data;
}

std::vector<VertexData> genVertices (const TestPrimitive primitive, const Vec4& renderArea, const Vec4& primitiveColor)
{
	std::vector<VertexData> vertices;
	de::Random				rng			(1234);

	const float	x0		= 2.0f * renderArea.x() - 1.0f;
	const float y0		= 2.0f * renderArea.y() - 1.0f;
	const float	rx		= 2.0f * renderArea.z();
	const float	ry		= 2.0f * renderArea.w();
	const float	size	= 0.2f;

	switch (primitive)
	{
		case TEST_PRIMITIVE_POINTS:
			for (int i = 0; i < 50; ++i)
			{
				const float x = x0 + rng.getFloat(0.0f, rx);
				const float y = y0 + rng.getFloat(0.0f, ry);
				vertices.push_back(makeVertex(x, y, primitiveColor));
			}
			break;

		case TEST_PRIMITIVE_LINES:
			for (int i = 0; i < 30; ++i)
			{
				const float x = x0 + rng.getFloat(0.0f, rx - size);
				const float y = y0 + rng.getFloat(0.0f, ry - size);
				vertices.push_back(makeVertex(x,        y,        primitiveColor));
				vertices.push_back(makeVertex(x + size, y + size, primitiveColor));
			}
			break;

		case TEST_PRIMITIVE_TRIANGLES:
			for (int i = 0; i < 20; ++i)
			{
				const float x = x0 + rng.getFloat(0.0f, rx - size);
				const float y = y0 + rng.getFloat(0.0f, ry - size);
				vertices.push_back(makeVertex(x,             y,        primitiveColor));
				vertices.push_back(makeVertex(x + size/2.0f, y + size, primitiveColor));
				vertices.push_back(makeVertex(x + size,      y,        primitiveColor));
			}
			break;

		case TEST_PRIMITIVE_BIG_LINE:
			vertices.push_back(makeVertex(x0,      y0,      primitiveColor));
			vertices.push_back(makeVertex(x0 + rx, y0 + ry, primitiveColor));
			break;

		case TEST_PRIMITIVE_BIG_TRIANGLE:
			vertices.push_back(makeVertex(x0,           y0,      primitiveColor));
			vertices.push_back(makeVertex(x0 + rx/2.0f, y0 + ry, primitiveColor));
			vertices.push_back(makeVertex(x0 + rx,      y0,      primitiveColor));
			break;
	}

	return vertices;
}

VkPrimitiveTopology	getTopology (const TestPrimitive primitive)
{
	switch (primitive)
	{
		case TEST_PRIMITIVE_POINTS:			return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;

		case TEST_PRIMITIVE_LINES:
		case TEST_PRIMITIVE_BIG_LINE:		return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;

		case TEST_PRIMITIVE_TRIANGLES:
		case TEST_PRIMITIVE_BIG_TRIANGLE:	return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

		default:
			DE_ASSERT(0);
			return VK_PRIMITIVE_TOPOLOGY_LAST;
	}
}

void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize size)
{
	deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(size));
	flushAlloc(vk, device, alloc);
}

//! Transform from normalized coords to framebuffer space.
inline IVec4 getAreaRect (const Vec4& area, const int width, const int height)
{
	return IVec4(static_cast<deInt32>(static_cast<float>(width)  * area.x()),
				 static_cast<deInt32>(static_cast<float>(height) * area.y()),
				 static_cast<deInt32>(static_cast<float>(width)  * area.z()),
				 static_cast<deInt32>(static_cast<float>(height) * area.w()));
}

void applyScissor (tcu::PixelBufferAccess imageAccess, const Vec4& floatScissorArea, const Vec4& clearColor)
{
	const IVec4	scissorRect	(getAreaRect(floatScissorArea, imageAccess.getWidth(), imageAccess.getHeight()));
	const int	sx0			= scissorRect.x();
	const int	sx1			= scissorRect.x() + scissorRect.z();
	const int	sy0			= scissorRect.y();
	const int	sy1			= scissorRect.y() + scissorRect.w();

	for (int y = 0; y < imageAccess.getHeight(); ++y)
	for (int x = 0; x < imageAccess.getWidth(); ++x)
	{
		// Fragments outside fail the scissor test.
		if (x < sx0 || x >= sx1 || y < sy0 || y >= sy1)
			imageAccess.setPixel(clearColor, x, y);
	}
}

void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
{
	DE_UNREF(caseDef);

	// Vertex shader
	{
		const bool usePointSize = (caseDef.primitive == TEST_PRIMITIVE_POINTS);

		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(location = 0) in  vec4 in_position;\n"
			<< "layout(location = 1) in  vec4 in_color;\n"
			<< "layout(location = 0) out vec4 o_color;\n"
			<< "\n"
			<< "out gl_PerVertex {\n"
			<< "    vec4  gl_Position;\n"
			<< (usePointSize ? "    float gl_PointSize;\n" : "")
			<< "};\n"
			<< "\n"
			<< "void main(void)\n"
			<< "{\n"
			<< "    gl_Position  = in_position;\n"
			<< (usePointSize ? "    gl_PointSize = 1.0;\n" : "")
			<< "    o_color      = in_color;\n"
			<< "}\n";

		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
	}

	// Fragment shader
	{
		std::ostringstream src;
		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(location = 0) in  vec4 in_color;\n"
			<< "layout(location = 0) out vec4 o_color;\n"
			<< "\n"
			<< "void main(void)\n"
			<< "{\n"
			<< "    o_color = in_color;\n"
			<< "}\n";

		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
	}
}

class ScissorRenderer
{
public:
	ScissorRenderer (Context& context, const CaseDef caseDef, const IVec2& renderSize, const VkFormat colorFormat, const Vec4& primitiveColor, const Vec4& clearColor)
		: m_renderSize				(renderSize)
		, m_colorFormat				(colorFormat)
		, m_colorSubresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
		, m_primitiveColor			(primitiveColor)
		, m_clearColor				(clearColor)
		, m_vertices				(genVertices(caseDef.primitive, caseDef.renderArea, m_primitiveColor))
		, m_vertexBufferSize		(sizeInBytes(m_vertices))
		, m_topology				(getTopology(caseDef.primitive))
	{
		const DeviceInterface&		vk					= context.getDeviceInterface();
		const VkDevice				device				= context.getDevice();
		const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
		Allocator&					allocator			= context.getDefaultAllocator();

		m_colorImage			= makeImage(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
		m_colorImageAlloc		= bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
		m_colorAttachment		= makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);

		m_vertexBuffer			= makeBuffer(vk, device, makeBufferCreateInfo(m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
		m_vertexBufferAlloc		= bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible);

		{
			deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], static_cast<std::size_t>(m_vertexBufferSize));
			flushAlloc(vk, device, *m_vertexBufferAlloc);
		}

		m_vertexModule				= createShaderModule	(vk, device, context.getBinaryCollection().get("vert"), 0u);
		m_fragmentModule			= createShaderModule	(vk, device, context.getBinaryCollection().get("frag"), 0u);
		m_renderPass				= makeRenderPass		(vk, device, m_colorFormat);
		m_framebuffer				= makeFramebuffer		(vk, device, *m_renderPass, m_colorAttachment.get(),
															 static_cast<deUint32>(m_renderSize.x()),  static_cast<deUint32>(m_renderSize.y()));
		m_pipelineLayout			= makePipelineLayout	(vk, device);
		m_cmdPool					= createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
		m_cmdBuffer					= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);

	}

	void draw (Context& context, const Vec4& scissorAreaFloat, const VkBuffer colorBuffer) const
	{
		const DeviceInterface&		vk			= context.getDeviceInterface();
		const VkDevice				device		= context.getDevice();
		const VkQueue				queue		= context.getUniversalQueue();

		// New pipeline, because we're modifying scissor (we don't use dynamic state).
		const Unique<VkPipeline>	pipeline	(makeGraphicsPipeline(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule,
												 m_renderSize, getAreaRect(scissorAreaFloat, m_renderSize.x(), m_renderSize.y()), m_topology));

		beginCommandBuffer(vk, *m_cmdBuffer);

		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), m_clearColor);

		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
		{
			const VkDeviceSize vertexBufferOffset = 0ull;
			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
		}

		vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_vertices.size()), 1u, 0u, 0u);
		endRenderPass(vk, *m_cmdBuffer);

		copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, m_renderSize);

		endCommandBuffer(vk, *m_cmdBuffer);
		submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
	}

private:
	const IVec2						m_renderSize;
	const VkFormat					m_colorFormat;
	const VkImageSubresourceRange	m_colorSubresourceRange;
	const Vec4						m_primitiveColor;
	const Vec4						m_clearColor;
	const std::vector<VertexData>	m_vertices;
	const VkDeviceSize				m_vertexBufferSize;
	const VkPrimitiveTopology		m_topology;

	Move<VkImage>					m_colorImage;
	MovePtr<Allocation>				m_colorImageAlloc;
	Move<VkImageView>				m_colorAttachment;
	Move<VkBuffer>					m_vertexBuffer;
	MovePtr<Allocation>				m_vertexBufferAlloc;
	Move<VkShaderModule>			m_vertexModule;
	Move<VkShaderModule>			m_fragmentModule;
	Move<VkRenderPass>				m_renderPass;
	Move<VkFramebuffer>				m_framebuffer;
	Move<VkPipelineLayout>			m_pipelineLayout;
	Move<VkCommandPool>				m_cmdPool;
	Move<VkCommandBuffer>			m_cmdBuffer;

	// "deleted"
						ScissorRenderer	(const ScissorRenderer&);
	ScissorRenderer&	operator=		(const ScissorRenderer&);
};

tcu::TestStatus test (Context& context, const CaseDef caseDef)
{
	const DeviceInterface&			vk							= context.getDeviceInterface();
	const VkDevice					device						= context.getDevice();
	Allocator&						allocator					= context.getDefaultAllocator();

	const IVec2						renderSize					(128, 128);
	const VkFormat					colorFormat					= VK_FORMAT_R8G8B8A8_UNORM;
	const Vec4						scissorFullArea				(0.0f, 0.0f, 1.0f, 1.0f);
	const Vec4						primitiveColor				(1.0f, 1.0f, 1.0f, 1.0f);
	const Vec4						clearColor					(0.5f, 0.5f, 1.0f, 1.0f);

	const VkDeviceSize				colorBufferSize				= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
	const Unique<VkBuffer>			colorBufferFull				(makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
	const UniquePtr<Allocation>		colorBufferFullAlloc		(bindBuffer(vk, device, allocator, *colorBufferFull, MemoryRequirement::HostVisible));

	const Unique<VkBuffer>			colorBufferScissored		(makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
	const UniquePtr<Allocation>		colorBufferScissoredAlloc	(bindBuffer(vk, device, allocator, *colorBufferScissored, MemoryRequirement::HostVisible));

	zeroBuffer(vk, device, *colorBufferFullAlloc, colorBufferSize);
	zeroBuffer(vk, device, *colorBufferScissoredAlloc, colorBufferSize);

	// Draw
	{
		const ScissorRenderer renderer (context, caseDef, renderSize, colorFormat, primitiveColor, clearColor);

		renderer.draw(context, scissorFullArea, *colorBufferFull);
		renderer.draw(context, caseDef.scissorArea, *colorBufferScissored);
	}

	// Log image
	{
		invalidateAlloc(vk, device, *colorBufferFullAlloc);
		invalidateAlloc(vk, device, *colorBufferScissoredAlloc);

		const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferScissoredAlloc->getHostPtr());
		tcu::PixelBufferAccess				referenceImage	(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferFullAlloc->getHostPtr());

		// Apply scissor to the full image, so we can compare it with the result image.
		applyScissor (referenceImage, caseDef.scissorArea, clearColor);

		// Images should now match.
		if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage, resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
			return tcu::TestStatus::fail("Rendered image is not correct");
	}

	return tcu::TestStatus::pass("OK");
}

//! \note The ES 2.0 scissoring tests included color/depth/stencil clear cases, but these operations are not affected by scissor test in Vulkan.
//!       Scissor is part of the pipeline state and pipeline only affects the drawing commands.
void createTestsInGroup (tcu::TestCaseGroup* scissorGroup)
{
	tcu::TestContext& testCtx = scissorGroup->getTestContext();

	struct TestSpec
	{
		const char*		name;
		const char*		description;
		CaseDef			caseDef;
	};

	const Vec4	areaFull			(0.0f, 0.0f, 1.0f, 1.0f);
	const Vec4	areaCropped			(0.2f, 0.2f, 0.6f, 0.6f);
	const Vec4	areaCroppedMore		(0.4f, 0.4f, 0.2f, 0.2f);
	const Vec4	areaLeftHalf		(0.0f, 0.0f, 0.5f, 1.0f);
	const Vec4	areaRightHalf		(0.5f, 0.0f, 0.5f, 1.0f);

	// Points
	{
		MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "points", ""));

		const TestSpec	cases[] =
		{
			{ "inside",				"Points fully inside the scissor area",		{ areaFull,		areaFull,		TEST_PRIMITIVE_POINTS } },
			{ "partially_inside",	"Points partially inside the scissor area",	{ areaFull,		areaCropped,	TEST_PRIMITIVE_POINTS } },
			{ "outside",			"Points fully outside the scissor area",	{ areaLeftHalf,	areaRightHalf,	TEST_PRIMITIVE_POINTS } },
		};

		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
			addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef);

		scissorGroup->addChild(primitiveGroup.release());
	}

	// Lines
	{
		MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "lines", ""));

		const TestSpec	cases[] =
		{
			{ "inside",				"Lines fully inside the scissor area",		{ areaFull,		areaFull,			TEST_PRIMITIVE_LINES	} },
			{ "partially_inside",	"Lines partially inside the scissor area",	{ areaFull,		areaCropped,		TEST_PRIMITIVE_LINES	} },
			{ "outside",			"Lines fully outside the scissor area",		{ areaLeftHalf,	areaRightHalf,		TEST_PRIMITIVE_LINES	} },
			{ "crossing",			"A line crossing the scissor area",			{ areaFull,		areaCroppedMore,	TEST_PRIMITIVE_BIG_LINE	} },
		};

		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
			addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef);

		scissorGroup->addChild(primitiveGroup.release());
	}

	// Triangles
	{
		MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "triangles", ""));

		const TestSpec	cases[] =
		{
			{ "inside",				"Triangles fully inside the scissor area",		{ areaFull,		areaFull,			TEST_PRIMITIVE_TRIANGLES	} },
			{ "partially_inside",	"Triangles partially inside the scissor area",	{ areaFull,		areaCropped,		TEST_PRIMITIVE_TRIANGLES	} },
			{ "outside",			"Triangles fully outside the scissor area",		{ areaLeftHalf,	areaRightHalf,		TEST_PRIMITIVE_TRIANGLES	} },
			{ "crossing",			"A triangle crossing the scissor area",			{ areaFull,		areaCroppedMore,	TEST_PRIMITIVE_BIG_TRIANGLE	} },
		};

		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
			addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef);

		scissorGroup->addChild(primitiveGroup.release());
	}

	// Mulit-viewport scissor
	{
		scissorGroup->addChild(createScissorMultiViewportTests(testCtx));
	}
}

} // anonymous

tcu::TestCaseGroup* createScissorTests (tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "scissor", "Scissor tests", createTestsInGroup);
}

} // FragmentOperations
} // vkt
