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
35namespace deqp
36{
37namespace gles31
38{
39namespace Functional
40{
41namespace
42{
43
44class AttributeBindingCase : public TestCase
45{
46public:
47					AttributeBindingCase	(Context& context, const char* name, const char* desc);
48	IterateResult	iterate					(void);
49};
50
51AttributeBindingCase::AttributeBindingCase (Context& context, const char* name, const char* desc)
52	: TestCase(context, name, desc)
53{
54}
55
56AttributeBindingCase::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
160class AttributeRelativeOffsetCase : public TestCase
161{
162public:
163					AttributeRelativeOffsetCase	(Context& context, const char* name, const char* desc);
164	IterateResult	iterate						(void);
165};
166
167AttributeRelativeOffsetCase::AttributeRelativeOffsetCase (Context& context, const char* name, const char* desc)
168	: TestCase(context, name, desc)
169{
170}
171
172AttributeRelativeOffsetCase::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
275class IndexedCase : public TestCase
276{
277public:
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;
292private:
293	const VerifierType	m_verifier;
294};
295
296IndexedCase::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
303IndexedCase::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
313void 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
375class VertexBindingDivisorCase : public IndexedCase
376{
377public:
378			VertexBindingDivisorCase	(Context& context, const char* name, const char* desc, VerifierType verifier);
379	void	test						(void);
380};
381
382VertexBindingDivisorCase::VertexBindingDivisorCase (Context& context, const char* name, const char* desc, VerifierType verifier)
383	: IndexedCase(context, name, desc, verifier)
384{
385}
386
387void 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
442class VertexBindingOffsetCase : public IndexedCase
443{
444public:
445			VertexBindingOffsetCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
446	void	test						(void);
447};
448
449VertexBindingOffsetCase::VertexBindingOffsetCase (Context& context, const char* name, const char* desc, VerifierType verifier)
450	: IndexedCase(context, name, desc, verifier)
451{
452}
453
454void 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
510class VertexBindingStrideCase : public IndexedCase
511{
512public:
513			VertexBindingStrideCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
514	void	test						(void);
515};
516
517VertexBindingStrideCase::VertexBindingStrideCase (Context& context, const char* name, const char* desc, VerifierType verifier)
518	: IndexedCase(context, name, desc, verifier)
519{
520}
521
522void 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
578class VertexBindingBufferCase : public IndexedCase
579{
580public:
581			VertexBindingBufferCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
582	void	test						(void);
583};
584
585VertexBindingBufferCase::VertexBindingBufferCase (Context& context, const char* name, const char* desc, VerifierType verifier)
586	: IndexedCase(context, name, desc, verifier)
587{
588}
589
590void 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
651class MixedVertexBindingDivisorCase : public IndexedCase
652{
653public:
654			MixedVertexBindingDivisorCase	(Context& context, const char* name, const char* desc);
655	void	test							(void);
656};
657
658MixedVertexBindingDivisorCase::MixedVertexBindingDivisorCase (Context& context, const char* name, const char* desc)
659	: IndexedCase(context, name, desc, VERIFIER_INT)
660{
661}
662
663void 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
674class MixedVertexBindingOffsetCase : public IndexedCase
675{
676public:
677			MixedVertexBindingOffsetCase	(Context& context, const char* name, const char* desc);
678	void	test							(void);
679};
680
681MixedVertexBindingOffsetCase::MixedVertexBindingOffsetCase (Context& context, const char* name, const char* desc)
682	: IndexedCase(context, name, desc, VERIFIER_INT)
683{
684}
685
686void 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
700class MixedVertexBindingStrideCase : public IndexedCase
701{
702public:
703			MixedVertexBindingStrideCase	(Context& context, const char* name, const char* desc);
704	void	test							(void);
705};
706
707MixedVertexBindingStrideCase::MixedVertexBindingStrideCase (Context& context, const char* name, const char* desc)
708	: IndexedCase(context, name, desc, VERIFIER_INT)
709{
710}
711
712void 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
729class MixedVertexBindingBufferCase : public IndexedCase
730{
731public:
732			MixedVertexBindingBufferCase	(Context& context, const char* name, const char* desc);
733	void	test							(void);
734};
735
736MixedVertexBindingBufferCase::MixedVertexBindingBufferCase (Context& context, const char* name, const char* desc)
737	: IndexedCase(context, name, desc, VERIFIER_INT)
738{
739}
740
741void 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
756VertexAttributeBindingStateQueryTests::VertexAttributeBindingStateQueryTests (Context& context)
757	: TestCaseGroup(context, "vertex_attribute_binding", "Query vertex attribute binding state.")
758{
759}
760
761VertexAttributeBindingStateQueryTests::~VertexAttributeBindingStateQueryTests (void)
762{
763}
764
765void 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