/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL Utilities
 * ---------------------------------------------
 *
 * Copyright 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 Draw call utilities.
 *//*--------------------------------------------------------------------*/

#include "gluDrawUtil.hpp"
#include "gluRenderContext.hpp"
#include "gluObjectWrapper.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "deInt32.h"
#include "deMemory.h"

#include <vector>
#include <set>
#include <iterator>

namespace glu
{
namespace
{

struct VertexAttributeDescriptor
{
	int							location;
	VertexComponentType			componentType;
	VertexComponentConversion	convert;
	int							numComponents;
	int							numElements;
	int							stride;				//!< Stride or 0 if using default stride.
	const void*					pointer;			//!< Pointer or offset.

	VertexAttributeDescriptor (int							location_,
							   VertexComponentType			componentType_,
							   VertexComponentConversion	convert_,
							   int							numComponents_,
							   int							numElements_,
							   int							stride_,
							   const void*					pointer_)
		: location		(location_)
		, componentType	(componentType_)
		, convert		(convert_)
		, numComponents	(numComponents_)
		, numElements	(numElements_)
		, stride		(stride_)
		, pointer		(pointer_)
	{
	}

	VertexAttributeDescriptor (void)
		: location		(0)
		, componentType	(VTX_COMP_TYPE_LAST)
		, convert		(VTX_COMP_CONVERT_LAST)
		, numComponents	(0)
		, numElements	(0)
		, stride		(0)
		, pointer		(0)
	{
	}
};

struct VertexBufferLayout
{
	int										size;
	std::vector<VertexAttributeDescriptor>	attributes;

	VertexBufferLayout (int size_ = 0)
		: size(size_)
	{
	}
};

struct VertexBufferDescriptor
{
	deUint32								buffer;
	std::vector<VertexAttributeDescriptor>	attributes;

	VertexBufferDescriptor (deUint32 buffer_ = 0)
		: buffer(buffer_)
	{
	}
};

class VertexBuffer : public Buffer
{
public:
	enum Type
	{
		TYPE_PLANAR = 0,	//!< Data for each vertex array resides in a separate contiguous block in buffer.
		TYPE_STRIDED,		//!< Vertex arrays are interleaved.

		TYPE_LAST
	};

									VertexBuffer		(const RenderContext& context, int numBindings, const VertexArrayBinding* bindings, Type type = TYPE_PLANAR);
									~VertexBuffer		(void);

	const VertexBufferDescriptor&	getDescriptor		(void) const { return m_layout; }

private:
									VertexBuffer		(const VertexBuffer& other);
	VertexBuffer&					operator=			(const VertexBuffer& other);

