1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL (ES) Module
3e5c31af7Sopenharmony_ci * -----------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Buffer test utilities.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "glsBufferTestUtil.hpp"
25e5c31af7Sopenharmony_ci#include "tcuRandomValueIterator.hpp"
26e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
27e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
28e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
29e5c31af7Sopenharmony_ci#include "tcuFormatUtil.hpp"
30e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
31e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
32e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
33e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
34e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp"
35e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp"
36e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
37e5c31af7Sopenharmony_ci#include "deMemory.h"
38e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
39e5c31af7Sopenharmony_ci#include "deArrayUtil.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci#include <algorithm>
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
44e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_cinamespace deqp
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_cinamespace gls
49e5c31af7Sopenharmony_ci{
50e5c31af7Sopenharmony_cinamespace BufferTestUtil
51e5c31af7Sopenharmony_ci{
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_cienum
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_ci	VERIFY_QUAD_SIZE					= 8,		//!< Quad size in VertexArrayVerifier
56e5c31af7Sopenharmony_ci	MAX_LINES_PER_INDEX_ARRAY_DRAW		= 128,		//!< Maximum number of lines per one draw in IndexArrayVerifier
57e5c31af7Sopenharmony_ci	INDEX_ARRAY_DRAW_VIEWPORT_WIDTH		= 128,
58e5c31af7Sopenharmony_ci	INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT	= 128
59e5c31af7Sopenharmony_ci};
60e5c31af7Sopenharmony_ci
61e5c31af7Sopenharmony_ciusing tcu::TestLog;
62e5c31af7Sopenharmony_ciusing std::vector;
63e5c31af7Sopenharmony_ciusing std::string;
64e5c31af7Sopenharmony_ciusing std::set;
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_ci// Helper functions.
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_civoid fillWithRandomBytes (deUint8* ptr, int numBytes, deUint32 seed)
69e5c31af7Sopenharmony_ci{
70e5c31af7Sopenharmony_ci	std::copy(tcu::RandomValueIterator<deUint8>::begin(seed, numBytes), tcu::RandomValueIterator<deUint8>::end(), ptr);
71e5c31af7Sopenharmony_ci}
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_cibool compareByteArrays (tcu::TestLog& log, const deUint8* resPtr, const deUint8* refPtr, int numBytes)
74e5c31af7Sopenharmony_ci{
75e5c31af7Sopenharmony_ci	bool			isOk			= true;
76e5c31af7Sopenharmony_ci	const int		maxSpanLen		= 8;
77e5c31af7Sopenharmony_ci	const int		maxDiffSpans	= 4;
78e5c31af7Sopenharmony_ci	int				numDiffSpans	= 0;
79e5c31af7Sopenharmony_ci	int				diffSpanStart	= -1;
80e5c31af7Sopenharmony_ci	int				ndx				= 0;
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci	log << TestLog::Section("Verify", "Verification result");
83e5c31af7Sopenharmony_ci
84e5c31af7Sopenharmony_ci	for (;ndx < numBytes; ndx++)
85e5c31af7Sopenharmony_ci	{
86e5c31af7Sopenharmony_ci		if (resPtr[ndx] != refPtr[ndx])
87e5c31af7Sopenharmony_ci		{
88e5c31af7Sopenharmony_ci			if (diffSpanStart < 0)
89e5c31af7Sopenharmony_ci				diffSpanStart = ndx;
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci			isOk = false;
92e5c31af7Sopenharmony_ci		}
93e5c31af7Sopenharmony_ci		else if (diffSpanStart >= 0)
94e5c31af7Sopenharmony_ci		{
95e5c31af7Sopenharmony_ci			if (numDiffSpans < maxDiffSpans)
96e5c31af7Sopenharmony_ci			{
97e5c31af7Sopenharmony_ci				int len			= ndx-diffSpanStart;
98e5c31af7Sopenharmony_ci				int	printLen	= de::min(len, maxSpanLen);
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci				log << TestLog::Message << len << " byte difference at offset " << diffSpanStart << "\n"
101e5c31af7Sopenharmony_ci										<< "  expected "	<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart+printLen)) << "\n"
102e5c31af7Sopenharmony_ci										<< "  got "			<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart+printLen))
103e5c31af7Sopenharmony_ci					<< TestLog::EndMessage;
104e5c31af7Sopenharmony_ci			}
105e5c31af7Sopenharmony_ci			else
106e5c31af7Sopenharmony_ci				log << TestLog::Message << "(output too long, truncated)" << TestLog::EndMessage;
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ci			numDiffSpans	+= 1;
109e5c31af7Sopenharmony_ci			diffSpanStart	 = -1;
110e5c31af7Sopenharmony_ci		}
111e5c31af7Sopenharmony_ci	}
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci	if (diffSpanStart >= 0)
114e5c31af7Sopenharmony_ci	{
115e5c31af7Sopenharmony_ci		if (numDiffSpans < maxDiffSpans)
116e5c31af7Sopenharmony_ci		{
117e5c31af7Sopenharmony_ci				int len			= ndx-diffSpanStart;
118e5c31af7Sopenharmony_ci				int	printLen	= de::min(len, maxSpanLen);
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci				log << TestLog::Message << len << " byte difference at offset " << diffSpanStart << "\n"
121e5c31af7Sopenharmony_ci										<< "  expected "	<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart+printLen)) << "\n"
122e5c31af7Sopenharmony_ci										<< "  got "			<< tcu::formatArray(tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart+printLen))
123e5c31af7Sopenharmony_ci					<< TestLog::EndMessage;
124e5c31af7Sopenharmony_ci		}
125e5c31af7Sopenharmony_ci		else
126e5c31af7Sopenharmony_ci			log << TestLog::Message << "(output too long, truncated)" << TestLog::EndMessage;
127e5c31af7Sopenharmony_ci	}
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ci	log << TestLog::Message << (isOk ? "Verification passed." : "Verification FAILED!") << TestLog::EndMessage;
130e5c31af7Sopenharmony_ci	log << TestLog::EndSection;
131e5c31af7Sopenharmony_ci
132e5c31af7Sopenharmony_ci	return isOk;
133e5c31af7Sopenharmony_ci}
134e5c31af7Sopenharmony_ci
135e5c31af7Sopenharmony_ciconst char* getBufferTargetName (deUint32 target)
136e5c31af7Sopenharmony_ci{
137e5c31af7Sopenharmony_ci	switch (target)
138e5c31af7Sopenharmony_ci	{
139e5c31af7Sopenharmony_ci		case GL_ARRAY_BUFFER:				return "array";
140e5c31af7Sopenharmony_ci		case GL_COPY_READ_BUFFER:			return "copy_read";
141e5c31af7Sopenharmony_ci		case GL_COPY_WRITE_BUFFER:			return "copy_write";
142e5c31af7Sopenharmony_ci		case GL_ELEMENT_ARRAY_BUFFER:		return "element_array";
143e5c31af7Sopenharmony_ci		case GL_PIXEL_PACK_BUFFER:			return "pixel_pack";
144e5c31af7Sopenharmony_ci		case GL_PIXEL_UNPACK_BUFFER:		return "pixel_unpack";
145e5c31af7Sopenharmony_ci		case GL_TEXTURE_BUFFER:				return "texture";
146e5c31af7Sopenharmony_ci		case GL_TRANSFORM_FEEDBACK_BUFFER:	return "transform_feedback";
147e5c31af7Sopenharmony_ci		case GL_UNIFORM_BUFFER:				return "uniform";
148e5c31af7Sopenharmony_ci		default:
149e5c31af7Sopenharmony_ci			DE_ASSERT(false);
150e5c31af7Sopenharmony_ci			return DE_NULL;
151e5c31af7Sopenharmony_ci	}
152e5c31af7Sopenharmony_ci}
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_ciconst char* getUsageHintName (deUint32 hint)
155e5c31af7Sopenharmony_ci{
156e5c31af7Sopenharmony_ci	switch (hint)
157e5c31af7Sopenharmony_ci	{
158e5c31af7Sopenharmony_ci		case GL_STREAM_DRAW:	return "stream_draw";
159e5c31af7Sopenharmony_ci		case GL_STREAM_READ:	return "stream_read";
160e5c31af7Sopenharmony_ci		case GL_STREAM_COPY:	return "stream_copy";
161e5c31af7Sopenharmony_ci		case GL_STATIC_DRAW:	return "static_draw";
162e5c31af7Sopenharmony_ci		case GL_STATIC_READ:	return "static_read";
163e5c31af7Sopenharmony_ci		case GL_STATIC_COPY:	return "static_copy";
164e5c31af7Sopenharmony_ci		case GL_DYNAMIC_DRAW:	return "dynamic_draw";
165e5c31af7Sopenharmony_ci		case GL_DYNAMIC_READ:	return "dynamic_read";
166e5c31af7Sopenharmony_ci		case GL_DYNAMIC_COPY:	return "dynamic_copy";
167e5c31af7Sopenharmony_ci		default:
168e5c31af7Sopenharmony_ci			DE_ASSERT(false);
169e5c31af7Sopenharmony_ci			return DE_NULL;
170e5c31af7Sopenharmony_ci	}
171e5c31af7Sopenharmony_ci}
172e5c31af7Sopenharmony_ci
173e5c31af7Sopenharmony_ci// BufferCase
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ciBufferCase::BufferCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description)
176e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, description)
177e5c31af7Sopenharmony_ci	, CallLogWrapper	(renderCtx.getFunctions(), testCtx.getLog())
178e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
179e5c31af7Sopenharmony_ci{
180e5c31af7Sopenharmony_ci}
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ciBufferCase::~BufferCase (void)
183e5c31af7Sopenharmony_ci{
184e5c31af7Sopenharmony_ci	enableLogging(false);
185e5c31af7Sopenharmony_ci	BufferCase::deinit();
186e5c31af7Sopenharmony_ci}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_civoid BufferCase::init (void)
189e5c31af7Sopenharmony_ci{
190e5c31af7Sopenharmony_ci	enableLogging(true);
191e5c31af7Sopenharmony_ci}
192e5c31af7Sopenharmony_ci
193e5c31af7Sopenharmony_civoid BufferCase::deinit (void)
194e5c31af7Sopenharmony_ci{
195e5c31af7Sopenharmony_ci	for (set<deUint32>::const_iterator bufIter = m_allocatedBuffers.begin(); bufIter != m_allocatedBuffers.end(); bufIter++)
196e5c31af7Sopenharmony_ci		glDeleteBuffers(1, &(*bufIter));
197e5c31af7Sopenharmony_ci}
198e5c31af7Sopenharmony_ci
199e5c31af7Sopenharmony_cideUint32 BufferCase::genBuffer (void)
200e5c31af7Sopenharmony_ci{
201e5c31af7Sopenharmony_ci	deUint32 buf = 0;
202e5c31af7Sopenharmony_ci	glGenBuffers(1, &buf);
203e5c31af7Sopenharmony_ci	if (buf != 0)
204e5c31af7Sopenharmony_ci	{
205e5c31af7Sopenharmony_ci		try
206e5c31af7Sopenharmony_ci		{
207e5c31af7Sopenharmony_ci			m_allocatedBuffers.insert(buf);
208e5c31af7Sopenharmony_ci		}
209e5c31af7Sopenharmony_ci		catch (const std::exception&)
210e5c31af7Sopenharmony_ci		{
211e5c31af7Sopenharmony_ci			glDeleteBuffers(1, &buf);
212e5c31af7Sopenharmony_ci			throw;
213e5c31af7Sopenharmony_ci		}
214e5c31af7Sopenharmony_ci	}
215e5c31af7Sopenharmony_ci	return buf;
216e5c31af7Sopenharmony_ci}
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_civoid BufferCase::deleteBuffer (deUint32 buffer)
219e5c31af7Sopenharmony_ci{
220e5c31af7Sopenharmony_ci	glDeleteBuffers(1, &buffer);
221e5c31af7Sopenharmony_ci	m_allocatedBuffers.erase(buffer);
222e5c31af7Sopenharmony_ci}
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_civoid BufferCase::checkError (void)
225e5c31af7Sopenharmony_ci{
226e5c31af7Sopenharmony_ci	glw::GLenum err = glGetError();
227e5c31af7Sopenharmony_ci	if (err != GL_NO_ERROR)
228e5c31af7Sopenharmony_ci		throw tcu::TestError(string("Got ") + glu::getErrorStr(err).toString());
229e5c31af7Sopenharmony_ci}
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ci// ReferenceBuffer
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_civoid ReferenceBuffer::setSize (int numBytes)
234e5c31af7Sopenharmony_ci{
235e5c31af7Sopenharmony_ci	m_data.resize(numBytes);
236e5c31af7Sopenharmony_ci}
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_civoid ReferenceBuffer::setData (int numBytes, const deUint8* bytes)
239e5c31af7Sopenharmony_ci{
240e5c31af7Sopenharmony_ci	m_data.resize(numBytes);
241e5c31af7Sopenharmony_ci	std::copy(bytes, bytes+numBytes, m_data.begin());
242e5c31af7Sopenharmony_ci}
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_civoid ReferenceBuffer::setSubData (int offset, int numBytes, const deUint8* bytes)
245e5c31af7Sopenharmony_ci{
246e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(offset, 0, (int)m_data.size()) && de::inRange(offset+numBytes, offset, (int)m_data.size()));
247e5c31af7Sopenharmony_ci	std::copy(bytes, bytes+numBytes, m_data.begin()+offset);
248e5c31af7Sopenharmony_ci}
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci// BufferWriterBase
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ciBufferWriterBase::BufferWriterBase (glu::RenderContext& renderCtx, tcu::TestLog& log)
253e5c31af7Sopenharmony_ci	: CallLogWrapper	(renderCtx.getFunctions(), log)
254e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
255e5c31af7Sopenharmony_ci{
256e5c31af7Sopenharmony_ci	enableLogging(true);
257e5c31af7Sopenharmony_ci}
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_civoid BufferWriterBase::write (deUint32 buffer, int offset, int numBytes, const deUint8* bytes, deUint32 targetHint)
260e5c31af7Sopenharmony_ci{
261e5c31af7Sopenharmony_ci	DE_UNREF(targetHint);
262e5c31af7Sopenharmony_ci	write(buffer, offset, numBytes, bytes);
263e5c31af7Sopenharmony_ci}
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_ci// BufferWriter
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_ciBufferWriter::BufferWriter (glu::RenderContext& renderCtx, tcu::TestLog& log, WriteType writeType)
268e5c31af7Sopenharmony_ci	: m_writer(DE_NULL)
269e5c31af7Sopenharmony_ci{
270e5c31af7Sopenharmony_ci	switch (writeType)
271e5c31af7Sopenharmony_ci	{
272e5c31af7Sopenharmony_ci		case WRITE_BUFFER_SUB_DATA:		m_writer = new BufferSubDataWriter	(renderCtx, log);	break;
273e5c31af7Sopenharmony_ci		case WRITE_BUFFER_WRITE_MAP:	m_writer = new BufferWriteMapWriter	(renderCtx, log);	break;
274e5c31af7Sopenharmony_ci		default:
275e5c31af7Sopenharmony_ci			TCU_FAIL("Unsupported writer");
276e5c31af7Sopenharmony_ci	}
277e5c31af7Sopenharmony_ci}
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ciBufferWriter::~BufferWriter (void)
280e5c31af7Sopenharmony_ci{
281e5c31af7Sopenharmony_ci	delete m_writer;
282e5c31af7Sopenharmony_ci}
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_civoid BufferWriter::write (deUint32 buffer, int offset, int numBytes, const deUint8* bytes)
285e5c31af7Sopenharmony_ci{
286e5c31af7Sopenharmony_ci	DE_ASSERT(numBytes >= getMinSize());
287e5c31af7Sopenharmony_ci	DE_ASSERT(offset%getAlignment() == 0);
288e5c31af7Sopenharmony_ci	DE_ASSERT((offset+numBytes)%getAlignment() == 0);
289e5c31af7Sopenharmony_ci	return m_writer->write(buffer, offset, numBytes, bytes);
290e5c31af7Sopenharmony_ci}
291e5c31af7Sopenharmony_ci
292e5c31af7Sopenharmony_civoid BufferWriter::write (deUint32 buffer, int offset, int numBytes, const deUint8* bytes, deUint32 targetHint)
293e5c31af7Sopenharmony_ci{
294e5c31af7Sopenharmony_ci	DE_ASSERT(numBytes >= getMinSize());
295e5c31af7Sopenharmony_ci	DE_ASSERT(offset%getAlignment() == 0);
296e5c31af7Sopenharmony_ci	DE_ASSERT((offset+numBytes)%getAlignment() == 0);
297e5c31af7Sopenharmony_ci	return m_writer->write(buffer, offset, numBytes, bytes, targetHint);
298e5c31af7Sopenharmony_ci}
299e5c31af7Sopenharmony_ci
300e5c31af7Sopenharmony_ci// BufferSubDataWriter
301e5c31af7Sopenharmony_ci
302e5c31af7Sopenharmony_civoid BufferSubDataWriter::write (deUint32 buffer, int offset, int numBytes, const deUint8* bytes)
303e5c31af7Sopenharmony_ci{
304e5c31af7Sopenharmony_ci	write(buffer, offset, numBytes, bytes, GL_ARRAY_BUFFER);
305e5c31af7Sopenharmony_ci}
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_civoid BufferSubDataWriter::write (deUint32 buffer, int offset, int numBytes, const deUint8* bytes, deUint32 target)
308e5c31af7Sopenharmony_ci{
309e5c31af7Sopenharmony_ci	glBindBuffer(target, buffer);
310e5c31af7Sopenharmony_ci	glBufferSubData(target, offset, numBytes, bytes);
311e5c31af7Sopenharmony_ci	glBindBuffer(target, 0);
312e5c31af7Sopenharmony_ci	GLU_CHECK();
313e5c31af7Sopenharmony_ci}
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci// BufferWriteMapWriter
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_civoid BufferWriteMapWriter::write (deUint32 buffer, int offset, int numBytes, const deUint8* bytes)
318e5c31af7Sopenharmony_ci{
319e5c31af7Sopenharmony_ci	write(buffer, offset, numBytes, bytes, GL_ARRAY_BUFFER);
320e5c31af7Sopenharmony_ci}
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_civoid BufferWriteMapWriter::write (deUint32 buffer, int offset, int numBytes, const deUint8* bytes, deUint32 target)
323e5c31af7Sopenharmony_ci{
324e5c31af7Sopenharmony_ci	glBindBuffer(target, buffer);
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ci	void* ptr = glMapBufferRange(target, offset, numBytes, GL_MAP_WRITE_BIT);
327e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("glMapBufferRange");
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci	deMemcpy(ptr, bytes, numBytes);
330e5c31af7Sopenharmony_ci
331e5c31af7Sopenharmony_ci	glUnmapBuffer(target);
332e5c31af7Sopenharmony_ci	glBindBuffer(target, 0);
333e5c31af7Sopenharmony_ci	GLU_CHECK();
334e5c31af7Sopenharmony_ci}
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci// BufferVerifierBase
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_ciBufferVerifierBase::BufferVerifierBase (glu::RenderContext& renderCtx, tcu::TestLog& log)
339e5c31af7Sopenharmony_ci	: CallLogWrapper	(renderCtx.getFunctions(), log)
340e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
341e5c31af7Sopenharmony_ci	, m_log				(log)
342e5c31af7Sopenharmony_ci{
343e5c31af7Sopenharmony_ci	enableLogging(true);
344e5c31af7Sopenharmony_ci}
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_cibool BufferVerifierBase::verify (deUint32 buffer, const deUint8* reference, int offset, int numBytes, deUint32 targetHint)
347e5c31af7Sopenharmony_ci{
348e5c31af7Sopenharmony_ci	DE_UNREF(targetHint);
349e5c31af7Sopenharmony_ci	return verify(buffer, reference, offset, numBytes);
350e5c31af7Sopenharmony_ci}
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci// BufferVerifier
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_ciBufferVerifier::BufferVerifier (glu::RenderContext& renderCtx, tcu::TestLog& log, VerifyType verifyType)
355e5c31af7Sopenharmony_ci	: m_verifier(DE_NULL)
356e5c31af7Sopenharmony_ci{
357e5c31af7Sopenharmony_ci	switch (verifyType)
358e5c31af7Sopenharmony_ci	{
359e5c31af7Sopenharmony_ci		case VERIFY_AS_VERTEX_ARRAY:	m_verifier = new VertexArrayVerifier(renderCtx, log);	break;
360e5c31af7Sopenharmony_ci		case VERIFY_AS_INDEX_ARRAY:		m_verifier = new IndexArrayVerifier	(renderCtx, log);	break;
361e5c31af7Sopenharmony_ci		case VERIFY_BUFFER_READ_MAP:	m_verifier = new BufferMapVerifier	(renderCtx, log);	break;
362e5c31af7Sopenharmony_ci		default:
363e5c31af7Sopenharmony_ci			TCU_FAIL("Unsupported verifier");
364e5c31af7Sopenharmony_ci	}
365e5c31af7Sopenharmony_ci}
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ciBufferVerifier::~BufferVerifier (void)
368e5c31af7Sopenharmony_ci{
369e5c31af7Sopenharmony_ci	delete m_verifier;
370e5c31af7Sopenharmony_ci}
371e5c31af7Sopenharmony_ci
372e5c31af7Sopenharmony_cibool BufferVerifier::verify (deUint32 buffer, const deUint8* reference, int offset, int numBytes)
373e5c31af7Sopenharmony_ci{
374e5c31af7Sopenharmony_ci	DE_ASSERT(numBytes >= getMinSize());
375e5c31af7Sopenharmony_ci	DE_ASSERT(offset%getAlignment() == 0);
376e5c31af7Sopenharmony_ci	DE_ASSERT((offset+numBytes)%getAlignment() == 0);
377e5c31af7Sopenharmony_ci	return m_verifier->verify(buffer, reference, offset, numBytes);
378e5c31af7Sopenharmony_ci}
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_cibool BufferVerifier::verify (deUint32 buffer, const deUint8* reference, int offset, int numBytes, deUint32 targetHint)
381e5c31af7Sopenharmony_ci{
382e5c31af7Sopenharmony_ci	DE_ASSERT(numBytes >= getMinSize());
383e5c31af7Sopenharmony_ci	DE_ASSERT(offset%getAlignment() == 0);
384e5c31af7Sopenharmony_ci	DE_ASSERT((offset+numBytes)%getAlignment() == 0);
385e5c31af7Sopenharmony_ci	return m_verifier->verify(buffer, reference, offset, numBytes, targetHint);
386e5c31af7Sopenharmony_ci}
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci// BufferMapVerifier
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_cibool BufferMapVerifier::verify (deUint32 buffer, const deUint8* reference, int offset, int numBytes)
391e5c31af7Sopenharmony_ci{
392e5c31af7Sopenharmony_ci	return verify(buffer, reference, offset, numBytes, GL_ARRAY_BUFFER);
393e5c31af7Sopenharmony_ci}
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_cibool BufferMapVerifier::verify (deUint32 buffer, const deUint8* reference, int offset, int numBytes, deUint32 target)
396e5c31af7Sopenharmony_ci{
397e5c31af7Sopenharmony_ci	const deUint8*	mapPtr		= DE_NULL;
398e5c31af7Sopenharmony_ci	bool			isOk		= false;
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci	glBindBuffer(target, buffer);
401e5c31af7Sopenharmony_ci	mapPtr = (const deUint8*)glMapBufferRange(target, offset, numBytes, GL_MAP_READ_BIT);
402e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("glMapBufferRange");
403e5c31af7Sopenharmony_ci	TCU_CHECK(mapPtr);
404e5c31af7Sopenharmony_ci
405e5c31af7Sopenharmony_ci	isOk = compareByteArrays(m_log, mapPtr, reference+offset, numBytes);
406e5c31af7Sopenharmony_ci
407e5c31af7Sopenharmony_ci	glUnmapBuffer(target);
408e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("glUnmapBuffer");
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci	glBindBuffer(target, 0);
411e5c31af7Sopenharmony_ci
412e5c31af7Sopenharmony_ci	return isOk;
413e5c31af7Sopenharmony_ci}
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci// VertexArrayVerifier
416e5c31af7Sopenharmony_ci
417e5c31af7Sopenharmony_ciVertexArrayVerifier::VertexArrayVerifier (glu::RenderContext& renderCtx, tcu::TestLog& log)
418e5c31af7Sopenharmony_ci	: BufferVerifierBase	(renderCtx, log)
419e5c31af7Sopenharmony_ci	, m_program				(DE_NULL)
420e5c31af7Sopenharmony_ci	, m_posLoc				(0)
421e5c31af7Sopenharmony_ci	, m_byteVecLoc			(0)
422e5c31af7Sopenharmony_ci	, m_vao					(0)
423e5c31af7Sopenharmony_ci{
424e5c31af7Sopenharmony_ci	const glu::ContextType	ctxType		= renderCtx.getType();
425e5c31af7Sopenharmony_ci	const glu::GLSLVersion	glslVersion	= glu::isContextTypeES(ctxType) ? glu::GLSL_VERSION_300_ES : glu::GLSL_VERSION_330;
426e5c31af7Sopenharmony_ci
427e5c31af7Sopenharmony_ci	DE_ASSERT(glu::isGLSLVersionSupported(ctxType, glslVersion));
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(
430e5c31af7Sopenharmony_ci		string(glu::getGLSLVersionDeclaration(glslVersion)) + "\n"
431e5c31af7Sopenharmony_ci		"in highp vec2 a_position;\n"
432e5c31af7Sopenharmony_ci		"in mediump vec3 a_byteVec;\n"
433e5c31af7Sopenharmony_ci		"out mediump vec3 v_byteVec;\n"
434e5c31af7Sopenharmony_ci		"void main (void)\n"
435e5c31af7Sopenharmony_ci		"{\n"
436e5c31af7Sopenharmony_ci		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
437e5c31af7Sopenharmony_ci		"	v_byteVec = a_byteVec;\n"
438e5c31af7Sopenharmony_ci		"}\n",
439e5c31af7Sopenharmony_ci
440e5c31af7Sopenharmony_ci		string(glu::getGLSLVersionDeclaration(glslVersion)) + "\n"
441e5c31af7Sopenharmony_ci		"in mediump vec3 v_byteVec;\n"
442e5c31af7Sopenharmony_ci		"layout(location = 0) out mediump vec4 o_color;\n"
443e5c31af7Sopenharmony_ci		"void main (void)\n"
444e5c31af7Sopenharmony_ci		"{\n"
445e5c31af7Sopenharmony_ci		"	o_color = vec4(v_byteVec, 1.0);\n"
446e5c31af7Sopenharmony_ci		"}\n"));
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ci	if (!m_program->isOk())
449e5c31af7Sopenharmony_ci	{
450e5c31af7Sopenharmony_ci		m_log << *m_program;
451e5c31af7Sopenharmony_ci		delete m_program;
452e5c31af7Sopenharmony_ci		TCU_FAIL("Compile failed");
453e5c31af7Sopenharmony_ci	}
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_renderCtx.getFunctions();
456e5c31af7Sopenharmony_ci	m_posLoc		= gl.getAttribLocation(m_program->getProgram(), "a_position");
457e5c31af7Sopenharmony_ci	m_byteVecLoc	= gl.getAttribLocation(m_program->getProgram(), "a_byteVec");
458e5c31af7Sopenharmony_ci
459e5c31af7Sopenharmony_ci	gl.genVertexArrays(1, &m_vao);
460e5c31af7Sopenharmony_ci	gl.genBuffers(1, &m_positionBuf);
461e5c31af7Sopenharmony_ci	gl.genBuffers(1, &m_indexBuf);
462e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Initialization failed");
463e5c31af7Sopenharmony_ci}
464e5c31af7Sopenharmony_ci
465e5c31af7Sopenharmony_ciVertexArrayVerifier::~VertexArrayVerifier (void)
466e5c31af7Sopenharmony_ci{
467e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_renderCtx.getFunctions();
468e5c31af7Sopenharmony_ci
469e5c31af7Sopenharmony_ci	if (m_vao)			gl.deleteVertexArrays(1, &m_vao);
470e5c31af7Sopenharmony_ci	if (m_positionBuf)	gl.deleteBuffers(1, &m_positionBuf);
471e5c31af7Sopenharmony_ci	if (m_indexBuf)		gl.deleteBuffers(1, &m_indexBuf);
472e5c31af7Sopenharmony_ci
473e5c31af7Sopenharmony_ci	delete m_program;
474e5c31af7Sopenharmony_ci}
475e5c31af7Sopenharmony_ci
476e5c31af7Sopenharmony_cistatic void computePositions (vector<tcu::Vec2>& positions, int gridSizeX, int gridSizeY)
477e5c31af7Sopenharmony_ci{
478e5c31af7Sopenharmony_ci	positions.resize(gridSizeX*gridSizeY*4);
479e5c31af7Sopenharmony_ci
480e5c31af7Sopenharmony_ci	for (int y = 0; y < gridSizeY; y++)
481e5c31af7Sopenharmony_ci	for (int x = 0; x < gridSizeX; x++)
482e5c31af7Sopenharmony_ci	{
483e5c31af7Sopenharmony_ci		float	sx0			= (float)(x+0) / (float)gridSizeX;
484e5c31af7Sopenharmony_ci		float	sy0			= (float)(y+0) / (float)gridSizeY;
485e5c31af7Sopenharmony_ci		float	sx1			= (float)(x+1) / (float)gridSizeX;
486e5c31af7Sopenharmony_ci		float	sy1			= (float)(y+1) / (float)gridSizeY;
487e5c31af7Sopenharmony_ci		float	fx0			= 2.0f * sx0 - 1.0f;
488e5c31af7Sopenharmony_ci		float	fy0			= 2.0f * sy0 - 1.0f;
489e5c31af7Sopenharmony_ci		float	fx1			= 2.0f * sx1 - 1.0f;
490e5c31af7Sopenharmony_ci		float	fy1			= 2.0f * sy1 - 1.0f;
491e5c31af7Sopenharmony_ci		int		baseNdx		= (y * gridSizeX + x)*4;
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ci		positions[baseNdx+0] = tcu::Vec2(fx0, fy0);
494e5c31af7Sopenharmony_ci		positions[baseNdx+1] = tcu::Vec2(fx0, fy1);
495e5c31af7Sopenharmony_ci		positions[baseNdx+2] = tcu::Vec2(fx1, fy0);
496e5c31af7Sopenharmony_ci		positions[baseNdx+3] = tcu::Vec2(fx1, fy1);
497e5c31af7Sopenharmony_ci	}
498e5c31af7Sopenharmony_ci}
499e5c31af7Sopenharmony_ci
500e5c31af7Sopenharmony_cistatic void computeIndices (vector<deUint16>& indices, int gridSizeX, int gridSizeY)
501e5c31af7Sopenharmony_ci{
502e5c31af7Sopenharmony_ci	indices.resize(3 * 2 * gridSizeX * gridSizeY);
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci	for (int quadNdx = 0; quadNdx < gridSizeX*gridSizeY; quadNdx++)
505e5c31af7Sopenharmony_ci	{
506e5c31af7Sopenharmony_ci		int v00 = quadNdx*4 + 0;
507e5c31af7Sopenharmony_ci		int v01 = quadNdx*4 + 1;
508e5c31af7Sopenharmony_ci		int v10 = quadNdx*4 + 2;
509e5c31af7Sopenharmony_ci		int v11 = quadNdx*4 + 3;
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci		DE_ASSERT(v11 < (1<<16));
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci		indices[quadNdx*6 + 0] = (deUint16)v10;
514e5c31af7Sopenharmony_ci		indices[quadNdx*6 + 1] = (deUint16)v00;
515e5c31af7Sopenharmony_ci		indices[quadNdx*6 + 2] = (deUint16)v01;
516e5c31af7Sopenharmony_ci
517e5c31af7Sopenharmony_ci		indices[quadNdx*6 + 3] = (deUint16)v10;
518e5c31af7Sopenharmony_ci		indices[quadNdx*6 + 4] = (deUint16)v01;
519e5c31af7Sopenharmony_ci		indices[quadNdx*6 + 5] = (deUint16)v11;
520e5c31af7Sopenharmony_ci	}
521e5c31af7Sopenharmony_ci}
522e5c31af7Sopenharmony_ci
523e5c31af7Sopenharmony_cistatic inline tcu::Vec4 fetchVtxColor (const deUint8* ptr, int vtxNdx)
524e5c31af7Sopenharmony_ci{
525e5c31af7Sopenharmony_ci	return tcu::RGBA(*(ptr + vtxNdx*3 + 0),
526e5c31af7Sopenharmony_ci					 *(ptr + vtxNdx*3 + 1),
527e5c31af7Sopenharmony_ci					 *(ptr + vtxNdx*3 + 2),
528e5c31af7Sopenharmony_ci					 255).toVec();
529e5c31af7Sopenharmony_ci}
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_cistatic void renderQuadGridReference (tcu::Surface& dst, int numQuads, int rowLength, const deUint8* inPtr)
532e5c31af7Sopenharmony_ci{
533e5c31af7Sopenharmony_ci	using tcu::Vec4;
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ci	dst.setSize(rowLength*VERIFY_QUAD_SIZE, (numQuads/rowLength + (numQuads%rowLength != 0 ? 1 : 0))*VERIFY_QUAD_SIZE);
536e5c31af7Sopenharmony_ci
537e5c31af7Sopenharmony_ci	tcu::PixelBufferAccess dstAccess = dst.getAccess();
538e5c31af7Sopenharmony_ci	tcu::clear(dstAccess, tcu::IVec4(0, 0, 0, 0xff));
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_ci	for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
541e5c31af7Sopenharmony_ci	{
542e5c31af7Sopenharmony_ci		int		x0		= (quadNdx%rowLength)*VERIFY_QUAD_SIZE;
543e5c31af7Sopenharmony_ci		int		y0		= (quadNdx/rowLength)*VERIFY_QUAD_SIZE;
544e5c31af7Sopenharmony_ci		Vec4	v00		= fetchVtxColor(inPtr, quadNdx*4 + 0);
545e5c31af7Sopenharmony_ci		Vec4	v10		= fetchVtxColor(inPtr, quadNdx*4 + 1);
546e5c31af7Sopenharmony_ci		Vec4	v01		= fetchVtxColor(inPtr, quadNdx*4 + 2);
547e5c31af7Sopenharmony_ci		Vec4	v11		= fetchVtxColor(inPtr, quadNdx*4 + 3);
548e5c31af7Sopenharmony_ci
549e5c31af7Sopenharmony_ci		for (int y = 0; y < VERIFY_QUAD_SIZE; y++)
550e5c31af7Sopenharmony_ci		for (int x = 0; x < VERIFY_QUAD_SIZE; x++)
551e5c31af7Sopenharmony_ci		{
552e5c31af7Sopenharmony_ci			float		fx		= ((float)x+0.5f) / (float)VERIFY_QUAD_SIZE;
553e5c31af7Sopenharmony_ci			float		fy		= ((float)y+0.5f) / (float)VERIFY_QUAD_SIZE;
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci			bool		tri		= fx + fy <= 1.0f;
556e5c31af7Sopenharmony_ci			float		tx		= tri ? fx : (1.0f-fx);
557e5c31af7Sopenharmony_ci			float		ty		= tri ? fy : (1.0f-fy);
558e5c31af7Sopenharmony_ci			const Vec4&	t0		= tri ? v00 : v11;
559e5c31af7Sopenharmony_ci			const Vec4&	t1		= tri ? v01 : v10;
560e5c31af7Sopenharmony_ci			const Vec4&	t2		= tri ? v10 : v01;
561e5c31af7Sopenharmony_ci			Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
562e5c31af7Sopenharmony_ci
563e5c31af7Sopenharmony_ci			dstAccess.setPixel(color, x0+x, y0+y);
564e5c31af7Sopenharmony_ci		}
565e5c31af7Sopenharmony_ci	}
566e5c31af7Sopenharmony_ci}
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_cibool VertexArrayVerifier::verify (deUint32 buffer, const deUint8* refPtr, int offset, int numBytes)
569e5c31af7Sopenharmony_ci{
570e5c31af7Sopenharmony_ci	const tcu::RenderTarget&	renderTarget		= m_renderCtx.getRenderTarget();
571e5c31af7Sopenharmony_ci	const int					numBytesInVtx		= 3;
572e5c31af7Sopenharmony_ci	const int					numBytesInQuad		= numBytesInVtx*4;
573e5c31af7Sopenharmony_ci	int							maxQuadsX			= de::min(128, renderTarget.getWidth()	/ VERIFY_QUAD_SIZE);
574e5c31af7Sopenharmony_ci	int							maxQuadsY			= de::min(128, renderTarget.getHeight()	/ VERIFY_QUAD_SIZE);
575e5c31af7Sopenharmony_ci	int							maxQuadsPerBatch	= maxQuadsX*maxQuadsY;
576e5c31af7Sopenharmony_ci	int							numVerified			= 0;
577e5c31af7Sopenharmony_ci	deUint32					program				= m_program->getProgram();
578e5c31af7Sopenharmony_ci	tcu::RGBA					threshold			= renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(3,3,3,3);
579e5c31af7Sopenharmony_ci	bool						isOk				= true;
580e5c31af7Sopenharmony_ci
581e5c31af7Sopenharmony_ci	vector<tcu::Vec2>			positions;
582e5c31af7Sopenharmony_ci	vector<deUint16>			indices;
583e5c31af7Sopenharmony_ci
584e5c31af7Sopenharmony_ci	tcu::Surface				rendered;
585e5c31af7Sopenharmony_ci	tcu::Surface				reference;
586e5c31af7Sopenharmony_ci
587e5c31af7Sopenharmony_ci	DE_ASSERT(numBytes >= numBytesInQuad); // Can't render full quad with smaller buffers.
588e5c31af7Sopenharmony_ci
589e5c31af7Sopenharmony_ci	computePositions(positions, maxQuadsX, maxQuadsY);
590e5c31af7Sopenharmony_ci	computeIndices(indices, maxQuadsX, maxQuadsY);
591e5c31af7Sopenharmony_ci
592e5c31af7Sopenharmony_ci	// Reset buffer bindings.
593e5c31af7Sopenharmony_ci	glBindBuffer				(GL_PIXEL_PACK_BUFFER, 0);
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci	// Setup rendering state.
596e5c31af7Sopenharmony_ci	glViewport					(0, 0, maxQuadsX*VERIFY_QUAD_SIZE, maxQuadsY*VERIFY_QUAD_SIZE);
597e5c31af7Sopenharmony_ci	glClearColor				(0.0f, 0.0f, 0.0f, 1.0f);
598e5c31af7Sopenharmony_ci	glUseProgram				(program);
599e5c31af7Sopenharmony_ci	glBindVertexArray			(m_vao);
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_ci	// Upload positions
602e5c31af7Sopenharmony_ci	glBindBuffer				(GL_ARRAY_BUFFER, m_positionBuf);
603e5c31af7Sopenharmony_ci	glBufferData				(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(positions.size()*sizeof(positions[0])), &positions[0], GL_STATIC_DRAW);
604e5c31af7Sopenharmony_ci	glEnableVertexAttribArray	(m_posLoc);
605e5c31af7Sopenharmony_ci	glVertexAttribPointer		(m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);
606e5c31af7Sopenharmony_ci
607e5c31af7Sopenharmony_ci	// Upload indices
608e5c31af7Sopenharmony_ci	glBindBuffer				(GL_ELEMENT_ARRAY_BUFFER, m_indexBuf);
609e5c31af7Sopenharmony_ci	glBufferData				(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size()*sizeof(indices[0])), &indices[0], GL_STATIC_DRAW);
610e5c31af7Sopenharmony_ci
611e5c31af7Sopenharmony_ci	glEnableVertexAttribArray	(m_byteVecLoc);
612e5c31af7Sopenharmony_ci	glBindBuffer				(GL_ARRAY_BUFFER, buffer);
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci	while (numVerified < numBytes)
615e5c31af7Sopenharmony_ci	{
616e5c31af7Sopenharmony_ci		int		numRemaining		= numBytes-numVerified;
617e5c31af7Sopenharmony_ci		bool	isLeftoverBatch		= numRemaining < numBytesInQuad;
618e5c31af7Sopenharmony_ci		int		numBytesToVerify	= isLeftoverBatch ? numBytesInQuad				: de::min(maxQuadsPerBatch*numBytesInQuad, numRemaining - numRemaining%numBytesInQuad);
619e5c31af7Sopenharmony_ci		int		curOffset			= isLeftoverBatch ? (numBytes-numBytesInQuad)	: numVerified;
620e5c31af7Sopenharmony_ci		int		numQuads			= numBytesToVerify/numBytesInQuad;
621e5c31af7Sopenharmony_ci		int		numCols				= de::min(maxQuadsX, numQuads);
622e5c31af7Sopenharmony_ci		int		numRows				= numQuads/maxQuadsX + (numQuads%maxQuadsX != 0 ? 1 : 0);
623e5c31af7Sopenharmony_ci		string	imageSetDesc		= string("Bytes ") + de::toString(offset+curOffset) + " to " + de::toString(offset+curOffset+numBytesToVerify-1);
624e5c31af7Sopenharmony_ci
625e5c31af7Sopenharmony_ci		DE_ASSERT(numBytesToVerify > 0 && numBytesToVerify%numBytesInQuad == 0);
626e5c31af7Sopenharmony_ci		DE_ASSERT(de::inBounds(curOffset, 0, numBytes));
627e5c31af7Sopenharmony_ci		DE_ASSERT(de::inRange(curOffset+numBytesToVerify, curOffset, numBytes));
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_ci		// Render batch.
630e5c31af7Sopenharmony_ci		glClear					(GL_COLOR_BUFFER_BIT);
631e5c31af7Sopenharmony_ci		glVertexAttribPointer	(m_byteVecLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, (const glw::GLvoid*)(deUintptr)(offset + curOffset));
632e5c31af7Sopenharmony_ci		glDrawElements			(GL_TRIANGLES, numQuads*6, GL_UNSIGNED_SHORT, DE_NULL);
633e5c31af7Sopenharmony_ci
634e5c31af7Sopenharmony_ci		renderQuadGridReference(reference,  numQuads, numCols, refPtr + offset + curOffset);
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_ci		rendered.setSize(numCols*VERIFY_QUAD_SIZE, numRows*VERIFY_QUAD_SIZE);
637e5c31af7Sopenharmony_ci		glu::readPixels(m_renderCtx, 0, 0, rendered.getAccess());
638e5c31af7Sopenharmony_ci
639e5c31af7Sopenharmony_ci		if (!tcu::pixelThresholdCompare(m_log, "RenderResult", imageSetDesc.c_str(), reference, rendered, threshold, tcu::COMPARE_LOG_RESULT))
640e5c31af7Sopenharmony_ci		{
641e5c31af7Sopenharmony_ci			isOk = false;
642e5c31af7Sopenharmony_ci			break;
643e5c31af7Sopenharmony_ci		}
644e5c31af7Sopenharmony_ci
645e5c31af7Sopenharmony_ci		numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
646e5c31af7Sopenharmony_ci	}
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_ci	glBindVertexArray(0);
649e5c31af7Sopenharmony_ci
650e5c31af7Sopenharmony_ci	return isOk;
651e5c31af7Sopenharmony_ci}
652e5c31af7Sopenharmony_ci
653e5c31af7Sopenharmony_ci// IndexArrayVerifier
654e5c31af7Sopenharmony_ci
655e5c31af7Sopenharmony_ciIndexArrayVerifier::IndexArrayVerifier (glu::RenderContext& renderCtx, tcu::TestLog& log)
656e5c31af7Sopenharmony_ci	: BufferVerifierBase	(renderCtx, log)
657e5c31af7Sopenharmony_ci	, m_program				(DE_NULL)
658e5c31af7Sopenharmony_ci	, m_posLoc				(0)
659e5c31af7Sopenharmony_ci	, m_colorLoc			(0)
660e5c31af7Sopenharmony_ci{
661e5c31af7Sopenharmony_ci
662e5c31af7Sopenharmony_ci	const glu::ContextType	ctxType		= renderCtx.getType();
663e5c31af7Sopenharmony_ci	const glu::GLSLVersion	glslVersion	= glu::isContextTypeES(ctxType) ? glu::GLSL_VERSION_300_ES : glu::GLSL_VERSION_330;
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_ci	DE_ASSERT(glu::isGLSLVersionSupported(ctxType, glslVersion));
666e5c31af7Sopenharmony_ci
667e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(
668e5c31af7Sopenharmony_ci		string(glu::getGLSLVersionDeclaration(glslVersion)) + "\n"
669e5c31af7Sopenharmony_ci		"in highp vec2 a_position;\n"
670e5c31af7Sopenharmony_ci		"in mediump vec3 a_color;\n"
671e5c31af7Sopenharmony_ci		"out mediump vec3 v_color;\n"
672e5c31af7Sopenharmony_ci		"void main (void)\n"
673e5c31af7Sopenharmony_ci		"{\n"
674e5c31af7Sopenharmony_ci		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
675e5c31af7Sopenharmony_ci		"	v_color = a_color;\n"
676e5c31af7Sopenharmony_ci		"}\n",
677e5c31af7Sopenharmony_ci
678e5c31af7Sopenharmony_ci		string(glu::getGLSLVersionDeclaration(glslVersion)) + "\n"
679e5c31af7Sopenharmony_ci		"in mediump vec3 v_color;\n"
680e5c31af7Sopenharmony_ci		"layout(location = 0) out mediump vec4 o_color;\n"
681e5c31af7Sopenharmony_ci		"void main (void)\n"
682e5c31af7Sopenharmony_ci		"{\n"
683e5c31af7Sopenharmony_ci		"	o_color = vec4(v_color, 1.0);\n"
684e5c31af7Sopenharmony_ci		"}\n"));
685e5c31af7Sopenharmony_ci
686e5c31af7Sopenharmony_ci	if (!m_program->isOk())
687e5c31af7Sopenharmony_ci	{
688e5c31af7Sopenharmony_ci		m_log << *m_program;
689e5c31af7Sopenharmony_ci		delete m_program;
690e5c31af7Sopenharmony_ci		TCU_FAIL("Compile failed");
691e5c31af7Sopenharmony_ci	}
692e5c31af7Sopenharmony_ci
693e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_renderCtx.getFunctions();
694e5c31af7Sopenharmony_ci	m_posLoc	= gl.getAttribLocation(m_program->getProgram(), "a_position");
695e5c31af7Sopenharmony_ci	m_colorLoc	= gl.getAttribLocation(m_program->getProgram(), "a_color");
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci	gl.genVertexArrays(1, &m_vao);
698e5c31af7Sopenharmony_ci	gl.genBuffers(1, &m_positionBuf);
699e5c31af7Sopenharmony_ci	gl.genBuffers(1, &m_colorBuf);
700e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Initialization failed");
701e5c31af7Sopenharmony_ci}
702e5c31af7Sopenharmony_ci
703e5c31af7Sopenharmony_ciIndexArrayVerifier::~IndexArrayVerifier (void)
704e5c31af7Sopenharmony_ci{
705e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_renderCtx.getFunctions();
706e5c31af7Sopenharmony_ci
707e5c31af7Sopenharmony_ci	if (m_vao)			gl.deleteVertexArrays(1, &m_vao);
708e5c31af7Sopenharmony_ci	if (m_positionBuf)	gl.deleteBuffers(1, &m_positionBuf);
709e5c31af7Sopenharmony_ci	if (m_colorBuf)		gl.deleteBuffers(1, &m_colorBuf);
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci	delete m_program;
712e5c31af7Sopenharmony_ci}
713e5c31af7Sopenharmony_ci
714e5c31af7Sopenharmony_cistatic void computeIndexVerifierPositions (std::vector<tcu::Vec2>& dst)
715e5c31af7Sopenharmony_ci{
716e5c31af7Sopenharmony_ci	const int	numPosX		= 16;
717e5c31af7Sopenharmony_ci	const int	numPosY		= 16;
718e5c31af7Sopenharmony_ci
719e5c31af7Sopenharmony_ci	dst.resize(numPosX*numPosY);
720e5c31af7Sopenharmony_ci
721e5c31af7Sopenharmony_ci	for (int y = 0; y < numPosY; y++)
722e5c31af7Sopenharmony_ci	{
723e5c31af7Sopenharmony_ci		for (int x = 0; x < numPosX; x++)
724e5c31af7Sopenharmony_ci		{
725e5c31af7Sopenharmony_ci			float	xf	= float(x) / float(numPosX-1);
726e5c31af7Sopenharmony_ci			float	yf	= float(y) / float(numPosY-1);
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci			dst[y*numPosX + x] = tcu::Vec2(2.0f*xf - 1.0f, 2.0f*yf - 1.0f);
729e5c31af7Sopenharmony_ci		}
730e5c31af7Sopenharmony_ci	}
731e5c31af7Sopenharmony_ci}
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_cistatic void computeIndexVerifierColors (std::vector<tcu::Vec3>& dst)
734e5c31af7Sopenharmony_ci{
735e5c31af7Sopenharmony_ci	const int	numColors	= 256;
736e5c31af7Sopenharmony_ci	const float	minVal		= 0.1f;
737e5c31af7Sopenharmony_ci	const float maxVal		= 0.5f;
738e5c31af7Sopenharmony_ci	de::Random	rnd			(0xabc231);
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ci	dst.resize(numColors);
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci	for (std::vector<tcu::Vec3>::iterator i = dst.begin(); i != dst.end(); ++i)
743e5c31af7Sopenharmony_ci	{
744e5c31af7Sopenharmony_ci		i->x()	= rnd.getFloat(minVal, maxVal);
745e5c31af7Sopenharmony_ci		i->y()	= rnd.getFloat(minVal, maxVal);
746e5c31af7Sopenharmony_ci		i->z()	= rnd.getFloat(minVal, maxVal);
747e5c31af7Sopenharmony_ci	}
748e5c31af7Sopenharmony_ci}
749e5c31af7Sopenharmony_ci
750e5c31af7Sopenharmony_citemplate<typename T>
751e5c31af7Sopenharmony_cistatic void execVertexFetch (T* dst, const T* src, const deUint8* indices, int numIndices)
752e5c31af7Sopenharmony_ci{
753e5c31af7Sopenharmony_ci	for (int i = 0; i < numIndices; ++i)
754e5c31af7Sopenharmony_ci		dst[i] = src[indices[i]];
755e5c31af7Sopenharmony_ci}
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_cibool IndexArrayVerifier::verify (deUint32 buffer, const deUint8* refPtr, int offset, int numBytes)
758e5c31af7Sopenharmony_ci{
759e5c31af7Sopenharmony_ci	const tcu::RenderTarget&	renderTarget		= m_renderCtx.getRenderTarget();
760e5c31af7Sopenharmony_ci	const int					viewportW			= de::min<int>(INDEX_ARRAY_DRAW_VIEWPORT_WIDTH, renderTarget.getWidth());
761e5c31af7Sopenharmony_ci	const int					viewportH			= de::min<int>(INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT, renderTarget.getHeight());
762e5c31af7Sopenharmony_ci	const int					minBytesPerBatch	= 2;
763e5c31af7Sopenharmony_ci	const tcu::RGBA				threshold			(0,0,0,0);
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci	std::vector<tcu::Vec2>		positions;
766e5c31af7Sopenharmony_ci	std::vector<tcu::Vec3>		colors;
767e5c31af7Sopenharmony_ci
768e5c31af7Sopenharmony_ci	std::vector<tcu::Vec2>		fetchedPos			(MAX_LINES_PER_INDEX_ARRAY_DRAW+1);
769e5c31af7Sopenharmony_ci	std::vector<tcu::Vec3>		fetchedColor		(MAX_LINES_PER_INDEX_ARRAY_DRAW+1);
770e5c31af7Sopenharmony_ci
771e5c31af7Sopenharmony_ci	tcu::Surface				indexBufferImg		(viewportW, viewportH);
772e5c31af7Sopenharmony_ci	tcu::Surface				referenceImg		(viewportW, viewportH);
773e5c31af7Sopenharmony_ci
774e5c31af7Sopenharmony_ci	int							numVerified			= 0;
775e5c31af7Sopenharmony_ci	bool						isOk				= true;
776e5c31af7Sopenharmony_ci
777e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(sizeof(tcu::Vec2) == sizeof(float)*2);
778e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(sizeof(tcu::Vec3) == sizeof(float)*3);
779e5c31af7Sopenharmony_ci
780e5c31af7Sopenharmony_ci	computeIndexVerifierPositions(positions);
781e5c31af7Sopenharmony_ci	computeIndexVerifierColors(colors);
782e5c31af7Sopenharmony_ci
783e5c31af7Sopenharmony_ci	// Reset buffer bindings.
784e5c31af7Sopenharmony_ci	glBindVertexArray			(m_vao);
785e5c31af7Sopenharmony_ci	glBindBuffer				(GL_PIXEL_PACK_BUFFER,		0);
786e5c31af7Sopenharmony_ci	glBindBuffer				(GL_ELEMENT_ARRAY_BUFFER,	buffer);
787e5c31af7Sopenharmony_ci
788e5c31af7Sopenharmony_ci	// Setup rendering state.
789e5c31af7Sopenharmony_ci	glViewport					(0, 0, viewportW, viewportH);
790e5c31af7Sopenharmony_ci	glClearColor				(0.0f, 0.0f, 0.0f, 1.0f);
791e5c31af7Sopenharmony_ci	glUseProgram				(m_program->getProgram());
792e5c31af7Sopenharmony_ci	glEnableVertexAttribArray	(m_posLoc);
793e5c31af7Sopenharmony_ci	glEnableVertexAttribArray	(m_colorLoc);
794e5c31af7Sopenharmony_ci	glEnable					(GL_BLEND);
795e5c31af7Sopenharmony_ci	glBlendFunc					(GL_ONE, GL_ONE);
796e5c31af7Sopenharmony_ci	glBlendEquation				(GL_FUNC_ADD);
797e5c31af7Sopenharmony_ci
798e5c31af7Sopenharmony_ci	while (numVerified < numBytes)
799e5c31af7Sopenharmony_ci	{
800e5c31af7Sopenharmony_ci		int		numRemaining		= numBytes-numVerified;
801e5c31af7Sopenharmony_ci		bool	isLeftoverBatch		= numRemaining < minBytesPerBatch;
802e5c31af7Sopenharmony_ci		int		numBytesToVerify	= isLeftoverBatch ? minBytesPerBatch			: de::min(MAX_LINES_PER_INDEX_ARRAY_DRAW+1, numRemaining);
803e5c31af7Sopenharmony_ci		int		curOffset			= isLeftoverBatch ? (numBytes-minBytesPerBatch)	: numVerified;
804e5c31af7Sopenharmony_ci		string	imageSetDesc		= string("Bytes ") + de::toString(offset+curOffset) + " to " + de::toString(offset+curOffset+numBytesToVerify-1);
805e5c31af7Sopenharmony_ci
806e5c31af7Sopenharmony_ci		// Step 1: Render using index buffer.
807e5c31af7Sopenharmony_ci		glClear					(GL_COLOR_BUFFER_BIT);
808e5c31af7Sopenharmony_ci
809e5c31af7Sopenharmony_ci		glBindBuffer			(GL_ARRAY_BUFFER, m_positionBuf);
810e5c31af7Sopenharmony_ci		glBufferData			(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(positions.size()*sizeof(positions[0])), &positions[0], GL_STREAM_DRAW);
811e5c31af7Sopenharmony_ci		glVertexAttribPointer	(m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_ci		glBindBuffer			(GL_ARRAY_BUFFER, m_colorBuf);
814e5c31af7Sopenharmony_ci		glBufferData			(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(colors.size()*sizeof(colors[0])), &colors[0], GL_STREAM_DRAW);
815e5c31af7Sopenharmony_ci		glVertexAttribPointer	(m_colorLoc, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci		glDrawElements			(GL_LINE_STRIP, numBytesToVerify, GL_UNSIGNED_BYTE, (void*)(deUintptr)(offset+curOffset));
818e5c31af7Sopenharmony_ci		glu::readPixels			(m_renderCtx, 0, 0, indexBufferImg.getAccess());
819e5c31af7Sopenharmony_ci
820e5c31af7Sopenharmony_ci		// Step 2: Do manual fetch and render without index buffer.
821e5c31af7Sopenharmony_ci		execVertexFetch(&fetchedPos[0], &positions[0], refPtr+offset+curOffset, numBytesToVerify);
822e5c31af7Sopenharmony_ci		execVertexFetch(&fetchedColor[0], &colors[0], refPtr+offset+curOffset, numBytesToVerify);
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ci		glClear					(GL_COLOR_BUFFER_BIT);
825e5c31af7Sopenharmony_ci
826e5c31af7Sopenharmony_ci		glBindBuffer			(GL_ARRAY_BUFFER, m_positionBuf);
827e5c31af7Sopenharmony_ci		glBufferData			(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(fetchedPos.size()*sizeof(fetchedPos[0])), &fetchedPos[0], GL_STREAM_DRAW);
828e5c31af7Sopenharmony_ci		glVertexAttribPointer	(m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);
829e5c31af7Sopenharmony_ci
830e5c31af7Sopenharmony_ci		glBindBuffer			(GL_ARRAY_BUFFER, m_colorBuf);
831e5c31af7Sopenharmony_ci		glBufferData			(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(fetchedColor.size()*sizeof(fetchedColor[0])), &fetchedColor[0], GL_STREAM_DRAW);
832e5c31af7Sopenharmony_ci		glVertexAttribPointer	(m_colorLoc, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
833e5c31af7Sopenharmony_ci
834e5c31af7Sopenharmony_ci		glDrawArrays			(GL_LINE_STRIP, 0, numBytesToVerify);
835e5c31af7Sopenharmony_ci		glu::readPixels			(m_renderCtx, 0, 0, referenceImg.getAccess());
836e5c31af7Sopenharmony_ci
837e5c31af7Sopenharmony_ci		if (!tcu::pixelThresholdCompare(m_log, "RenderResult", imageSetDesc.c_str(), referenceImg, indexBufferImg, threshold, tcu::COMPARE_LOG_RESULT))
838e5c31af7Sopenharmony_ci		{
839e5c31af7Sopenharmony_ci			isOk = false;
840e5c31af7Sopenharmony_ci			break;
841e5c31af7Sopenharmony_ci		}
842e5c31af7Sopenharmony_ci
843e5c31af7Sopenharmony_ci		numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
844e5c31af7Sopenharmony_ci	}
845e5c31af7Sopenharmony_ci
846e5c31af7Sopenharmony_ci	glBindVertexArray(0);
847e5c31af7Sopenharmony_ci
848e5c31af7Sopenharmony_ci	return isOk;
849e5c31af7Sopenharmony_ci}
850e5c31af7Sopenharmony_ci
851e5c31af7Sopenharmony_ciconst char* getWriteTypeDescription (WriteType write)
852e5c31af7Sopenharmony_ci{
853e5c31af7Sopenharmony_ci	static const char* s_desc[] =
854e5c31af7Sopenharmony_ci	{
855e5c31af7Sopenharmony_ci		"glBufferSubData()",
856e5c31af7Sopenharmony_ci		"glMapBufferRange()",
857e5c31af7Sopenharmony_ci		"transform feedback",
858e5c31af7Sopenharmony_ci		"glReadPixels() into PBO binding"
859e5c31af7Sopenharmony_ci	};
860e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<WRITE_LAST>(s_desc, write);
861e5c31af7Sopenharmony_ci}
862e5c31af7Sopenharmony_ci
863e5c31af7Sopenharmony_ciconst char* getVerifyTypeDescription (VerifyType verify)
864e5c31af7Sopenharmony_ci{
865e5c31af7Sopenharmony_ci	static const char* s_desc[] =
866e5c31af7Sopenharmony_ci	{
867e5c31af7Sopenharmony_ci		"rendering as vertex data",
868e5c31af7Sopenharmony_ci		"rendering as index data",
869e5c31af7Sopenharmony_ci		"reading in shader as uniform buffer data",
870e5c31af7Sopenharmony_ci		"using as PBO and uploading to texture",
871e5c31af7Sopenharmony_ci		"reading back using glMapBufferRange()"
872e5c31af7Sopenharmony_ci	};
873e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<VERIFY_LAST>(s_desc, verify);
874e5c31af7Sopenharmony_ci}
875e5c31af7Sopenharmony_ci
876e5c31af7Sopenharmony_ci} // BufferTestUtil
877e5c31af7Sopenharmony_ci} // gls
878e5c31af7Sopenharmony_ci} // deqp
879