• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 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 Vertex attribute binding state query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fVertexAttributeBindingStateQueryTests.hpp"
25 #include "tcuTestLog.hpp"
26 #include "gluCallLogWrapper.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluObjectWrapper.hpp"
29 #include "gluStrUtil.hpp"
30 #include "glsStateQueryUtil.hpp"
31 #include "glwEnums.hpp"
32 #include "glwFunctions.hpp"
33 #include "deRandom.hpp"
34 
35 namespace deqp
36 {
37 namespace gles31
38 {
39 namespace Functional
40 {
41 namespace
42 {
43 
44 class AttributeBindingCase : public TestCase
45 {
46 public:
47 					AttributeBindingCase	(Context& context, const char* name, const char* desc);
48 	IterateResult	iterate					(void);
49 };
50 
AttributeBindingCase(Context & context,const char * name,const char * desc)51 AttributeBindingCase::AttributeBindingCase (Context& context, const char* name, const char* desc)
52 	: TestCase(context, name, desc)
53 {
54 }
55 
iterate(void)56 AttributeBindingCase::IterateResult AttributeBindingCase::iterate (void)
57 {
58 	glu::CallLogWrapper gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
59 	glu::VertexArray	vao			(m_context.getRenderContext());
60 	glw::GLenum			error		= 0;
61 	glw::GLint			maxAttrs	= -1;
62 	bool				allOk		= true;
63 
64 	gl.enableLogging(true);
65 
66 	gl.glBindVertexArray(*vao);
67 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrs);
68 
69 	// initial
70 	{
71 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
72 
73 		for (int attr = 0; attr < de::max(16, maxAttrs); ++attr)
74 		{
75 			glw::GLint bindingState = -1;
76 
77 			gl.glGetVertexAttribiv(attr, GL_VERTEX_ATTRIB_BINDING, &bindingState);
78 			error = gl.glGetError();
79 
80 			if (error != GL_NO_ERROR)
81 			{
82 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
83 				allOk = false;
84 			}
85 			else if (bindingState != attr)
86 			{
87 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << attr << ", got " << bindingState << tcu::TestLog::EndMessage;
88 				allOk = false;
89 			}
90 		}
91 	}
92 
93 	// is part of vao
94 	{
95 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
96 		glu::VertexArray			otherVao		(m_context.getRenderContext());
97 		glw::GLint					bindingState	= -1;
98 
99 		// set to value A in vao1
100 		gl.glVertexAttribBinding(1, 4);
101 
102 		// set to value B in vao2
103 		gl.glBindVertexArray(*otherVao);
104 		gl.glVertexAttribBinding(1, 7);
105 
106 		// check value is still ok in original vao
107 		gl.glBindVertexArray(*vao);
108 		gl.glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_BINDING, &bindingState);
109 		error = gl.glGetError();
110 
111 		if (error != GL_NO_ERROR)
112 		{
113 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
114 			allOk = false;
115 		}
116 		else if (bindingState != 4)
117 		{
118 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 4, got " << bindingState << tcu::TestLog::EndMessage;
119 			allOk = false;
120 		}
121 	}
122 
123 	// random values
124 	{
125 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
126 		de::Random					rnd				(0xabc);
127 		const int					numRandomTests	= 10;
128 
129 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
130 		{
131 			// switch random va to random binding
132 			const int	va				= rnd.getInt(0, de::max(16, maxAttrs)-1);
133 			const int	binding			= rnd.getInt(0, 16);
134 			glw::GLint	bindingState	= -1;
135 
136 			gl.glVertexAttribBinding(va, binding);
137 			gl.glGetVertexAttribiv(va, GL_VERTEX_ATTRIB_BINDING, &bindingState);
138 			error = gl.glGetError();
139 
140 			if (error != GL_NO_ERROR)
141 			{
142 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
143 				allOk = false;
144 			}
145 			else if (bindingState != binding)
146 			{
147 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << binding << ", got " << bindingState << tcu::TestLog::EndMessage;
148 				allOk = false;
149 			}
150 		}
151 	}
152 
153 	if (allOk)
154 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
155 	else
156 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
157 	return STOP;
158 }
159 
160 class AttributeRelativeOffsetCase : public TestCase
161 {
162 public:
163 					AttributeRelativeOffsetCase	(Context& context, const char* name, const char* desc);
164 	IterateResult	iterate						(void);
165 };
166 
AttributeRelativeOffsetCase(Context & context,const char * name,const char * desc)167 AttributeRelativeOffsetCase::AttributeRelativeOffsetCase (Context& context, const char* name, const char* desc)
168 	: TestCase(context, name, desc)
169 {
170 }
171 
iterate(void)172 AttributeRelativeOffsetCase::IterateResult AttributeRelativeOffsetCase::iterate (void)
173 {
174 	glu::CallLogWrapper gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
175 	glu::VertexArray	vao			(m_context.getRenderContext());
176 	glw::GLenum			error		= 0;
177 	glw::GLint			maxAttrs	= -1;
178 	bool				allOk		= true;
179 
180 	gl.enableLogging(true);
181 
182 	gl.glBindVertexArray(*vao);
183 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrs);
184 
185 	// initial
186 	{
187 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
188 
189 		for (int attr = 0; attr < de::max(16, maxAttrs); ++attr)
190 		{
191 			glw::GLint relOffsetState = -1;
192 
193 			gl.glGetVertexAttribiv(attr, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
194 			error = gl.glGetError();
195 
196 			if (error != GL_NO_ERROR)
197 			{
198 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
199 				allOk = false;
200 			}
201 			else if (relOffsetState != 0)
202 			{
203 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 0, got " << relOffsetState << tcu::TestLog::EndMessage;
204 				allOk = false;
205 			}
206 		}
207 	}
208 
209 	// is part of vao
210 	{
211 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
212 		glu::VertexArray			otherVao		(m_context.getRenderContext());
213 		glw::GLint					relOffsetState	= -1;
214 
215 		// set to value A in vao1
216 		gl.glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 9);
217 
218 		// set to value B in vao2
219 		gl.glBindVertexArray(*otherVao);
220 		gl.glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 21);
221 
222 		// check value is still ok in original vao
223 		gl.glBindVertexArray(*vao);
224 		gl.glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
225 		error = gl.glGetError();
226 
227 		if (error != GL_NO_ERROR)
228 		{
229 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
230 			allOk = false;
231 		}
232 		else if (relOffsetState != 9)
233 		{
234 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 9, got " << relOffsetState << tcu::TestLog::EndMessage;
235 			allOk = false;
236 		}
237 	}
238 
239 	// random values
240 	{
241 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
242 		de::Random					rnd				(0xabc);
243 		const int					numRandomTests	= 10;
244 
245 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
246 		{
247 			const int	va				= rnd.getInt(0, de::max(16, maxAttrs)-1);
248 			const int	offset			= rnd.getInt(0, 2047);
249 			glw::GLint	relOffsetState	= -1;
250 
251 			gl.glVertexAttribFormat(va, 4, GL_FLOAT, GL_FALSE, offset);
252 			gl.glGetVertexAttribiv(va, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
253 			error = gl.glGetError();
254 
255 			if (error != GL_NO_ERROR)
256 			{
257 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
258 				allOk = false;
259 			}
260 			else if (relOffsetState != offset)
261 			{
262 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << offset << ", got " << relOffsetState << tcu::TestLog::EndMessage;
263 				allOk = false;
264 			}
265 		}
266 	}
267 
268 	if (allOk)
269 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
270 	else
271 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
272 	return STOP;
273 }
274 
275 class IndexedCase : public TestCase
276 {
277 public:
278 	enum VerifierType
279 	{
280 		VERIFIER_INT,
281 		VERIFIER_INT64,
282 
283 		VERIFIER_LAST
284 	};
285 
286 						IndexedCase			(Context& context, const char* name, const char* desc, VerifierType verifier);
287 
288 	IterateResult		iterate				(void);
289 	void				verifyValue			(glu::CallLogWrapper& gl, glw::GLenum name, int index, int expected);
290 
291 	virtual void		test				(void) = 0;
292 private:
293 	const VerifierType	m_verifier;
294 };
295 
IndexedCase(Context & context,const char * name,const char * desc,VerifierType verifier)296 IndexedCase::IndexedCase (Context& context, const char* name, const char* desc, VerifierType verifier)
297 	: TestCase		(context, name, desc)
298 	, m_verifier	(verifier)
299 {
300 	DE_ASSERT(verifier < VERIFIER_LAST);
301 }
302 
iterate(void)303 IndexedCase::IterateResult IndexedCase::iterate (void)
304 {
305 	// default value
306 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
307 
308 	test();
309 
310 	return STOP;
311 }
312 
verifyValue(glu::CallLogWrapper & gl,glw::GLenum name,int index,int expected)313 void IndexedCase::verifyValue (glu::CallLogWrapper& gl, glw::GLenum name, int index, int expected)
314 {
315 	if (m_verifier == VERIFIER_INT)
316 	{
317 		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>	value;
318 		glw::GLenum													error = 0;
319 
320 		gl.glGetIntegeri_v(name, index, &value);
321 		error = gl.glGetError();
322 
323 		if (error != GL_NO_ERROR)
324 		{
325 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got unexpected error: " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
326 			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
327 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error");
328 		}
329 		else if (!value.verifyValidity(m_testCtx))
330 		{
331 			// verifyValidity sets error
332 		}
333 		else
334 		{
335 			if (value != expected)
336 			{
337 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << expected << ", got " << value << tcu::TestLog::EndMessage;
338 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
339 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
340 			}
341 		}
342 	}
343 	else if (m_verifier == VERIFIER_INT64)
344 	{
345 		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64>	value;
346 		glw::GLenum														error = 0;
347 
348 		gl.glGetInteger64i_v(name, index, &value);
349 		error = gl.glGetError();
350 
351 		if (error != GL_NO_ERROR)
352 		{
353 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got unexpected error: " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
354 			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
355 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error");
356 		}
357 		else if (!value.verifyValidity(m_testCtx))
358 		{
359 			// verifyValidity sets error
360 		}
361 		else
362 		{
363 			if (value != expected)
364 			{
365 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << expected << ", got " << value << tcu::TestLog::EndMessage;
366 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
367 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
368 			}
369 		}
370 	}
371 	else
372 		DE_ASSERT(false);
373 }
374 
375 class VertexBindingDivisorCase : public IndexedCase
376 {
377 public:
378 			VertexBindingDivisorCase	(Context& context, const char* name, const char* desc, VerifierType verifier);
379 	void	test						(void);
380 };
381 
VertexBindingDivisorCase(Context & context,const char * name,const char * desc,VerifierType verifier)382 VertexBindingDivisorCase::VertexBindingDivisorCase (Context& context, const char* name, const char* desc, VerifierType verifier)
383 	: IndexedCase(context, name, desc, verifier)
384 {
385 }
386 
test(void)387 void VertexBindingDivisorCase::test (void)
388 {
389 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
390 	glu::VertexArray	vao					(m_context.getRenderContext());
391 	glw::GLint			reportedMaxBindings	= -1;
392 	glw::GLint			maxBindings;
393 
394 	gl.enableLogging(true);
395 
396 	gl.glBindVertexArray(*vao);
397 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
398 	maxBindings = de::max(16, reportedMaxBindings);
399 
400 	// initial
401 	{
402 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
403 
404 		for (int binding = 0; binding < maxBindings; ++binding)
405 			verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, binding, 0);
406 	}
407 
408 	// is part of vao
409 	{
410 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
411 		glu::VertexArray			otherVao		(m_context.getRenderContext());
412 
413 		// set to value A in vao1
414 		gl.glVertexBindingDivisor(1, 4);
415 
416 		// set to value B in vao2
417 		gl.glBindVertexArray(*otherVao);
418 		gl.glVertexBindingDivisor(1, 9);
419 
420 		// check value is still ok in original vao
421 		gl.glBindVertexArray(*vao);
422 		verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, 1, 4);
423 	}
424 
425 	// random values
426 	{
427 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
428 		de::Random					rnd				(0xabc);
429 		const int					numRandomTests	= 10;
430 
431 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
432 		{
433 			const int	binding			= rnd.getInt(0, maxBindings-1);
434 			const int	divisor			= rnd.getInt(0, 2047);
435 
436 			gl.glVertexBindingDivisor(binding, divisor);
437 			verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, binding, divisor);
438 		}
439 	}
440 }
441 
442 class VertexBindingOffsetCase : public IndexedCase
443 {
444 public:
445 			VertexBindingOffsetCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
446 	void	test						(void);
447 };
448 
VertexBindingOffsetCase(Context & context,const char * name,const char * desc,VerifierType verifier)449 VertexBindingOffsetCase::VertexBindingOffsetCase (Context& context, const char* name, const char* desc, VerifierType verifier)
450 	: IndexedCase(context, name, desc, verifier)
451 {
452 }
453 
test(void)454 void VertexBindingOffsetCase::test (void)
455 {
456 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
457 	glu::VertexArray	vao					(m_context.getRenderContext());
458 	glu::Buffer			buffer				(m_context.getRenderContext());
459 	glw::GLint			reportedMaxBindings	= -1;
460 	glw::GLint			maxBindings;
461 
462 	gl.enableLogging(true);
463 
464 	gl.glBindVertexArray(*vao);
465 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
466 	maxBindings = de::max(16, reportedMaxBindings);
467 
468 	// initial
469 	{
470 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
471 
472 		for (int binding = 0; binding < maxBindings; ++binding)
473 			verifyValue(gl, GL_VERTEX_BINDING_OFFSET, binding, 0);
474 	}
475 
476 	// is part of vao
477 	{
478 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
479 		glu::VertexArray			otherVao		(m_context.getRenderContext());
480 
481 		// set to value A in vao1
482 		gl.glBindVertexBuffer(1, *buffer, 4, 32);
483 
484 		// set to value B in vao2
485 		gl.glBindVertexArray(*otherVao);
486 		gl.glBindVertexBuffer(1, *buffer, 13, 32);
487 
488 		// check value is still ok in original vao
489 		gl.glBindVertexArray(*vao);
490 		verifyValue(gl, GL_VERTEX_BINDING_OFFSET, 1, 4);
491 	}
492 
493 	// random values
494 	{
495 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
496 		de::Random					rnd				(0xabc);
497 		const int					numRandomTests	= 10;
498 
499 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
500 		{
501 			const int	binding			= rnd.getInt(0, maxBindings-1);
502 			const int	offset			= rnd.getInt(0, 4000);
503 
504 			gl.glBindVertexBuffer(binding, *buffer, offset, 32);
505 			verifyValue(gl, GL_VERTEX_BINDING_OFFSET, binding, offset);
506 		}
507 	}
508 }
509 
510 class VertexBindingStrideCase : public IndexedCase
511 {
512 public:
513 			VertexBindingStrideCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
514 	void	test						(void);
515 };
516 
VertexBindingStrideCase(Context & context,const char * name,const char * desc,VerifierType verifier)517 VertexBindingStrideCase::VertexBindingStrideCase (Context& context, const char* name, const char* desc, VerifierType verifier)
518 	: IndexedCase(context, name, desc, verifier)
519 {
520 }
521 
test(void)522 void VertexBindingStrideCase::test (void)
523 {
524 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
525 	glu::VertexArray	vao					(m_context.getRenderContext());
526 	glu::Buffer			buffer				(m_context.getRenderContext());
527 	glw::GLint			reportedMaxBindings	= -1;
528 	glw::GLint			maxBindings;
529 
530 	gl.enableLogging(true);
531 
532 	gl.glBindVertexArray(*vao);
533 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
534 	maxBindings = de::max(16, reportedMaxBindings);
535 
536 	// initial
537 	{
538 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
539 
540 		for (int binding = 0; binding < maxBindings; ++binding)
541 			verifyValue(gl, GL_VERTEX_BINDING_STRIDE, binding, 16);
542 	}
543 
544 	// is part of vao
545 	{
546 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
547 		glu::VertexArray			otherVao		(m_context.getRenderContext());
548 
549 		// set to value A in vao1
550 		gl.glBindVertexBuffer(1, *buffer, 0, 32);
551 
552 		// set to value B in vao2
553 		gl.glBindVertexArray(*otherVao);
554 		gl.glBindVertexBuffer(1, *buffer, 0, 64);
555 
556 		// check value is still ok in original vao
557 		gl.glBindVertexArray(*vao);
558 		verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 32);
559 	}
560 
561 	// random values
562 	{
563 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
564 		de::Random					rnd				(0xabc);
565 		const int					numRandomTests	= 10;
566 
567 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
568 		{
569 			const int	binding			= rnd.getInt(0, maxBindings-1);
570 			const int	stride			= rnd.getInt(0, 2048);
571 
572 			gl.glBindVertexBuffer(binding, *buffer, 0, stride);
573 			verifyValue(gl, GL_VERTEX_BINDING_STRIDE, binding, stride);
574 		}
575 	}
576 }
577 
578 class VertexBindingBufferCase : public IndexedCase
579 {
580 public:
581 			VertexBindingBufferCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
582 	void	test						(void);
583 };
584 
VertexBindingBufferCase(Context & context,const char * name,const char * desc,VerifierType verifier)585 VertexBindingBufferCase::VertexBindingBufferCase (Context& context, const char* name, const char* desc, VerifierType verifier)
586 	: IndexedCase(context, name, desc, verifier)
587 {
588 }
589 
test(void)590 void VertexBindingBufferCase::test (void)
591 {
592 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
593 	glu::VertexArray	vao					(m_context.getRenderContext());
594 	glu::Buffer			buffer				(m_context.getRenderContext());
595 	glw::GLint			reportedMaxBindings	= -1;
596 	glw::GLint			maxBindings;
597 
598 	gl.enableLogging(true);
599 
600 	gl.glBindVertexArray(*vao);
601 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
602 	maxBindings = de::max(16, reportedMaxBindings);
603 
604 	// initial
605 	{
606 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
607 
608 		for (int binding = 0; binding < maxBindings; ++binding)
609 			verifyValue(gl, GL_VERTEX_BINDING_BUFFER, binding, 0);
610 	}
611 
612 	// is part of vao
613 	{
614 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
615 		glu::VertexArray			otherVao		(m_context.getRenderContext());
616 		glu::Buffer					otherBuffer		(m_context.getRenderContext());
617 
618 		// set to value A in vao1
619 		gl.glBindVertexBuffer(1, *buffer, 0, 32);
620 
621 		// set to value B in vao2
622 		gl.glBindVertexArray(*otherVao);
623 		gl.glBindVertexBuffer(1, *otherBuffer, 0, 32);
624 
625 		// check value is still ok in original vao
626 		gl.glBindVertexArray(*vao);
627 		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer);
628 	}
629 
630 	// Is detached in delete from active vao and not from deactive
631 	{
632 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "autoUnbind", "Unbind on delete");
633 		glu::VertexArray			otherVao		(m_context.getRenderContext());
634 		glw::GLuint					otherBuffer		= -1;
635 
636 		gl.glGenBuffers(1, &otherBuffer);
637 
638 		// set in vao1 and vao2
639 		gl.glBindVertexBuffer(1, otherBuffer, 0, 32);
640 		gl.glBindVertexArray(*otherVao);
641 		gl.glBindVertexBuffer(1, otherBuffer, 0, 32);
642 
643 		// delete buffer. This unbinds it from active (vao2) but not from unactive
644 		gl.glDeleteBuffers(1, &otherBuffer);
645 		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, 0);
646 		gl.glBindVertexArray(*vao);
647 		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, otherBuffer);
648 	}
649 }
650 
651 class MixedVertexBindingDivisorCase : public IndexedCase
652 {
653 public:
654 			MixedVertexBindingDivisorCase	(Context& context, const char* name, const char* desc);
655 	void	test							(void);
656 };
657 
MixedVertexBindingDivisorCase(Context & context,const char * name,const char * desc)658 MixedVertexBindingDivisorCase::MixedVertexBindingDivisorCase (Context& context, const char* name, const char* desc)
659 	: IndexedCase(context, name, desc, VERIFIER_INT)
660 {
661 }
662 
test(void)663 void MixedVertexBindingDivisorCase::test (void)
664 {
665 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
666 	glu::VertexArray	vao					(m_context.getRenderContext());
667 
668 	gl.enableLogging(true);
669 
670 	gl.glVertexAttribDivisor(1, 4);
671 	verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, 1, 4);
672 }
673 
674 class MixedVertexBindingOffsetCase : public IndexedCase
675 {
676 public:
677 			MixedVertexBindingOffsetCase	(Context& context, const char* name, const char* desc);
678 	void	test							(void);
679 };
680 
MixedVertexBindingOffsetCase(Context & context,const char * name,const char * desc)681 MixedVertexBindingOffsetCase::MixedVertexBindingOffsetCase (Context& context, const char* name, const char* desc)
682 	: IndexedCase(context, name, desc, VERIFIER_INT)
683 {
684 }
685 
test(void)686 void MixedVertexBindingOffsetCase::test (void)
687 {
688 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
689 	glu::VertexArray	vao					(m_context.getRenderContext());
690 	glu::Buffer			buffer				(m_context.getRenderContext());
691 
692 	gl.enableLogging(true);
693 
694 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
695 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (const deUint8*)DE_NULL + 12);
696 
697 	verifyValue(gl, GL_VERTEX_BINDING_OFFSET, 1, 12);
698 }
699 
700 class MixedVertexBindingStrideCase : public IndexedCase
701 {
702 public:
703 			MixedVertexBindingStrideCase	(Context& context, const char* name, const char* desc);
704 	void	test							(void);
705 };
706 
MixedVertexBindingStrideCase(Context & context,const char * name,const char * desc)707 MixedVertexBindingStrideCase::MixedVertexBindingStrideCase (Context& context, const char* name, const char* desc)
708 	: IndexedCase(context, name, desc, VERIFIER_INT)
709 {
710 }
711 
test(void)712 void MixedVertexBindingStrideCase::test (void)
713 {
714 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
715 	glu::VertexArray	vao					(m_context.getRenderContext());
716 	glu::Buffer			buffer				(m_context.getRenderContext());
717 
718 	gl.enableLogging(true);
719 
720 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
721 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 12, 0);
722 	verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 12);
723 
724 	// test effectiveStride
725 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
726 	verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 16);
727 }
728 
729 class MixedVertexBindingBufferCase : public IndexedCase
730 {
731 public:
732 			MixedVertexBindingBufferCase	(Context& context, const char* name, const char* desc);
733 	void	test							(void);
734 };
735 
MixedVertexBindingBufferCase(Context & context,const char * name,const char * desc)736 MixedVertexBindingBufferCase::MixedVertexBindingBufferCase (Context& context, const char* name, const char* desc)
737 	: IndexedCase(context, name, desc, VERIFIER_INT)
738 {
739 }
740 
test(void)741 void MixedVertexBindingBufferCase::test (void)
742 {
743 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
744 	glu::VertexArray	vao					(m_context.getRenderContext());
745 	glu::Buffer			buffer				(m_context.getRenderContext());
746 
747 	gl.enableLogging(true);
748 
749 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
750 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
751 	verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer);
752 }
753 
754 } // anonymous
755 
VertexAttributeBindingStateQueryTests(Context & context)756 VertexAttributeBindingStateQueryTests::VertexAttributeBindingStateQueryTests (Context& context)
757 	: TestCaseGroup(context, "vertex_attribute_binding", "Query vertex attribute binding state.")
758 {
759 }
760 
~VertexAttributeBindingStateQueryTests(void)761 VertexAttributeBindingStateQueryTests::~VertexAttributeBindingStateQueryTests (void)
762 {
763 }
764 
init(void)765 void VertexAttributeBindingStateQueryTests::init (void)
766 {
767 	tcu::TestCaseGroup* const attributeGroup	= new TestCaseGroup(m_context, "vertex_attrib", "Vertex attribute state");
768 	tcu::TestCaseGroup* const indexedGroup		= new TestCaseGroup(m_context, "indexed", "Indexed state");
769 
770 	addChild(attributeGroup);
771 	addChild(indexedGroup);
772 
773 	// .vertex_attrib
774 	{
775 		attributeGroup->addChild(new AttributeBindingCase		(m_context,	"vertex_attrib_binding",			"Test VERTEX_ATTRIB_BINDING"));
776 		attributeGroup->addChild(new AttributeRelativeOffsetCase(m_context,	"vertex_attrib_relative_offset",	"Test VERTEX_ATTRIB_RELATIVE_OFFSET"));
777 	}
778 
779 	// .indexed (and 64)
780 	{
781 		static const struct Verifier
782 		{
783 			const char*					name;
784 			IndexedCase::VerifierType	type;
785 		} verifiers[] =
786 		{
787 			{ "getintegeri",	IndexedCase::VERIFIER_INT	},
788 			{ "getintegeri64",	IndexedCase::VERIFIER_INT64	},
789 		};
790 
791 		// states
792 
793 		for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)
794 		{
795 			indexedGroup->addChild(new VertexBindingDivisorCase	(m_context, (std::string("vertex_binding_divisor_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_DIVISOR",	verifiers[verifierNdx].type));
796 			indexedGroup->addChild(new VertexBindingOffsetCase	(m_context, (std::string("vertex_binding_offset_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_OFFSET",	verifiers[verifierNdx].type));
797 			indexedGroup->addChild(new VertexBindingStrideCase	(m_context, (std::string("vertex_binding_stride_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_STRIDE",	verifiers[verifierNdx].type));
798 			indexedGroup->addChild(new VertexBindingBufferCase	(m_context, (std::string("vertex_binding_buffer_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_BUFFER",	verifiers[verifierNdx].type));
799 		}
800 
801 		// mixed apis
802 
803 		indexedGroup->addChild(new MixedVertexBindingDivisorCase(m_context, "vertex_binding_divisor_mixed",	"Test VERTEX_BINDING_DIVISOR"));
804 		indexedGroup->addChild(new MixedVertexBindingOffsetCase	(m_context, "vertex_binding_offset_mixed",	"Test VERTEX_BINDING_OFFSET"));
805 		indexedGroup->addChild(new MixedVertexBindingStrideCase	(m_context, "vertex_binding_stride_mixed",	"Test VERTEX_BINDING_STRIDE"));
806 		indexedGroup->addChild(new MixedVertexBindingBufferCase	(m_context, "vertex_binding_buffer_mixed",	"Test VERTEX_BINDING_BUFFER"));
807 	}
808 }
809 
810 } // Functional
811 } // gles31
812 } // deqp
813