1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.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 copying tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fBufferCopyTests.hpp"
25#include "glsBufferTestUtil.hpp"
26#include "tcuTestLog.hpp"
27#include "deMemory.h"
28#include "deString.h"
29#include "glwEnums.hpp"
30#include "glwFunctions.hpp"
31
32#include <algorithm>
33
34using std::vector;
35using std::string;
36using tcu::TestLog;
37
38namespace deqp
39{
40namespace gles3
41{
42namespace Functional
43{
44
45using namespace gls::BufferTestUtil;
46
47class BasicBufferCopyCase : public BufferCase
48{
49public:
50	BasicBufferCopyCase (Context&		context,
51						 const char*	name,
52						 const char*	desc,
53						 deUint32		srcTarget,
54						 int			srcSize,
55						 deUint32		srcHint,
56						 deUint32		dstTarget,
57						 int			dstSize,
58						 deUint32		dstHint,
59						 int			copySrcOffset,
60						 int			copyDstOffset,
61						 int			copySize,
62						 VerifyType		verifyType)
63		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
64		, m_srcTarget		(srcTarget)
65		, m_srcSize			(srcSize)
66		, m_srcHint			(srcHint)
67		, m_dstTarget		(dstTarget)
68		, m_dstSize			(dstSize)
69		, m_dstHint			(dstHint)
70		, m_copySrcOffset	(copySrcOffset)
71		, m_copyDstOffset	(copyDstOffset)
72		, m_copySize		(copySize)
73		, m_verifyType		(verifyType)
74	{
75		DE_ASSERT(de::inBounds(m_copySrcOffset, 0, m_srcSize) && de::inRange(m_copySrcOffset+m_copySize, m_copySrcOffset, m_srcSize));
76		DE_ASSERT(de::inBounds(m_copyDstOffset, 0, m_dstSize) && de::inRange(m_copyDstOffset+m_copySize, m_copyDstOffset, m_dstSize));
77	}
78
79	IterateResult iterate (void)
80	{
81		BufferVerifier	verifier	(m_renderCtx, m_testCtx.getLog(), m_verifyType);
82		ReferenceBuffer	srcRef;
83		ReferenceBuffer	dstRef;
84		deUint32		srcBuf		= 0;
85		deUint32		dstBuf		= 0;
86		deUint32		srcSeed		= deStringHash(getName()) ^ 0xabcd;
87		deUint32		dstSeed		= deStringHash(getName()) ^ 0xef01;
88		bool			isOk		= true;
89
90		srcRef.setSize(m_srcSize);
91		fillWithRandomBytes(srcRef.getPtr(), m_srcSize, srcSeed);
92
93		dstRef.setSize(m_dstSize);
94		fillWithRandomBytes(dstRef.getPtr(), m_dstSize, dstSeed);
95
96		// Create source buffer and fill with data.
97		srcBuf = genBuffer();
98		glBindBuffer(m_srcTarget, srcBuf);
99		glBufferData(m_srcTarget, m_srcSize, srcRef.getPtr(), m_srcHint);
100		GLU_CHECK_MSG("glBufferData");
101
102		// Create destination buffer and fill with data.
103		dstBuf = genBuffer();
104		glBindBuffer(m_dstTarget, dstBuf);
105		glBufferData(m_dstTarget, m_dstSize, dstRef.getPtr(), m_dstHint);
106		GLU_CHECK_MSG("glBufferData");
107
108		// Verify both buffers before executing copy.
109		isOk = verifier.verify(srcBuf, srcRef.getPtr(), 0, m_srcSize, m_srcTarget) && isOk;
110		isOk = verifier.verify(dstBuf, dstRef.getPtr(), 0, m_dstSize, m_dstTarget) && isOk;
111
112		// Execute copy.
113		deMemcpy(dstRef.getPtr()+m_copyDstOffset, srcRef.getPtr()+m_copySrcOffset, m_copySize);
114
115		glBindBuffer(m_srcTarget, srcBuf);
116		glBindBuffer(m_dstTarget, dstBuf);
117		glCopyBufferSubData(m_srcTarget, m_dstTarget, m_copySrcOffset, m_copyDstOffset, m_copySize);
118		GLU_CHECK_MSG("glCopyBufferSubData");
119
120		// Verify both buffers after copy.
121		isOk = verifier.verify(srcBuf, srcRef.getPtr(), 0, m_srcSize, m_srcTarget) && isOk;
122		isOk = verifier.verify(dstBuf, dstRef.getPtr(), 0, m_dstSize, m_dstTarget) && isOk;
123
124		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
125								isOk ? "Pass"				: "Buffer verification failed");
126		return STOP;
127	}
128
129private:
130	deUint32	m_srcTarget;
131	int			m_srcSize;
132	deUint32	m_srcHint;
133
134	deUint32	m_dstTarget;
135	int			m_dstSize;
136	deUint32	m_dstHint;
137
138	int			m_copySrcOffset;
139	int			m_copyDstOffset;
140	int			m_copySize;
141
142	VerifyType	m_verifyType;
143};
144
145// Case B: same buffer, take range as parameter
146
147class SingleBufferCopyCase : public BufferCase
148{
149public:
150	SingleBufferCopyCase (Context&		context,
151						  const char*	name,
152						  const char*	desc,
153						  deUint32		srcTarget,
154						  deUint32		dstTarget,
155						  deUint32		hint,
156						  VerifyType	verifyType)
157		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
158		, m_srcTarget		(srcTarget)
159		, m_dstTarget		(dstTarget)
160		, m_hint			(hint)
161		, m_verifyType		(verifyType)
162	{
163	}
164
165	IterateResult iterate (void)
166	{
167		const int		size		= 1000;
168		BufferVerifier	verifier	(m_renderCtx, m_testCtx.getLog(), m_verifyType);
169		ReferenceBuffer	ref;
170		deUint32		buf			= 0;
171		deUint32		baseSeed	= deStringHash(getName());
172		bool			isOk		= true;
173
174		ref.setSize(size);
175
176		// Create buffer.
177		buf = genBuffer();
178		glBindBuffer(m_srcTarget, buf);
179
180		static const struct
181		{
182			int				srcOffset;
183			int				dstOffset;
184			int				copySize;
185		} copyRanges[] =
186		{
187			{ 57,		701,	101 },	// Non-adjecent, from low to high.
188			{ 640,		101,	101 },	// Non-adjecent, from high to low.
189			{ 0,		500,	500 },	// Lower half to upper half.
190			{ 500,		0,		500 }	// Upper half to lower half.
191		};
192
193		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(copyRanges) && isOk; ndx++)
194		{
195			int	srcOffset	= copyRanges[ndx].srcOffset;
196			int	dstOffset	= copyRanges[ndx].dstOffset;
197			int	copySize	= copyRanges[ndx].copySize;
198
199			fillWithRandomBytes(ref.getPtr(), size, baseSeed ^ deInt32Hash(ndx));
200
201			// Fill with data.
202			glBindBuffer(m_srcTarget, buf);
203			glBufferData(m_srcTarget, size, ref.getPtr(), m_hint);
204			GLU_CHECK_MSG("glBufferData");
205
206			// Execute copy.
207			deMemcpy(ref.getPtr()+dstOffset, ref.getPtr()+srcOffset, copySize);
208
209			glBindBuffer(m_dstTarget, buf);
210			glCopyBufferSubData(m_srcTarget, m_dstTarget, srcOffset, dstOffset, copySize);
211			GLU_CHECK_MSG("glCopyBufferSubData");
212
213			// Verify buffer after copy.
214			isOk = verifier.verify(buf, ref.getPtr(), 0, size, m_dstTarget) && isOk;
215		}
216
217		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
218								isOk ? "Pass"				: "Buffer verification failed");
219		return STOP;
220	}
221
222private:
223	deUint32	m_srcTarget;
224	deUint32	m_dstTarget;
225	deUint32	m_hint;
226
227	VerifyType	m_verifyType;
228};
229
230BufferCopyTests::BufferCopyTests (Context& context)
231	: TestCaseGroup(context, "copy", "Buffer copy tests")
232{
233}
234
235BufferCopyTests::~BufferCopyTests (void)
236{
237}
238
239void BufferCopyTests::init (void)
240{
241	static const deUint32 bufferTargets[] =
242	{
243		GL_ARRAY_BUFFER,
244		GL_COPY_READ_BUFFER,
245		GL_COPY_WRITE_BUFFER,
246		GL_ELEMENT_ARRAY_BUFFER,
247		GL_PIXEL_PACK_BUFFER,
248		GL_PIXEL_UNPACK_BUFFER,
249		GL_TRANSFORM_FEEDBACK_BUFFER,
250		GL_UNIFORM_BUFFER
251	};
252
253	// .basic
254	{
255		tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic buffer copy cases");
256		addChild(basicGroup);
257
258		for (int srcTargetNdx = 0; srcTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); srcTargetNdx++)
259		{
260			for (int dstTargetNdx = 0; dstTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); dstTargetNdx++)
261			{
262				if (srcTargetNdx == dstTargetNdx)
263					continue;
264
265				deUint32		srcTarget		= bufferTargets[srcTargetNdx];
266				deUint32		dstTarget		= bufferTargets[dstTargetNdx];
267				const int		size			= 1017;
268				const deUint32	hint			= GL_STATIC_DRAW;
269				VerifyType		verify			= VERIFY_AS_VERTEX_ARRAY;
270				string			name			= string(getBufferTargetName(srcTarget)) + "_" + getBufferTargetName(dstTarget);
271
272				basicGroup->addChild(new BasicBufferCopyCase(m_context, name.c_str(), "", srcTarget, size, hint, dstTarget, size, hint, 0, 0, size, verify));
273			}
274		}
275	}
276
277	// .subrange
278	{
279		tcu::TestCaseGroup* subrangeGroup = new tcu::TestCaseGroup(m_testCtx, "subrange", "Buffer subrange copy tests");
280		addChild(subrangeGroup);
281
282		static const struct
283		{
284			const char*		name;
285			int				srcSize;
286			int				dstSize;
287			int				srcOffset;
288			int				dstOffset;
289			int				copySize;
290		} cases[] =
291		{
292			//						srcSize		dstSize		srcOffs		dstOffs		copySize
293			{ "middle",				1000,		1000,		250,		250,		500 },
294			{ "small_to_large",		100,		1000,		0,			409,		100 },
295			{ "large_to_small",		1000,		100,		409,		0,			100 },
296			{ "low_to_high_1",		1000,		1000,		0,			500,		500 },
297			{ "low_to_high_2",		997,		1027,		0,			701,		111 },
298			{ "high_to_low_1",		1000,		1000,		500,		0,			500 },
299			{ "high_to_low_2",		1027,		997,		701,		17,			111 }
300		};
301
302		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
303		{
304			deUint32		srcTarget		= GL_COPY_READ_BUFFER;
305			deUint32		dstTarget		= GL_COPY_WRITE_BUFFER;
306			deUint32		hint			= GL_STATIC_DRAW;
307			VerifyType		verify			= VERIFY_AS_VERTEX_ARRAY;
308
309			subrangeGroup->addChild(new BasicBufferCopyCase(m_context, cases[ndx].name, "",
310															srcTarget, cases[ndx].srcSize, hint,
311															dstTarget, cases[ndx].dstSize, hint,
312															cases[ndx].srcOffset, cases[ndx].dstOffset, cases[ndx].copySize,
313															verify));
314		}
315	}
316
317	// .single_buffer
318	{
319		tcu::TestCaseGroup* singleBufGroup = new tcu::TestCaseGroup(m_testCtx, "single_buffer", "Copies within single buffer");
320		addChild(singleBufGroup);
321
322		for (int srcTargetNdx = 0; srcTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); srcTargetNdx++)
323		{
324			for (int dstTargetNdx = 0; dstTargetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); dstTargetNdx++)
325			{
326				if (srcTargetNdx == dstTargetNdx)
327					continue;
328
329				deUint32		srcTarget		= bufferTargets[srcTargetNdx];
330				deUint32		dstTarget		= bufferTargets[dstTargetNdx];
331				const deUint32	hint			= GL_STATIC_DRAW;
332				VerifyType		verify			= VERIFY_AS_VERTEX_ARRAY;
333				string			name			= string(getBufferTargetName(srcTarget)) + "_" + getBufferTargetName(dstTarget);
334
335				singleBufGroup->addChild(new SingleBufferCopyCase(m_context, name.c_str(), "", srcTarget, dstTarget, hint, verify));
336			}
337		}
338	}
339}
340
341} // Functional
342} // gles3
343} // deqp
344