/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2017 The Khronos Group Inc.
 *
 * 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
 */ /*-------------------------------------------------------------------*/

/**
 */ /*!
 * \file  gl4cIndirectParametersTests.cpp
 * \brief Conformance tests for the GL_ARB_indirect_parameters functionality.
 */ /*-------------------------------------------------------------------*/

#include "gl4cIndirectParametersTests.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluDrawUtil.hpp"
#include "gluShaderProgram.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuTestLog.hpp"

using namespace glw;
using namespace glu;

namespace gl4cts
{

static const char* c_vertShader = "#version 430\n"
								  "\n"
								  "in vec3 vertex;\n"
								  "\n"
								  "void main()\n"
								  "{\n"
								  "    gl_Position = vec4(vertex, 1);\n"
								  "}\n";

static const char* c_fragShader = "#version 430\n"
								  "\n"
								  "out vec4 fragColor;\n"
								  "\n"
								  "void main()\n"
								  "{\n"
								  "    fragColor = vec4(1, 1, 1, 0.5);\n"
								  "}\n";

/** Constructor.
 *
 *  @param context     Rendering context
 */
ParameterBufferOperationsCase::ParameterBufferOperationsCase(deqp::Context& context)
	: TestCase(context, "ParameterBufferOperations",
			   "Verifies if operations on new buffer object PARAMETER_BUFFER_ARB works as expected.")
{
	/* Left blank intentionally */
}

/** Stub init method */
void ParameterBufferOperationsCase::init()
{
}

/** Executes test iteration.
 *
 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
 */
tcu::TestNode::IterateResult ParameterBufferOperationsCase::iterate()
{
	glu::ContextType contextType = m_context.getRenderContext().getType();
	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
		return STOP;
	}

	const Functions& gl = m_context.getRenderContext().getFunctions();

	GLuint paramBuffer;

	GLint data[]	= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	GLint subData[] = { 10, 11, 12, 13, 14 };
	GLint expData[] = { 0, 1, 10, 11, 12, 13, 14, 7, 8, 9 };

	bool result = true;