	VertexBufferDescriptor			m_layout;
};

class IndexBuffer : public Buffer
{
public:
									IndexBuffer			(const RenderContext& context, IndexType indexType, int numIndices, const void* indices);
									~IndexBuffer		(void);

private:
									IndexBuffer			(const IndexBuffer& other);
	IndexBuffer&					operator=			(const IndexBuffer& other);
};

static deUint32 getVtxCompGLType (VertexComponentType type)
{
	switch (type)
	{
		case VTX_COMP_UNSIGNED_INT8:	return GL_UNSIGNED_BYTE;
		case VTX_COMP_UNSIGNED_INT16:	return GL_UNSIGNED_SHORT;
		case VTX_COMP_UNSIGNED_INT32:	return GL_UNSIGNED_INT;
		case VTX_COMP_SIGNED_INT8:		return GL_BYTE;
		case VTX_COMP_SIGNED_INT16:		return GL_SHORT;
		case VTX_COMP_SIGNED_INT32:		return GL_INT;
		case VTX_COMP_FIXED:			return GL_FIXED;
		case VTX_COMP_HALF_FLOAT:		return GL_HALF_FLOAT;
		case VTX_COMP_FLOAT:			return GL_FLOAT;
		default:
			DE_ASSERT(false);
			return GL_NONE;
	}
}

static int getVtxCompSize (VertexComponentType type)
{
	switch (type)
	{
		case VTX_COMP_UNSIGNED_INT8:	return 1;
		case VTX_COMP_UNSIGNED_INT16:	return 2;
		case VTX_COMP_UNSIGNED_INT32:	return 4;
		case VTX_COMP_SIGNED_INT8:		return 1;
		case VTX_COMP_SIGNED_INT16:		return 2;
		case VTX_COMP_SIGNED_INT32:		return 4;
		case VTX_COMP_FIXED:			return 4;
		case VTX_COMP_HALF_FLOAT:		return 2;
		case VTX_COMP_FLOAT:			return 4;
		default:
			DE_ASSERT(false);
			return 0;
	}
}

static deUint32 getIndexGLType (IndexType type)
{
	switch (type)
	{
		case INDEXTYPE_UINT8:	return GL_UNSIGNED_BYTE;
		case INDEXTYPE_UINT16:	return GL_UNSIGNED_SHORT;
		case INDEXTYPE_UINT32:	return GL_UNSIGNED_INT;
		default:
			DE_ASSERT(false);
			return 0;
	}
}

static int getIndexSize (IndexType type)
{
	switch (type)
	{
		case INDEXTYPE_UINT8:	return 1;
		case INDEXTYPE_UINT16:	return 2;
		case INDEXTYPE_UINT32:	return 4;
		default:
			DE_ASSERT(false);
			return 0;
	}
}

static deUint32 getPrimitiveGLType (PrimitiveType type)
{
	switch (type)
	{
		case PRIMITIVETYPE_TRIANGLES:		return GL_TRIANGLES;
		case PRIMITIVETYPE_TRIANGLE_STRIP:	return GL_TRIANGLE_STRIP;
		case PRIMITIVETYPE_TRIANGLE_FAN:	return GL_TRIANGLE_FAN;
		case PRIMITIVETYPE_LINES:			return GL_LINES;
		case PRIMITIVETYPE_LINE_STRIP:		return GL_LINE_STRIP;
		case PRIMITIVETYPE_LINE_LOOP:		return GL_LINE_LOOP;
		case PRIMITIVETYPE_POINTS:			return GL_POINTS;
		case PRIMITIVETYPE_PATCHES:			return GL_PATCHES;
		default:
			DE_ASSERT(false);
			return 0;
	}
}

//! Lower named bindings to locations and eliminate bindings that are not used by program.
template<typename InputIter, typename OutputIter>
static OutputIter namedBindingsToProgramLocations (const glw::Functions& gl, deUint32 program, InputIter first, InputIter end, OutputIter out)
{
	for (InputIter cur = first; cur != end; ++cur)
	{
		const BindingPoint& binding = cur->binding;
		if (binding.type == BindingPoint::TYPE_NAME)
		{
			DE_ASSERT(binding.location >= 0);
			int location = gl.getAttribLocation(program, binding.name.c_str());
			if (location >= 0)
			{
				// Add binding.location as an offset to accommodate matrices.
				*out = VertexArrayBinding(BindingPoint(location + binding.location), cur->pointer);
				++out;
			}
		}
		else
		{
			*out = *cur;
			++out;
		}
	}

	return out;
}

static deUint32 getMinimumAlignment (const VertexArrayPointer& pointer)
{
	// \todo [2013-05-07 pyry] What is the actual min?
	DE_UNREF(pointer);
	return (deUint32)sizeof(float);
}

template<typename BindingIter>
static bool areVertexArrayLocationsValid (BindingIter first, BindingIter end)
{
	std::set<int> usedLocations;
	for (BindingIter cur = first; cur != end; ++cur)
	{
		const BindingPoint& binding = cur->binding;

		if (binding.type != BindingPoint::TYPE_LOCATION)
			return false;

		if (usedLocations.find(binding.location) != usedLocations.end())
			return false;

		usedLocations.insert(binding.location);
	}

	return true;
}

// \todo [2013-05-08 pyry] Buffer upload should try to match pointers to reduce dataset size.

static void appendAttributeNonStrided (VertexBufferLayout& layout, const VertexArrayBinding& va)
{
	const int	offset		= deAlign32(layout.size, getMinimumAlignment(va.pointer));
	const int	elementSize	= getVtxCompSize(va.pointer.componentType)*va.pointer.numComponents;
	const int	size		= elementSize*va.pointer.numElements;

	// Must be assigned to location at this point.
	DE_ASSERT(va.binding.type == BindingPoint::TYPE_LOCATION);

	layout.attributes.push_back(VertexAttributeDescriptor(va.binding.location,
														  va.pointer.componentType,
														  va.pointer.convert,
														  va.pointer.numComponents,
														  va.pointer.numElements,
														  0, // default stride
														  (const void*)(deUintptr)offset));
	layout.size = offset+size;
}

template<typename BindingIter>
static void computeNonStridedBufferLayout (VertexBufferLayout& layout, BindingIter first, BindingIter end)
{
	for (BindingIter iter = first; iter != end; ++iter)
		appendAttributeNonStrided(layout, *iter);
}

static void copyToLayout (void* dstBasePtr, const VertexAttributeDescriptor& dstVA, const VertexArrayPointer& srcPtr)
{
	DE_ASSERT(dstVA.componentType	== srcPtr.componentType &&
			  dstVA.numComponents	== srcPtr.numComponents &&
			  dstVA.numElements		== srcPtr.numElements);

	const int	elementSize			= getVtxCompSize(dstVA.componentType)*dstVA.numComponents;
	const bool	srcHasCustomStride	= srcPtr.stride != 0 && srcPtr.stride != elementSize;
	const bool	dstHasCustomStride	= dstVA.stride != 0 && dstVA.stride != elementSize;

	if (srcHasCustomStride || dstHasCustomStride)
	{
		const int	dstStride	= dstVA.stride != 0 ? dstVA.stride : elementSize;
		const int	srcStride	= srcPtr.stride != 0 ? srcPtr.stride : elementSize;

		for (int ndx = 0; ndx < dstVA.numElements; ndx++)
			deMemcpy((deUint8*)dstBasePtr + (deUintptr)dstVA.pointer + ndx*dstStride, (const deUint8*)srcPtr.data + ndx*srcStride, elementSize);
	}
	else
		deMemcpy((deUint8*)dstBasePtr + (deUintptr)dstVA.pointer, srcPtr.data, elementSize*dstVA.numElements);
}

void uploadBufferData (const glw::Functions& gl, deUint32 buffer, deUint32 usage, const VertexBufferLayout& layout, const VertexArrayPointer* srcArrays)
{
	// Create temporary data buffer for upload.
	std::vector<deUint8> localBuf(layout.size);

	for (int attrNdx = 0; attrNdx < (int)layout.attributes.size(); ++attrNdx)
		copyToLayout(&localBuf[0], layout.attributes[attrNdx], srcArrays[attrNdx]);

	gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
	gl.bufferData(GL_ARRAY_BUFFER, (int)localBuf.size(), &localBuf[0], usage);
	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading buffer data failed");
}

// VertexBuffer

VertexBuffer::VertexBuffer (const RenderContext& context, int numBindings, const VertexArrayBinding* bindings, Type type)
	: Buffer(context)
{
	const glw::Functions&	gl		= context.getFunctions();
	const deUint32			usage	= GL_STATIC_DRAW;
	VertexBufferLayout		layout;

	if (!areVertexArrayLocationsValid(bindings, bindings+numBindings))
		throw tcu::TestError("Invalid vertex array locations");

	if (type == TYPE_PLANAR)
		computeNonStridedBufferLayout(layout, bindings, bindings+numBindings);
	else
		throw tcu::InternalError("Strided layout is not yet supported");

	std::vector<VertexArrayPointer> srcPtrs(numBindings);
	for (int ndx = 0; ndx < numBindings; ndx++)
		srcPtrs[ndx] = bindings[ndx].pointer;

	DE_ASSERT(srcPtrs.size() == layout.attributes.size());
	if (!srcPtrs.empty())
		uploadBufferData(gl, m_object, usage, layout, &srcPtrs[0]);

	// Construct descriptor.
	m_layout.buffer		= m_object;
	m_layout.attributes	= layout.attributes;
}

VertexBuffer::~VertexBuffer (void)
{
}

// IndexBuffer

IndexBuffer::IndexBuffer (const RenderContext& context, IndexType indexType, int numIndices, const void* indices)
	: Buffer(context)
{
	const glw::Functions&	gl		= context.getFunctions();
	const deUint32			usage	= GL_STATIC_DRAW;

	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_object);
	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*getIndexSize(indexType), indices, usage);
	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading index data failed");
}

