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