• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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 Buffer test utilities.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fBufferTestUtil.hpp"
25 #include "tcuRandomValueIterator.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuImageCompare.hpp"
28 #include "tcuVector.hpp"
29 #include "tcuFormatUtil.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuRenderTarget.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluRenderContext.hpp"
34 #include "gluStrUtil.hpp"
35 #include "gluShaderProgram.hpp"
36 #include "deMemory.h"
37 #include "deStringUtil.hpp"
38 
39 #include <algorithm>
40 
41 #include "glwEnums.hpp"
42 #include "glwFunctions.hpp"
43 
44 namespace deqp
45 {
46 namespace gles2
47 {
48 namespace Functional
49 {
50 namespace BufferTestUtil
51 {
52 
53 enum
54 {
55 	VERIFY_QUAD_SIZE					= 8,		//!< Quad size in VertexArrayVerifier
56 	MAX_LINES_PER_INDEX_ARRAY_DRAW		= 128,		//!< Maximum number of lines per one draw in IndexArrayVerifier
57 	INDEX_ARRAY_DRAW_VIEWPORT_WIDTH		= 128,
58 	INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT	= 128
59 };
60 
61 static const bool LOG_VERIFIER_CALLS = false; //! \note Especially array verifier generates a lot of calls.
62 
63 using tcu::TestLog;
64 using std::vector;
65 using std::string;
66 using std::set;
67 
68 // Helper functions.
69 
fillWithRandomBytes(deUint8 * ptr,int numBytes,deUint32 seed)70 void fillWithRandomBytes (deUint8* ptr, int numBytes, deUint32 seed)
71 {
72 	std::copy(tcu::RandomValueIterator<deUint8>::begin(seed, numBytes), tcu::RandomValueIterator<deUint8>::end(), ptr);
73 }
74 
compareByteArrays(tcu::TestLog & log,const deUint8 * resPtr,const deUint8 * refPtr,int numBytes)75 bool compareByteArrays (tcu::TestLog& log, const deUint8* resPtr, const deUint8* refPtr, int numBytes)
76 {
77 	bool			isOk			= true;
78 	const int		maxSpanLen		= 8;
79 	const int		maxDiffSpans	= 4;
80 	int				numDiffSpans	= 0;
81 	int				diffSpanStart	= -1;
82 	int				ndx				= 0;
83 
84 	log << TestLog::Section("Verify", "Verification result");
85 
86 	for (;ndx < numBytes; ndx++)
87 	{
88 		if (resPtr[ndx] != refPtr[ndx])
89 		{
90 			if (diffSpanStart < 0)
91 				diffSpanStart = ndx;
92 
93 			isOk = false;
94 		}
95 		else if (diffSpanStart >= 0)
96 		{
97 			if (numDiffSpans < maxDiffSpans)
98 			{
99 				int len			= ndx-diffSpanStart;
100 				int	printLen	= de::min(len, maxSpanLen);
101 
102 				log << TestLog::Message << len << " byte difference at offset " << diffSpanStart << "\n"
103 										<< "  expected "	<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart+printLen)) << "\n"
104 										<< "  got "			<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart+printLen))
105 					<< TestLog::EndMessage;
106 			}
107 			else
108 				log << TestLog::Message << "(output too long, truncated)" << TestLog::EndMessage;
109 
110 			numDiffSpans	+= 1;
111 			diffSpanStart	 = -1;
112 		}
113 	}
114 
115 	if (diffSpanStart >= 0)
116 	{
117 		if (numDiffSpans < maxDiffSpans)
118 		{
119 				int len			= ndx-diffSpanStart;
120 				int	printLen	= de::min(len, maxSpanLen);
121 
122 				log << TestLog::Message << len << " byte difference at offset " << diffSpanStart << "\n"
123 										<< "  expected "	<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart+printLen)) << "\n"
124 										<< "  got "			<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart+printLen))
125 					<< TestLog::EndMessage;
126 		}
127 		else
128 			log << TestLog::Message << "(output too long, truncated)" << TestLog::EndMessage;
129 	}
130 
131 	log << TestLog::Message << (isOk ? "Verification passed." : "Verification FAILED!") << TestLog::EndMessage;
132 	log << TestLog::EndSection;
133 
134 	return isOk;
135 }
136 
getBufferTargetName(deUint32 target)137 const char* getBufferTargetName (deUint32 target)
138 {
139 	switch (target)
140 	{
141 		case GL_ARRAY_BUFFER:				return "array";
142 		case GL_ELEMENT_ARRAY_BUFFER:		return "element_array";
143 		default:
144 			DE_ASSERT(false);
145 			return DE_NULL;
146 	}
147 }
148 
getUsageHintName(deUint32 hint)149 const char* getUsageHintName (deUint32 hint)
150 {
151 	switch (hint)
152 	{
153 		case GL_STREAM_DRAW:	return "stream_draw";
154 		case GL_STATIC_DRAW:	return "static_draw";
155 		case GL_DYNAMIC_DRAW:	return "dynamic_draw";
156 		default:
157 			DE_ASSERT(false);
158 			return DE_NULL;
159 	}
160 }
161 
162 // BufferCase
163 
BufferCase(Context & context,const char * name,const char * description)164 BufferCase::BufferCase (Context& context, const char* name, const char* description)
165 	: TestCase			(context, name, description)
166 	, CallLogWrapper	(context.getRenderContext().getFunctions(), m_context.getTestContext().getLog())
167 {
168 }
169 
~BufferCase(void)170 BufferCase::~BufferCase (void)
171 {
172 	enableLogging(false);
173 	BufferCase::deinit();
174 }
175 
init(void)176 void BufferCase::init (void)
177 {
178 	enableLogging(true);
179 }
180 
deinit(void)181 void BufferCase::deinit (void)
182 {
183 	for (set<deUint32>::const_iterator bufIter = m_allocatedBuffers.begin(); bufIter != m_allocatedBuffers.end(); bufIter++)
184 		glDeleteBuffers(1, &(*bufIter));
185 }
186 
genBuffer(void)187 deUint32 BufferCase::genBuffer (void)
188 {
189 	deUint32 buf = 0;
190 	glGenBuffers(1, &buf);
191 	if (buf != 0)
192 	{
193 		try
194 		{
195 			m_allocatedBuffers.insert(buf);
196 		}
197 		catch (const std::exception&)
198 		{
199 			glDeleteBuffers(1, &buf);
200 			throw;
201 		}
202 	}
203 	return buf;
204 }
205 
deleteBuffer(deUint32 buffer)206 void BufferCase::deleteBuffer (deUint32 buffer)
207 {
208 	glDeleteBuffers(1, &buffer);
209 	m_allocatedBuffers.erase(buffer);
210 }
211 
checkError(void)212 void BufferCase::checkError (void)
213 {
214 	glw::GLenum err = glGetError();
215 	if (err != GL_NO_ERROR)
216 		throw tcu::TestError(string("Got ") + glu::getErrorStr(err).toString());
217 }
218 
219 // ReferenceBuffer
220 
setSize(int numBytes)221 void ReferenceBuffer::setSize (int numBytes)
222 {
223 	m_data.resize(numBytes);
224 }
225 
setData(int numBytes,const deUint8 * bytes)226 void ReferenceBuffer::setData (int numBytes, const deUint8* bytes)
227 {
228 	m_data.resize(numBytes);
229 	std::copy(bytes, bytes+numBytes, m_data.begin());
230 }
231 
setSubData(int offset,int numBytes,const deUint8 * bytes)232 void ReferenceBuffer::setSubData (int offset, int numBytes, const deUint8* bytes)
233 {
234 	DE_ASSERT(de::inBounds(offset, 0, (int)m_data.size()) && de::inRange(offset+numBytes, offset, (int)m_data.size()));
235 	std::copy(bytes, bytes+numBytes, m_data.begin()+offset);
236 }
237 
238 // BufferVerifierBase
239 
BufferVerifierBase(Context & context)240 BufferVerifierBase::BufferVerifierBase (Context& context)
241 	: CallLogWrapper	(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
242 	, m_context			(context)
243 {
244 	enableLogging(LOG_VERIFIER_CALLS);
245 }
246 
247 // BufferVerifier
248 
BufferVerifier(Context & context,VerifyType verifyType)249 BufferVerifier::BufferVerifier (Context& context, VerifyType verifyType)
250 	: m_verifier(DE_NULL)
251 {
252 	switch (verifyType)
253 	{
254 		case VERIFY_AS_VERTEX_ARRAY:	m_verifier = new VertexArrayVerifier(context);	break;
255 		case VERIFY_AS_INDEX_ARRAY:		m_verifier = new IndexArrayVerifier	(context);	break;
256 		default:
257 			TCU_FAIL("Unsupported verifier");
258 	}
259 }
260 
~BufferVerifier(void)261 BufferVerifier::~BufferVerifier (void)
262 {
263 	delete m_verifier;
264 }
265 
verify(deUint32 buffer,const deUint8 * reference,int offset,int numBytes)266 bool BufferVerifier::verify (deUint32 buffer, const deUint8* reference, int offset, int numBytes)
267 {
268 	DE_ASSERT(numBytes >= getMinSize());
269 	DE_ASSERT(offset%getAlignment() == 0);
270 	DE_ASSERT((offset+numBytes)%getAlignment() == 0);
271 	return m_verifier->verify(buffer, reference, offset, numBytes);
272 }
273 
274 // VertexArrayVerifier
275 
VertexArrayVerifier(Context & context)276 VertexArrayVerifier::VertexArrayVerifier (Context& context)
277 	: BufferVerifierBase	(context)
278 	, m_program				(DE_NULL)
279 	, m_posLoc				(0)
280 	, m_byteVecLoc			(0)
281 {
282 	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
283 		"attribute highp vec2 a_position;\n"
284 		"attribute mediump vec3 a_byteVec;\n"
285 		"varying mediump vec3 v_byteVec;\n"
286 		"void main (void)\n"
287 		"{\n"
288 		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
289 		"	v_byteVec = a_byteVec;\n"
290 		"}\n",
291 
292 		"varying mediump vec3 v_byteVec;\n"
293 		"void main (void)\n"
294 		"{\n"
295 		"	gl_FragColor = vec4(v_byteVec, 1.0);\n"
296 		"}\n"));
297 
298 	if (!m_program->isOk())
299 	{
300 		m_context.getTestContext().getLog() << *m_program;
301 		delete m_program;
302 		TCU_FAIL("Compile failed");
303 	}
304 
305 	const glw::Functions& funcs = context.getRenderContext().getFunctions();
306 	m_posLoc		= funcs.getAttribLocation(m_program->getProgram(), "a_position");
307 	m_byteVecLoc	= funcs.getAttribLocation(m_program->getProgram(), "a_byteVec");
308 }
309 
~VertexArrayVerifier(void)310 VertexArrayVerifier::~VertexArrayVerifier (void)
311 {
312 	delete m_program;
313 }
314 
computePositions(vector<tcu::Vec2> & positions,int gridSizeX,int gridSizeY)315 static void computePositions (vector<tcu::Vec2>& positions, int gridSizeX, int gridSizeY)
316 {
317 	positions.resize(gridSizeX*gridSizeY*4);
318 
319 	for (int y = 0; y < gridSizeY; y++)
320 	for (int x = 0; x < gridSizeX; x++)
321 	{
322 		float	sx0			= (float)(x+0) / (float)gridSizeX;
323 		float	sy0			= (float)(y+0) / (float)gridSizeY;
324 		float	sx1			= (float)(x+1) / (float)gridSizeX;
325 		float	sy1			= (float)(y+1) / (float)gridSizeY;
326 		float	fx0			= 2.0f * sx0 - 1.0f;
327 		float	fy0			= 2.0f * sy0 - 1.0f;
328 		float	fx1			= 2.0f * sx1 - 1.0f;
329 		float	fy1			= 2.0f * sy1 - 1.0f;
330 		int		baseNdx		= (y * gridSizeX + x)*4;
331 
332 		positions[baseNdx+0] = tcu::Vec2(fx0, fy0);
333 		positions[baseNdx+1] = tcu::Vec2(fx0, fy1);
334 		positions[baseNdx+2] = tcu::Vec2(fx1, fy0);
335 		positions[baseNdx+3] = tcu::Vec2(fx1, fy1);
336 	}
337 }
338 
computeIndices(vector<deUint16> & indices,int gridSizeX,int gridSizeY)339 static void computeIndices (vector<deUint16>& indices, int gridSizeX, int gridSizeY)
340 {
341 	indices.resize(3 * 2 * gridSizeX * gridSizeY);
342 
343 	for (int quadNdx = 0; quadNdx < gridSizeX*gridSizeY; quadNdx++)
344 	{
345 		int v00 = quadNdx*4 + 0;
346 		int v01 = quadNdx*4 + 1;
347 		int v10 = quadNdx*4 + 2;
348 		int v11 = quadNdx*4 + 3;
349 
350 		DE_ASSERT(v11 < (1<<16));
351 
352 		indices[quadNdx*6 + 0] = (deUint16)v10;
353 		indices[quadNdx*6 + 1] = (deUint16)v00;
354 		indices[quadNdx*6 + 2] = (deUint16)v01;
355 
356 		indices[quadNdx*6 + 3] = (deUint16)v10;
357 		indices[quadNdx*6 + 4] = (deUint16)v01;
358 		indices[quadNdx*6 + 5] = (deUint16)v11;
359 	}
360 }
361 
fetchVtxColor(const deUint8 * ptr,int vtxNdx)362 static inline tcu::Vec4 fetchVtxColor (const deUint8* ptr, int vtxNdx)
363 {
364 	return tcu::RGBA(*(ptr + vtxNdx*3 + 0),
365 					 *(ptr + vtxNdx*3 + 1),
366 					 *(ptr + vtxNdx*3 + 2),
367 					 255).toVec();
368 }
369 
renderQuadGridReference(tcu::Surface & dst,int numQuads,int rowLength,const deUint8 * inPtr)370 static void renderQuadGridReference (tcu::Surface& dst, int numQuads, int rowLength, const deUint8* inPtr)
371 {
372 	using tcu::Vec4;
373 
374 	dst.setSize(rowLength*VERIFY_QUAD_SIZE, (numQuads/rowLength + (numQuads%rowLength != 0 ? 1 : 0))*VERIFY_QUAD_SIZE);
375 
376 	tcu::PixelBufferAccess dstAccess = dst.getAccess();
377 	tcu::clear(dstAccess, tcu::IVec4(0, 0, 0, 0xff));
378 
379 	for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
380 	{
381 		int		x0		= (quadNdx%rowLength)*VERIFY_QUAD_SIZE;
382 		int		y0		= (quadNdx/rowLength)*VERIFY_QUAD_SIZE;
383 		Vec4	v00		= fetchVtxColor(inPtr, quadNdx*4 + 0);
384 		Vec4	v10		= fetchVtxColor(inPtr, quadNdx*4 + 1);
385 		Vec4	v01		= fetchVtxColor(inPtr, quadNdx*4 + 2);
386 		Vec4	v11		= fetchVtxColor(inPtr, quadNdx*4 + 3);
387 
388 		for (int y = 0; y < VERIFY_QUAD_SIZE; y++)
389 		for (int x = 0; x < VERIFY_QUAD_SIZE; x++)
390 		{
391 			float		fx		= ((float)x+0.5f) / (float)VERIFY_QUAD_SIZE;
392 			float		fy		= ((float)y+0.5f) / (float)VERIFY_QUAD_SIZE;
393 
394 			bool		tri		= fx + fy <= 1.0f;
395 			float		tx		= tri ? fx : (1.0f-fx);
396 			float		ty		= tri ? fy : (1.0f-fy);
397 			const Vec4&	t0		= tri ? v00 : v11;
398 			const Vec4&	t1		= tri ? v01 : v10;
399 			const Vec4&	t2		= tri ? v10 : v01;
400 			Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
401 
402 			dstAccess.setPixel(color, x0+x, y0+y);
403 		}
404 	}
405 }
406 
verify(deUint32 buffer,const deUint8 * refPtr,int offset,int numBytes)407 bool VertexArrayVerifier::verify (deUint32 buffer, const deUint8* refPtr, int offset, int numBytes)
408 {
409 	const tcu::RenderTarget&	renderTarget		= m_context.getRenderContext().getRenderTarget();
410 	const int					numBytesInVtx		= 3;
411 	const int					numBytesInQuad		= numBytesInVtx*4;
412 	int							maxQuadsX			= de::min(128, renderTarget.getWidth()	/ VERIFY_QUAD_SIZE);
413 	int							maxQuadsY			= de::min(128, renderTarget.getHeight()	/ VERIFY_QUAD_SIZE);
414 	int							maxQuadsPerBatch	= maxQuadsX*maxQuadsY;
415 	int							numVerified			= 0;
416 	deUint32					program				= m_program->getProgram();
417 	tcu::RGBA					threshold			= renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(4,4,4,4);
418 	bool						isOk				= true;
419 
420 	vector<tcu::Vec2>			positions;
421 	vector<deUint16>			indices;
422 
423 	tcu::Surface				rendered;
424 	tcu::Surface				reference;
425 
426 	DE_ASSERT(numBytes >= numBytesInQuad); // Can't render full quad with smaller buffers.
427 
428 	computePositions(positions, maxQuadsX, maxQuadsY);
429 	computeIndices(indices, maxQuadsX, maxQuadsY);
430 
431 	// Reset buffer bindings.
432 	glBindBuffer				(GL_ELEMENT_ARRAY_BUFFER,	0);
433 	glBindBuffer				(GL_ARRAY_BUFFER,			0);
434 
435 	// Setup rendering state.
436 	glViewport					(0, 0, maxQuadsX*VERIFY_QUAD_SIZE, maxQuadsY*VERIFY_QUAD_SIZE);
437 	glClearColor				(0.0f, 0.0f, 0.0f, 1.0f);
438 	glUseProgram				(program);
439 	glEnableVertexAttribArray	(m_posLoc);
440 	glVertexAttribPointer		(m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, &positions[0]);
441 	glEnableVertexAttribArray	(m_byteVecLoc);
442 	glBindBuffer				(GL_ARRAY_BUFFER, buffer);
443 
444 	while (numVerified < numBytes)
445 	{
446 		int		numRemaining		= numBytes-numVerified;
447 		bool	isLeftoverBatch		= numRemaining < numBytesInQuad;
448 		int		numBytesToVerify	= isLeftoverBatch ? numBytesInQuad				: de::min(maxQuadsPerBatch*numBytesInQuad, numRemaining - numRemaining%numBytesInQuad);
449 		int		curOffset			= isLeftoverBatch ? (numBytes-numBytesInQuad)	: numVerified;
450 		int		numQuads			= numBytesToVerify/numBytesInQuad;
451 		int		numCols				= de::min(maxQuadsX, numQuads);
452 		int		numRows				= numQuads/maxQuadsX + (numQuads%maxQuadsX != 0 ? 1 : 0);
453 		string	imageSetDesc		= string("Bytes ") + de::toString(offset+curOffset) + " to " + de::toString(offset+curOffset+numBytesToVerify-1);
454 
455 		DE_ASSERT(numBytesToVerify > 0 && numBytesToVerify%numBytesInQuad == 0);
456 		DE_ASSERT(de::inBounds(curOffset, 0, numBytes));
457 		DE_ASSERT(de::inRange(curOffset+numBytesToVerify, curOffset, numBytes));
458 
459 		// Render batch.
460 		glClear					(GL_COLOR_BUFFER_BIT);
461 		glVertexAttribPointer	(m_byteVecLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, (const glw::GLvoid*)(deUintptr)(offset + curOffset));
462 		glDrawElements			(GL_TRIANGLES, numQuads*6, GL_UNSIGNED_SHORT, &indices[0]);
463 
464 		renderQuadGridReference(reference,  numQuads, numCols, refPtr + offset + curOffset);
465 
466 		rendered.setSize(numCols*VERIFY_QUAD_SIZE, numRows*VERIFY_QUAD_SIZE);
467 		glu::readPixels(m_context.getRenderContext(), 0, 0, rendered.getAccess());
468 
469 		if (!tcu::pixelThresholdCompare(m_context.getTestContext().getLog(), "RenderResult", imageSetDesc.c_str(), reference, rendered, threshold, tcu::COMPARE_LOG_RESULT))
470 		{
471 			isOk = false;
472 			break;
473 		}
474 
475 		numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
476 	}
477 
478 	glDisableVertexAttribArray	(m_posLoc);
479 	glDisableVertexAttribArray	(m_byteVecLoc);
480 
481 	return isOk;
482 }
483 
484 // IndexArrayVerifier
485 
IndexArrayVerifier(Context & context)486 IndexArrayVerifier::IndexArrayVerifier (Context& context)
487 	: BufferVerifierBase	(context)
488 	, m_program				(DE_NULL)
489 	, m_posLoc				(0)
490 	, m_colorLoc			(0)
491 {
492 	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
493 		"attribute highp vec2 a_position;\n"
494 		"attribute mediump vec3 a_color;\n"
495 		"varying mediump vec3 v_color;\n"
496 		"void main (void)\n"
497 		"{\n"
498 		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
499 		"	v_color = a_color;\n"
500 		"}\n",
501 
502 		"varying mediump vec3 v_color;\n"
503 		"void main (void)\n"
504 		"{\n"
505 		"	gl_FragColor = vec4(v_color, 1.0);\n"
506 		"}\n"));
507 
508 	if (!m_program->isOk())
509 	{
510 		m_context.getTestContext().getLog() << *m_program;
511 		delete m_program;
512 		TCU_FAIL("Compile failed");
513 	}
514 
515 	const glw::Functions& funcs = context.getRenderContext().getFunctions();
516 	m_posLoc	= funcs.getAttribLocation(m_program->getProgram(), "a_position");
517 	m_colorLoc	= funcs.getAttribLocation(m_program->getProgram(), "a_color");
518 }
519 
~IndexArrayVerifier(void)520 IndexArrayVerifier::~IndexArrayVerifier (void)
521 {
522 	delete m_program;
523 }
524 
computeIndexVerifierPositions(std::vector<tcu::Vec2> & dst)525 static void computeIndexVerifierPositions (std::vector<tcu::Vec2>& dst)
526 {
527 	const int	numPosX		= 16;
528 	const int	numPosY		= 16;
529 
530 	dst.resize(numPosX*numPosY);
531 
532 	for (int y = 0; y < numPosY; y++)
533 	{
534 		for (int x = 0; x < numPosX; x++)
535 		{
536 			float	xf	= float(x) / float(numPosX-1);
537 			float	yf	= float(y) / float(numPosY-1);
538 
539 			dst[y*numPosX + x] = tcu::Vec2(2.0f*xf - 1.0f, 2.0f*yf - 1.0f);
540 		}
541 	}
542 }
543 
computeIndexVerifierColors(std::vector<tcu::Vec3> & dst)544 static void computeIndexVerifierColors (std::vector<tcu::Vec3>& dst)
545 {
546 	const int	numColors	= 256;
547 	const float	minVal		= 0.1f;
548 	const float maxVal		= 0.5f;
549 	de::Random	rnd			(0xabc231);
550 
551 	dst.resize(numColors);
552 
553 	for (std::vector<tcu::Vec3>::iterator i = dst.begin(); i != dst.end(); ++i)
554 	{
555 		i->x()	= rnd.getFloat(minVal, maxVal);
556 		i->y()	= rnd.getFloat(minVal, maxVal);
557 		i->z()	= rnd.getFloat(minVal, maxVal);
558 	}
559 }
560 
561 template<typename T>
execVertexFetch(T * dst,const T * src,const deUint8 * indices,int numIndices)562 static void execVertexFetch (T* dst, const T* src, const deUint8* indices, int numIndices)
563 {
564 	for (int i = 0; i < numIndices; ++i)
565 		dst[i] = src[indices[i]];
566 }
567 
verify(deUint32 buffer,const deUint8 * refPtr,int offset,int numBytes)568 bool IndexArrayVerifier::verify (deUint32 buffer, const deUint8* refPtr, int offset, int numBytes)
569 {
570 	const tcu::RenderTarget&	renderTarget		= m_context.getRenderContext().getRenderTarget();
571 	const int					viewportW			= de::min<int>(INDEX_ARRAY_DRAW_VIEWPORT_WIDTH, renderTarget.getWidth());
572 	const int					viewportH			= de::min<int>(INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT, renderTarget.getHeight());
573 	const int					minBytesPerBatch	= 2;
574 	const tcu::RGBA				threshold			(0,0,0,0);
575 
576 	std::vector<tcu::Vec2>		positions;
577 	std::vector<tcu::Vec3>		colors;
578 
579 	std::vector<tcu::Vec2>		fetchedPos			(MAX_LINES_PER_INDEX_ARRAY_DRAW+1);
580 	std::vector<tcu::Vec3>		fetchedColor		(MAX_LINES_PER_INDEX_ARRAY_DRAW+1);
581 
582 	tcu::Surface				indexBufferImg		(viewportW, viewportH);
583 	tcu::Surface				referenceImg		(viewportW, viewportH);
584 
585 	int							numVerified			= 0;
586 	bool						isOk				= true;
587 
588 	DE_STATIC_ASSERT(sizeof(tcu::Vec2) == sizeof(float)*2);
589 	DE_STATIC_ASSERT(sizeof(tcu::Vec3) == sizeof(float)*3);
590 
591 	computeIndexVerifierPositions(positions);
592 	computeIndexVerifierColors(colors);
593 
594 	// Reset buffer bindings.
595 	glBindBuffer				(GL_ARRAY_BUFFER,			0);
596 	glBindBuffer				(GL_ELEMENT_ARRAY_BUFFER,	buffer);
597 
598 	// Setup rendering state.
599 	glViewport					(0, 0, viewportW, viewportH);
600 	glClearColor				(0.0f, 0.0f, 0.0f, 1.0f);
601 	glUseProgram				(m_program->getProgram());
602 	glEnableVertexAttribArray	(m_posLoc);
603 	glEnableVertexAttribArray	(m_colorLoc);
604 	glEnable					(GL_BLEND);
605 	glBlendFunc					(GL_ONE, GL_ONE);
606 	glBlendEquation				(GL_FUNC_ADD);
607 
608 	while (numVerified < numBytes)
609 	{
610 		int		numRemaining		= numBytes-numVerified;
611 		bool	isLeftoverBatch		= numRemaining < minBytesPerBatch;
612 		int		numBytesToVerify	= isLeftoverBatch ? minBytesPerBatch			: de::min(MAX_LINES_PER_INDEX_ARRAY_DRAW+1, numRemaining);
613 		int		curOffset			= isLeftoverBatch ? (numBytes-minBytesPerBatch)	: numVerified;
614 		string	imageSetDesc		= string("Bytes ") + de::toString(offset+curOffset) + " to " + de::toString(offset+curOffset+numBytesToVerify-1);
615 
616 		// Step 1: Render using index buffer.
617 		glClear					(GL_COLOR_BUFFER_BIT);
618 		glVertexAttribPointer	(m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, &positions[0]);
619 		glVertexAttribPointer	(m_colorLoc, 3, GL_FLOAT, GL_FALSE, 0, &colors[0]);
620 		glDrawElements			(GL_LINE_STRIP, numBytesToVerify, GL_UNSIGNED_BYTE, (void*)(deUintptr)(offset+curOffset));
621 		glu::readPixels			(m_context.getRenderContext(), 0, 0, indexBufferImg.getAccess());
622 
623 		// Step 2: Do manual fetch and render without index buffer.
624 		execVertexFetch(&fetchedPos[0], &positions[0], refPtr+offset+curOffset, numBytesToVerify);
625 		execVertexFetch(&fetchedColor[0], &colors[0], refPtr+offset+curOffset, numBytesToVerify);
626 
627 		glClear					(GL_COLOR_BUFFER_BIT);
628 		glVertexAttribPointer	(m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, &fetchedPos[0]);
629 		glVertexAttribPointer	(m_colorLoc, 3, GL_FLOAT, GL_FALSE, 0, &fetchedColor[0]);
630 		glDrawArrays			(GL_LINE_STRIP, 0, numBytesToVerify);
631 		glu::readPixels			(m_context.getRenderContext(), 0, 0, referenceImg.getAccess());
632 
633 		if (!tcu::pixelThresholdCompare(m_context.getTestContext().getLog(), "RenderResult", imageSetDesc.c_str(), referenceImg, indexBufferImg, threshold, tcu::COMPARE_LOG_RESULT))
634 		{
635 			isOk = false;
636 			break;
637 		}
638 
639 		numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
640 	}
641 
642 	return isOk;
643 }
644 
645 } // BufferTestUtil
646 } // Functional
647 } // gles2
648 } // deqp
649