IndexBuffer::~IndexBuffer (void)
{
}

static inline VertexAttributeDescriptor getUserPointerDescriptor (const VertexArrayBinding& vertexArray)
{
	DE_ASSERT(vertexArray.binding.type == BindingPoint::TYPE_LOCATION);

	return VertexAttributeDescriptor(vertexArray.binding.location,
									 vertexArray.pointer.componentType,
									 vertexArray.pointer.convert,
									 vertexArray.pointer.numComponents,
									 vertexArray.pointer.numElements,
									 vertexArray.pointer.stride,
									 vertexArray.pointer.data);
}

//! Setup VA according to allocation spec. Assumes that other state (VAO binding, buffer) is set already.
static void setVertexAttribPointer (const glw::Functions& gl, const VertexAttributeDescriptor& va)
{
	const bool		isIntType		= de::inRange<int>(va.componentType, VTX_COMP_UNSIGNED_INT8, VTX_COMP_SIGNED_INT32);
	const bool		isSpecialType	= de::inRange<int>(va.componentType, VTX_COMP_FIXED, VTX_COMP_FLOAT);
	const deUint32	compTypeGL		= getVtxCompGLType(va.componentType);

	DE_ASSERT(isIntType != isSpecialType); // Must be either int or special type.
	DE_ASSERT(isIntType || va.convert == VTX_COMP_CONVERT_NONE); // Conversion allowed only for special types.
	DE_UNREF(isSpecialType);

	gl.enableVertexAttribArray(va.location);

	if (isIntType && va.convert == VTX_COMP_CONVERT_NONE)
		gl.vertexAttribIPointer(va.location, va.numComponents, compTypeGL, va.stride, va.pointer);
	else
		gl.vertexAttribPointer(va.location, va.numComponents, compTypeGL, va.convert == VTX_COMP_CONVERT_NORMALIZE_TO_FLOAT ? GL_TRUE : GL_FALSE, va.stride, va.pointer);
}

