/*-------------------------------------------------------------------------
 * 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::BPTYPE_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::BPTYPE_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::BPTYPE_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::BPTYPE_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::BPTYPE_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
