Home | History | Annotate | Download | only in gl
      1 /*-------------------------------------------------------------------------
      2  * OpenGL Conformance Test Suite
      3  * -----------------------------
      4  *
      5  * Copyright (c) 2017 The Khronos Group Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  */ /*!
     20  * \file
     21  * \brief
     22  */ /*-------------------------------------------------------------------*/
     23 
     24 /**
     25  */ /*!
     26  * \file  gl4cIndirectParametersTests.cpp
     27  * \brief Conformance tests for the GL_ARB_indirect_parameters functionality.
     28  */ /*-------------------------------------------------------------------*/
     29 
     30 #include "gl4cIndirectParametersTests.hpp"
     31 #include "gluContextInfo.hpp"
     32 #include "gluDefs.hpp"
     33 #include "gluDrawUtil.hpp"
     34 #include "gluShaderProgram.hpp"
     35 #include "glwEnums.hpp"
     36 #include "glwFunctions.hpp"
     37 #include "tcuRenderTarget.hpp"
     38 #include "tcuTestLog.hpp"
     39 
     40 using namespace glw;
     41 using namespace glu;
     42 
     43 namespace gl4cts
     44 {
     45 
     46 static const char* c_vertShader = "#version 430\n"
     47 								  "\n"
     48 								  "in vec3 vertex;\n"
     49 								  "\n"
     50 								  "void main()\n"
     51 								  "{\n"
     52 								  "    gl_Position = vec4(vertex, 1);\n"
     53 								  "}\n";
     54 
     55 static const char* c_fragShader = "#version 430\n"
     56 								  "\n"
     57 								  "out vec4 fragColor;\n"
     58 								  "\n"
     59 								  "void main()\n"
     60 								  "{\n"
     61 								  "    fragColor = vec4(1, 1, 1, 0.5);\n"
     62 								  "}\n";
     63 
     64 /** Constructor.
     65  *
     66  *  @param context     Rendering context
     67  */
     68 ParameterBufferOperationsCase::ParameterBufferOperationsCase(deqp::Context& context)
     69 	: TestCase(context, "ParameterBufferOperations",
     70 			   "Verifies if operations on new buffer object PARAMETER_BUFFER_ARB works as expected.")
     71 {
     72 	/* Left blank intentionally */
     73 }
     74 
     75 /** Stub init method */
     76 void ParameterBufferOperationsCase::init()
     77 {
     78 }
     79 
     80 /** Executes test iteration.
     81  *
     82  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
     83  */
     84 tcu::TestNode::IterateResult ParameterBufferOperationsCase::iterate()
     85 {
     86 	glu::ContextType contextType = m_context.getRenderContext().getType();
     87 	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
     88 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
     89 	{
     90 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
     91 		return STOP;
     92 	}
     93 
     94 	const Functions& gl = m_context.getRenderContext().getFunctions();
     95 
     96 	GLuint paramBuffer;
     97 
     98 	GLint data[]	= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
     99 	GLint subData[] = { 10, 11, 12, 13, 14 };
    100 	GLint expData[] = { 0, 1, 10, 11, 12, 13, 14, 7, 8, 9 };
    101 
    102 	bool result = true;
    103 
    104 	// Test buffer generating and binding
    105 	gl.genBuffers(1, &paramBuffer);
    106 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    107 
    108 	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, paramBuffer);
    109 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    110 
    111 	GLint paramBinding;
    112 	gl.getIntegerv(GL_PARAMETER_BUFFER_BINDING_ARB, &paramBinding);
    113 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
    114 
    115 	if ((GLuint)paramBinding != paramBuffer)
    116 	{
    117 		result = false;
    118 		m_testCtx.getLog() << tcu::TestLog::Message << "Buffer binding mismatch" << tcu::TestLog::EndMessage;
    119 	}
    120 	else
    121 	{
    122 		// Test filling buffer with data
    123 		gl.bufferData(GL_PARAMETER_BUFFER_ARB, 10 * sizeof(GLint), data, GL_DYNAMIC_DRAW);
    124 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    125 
    126 		gl.bufferSubData(GL_PARAMETER_BUFFER_ARB, 2 * sizeof(GLint), 5 * sizeof(GLint), subData);
    127 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    128 
    129 		// Test buffer mapping
    130 		GLvoid* buffer = gl.mapBuffer(GL_PARAMETER_BUFFER_ARB, GL_READ_ONLY);
    131 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer");
    132 
    133 		if (memcmp(buffer, expData, 10 * sizeof(GLint)) != 0)
    134 		{
    135 			result = false;
    136 			m_testCtx.getLog() << tcu::TestLog::Message << "Buffer data mismatch" << tcu::TestLog::EndMessage;
    137 		}
    138 		else
    139 		{
    140 			GLvoid* bufferPointer;
    141 			gl.getBufferPointerv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_MAP_POINTER, &bufferPointer);
    142 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferPointerv");
    143 
    144 			if (buffer != bufferPointer)
    145 			{
    146 				result = false;
    147 				m_testCtx.getLog() << tcu::TestLog::Message << "Buffer pointer mismatch" << tcu::TestLog::EndMessage;
    148 			}
    149 			else
    150 			{
    151 				GLint bufferSize;
    152 				GLint bufferUsage;
    153 				gl.getBufferParameteriv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_SIZE, &bufferSize);
    154 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv");
    155 				gl.getBufferParameteriv(GL_PARAMETER_BUFFER_ARB, GL_BUFFER_USAGE, &bufferUsage);
    156 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv");
    157 
    158 				if (bufferSize != 10 * sizeof(GLint))
    159 				{
    160 					result = false;
    161 					m_testCtx.getLog() << tcu::TestLog::Message << "Buffer size mismatch" << tcu::TestLog::EndMessage;
    162 				}
    163 				else if (bufferUsage != GL_DYNAMIC_DRAW)
    164 				{
    165 					result = false;
    166 					m_testCtx.getLog() << tcu::TestLog::Message << "Buffer usage mismatch" << tcu::TestLog::EndMessage;
    167 				}
    168 			}
    169 		}
    170 
    171 		gl.unmapBuffer(GL_PARAMETER_BUFFER_ARB);
    172 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");
    173 
    174 		// Test buffer ranged mapping
    175 		buffer =
    176 			gl.mapBufferRange(GL_PARAMETER_BUFFER_ARB, 0, sizeof(GLint), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
    177 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange");
    178 
    179 		// Test buffer flushing
    180 		GLint* bufferInt = (GLint*)buffer;
    181 
    182 		bufferInt[0] = 100;
    183 		gl.flushMappedBufferRange(GL_PARAMETER_BUFFER_ARB, 0, sizeof(GLint));
    184 		GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
    185 
    186 		gl.unmapBuffer(GL_PARAMETER_BUFFER_ARB);
    187 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");
    188 
    189 		// Test buffers data copying
    190 		GLuint arrayBuffer;
    191 		gl.genBuffers(1, &arrayBuffer);
    192 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    193 
    194 		gl.bindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
    195 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    196 
    197 		gl.bufferData(GL_ARRAY_BUFFER, 10 * sizeof(GLint), data, GL_DYNAMIC_DRAW);
    198 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    199 
    200 		gl.copyBufferSubData(GL_PARAMETER_BUFFER_ARB, GL_ARRAY_BUFFER, 0, 0, sizeof(GLint));
    201 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyBufferSubData");
    202 
    203 		gl.mapBufferRange(GL_ARRAY_BUFFER, 0, 1, GL_MAP_READ_BIT);
    204 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange");
    205 
    206 		bufferInt = (GLint*)buffer;
    207 		if (bufferInt[0] != 100)
    208 		{
    209 			result = false;
    210 			m_testCtx.getLog() << tcu::TestLog::Message << "Buffer copy operation failed" << tcu::TestLog::EndMessage;
    211 		}
    212 
    213 		gl.unmapBuffer(GL_ARRAY_BUFFER);
    214 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");
    215 
    216 		// Release array buffer
    217 		gl.deleteBuffers(1, &arrayBuffer);
    218 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
    219 	}
    220 
    221 	// Release parameter buffer
    222 	gl.deleteBuffers(1, &paramBuffer);
    223 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
    224 
    225 	if (result)
    226 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    227 	else
    228 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    229 
    230 	return STOP;
    231 }
    232 
    233 /** Constructor.
    234  *
    235  *  @param context     Rendering context
    236  */
    237 VertexArrayIndirectDrawingBaseCase::VertexArrayIndirectDrawingBaseCase(deqp::Context& context, const char* name,
    238 																	   const char* description)
    239 	: TestCase(context, name, description)
    240 {
    241 	/* Left blank intentionally */
    242 }
    243 
    244 /** Executes test iteration.
    245  *
    246  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
    247  */
    248 tcu::TestNode::IterateResult VertexArrayIndirectDrawingBaseCase::iterate()
    249 {
    250 	glu::ContextType contextType = m_context.getRenderContext().getType();
    251 	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
    252 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
    253 	{
    254 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
    255 		return STOP;
    256 	}
    257 
    258 	if (draw() && verify())
    259 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    260 	else
    261 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    262 
    263 	return STOP;
    264 }
    265 
    266 /** This method verifies if drawn quads are as expected.
    267  *
    268  *  @return Returns true if quads are drawn properly, false otherwise.
    269  */
    270 bool VertexArrayIndirectDrawingBaseCase::verify()
    271 {
    272 	const Functions&		 gl = m_context.getRenderContext().getFunctions();
    273 	const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
    274 
    275 	const int width  = rt.getWidth();
    276 	const int height = rt.getHeight();
    277 
    278 	std::vector<GLubyte> pixels;
    279 	pixels.resize(width * height);
    280 
    281 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
    282 	gl.readPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, pixels.data());
    283 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
    284 
    285 	//Verify first quad
    286 	for (int y = 2; y < height - 2; ++y)
    287 	{
    288 		for (int x = 2; x < width / 2 - 2; ++x)
    289 		{
    290 			GLubyte value = pixels[x + y * width];
    291 			if (value < 190 || value > 194)
    292 			{
    293 				m_testCtx.getLog() << tcu::TestLog::Message << "First quad verification failed. "
    294 								   << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value
    295 								   << ", expected: <190-194>" << tcu::TestLog::EndMessage;
    296 				return false;
    297 			}
    298 		}
    299 	}
    300 
    301 	//Verify second quad
    302 	for (int y = 2; y < height - 2; ++y)
    303 	{
    304 		for (int x = width / 2 + 2; x < width - 2; ++x)
    305 		{
    306 			GLubyte value = pixels[x + y * width];
    307 			if (value < 126 || value > 130)
    308 			{
    309 				m_testCtx.getLog() << tcu::TestLog::Message << "Second quad verification failed. "
    310 								   << "Wrong value read from framebuffer at " << x << "/" << y << " value: " << value
    311 								   << ", expected: <126-130>" << tcu::TestLog::EndMessage;
    312 				return false;
    313 			}
    314 		}
    315 	}
    316 
    317 	return verifyErrors();
    318 }
    319 
    320 /** Constructor.
    321  *
    322  *  @param context     Rendering context
    323  */
    324 MultiDrawArraysIndirectCountCase::MultiDrawArraysIndirectCountCase(deqp::Context& context)
    325 	: VertexArrayIndirectDrawingBaseCase(context, "MultiDrawArraysIndirectCount",
    326 										 "Test verifies if MultiDrawArraysIndirectCountARB function works as expected.")
    327 	, m_vao(0)
    328 	, m_arrayBuffer(0)
    329 	, m_drawIndirectBuffer(0)
    330 	, m_parameterBuffer(0)
    331 {
    332 	/* Left blank intentionally */
    333 }
    334 
    335 /** Stub init method */
    336 void MultiDrawArraysIndirectCountCase::init()
    337 {
    338 	glu::ContextType contextType = m_context.getRenderContext().getType();
    339 	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
    340 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
    341 		return;
    342 
    343 	const Functions& gl = m_context.getRenderContext().getFunctions();
    344 
    345 	const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f,  0.0f, 0.0f, -1.0f, 0.0f,
    346 								 0.0f,  1.0f,  0.0f, 1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  0.0f };
    347 
    348 	const DrawArraysIndirectCommand indirect[] = {
    349 		{ 4, 2, 0, 0 }, //4 vertices, 2 instanceCount, 0 first, 0 baseInstance
    350 		{ 4, 1, 2, 0 }  //4 vertices, 1 instanceCount, 2 first, 0 baseInstance
    351 	};
    352 
    353 	const GLushort parameters[] = { 2, 1 };
    354 
    355 	// Generate vertex array object
    356 	gl.genVertexArrays(1, &m_vao);
    357 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
    358 
    359 	gl.bindVertexArray(m_vao);
    360 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
    361 
    362 	// Setup vertex array buffer
    363 	gl.genBuffers(1, &m_arrayBuffer);
    364 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    365 
    366 	gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
    367 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    368 
    369 	gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
    370 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    371 
    372 	// Setup indirect command buffer
    373 	gl.genBuffers(1, &m_drawIndirectBuffer);
    374 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    375 
    376 	gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
    377 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    378 
    379 	gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 2 * sizeof(DrawArraysIndirectCommand), indirect, GL_STATIC_DRAW);
    380 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    381 
    382 	// Setup parameter buffer
    383 	gl.genBuffers(1, &m_parameterBuffer);
    384 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    385 
    386 	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer);
    387 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    388 
    389 	gl.bufferData(GL_PARAMETER_BUFFER_ARB, 100 * sizeof(GLushort), parameters, GL_STATIC_DRAW);
    390 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    391 }
    392 
    393 /** Stub deinit method */
    394 void MultiDrawArraysIndirectCountCase::deinit()
    395 {
    396 	const Functions& gl = m_context.getRenderContext().getFunctions();
    397 
    398 	if (m_vao)
    399 		gl.deleteVertexArrays(1, &m_vao);
    400 	if (m_arrayBuffer)
    401 		gl.deleteBuffers(1, &m_arrayBuffer);
    402 	if (m_drawIndirectBuffer)
    403 		gl.deleteBuffers(1, &m_drawIndirectBuffer);
    404 	if (m_parameterBuffer)
    405 		gl.deleteBuffers(1, &m_parameterBuffer);
    406 }
    407 
    408 /** Drawing quads method using drawArrays.
    409  */
    410 bool MultiDrawArraysIndirectCountCase::draw()
    411 {
    412 	const Functions& gl = m_context.getRenderContext().getFunctions();
    413 
    414 	ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader);
    415 	ShaderProgram  program(gl, sources);
    416 
    417 	if (!program.isOk())
    418 	{
    419 		m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
    420 						   << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
    421 						   << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
    422 						   << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
    423 		return false;
    424 	}
    425 
    426 	gl.useProgram(program.getProgram());
    427 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
    428 
    429 	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    430 	gl.clear(GL_COLOR_BUFFER_BIT);
    431 
    432 	gl.enable(GL_BLEND);
    433 	gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    434 
    435 	gl.enableVertexAttribArray(0);
    436 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
    437 	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    438 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
    439 
    440 	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0);
    441 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawArraysIndirectCountARB");
    442 
    443 	gl.disableVertexAttribArray(0);
    444 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
    445 
    446 	gl.disable(GL_BLEND);
    447 
    448 	return true;
    449 }
    450 
    451 /** Verify MultiDrawArrayIndirectCountARB errors
    452  */
    453 bool MultiDrawArraysIndirectCountCase::verifyErrors()
    454 {
    455 	const Functions& gl = m_context.getRenderContext().getFunctions();
    456 
    457 	GLint errorCode;
    458 
    459 	bool result = true;
    460 
    461 	// INVALID_VALUE - drawcount offset not multiple of 4
    462 	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 2, 1, 0);
    463 	errorCode = gl.getError();
    464 	if (errorCode != GL_INVALID_VALUE)
    465 	{
    466 		m_testCtx.getLog() << tcu::TestLog::Message
    467 						   << "MultiDrawArraysIndirectCount error verifying failed (1). Expected code: "
    468 						   << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage;
    469 		result = false;
    470 	}
    471 
    472 	// INVALID_OPERATION - maxdrawcount greater then parameter buffer size
    473 	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 4, 0);
    474 	errorCode = gl.getError();
    475 	if (errorCode != GL_INVALID_OPERATION)
    476 	{
    477 		m_testCtx.getLog() << tcu::TestLog::Message
    478 						   << "MultiDrawArraysIndirectCount error verifying failed (2). Expected code: "
    479 						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
    480 		result = false;
    481 	}
    482 
    483 	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0);
    484 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    485 
    486 	// INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound
    487 	gl.multiDrawArraysIndirectCount(GL_TRIANGLE_STRIP, 0, 0, 2, 0);
    488 	errorCode = gl.getError();
    489 	if (errorCode != GL_INVALID_OPERATION)
    490 	{
    491 		m_testCtx.getLog() << tcu::TestLog::Message
    492 						   << "MultiDrawArraysIndirectCount error verifying failed (3). Expected code: "
    493 						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
    494 		result = false;
    495 	}
    496 
    497 	return result;
    498 }
    499 
    500 /** Constructor.
    501  *
    502  *  @param context     Rendering context
    503  */
    504 MultiDrawElementsIndirectCountCase::MultiDrawElementsIndirectCountCase(deqp::Context& context)
    505 	: VertexArrayIndirectDrawingBaseCase(
    506 		  context, "MultiDrawElementsIndirectCount",
    507 		  "Test verifies if MultiDrawElementsIndirectCountARB function works as expected.")
    508 	, m_vao(0)
    509 	, m_arrayBuffer(0)
    510 	, m_drawIndirectBuffer(0)
    511 	, m_parameterBuffer(0)
    512 {
    513 	/* Left blank intentionally */
    514 }
    515 
    516 /** Stub init method */
    517 void MultiDrawElementsIndirectCountCase::init()
    518 {
    519 	glu::ContextType contextType = m_context.getRenderContext().getType();
    520 	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
    521 		!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
    522 		return;
    523 
    524 	const Functions& gl = m_context.getRenderContext().getFunctions();
    525 
    526 	const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f,  0.0f, 0.0f, -1.0f, 0.0f,
    527 								 0.0f,  1.0f,  0.0f, 1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  0.0f };
    528 
    529 	const GLushort elements[] = { 0, 1, 2, 3, 4, 5 };
    530 
    531 	const DrawElementsIndirectCommand indirect[] = {
    532 		{ 4, 2, 0, 0, 0 }, //4 indices, 2 instanceCount, 0 firstIndex, 0 baseVertex, 0 baseInstance
    533 		{ 4, 1, 2, 0, 0 }  //4 indices, 1 instanceCount, 2 firstIndex, 0 baseVertex, 0 baseInstance
    534 	};
    535 
    536 	const GLushort parameters[] = { 2, 1 };
    537 
    538 	// Generate vertex array object
    539 	gl.genVertexArrays(1, &m_vao);
    540 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
    541 
    542 	gl.bindVertexArray(m_vao);
    543 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
    544 
    545 	// Setup vertex array buffer
    546 	gl.genBuffers(1, &m_arrayBuffer);
    547 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    548 
    549 	gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
    550 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    551 
    552 	gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
    553 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    554 
    555 	// Setup element array buffer
    556 	gl.genBuffers(1, &m_elementBuffer);
    557 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    558 
    559 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer);
    560 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    561 
    562 	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), elements, GL_STATIC_DRAW);
    563 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    564 
    565 	// Setup indirect command buffer
    566 	gl.genBuffers(1, &m_drawIndirectBuffer);
    567 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    568 
    569 	gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
    570 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    571 
    572 	gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 3 * sizeof(DrawElementsIndirectCommand), indirect, GL_STATIC_DRAW);
    573 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    574 
    575 	// Setup parameters Re: buffer
    576 	gl.genBuffers(1, &m_parameterBuffer);
    577 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    578 
    579 	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer);
    580 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    581 
    582 	gl.bufferData(GL_PARAMETER_BUFFER_ARB, 2 * sizeof(GLushort), parameters, GL_STATIC_DRAW);
    583 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    584 }
    585 
    586 /** Stub deinit method */
    587 void MultiDrawElementsIndirectCountCase::deinit()
    588 {
    589 	const Functions& gl = m_context.getRenderContext().getFunctions();
    590 
    591 	if (m_vao)
    592 		gl.deleteVertexArrays(1, &m_vao);
    593 	if (m_arrayBuffer)
    594 		gl.deleteBuffers(1, &m_arrayBuffer);
    595 	if (m_elementBuffer)
    596 		gl.deleteBuffers(1, &m_elementBuffer);
    597 	if (m_drawIndirectBuffer)
    598 		gl.deleteBuffers(1, &m_drawIndirectBuffer);
    599 	if (m_parameterBuffer)
    600 		gl.deleteBuffers(1, &m_parameterBuffer);
    601 }
    602 
    603 /** Drawing quads method using drawArrays.
    604  */
    605 bool MultiDrawElementsIndirectCountCase::draw()
    606 {
    607 	const Functions& gl = m_context.getRenderContext().getFunctions();
    608 
    609 	ProgramSources sources = makeVtxFragSources(c_vertShader, c_fragShader);
    610 	ShaderProgram  program(gl, sources);
    611 
    612 	if (!program.isOk())
    613 	{
    614 		m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
    615 						   << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
    616 						   << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
    617 						   << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
    618 		return false;
    619 	}
    620 
    621 	gl.useProgram(program.getProgram());
    622 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
    623 
    624 	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    625 	gl.clear(GL_COLOR_BUFFER_BIT);
    626 
    627 	gl.enable(GL_BLEND);
    628 	gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    629 
    630 	gl.enableVertexAttribArray(0);
    631 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
    632 	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    633 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
    634 
    635 	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_SHORT, 0, 0, 2, 0);
    636 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMultiDrawElementsIndirectCountARB");
    637 
    638 	gl.disableVertexAttribArray(0);
    639 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
    640 
    641 	gl.disable(GL_BLEND);
    642 
    643 	return true;
    644 }
    645 
    646 /** Verify MultiDrawElementsIndirectCountARB errors
    647  */
    648 bool MultiDrawElementsIndirectCountCase::verifyErrors()
    649 {
    650 	const Functions& gl = m_context.getRenderContext().getFunctions();
    651 
    652 	GLint errorCode;
    653 
    654 	bool result = true;
    655 
    656 	// INVALID_VALUE - drawcount offset not multiple of 4
    657 	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 2, 1, 0);
    658 	errorCode = gl.getError();
    659 	if (errorCode != GL_INVALID_VALUE)
    660 	{
    661 		m_testCtx.getLog() << tcu::TestLog::Message
    662 						   << "MultiDrawElementIndirectCount error verifying failed (1). Expected code: "
    663 						   << GL_INVALID_VALUE << ", current code: " << errorCode << tcu::TestLog::EndMessage;
    664 		result = false;
    665 	}
    666 
    667 	// INVALID_OPERATION - maxdrawcount greater then parameter buffer size
    668 	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 4, 0);
    669 	errorCode = gl.getError();
    670 	if (errorCode != GL_INVALID_OPERATION)
    671 	{
    672 		m_testCtx.getLog() << tcu::TestLog::Message
    673 						   << "MultiDrawElementIndirectCount error verifying failed (2). Expected code: "
    674 						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
    675 		result = false;
    676 	}
    677 
    678 	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, 0);
    679 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    680 
    681 	// INVALID_OPERATION - GL_PARAMETER_BUFFER_ARB not bound
    682 	gl.multiDrawElementsIndirectCount(GL_TRIANGLE_STRIP, GL_UNSIGNED_BYTE, 0, 0, 3, 0);
    683 	errorCode = gl.getError();
    684 	if (errorCode != GL_INVALID_OPERATION)
    685 	{
    686 		m_testCtx.getLog() << tcu::TestLog::Message
    687 						   << "MultiDrawElementIndirectCount error verifying failed (3). Expected code: "
    688 						   << GL_INVALID_OPERATION << ", current code: " << errorCode << tcu::TestLog::EndMessage;
    689 		result = false;
    690 	}
    691 
    692 	return result;
    693 }
    694 
    695 /** Constructor.
    696  *
    697  *  @param context Rendering context.
    698  */
    699 IndirectParametersTests::IndirectParametersTests(deqp::Context& context)
    700 	: TestCaseGroup(context, "indirect_parameters_tests",
    701 					"Verify conformance of CTS_ARB_indirect_parameters implementation")
    702 {
    703 }
    704 
    705 /** Initializes the test group contents. */
    706 void IndirectParametersTests::init()
    707 {
    708 	addChild(new ParameterBufferOperationsCase(m_context));
    709 	addChild(new MultiDrawArraysIndirectCountCase(m_context));
    710 	addChild(new MultiDrawElementsIndirectCountCase(m_context));
    711 }
    712 
    713 } /* gl4cts namespace */
    714