//! Setup vertex buffer and attributes.
static void setVertexBufferAttributes (const glw::Functions& gl, const VertexBufferDescriptor& buffer)
{
	gl.bindBuffer(GL_ARRAY_BUFFER, buffer.buffer);

	for (std::vector<VertexAttributeDescriptor>::const_iterator vaIter = buffer.attributes.begin(); vaIter != buffer.attributes.end(); ++vaIter)
		setVertexAttribPointer(gl, *vaIter);

	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
}

static void disableVertexArrays (const glw::Functions& gl, const std::vector<VertexArrayBinding>& bindings)
{
	for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindings.begin(); vaIter != bindings.end(); ++vaIter)
	{
		DE_ASSERT(vaIter->binding.type == BindingPoint::TYPE_LOCATION);
		gl.disableVertexAttribArray(vaIter->binding.location);
	}
}

#if defined(DE_DEBUG)
static bool isProgramActive (const RenderContext& context, deUint32 program)
{
	// \todo [2013-05-08 pyry] Is this query broken?
/*	deUint32 activeProgram = 0;
	context.getFunctions().getIntegerv(GL_ACTIVE_PROGRAM, (int*)&activeProgram);
	GLU_EXPECT_NO_ERROR(context.getFunctions().getError(), "oh");
	return activeProgram == program;*/
	DE_UNREF(context);
	DE_UNREF(program);
	return true;
}

static bool isDrawCallValid (int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives)
{
	if (numVertexArrays < 0)
		return false;

	if ((primitives.indexType == INDEXTYPE_LAST) != (primitives.indices == 0))
		return false;

	if (primitives.numElements < 0)
		return false;

	if (!primitives.indices)
	{
		for (int ndx = 0; ndx < numVertexArrays; ndx++)
		{
			if (primitives.numElements > vertexArrays[ndx].pointer.numElements)
				return false;
		}
	}
	// \todo [2013-05-08 pyry] We could walk whole index array and determine index range

	return true;
}
#endif // DE_DEBUG

static inline void drawNonIndexed (const glw::Functions& gl, PrimitiveType type, int numElements)
{
	deUint32 mode = getPrimitiveGLType(type);
	gl.drawArrays(mode, 0, numElements);
}