	// Test buffer generating and binding
	gl.genBuffers(1, &paramBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, paramBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	GLint paramBinding;
	gl.getIntegerv(GL_PARAMETER_BUFFER_BINDING_ARB, &paramBinding);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");

	if ((GLuint)paramBinding != paramBuffer)
	{
		result = false;
		m_testCtx.getLog() << tcu::TestLog::Message << "Buffer binding mismatch" << tcu::TestLog::EndMessage;
	}
	else
	{
		// Test filling buffer with data
		gl.bufferData(GL_PARAMETER_BUFFER_ARB, 10 * sizeof(GLint), data, GL_DYNAMIC_DRAW);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

		gl.bufferSubData(GL_PARAMETER_BUFFER_ARB, 2 * sizeof(GLint), 5 * sizeof(GLint), subData);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

		// Test buffer mapping
		GLvoid* buffer = gl.mapBuffer(GL_PARAMETER_BUFFER_ARB, GL_READ_ONLY);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer");

		if (memcmp(buffer, expData, 10 * sizeof(GLint)) != 0)
		{
			result = false;
			m_testCtx.getLog() << tcu::TestLog::Message << "Buffer data mismatch" << tcu::TestLog::EndMessage;
		}
		else
		{
			GLvoid* bufferPointer;
			gl.getBufferPointerv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_MAP_POINTER, &bufferPointer);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferPointerv");

			if (buffer != bufferPointer)
			{
				result = false;
				m_testCtx.getLog() << tcu::TestLog::Message << "Buffer pointer mismatch" << tcu::TestLog::EndMessage;
			}
			else
			{
				GLint bufferSize;
				GLint bufferUsage;
				gl.getBufferParameteriv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_SIZE, &bufferSize);
				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv");
				gl.getBufferParameteriv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_USAGE, &bufferUsage);
				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv");

				if (bufferSize != 10 * sizeof(GLint))
				{
					result = false;
					m_testCtx.getLog() << tcu::TestLog::Message << "Buffer size mismatch" << tcu::TestLog::EndMessage;
				}
				else if (bufferUsage != GL_DYNAMIC_DRAW)
				{
					result = false;
					m_testCtx.getLog() << tcu::TestLog::Message << "Buffer usage mismatch" << tcu::TestLog::EndMessage;
				}
			}
		}

		gl.unmapBuffer(GL_PARAMETER_BUFFER_ARB);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");

		// Test buffer ranged mapping
		buffer =
			gl.mapBufferRange(GL_PARAMETER_BUFFER_ARB, 0, sizeof(GLint), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange");

		// Test buffer flushing
		GLint* bufferInt = (GLint*)buffer;

		bufferInt[0] = 100;
		gl.flushMappedBufferRange(GL_PARAMETER_BUFFER_ARB, 0, sizeof(GLint));
		GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");

		gl.unmapBuffer(GL_PARAMETER_BUFFER_ARB);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");

		// Test buffers data copying
		GLuint arrayBuffer;
		gl.genBuffers(1, &arrayBuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

		gl.bindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

		gl.bufferData(GL_ARRAY_BUFFER, 10 * sizeof(GLint), data, GL_DYNAMIC_DRAW);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

		gl.copyBufferSubData(GL_PARAMETER_BUFFER_ARB, GL_ARRAY_BUFFER, 0, 0, sizeof(GLint));
		GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyBufferSubData");

		gl.mapBufferRange(GL_ARRAY_BUFFER, 0, 1, GL_MAP_READ_BIT);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange");

		bufferInt = (GLint*)buffer;
		if (bufferInt[0] != 100)
		{
			result = false;
			m_testCtx.getLog() << tcu::TestLog::Message << "Buffer copy operation failed" << tcu::TestLog::EndMessage;
		}

		gl.unmapBuffer(GL_ARRAY_BUFFER);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");

		// Release array buffer
		gl.deleteBuffers(1, &arrayBuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
	}

	// Release parameter buffer
	gl.deleteBuffers(1, &paramBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");

	if (result)
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	else
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");

	return STOP;
}

/** Constructor.
 *
 *  @param context     Rendering context
 */
VertexArrayIndirectDrawingBaseCase::VertexArrayIndirectDrawingBaseCase(deqp::Context& context, const char* name,
																	   const char* description)
	: TestCase(context, name, description)
{
	/* Left blank intentionally */
}

/** Executes test iteration.
 *
 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
 */
tcu::TestNode::IterateResult VertexArrayIndirectDrawingBaseCase::iterate()
{
	glu::ContextType contextType = m_context.getRenderContext().getType();
	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
		return STOP;
	}

	if (draw() && verify())
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	else
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");

	return STOP;
}

/** This method verifies if drawn quads are as expected.
 *
 *  @return Returns true if quads are drawn properly, false otherwise.
 */
bool VertexArrayIndirectDrawingBaseCase::verify()
{
	const Functions&		 gl = m_context.getRenderContext().getFunctions();
	const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();

	const int width  = rt.getWidth();
	const int height = rt.getHeight();

	std::vector<GLubyte> pixels;
	pixels.resize(width * height);

	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
	gl.readPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, pixels.data());
	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);

	//Verify first quad
	for (int y = 2; y < height - 2; ++y)
	{
		for (int x = 2; x < width / 2 - 2; ++x)
		{
			int value = pixels[x + y * width];
			// Support 5-bit precision for the framebuffer, re-quantized to 8-bits from glReadPixels.
			if (value < 189 || value > 197)
			{
				m_testCtx.getLog() << tcu::TestLog::Message << "First quad verification failed. "
								   << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value
								   << ", expected: <189-197>" << tcu::TestLog::EndMessage;
				return false;
			}
		}
	}

	//Verify second quad
	for (int y = 2; y < height - 2; ++y)
	{
		for (int x = width / 2 + 2; x < width - 2; ++x)
		{
			int value = pixels[x + y * width];
			// Support 5-bit precision for the framebuffer, re-quantized to 8-bits from glReadPixels.
			if (value < 123 || value > 132)
			{
				m_testCtx.getLog() << tcu::TestLog::Message << "Second quad verification failed. "
								   << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value
								   << ", expected: <123-132>" << tcu::TestLog::EndMessage;
				return false;
			}
		}
	}

	return verifyErrors();
}

/** Constructor.
 *
 *  @param context     Rendering context
 */
MultiDrawArraysIndirectCountCase::MultiDrawArraysIndirectCountCase(deqp::Context& context)
	: VertexArrayIndirectDrawingBaseCase(context, "MultiDrawArraysIndirectCount",
										 "Test verifies if MultiDrawArraysIndirectCountARB function works as expected.")
	, m_vao(0)
	, m_arrayBuffer(0)
	, m_drawIndirectBuffer(0)
	, m_parameterBuffer(0)
{
	/* Left blank intentionally */
}

/** Stub init method */
void MultiDrawArraysIndirectCountCase::init()
{
	glu::ContextType contextType = m_context.getRenderContext().getType();
	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
		return;

	const Functions& gl = m_context.getRenderContext().getFunctions();

	const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f,  0.0f, 0.0f, -1.0f, 0.0f,
								 0.0f,  1.0f,  0.0f, 1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  0.0f };

	const DrawArraysIndirectCommand indirect[] = {
		{ 4, 2, 0, 0 }, //4 vertices, 2 instanceCount, 0 first, 0 baseInstance
		{ 4, 1, 2, 0 }  //4 vertices, 1 instanceCount, 2 first, 0 baseInstance
	};

	const GLushort parameters[] = { 2, 1 };

	// Generate vertex array object
	gl.genVertexArrays(1, &m_vao);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");

	gl.bindVertexArray(m_vao);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");

	// Setup vertex array buffer
	gl.genBuffers(1, &m_arrayBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

	// Setup indirect command buffer
	gl.genBuffers(1, &m_drawIndirectBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 2 * sizeof(DrawArraysIndirectCommand), indirect, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

	// Setup parameter buffer
	gl.genBuffers(1, &m_parameterBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_PARAMETER_BUFFER_ARB, 100 * sizeof(GLushort), parameters, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
}

/** Stub deinit method */
void MultiDrawArraysIndirectCountCase::deinit()
{
	const Functions& gl = m_context.getRenderContext().getFunctions();

	if (m_vao)
		gl.deleteVertexArrays(1, &m_vao);
	if (m_arrayBuffer)
		gl.deleteBuffers(1, &m_arrayBuffer);
	if (m_drawIndirectBuffer)
		gl.deleteBuffers(1, &m_drawIndirectBuffer);
	if (m_parameterBuffer)
		gl.deleteBuffers(1, &m_parameterBuffer);
}

/** Drawing quads method using drawArrays.
 */
bool MultiDrawArraysIndirectCountCase::draw()
{
	const Functions& gl = m_context.getRenderContext().getFunctions();

	ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader);
	ShaderProgram  program(gl, sources);

	if (!program.isOk())
	{
		m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
						   << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
						   << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
						   << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
		return false;
	}

	gl.useProgram(program.getProgram());
	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");

	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT);

	gl.enable(GL_BLEND);
	gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	gl.enableVertexAttribArray(0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");

	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawArraysIndirectCountARB");

	gl.disableVertexAttribArray(0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");

	gl.disable(GL_BLEND);

	return true;
}

/** Verify MultiDrawArrayIndirectCountARB errors
 */
bool MultiDrawArraysIndirectCountCase::verifyErrors()
{
	const Functions& gl = m_context.getRenderContext().getFunctions();

	GLint errorCode;

	bool result = true;

	// INVALID_VALUE - drawcount offset not multiple of 4
	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 2, 1, 0);
	errorCode = gl.getError();
	if (errorCode != GL_INVALID_VALUE)
	{
		m_testCtx.getLog() << tcu::TestLog::Message
						   << "MultiDrawArraysIndirectCount error verifying failed (1). Expected code: "
						   << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage;
		result = false;
	}

	// INVALID_OPERATION - maxdrawcount greater then parameter buffer size
	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 4, 0);
	errorCode = gl.getError();
	if (errorCode != GL_INVALID_OPERATION)
	{
		m_testCtx.getLog() << tcu::TestLog::Message
						   << "MultiDrawArraysIndirectCount error verifying failed (2). Expected code: "
						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
		result = false;
	}

	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	// INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound
	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0);
	errorCode = gl.getError();
	if (errorCode != GL_INVALID_OPERATION)
	{
		m_testCtx.getLog() << tcu::TestLog::Message
						   << "MultiDrawArraysIndirectCount error verifying failed (3). Expected code: "
						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
		result = false;
	}

	return result;
}

/** Constructor.
 *
 *  @param context     Rendering context
 */
MultiDrawElementsIndirectCountCase::MultiDrawElementsIndirectCountCase(deqp::Context& context)
	: VertexArrayIndirectDrawingBaseCase(
		  context, "MultiDrawElementsIndirectCount",
		  "Test verifies if MultiDrawElementsIndirectCountARB function works as expected.")
	, m_vao(0)
	, m_arrayBuffer(0)
	, m_elementBuffer(0)
	, m_drawIndirectBuffer(0)
	, m_parameterBuffer(0)
{
	/* Left blank intentionally */
}