static inline void drawIndexed (const glw::Functions& gl, PrimitiveType type, int numElements, IndexType indexType, const void* indexPtr)
{
	deUint32	mode		= getPrimitiveGLType(type);
	deUint32	indexGLType	= getIndexGLType(indexType);

	gl.drawElements(mode, numElements, indexGLType, indexPtr);
}

} // anonymous

void drawFromUserPointers (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
{
	const glw::Functions&				gl		= context.getFunctions();
	std::vector<VertexArrayBinding>		bindingsWithLocations;

	DE_ASSERT(isDrawCallValid(numVertexArrays, vertexArrays, primitives));
	DE_ASSERT(isProgramActive(context, program));

	// Lower bindings to locations.
	namedBindingsToProgramLocations(gl, program, vertexArrays, vertexArrays+numVertexArrays, std::inserter(bindingsWithLocations, bindingsWithLocations.begin()));

	TCU_CHECK(areVertexArrayLocationsValid(bindingsWithLocations.begin(), bindingsWithLocations.end()));

	// Set VA state.
	for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindingsWithLocations.begin(); vaIter != bindingsWithLocations.end(); ++vaIter)
		setVertexAttribPointer(gl, getUserPointerDescriptor(*vaIter));

	if (callback)
		callback->beforeDrawCall();

	if (primitives.indices)
		drawIndexed(gl, primitives.type, primitives.numElements, primitives.indexType, primitives.indices);
	else
		drawNonIndexed(gl, primitives.type, primitives.numElements);

	if (callback)
		callback->afterDrawCall();

	// Disable attribute arrays or otherwise someone later on might get crash thanks to invalid pointers.
	disableVertexArrays(gl, bindingsWithLocations);
}

void drawFromBuffers (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
{
	const glw::Functions&				gl		= context.getFunctions();
	std::vector<VertexArrayBinding>		bindingsWithLocations;

	DE_ASSERT(isDrawCallValid(numVertexArrays, vertexArrays, primitives));
	DE_ASSERT(isProgramActive(context, program));

	// Lower bindings to locations.
	namedBindingsToProgramLocations(gl, program, vertexArrays, vertexArrays+numVertexArrays, std::inserter(bindingsWithLocations, bindingsWithLocations.begin()));

	TCU_CHECK(areVertexArrayLocationsValid(bindingsWithLocations.begin(), bindingsWithLocations.end()));

	// Create buffers for duration of draw call.
	{
		VertexBuffer vertexBuffer (context, (int)bindingsWithLocations.size(), (bindingsWithLocations.empty()) ? (DE_NULL) : (&bindingsWithLocations[0]));

		// Set state.
		setVertexBufferAttributes(gl, vertexBuffer.getDescriptor());

		if (primitives.indices)
		{
			IndexBuffer indexBuffer(context, primitives.indexType, primitives.numElements, primitives.indices);

			gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *indexBuffer);

			if (callback)
				callback->beforeDrawCall();

			drawIndexed(gl, primitives.type, primitives.numElements, primitives.indexType, 0);

			if (callback)
				callback->afterDrawCall();

			gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		}
		else
		{
			if (callback)
				callback->beforeDrawCall();

			drawNonIndexed(gl, primitives.type, primitives.numElements);

			if (callback)
				callback->afterDrawCall();
		}
	}

	// Disable attribute arrays or otherwise someone later on might get crash thanks to invalid pointers.
	for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindingsWithLocations.begin(); vaIter != bindingsWithLocations.end(); ++vaIter)
		gl.disableVertexAttribArray(vaIter->binding.location);
}

void drawFromVAOBuffers (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
{
	const glw::Functions&	gl		= context.getFunctions();
	VertexArray				vao		(context);

	gl.bindVertexArray(*vao);
	drawFromBuffers(context, program, numVertexArrays, vertexArrays, primitives, callback);
	gl.bindVertexArray(0);
}

void draw (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
{
	const glu::ContextType ctxType = context.getType();

	if (isContextTypeGLCore(ctxType) || contextSupports(ctxType, ApiType::es(3,1)))
		drawFromVAOBuffers(context, program, numVertexArrays, vertexArrays, primitives, callback);
	else
	{
		DE_ASSERT(isContextTypeES(ctxType));
		drawFromUserPointers(context, program, numVertexArrays, vertexArrays, primitives, callback);
	}
}

} // glu