/** Stub init method */
void MultiDrawElementsIndirectCountCase::init()
{
	glu::ContextType contextType = m_context.getRenderContext().getType();
	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
		return;

	const Functions& gl = m_context.getRenderContext().getFunctions();

	const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f,  0.0f, 0.0f, -1.0f, 0.0f,
								 0.0f,  1.0f,  0.0f, 1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  0.0f };

	const GLushort elements[] = { 0, 1, 2, 3, 4, 5 };

	const DrawElementsIndirectCommand indirect[] = {
		{ 4, 2, 0, 0, 0 }, //4 indices, 2 instanceCount, 0 firstIndex, 0 baseVertex, 0 baseInstance
		{ 4, 1, 2, 0, 0 }  //4 indices, 1 instanceCount, 2 firstIndex, 0 baseVertex, 0 baseInstance
	};

	const GLushort parameters[] = { 2, 1 };

	// Generate vertex array object
	gl.genVertexArrays(1, &m_vao);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");

	gl.bindVertexArray(m_vao);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");

	// Setup vertex array buffer
	gl.genBuffers(1, &m_arrayBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

	// Setup element array buffer
	gl.genBuffers(1, &m_elementBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), elements, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

	// Setup indirect command buffer
	gl.genBuffers(1, &m_drawIndirectBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 3 * sizeof(DrawElementsIndirectCommand), indirect, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

	// Setup parameters Re: buffer
	gl.genBuffers(1, &m_parameterBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_PARAMETER_BUFFER_ARB, 2 * sizeof(GLushort), parameters, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
}

/** Stub deinit method */
void MultiDrawElementsIndirectCountCase::deinit()
{
	const Functions& gl = m_context.getRenderContext().getFunctions();

	if (m_vao)
		gl.deleteVertexArrays(1, &m_vao);
	if (m_arrayBuffer)
		gl.deleteBuffers(1, &m_arrayBuffer);
	if (m_elementBuffer)
		gl.deleteBuffers(1, &m_elementBuffer);
	if (m_drawIndirectBuffer)
		gl.deleteBuffers(1, &m_drawIndirectBuffer);
	if (m_parameterBuffer)
		gl.deleteBuffers(1, &m_parameterBuffer);
}

/** Drawing quads method using drawArrays.
 */
bool MultiDrawElementsIndirectCountCase::draw()
{
	const Functions& gl = m_context.getRenderContext().getFunctions();

	ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader);
	ShaderProgram  program(gl, sources);

	if (!program.isOk())
	{
		m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
						   << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
						   << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
						   << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
		return false;
	}

	gl.useProgram(program.getProgram());
	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");

	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT);

	gl.enable(GL_BLEND);
	gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	gl.enableVertexAttribArray(0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");

	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_SHORT, 0, 0, 2, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawElementsIndirectCountARB");

	gl.disableVertexAttribArray(0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");

	gl.disable(GL_BLEND);

	return true;
}

/** Verify MultiDrawElementsIndirectCountARB errors
 */
bool MultiDrawElementsIndirectCountCase::verifyErrors()
{
	const Functions& gl = m_context.getRenderContext().getFunctions();

	GLint errorCode;

	bool result = true;

	// INVALID_VALUE - drawcount offset not multiple of 4
	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 2, 1, 0);
	errorCode = gl.getError();
	if (errorCode != GL_INVALID_VALUE)
	{
		m_testCtx.getLog() << tcu::TestLog::Message
						   << "MultiDrawElementIndirectCount error verifying failed (1). Expected code: "
						   << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage;
		result = false;
	}

	// INVALID_OPERATION - maxdrawcount greater then parameter buffer size
	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 4, 0);
	errorCode = gl.getError();
	if (errorCode != GL_INVALID_OPERATION)
	{
		m_testCtx.getLog() << tcu::TestLog::Message
						   << "MultiDrawElementIndirectCount error verifying failed (2). Expected code: "
						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
		result = false;
	}

	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	// INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound
	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 3, 0);
	errorCode = gl.getError();
	if (errorCode != GL_INVALID_OPERATION)
	{
		m_testCtx.getLog() << tcu::TestLog::Message
						   << "MultiDrawElementIndirectCount error verifying failed (3). Expected code: "
						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
		result = false;
	}

	return result;
}

/** Constructor.
 *
 *  @param context Rendering context.
 */
IndirectParametersTests::IndirectParametersTests(deqp::Context& context)
	: TestCaseGroup(context, "indirect_parameters_tests",
					"Verify conformance of CTS_ARB_indirect_parameters implementation")
{
}

/** Initializes the test group contents. */
void IndirectParametersTests::init()
{
	addChild(new ParameterBufferOperationsCase(m_context));
	addChild(new MultiDrawArraysIndirectCountCase(m_context));
	addChild(new MultiDrawElementsIndirectCountCase(m_context));
}

} /* gl4cts namespace */
