Merge "Use -Wno-date-time to allow __DATE__/__TIME__" am: bd1826b4a3 am: f4e3b26175
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fVertexArrayObjectTests.cpp
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 Vertex array object tests
22  *//*--------------------------------------------------------------------*/
23 #include "es3fVertexArrayObjectTests.hpp"
24
25 #include "gluShaderProgram.hpp"
26 #include "gluPixelTransfer.hpp"
27 #include "gluRenderContext.hpp"
28
29 #include "tcuTestLog.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuSurface.hpp"
32 #include "tcuRenderTarget.hpp"
33
34 #include "deRandom.hpp"
35 #include "deString.h"
36 #include "deMemory.h"
37
38 #include <vector>
39 #include <string>
40 #include <memory>
41
42 #include "glw.h"
43
44 using std::vector;
45 using std::string;
46
47 namespace deqp
48 {
49 namespace gles3
50 {
51 namespace Functional
52 {
53
54 namespace
55 {
56 struct Attribute
57 {
58                                 Attribute (void);
59         GLboolean       enabled;
60         GLint           size;
61         GLint           stride;
62         GLenum          type;
63         GLboolean       integer;
64         GLint           divisor;
65         GLint           offset;
66         GLboolean       normalized;
67
68         int                     bufferNdx;
69 };
70
71 struct VertexArrayState
72 {
73                                                 VertexArrayState        (void);
74
75         vector<Attribute>       attributes;
76         int                                     elementArrayBuffer;
77 };
78
79 VertexArrayState::VertexArrayState (void)
80         : elementArrayBuffer(-1)
81 {
82 }
83
84 Attribute::Attribute (void)
85         : enabled               (GL_FALSE)
86         , size                  (1)
87         , stride                (0)
88         , type                  (GL_FLOAT)
89         , integer               (GL_FALSE)
90         , divisor               (0)
91         , offset                (0)
92         , normalized    (GL_FALSE)
93         , bufferNdx             (0)
94 {
95 }
96
97 struct BufferSpec
98 {
99         int             count;
100         int             size;
101         int             componentCount;
102         int             stride;
103         int             offset;
104
105         GLenum  type;
106
107         int             intRangeMin;
108         int             intRangeMax;
109
110         float   floatRangeMin;
111         float   floatRangeMax;
112 };
113
114 struct Spec
115 {
116                                                 Spec    (void);
117
118         int                                     count;
119         int                                     instances;
120         bool                            useDrawElements;
121         GLenum                          indexType;
122         int                                     indexOffset;
123         int                                     indexRangeMin;
124         int                                     indexRangeMax;
125         int                                     indexCount;
126         VertexArrayState        state;
127         VertexArrayState        vao;
128         vector<BufferSpec>      buffers;
129 };
130
131 Spec::Spec (void)
132         : count                         (-1)
133         , instances                     (-1)
134         , useDrawElements       (false)
135         , indexType                     (GL_NONE)
136         , indexOffset           (-1)
137         , indexRangeMin         (-1)
138         , indexRangeMax         (-1)
139         , indexCount            (-1)
140 {
141 }
142
143 } // anonymous
144
145 class VertexArrayObjectTest : public TestCase
146 {
147 public:
148
149                                                         VertexArrayObjectTest   (Context& context, const Spec& spec, const char* name, const char* description);
150                                                         ~VertexArrayObjectTest  (void);
151         virtual void                    init                                    (void);
152         virtual void                    deinit                                  (void);
153         virtual IterateResult   iterate                                 (void);
154
155 private:
156         Spec                                    m_spec;
157         tcu::TestLog&                   m_log;
158         vector<GLuint>                  m_buffers;
159         glu::ShaderProgram*             m_vaoProgram;
160         glu::ShaderProgram*             m_stateProgram;
161         de::Random                              m_random;
162         deUint8*                                m_indices;
163
164         void                                    logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
165         deUint8*                                createRandomBufferData  (const BufferSpec& buffer);
166         deUint8*                                generateIndices                 (void);
167         glu::ShaderProgram*             createProgram                   (const VertexArrayState& state);
168         void                                    setState                                (const VertexArrayState& state);
169         void                                    render                                  (tcu::Surface& vaoResult, tcu::Surface& defaultResult);
170         void                                    makeDrawCall                    (const VertexArrayState& state);
171         void                                    genReferences                   (tcu::Surface& vaoRef, tcu::Surface& defaultRef);
172
173                                                         VertexArrayObjectTest   (const VertexArrayObjectTest&);
174         VertexArrayObjectTest&  operator=                               (const VertexArrayObjectTest&);
175 };
176
177 VertexArrayObjectTest::VertexArrayObjectTest (Context& context, const Spec& spec, const char* name, const char* description)
178         : TestCase                      (context, name, description)
179         , m_spec                        (spec)
180         , m_log                         (context.getTestContext().getLog())
181         , m_vaoProgram          (NULL)
182         , m_stateProgram        (NULL)
183         , m_random                      (deStringHash(name))
184         , m_indices                     (NULL)
185 {
186         // Makes zero to zero mapping for buffers
187         m_buffers.push_back(0);
188 }
189
190 VertexArrayObjectTest::~VertexArrayObjectTest (void)
191 {
192 }
193
194 void VertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
195 {
196         std::stringstream message;
197
198         message << msg << "\n";
199         message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
200
201         for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
202         {
203                 message
204                 << "attribute : " << attribNdx << "\n"
205                 << "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") <<  "\n"
206                 << "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size <<  "\n"
207                 << "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride <<  "\n"
208                 << "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type <<  "\n"
209                 << "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") <<  "\n"
210                 << "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") <<  "\n"
211                 << "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor <<  "\n"
212                 << "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset <<  "\n"
213                 << "\tGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] <<  "\n";
214         }
215         log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
216 }
217
218
219 void VertexArrayObjectTest::init (void)
220 {
221         // \note [mika] Index 0 is reserved for 0 buffer
222         for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
223         {
224                 deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
225
226                 try
227                 {
228                         GLuint buffer;
229                         GLU_CHECK_CALL(glGenBuffers(1, &buffer));
230                         m_buffers.push_back(buffer);
231
232                         GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
233                         GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
234                         GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
235
236                 } catch (...) {
237                         delete[] data;
238                         throw;
239                 }
240
241                 delete[] data;
242         }
243
244         m_vaoProgram    = createProgram(m_spec.vao);
245         m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
246         m_log << *m_vaoProgram;
247         m_stateProgram  = createProgram(m_spec.state);
248         m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
249         m_log << *m_stateProgram;
250
251         if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
252                 TCU_FAIL("Failed to compile shaders");
253
254         if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
255                 m_indices = generateIndices();
256 }
257
258 void VertexArrayObjectTest::deinit (void)
259 {
260         GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
261         m_buffers.clear();
262         delete m_vaoProgram;
263         delete m_stateProgram;
264         delete[] m_indices;
265 }
266
267 deUint8* VertexArrayObjectTest::generateIndices (void)
268 {
269         int typeSize = 0;
270         switch (m_spec.indexType)
271         {
272                 case GL_UNSIGNED_INT:   typeSize = sizeof(GLuint);              break;
273                 case GL_UNSIGNED_SHORT: typeSize = sizeof(GLushort);    break;
274                 case GL_UNSIGNED_BYTE:  typeSize = sizeof(GLubyte);             break;
275                 default:
276                         DE_ASSERT(false);
277         }
278
279         deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
280
281         for (int i = 0; i < m_spec.indexCount; i++)
282         {
283                 deUint8* pos = indices + typeSize * i;
284
285                 switch (m_spec.indexType)
286                 {
287                         case GL_UNSIGNED_INT:
288                         {
289                                 GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
290                                 deMemcpy(pos, &v, sizeof(v));
291                                 break;
292                         }
293
294                         case GL_UNSIGNED_SHORT:
295                         {
296                                 GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
297                                 deMemcpy(pos, &v, sizeof(v));
298                                 break;
299                         }
300
301                         case GL_UNSIGNED_BYTE:
302                         {
303                                 GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
304                                 deMemcpy(pos, &v, sizeof(v));
305                                 break;
306                         }
307
308                         default:
309                                 DE_ASSERT(false);
310                 }
311         }
312
313         return indices;
314 }
315
316 deUint8* VertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
317 {
318         deUint8* data = new deUint8[buffer.size];
319
320         int stride;
321
322         if (buffer.stride != 0)
323         {
324                 stride = buffer.stride;
325         }
326         else
327         {
328                 switch (buffer.type)
329                 {
330                         case GL_FLOAT:                  stride = buffer.componentCount * (int)sizeof(GLfloat);  break;
331                         case GL_INT:                    stride = buffer.componentCount * (int)sizeof(GLint);    break;
332                         case GL_UNSIGNED_INT:   stride = buffer.componentCount * (int)sizeof(GLuint);   break;
333                         case GL_SHORT:                  stride = buffer.componentCount * (int)sizeof(GLshort);  break;
334                         case GL_UNSIGNED_SHORT: stride = buffer.componentCount * (int)sizeof(GLushort); break;
335                         case GL_BYTE:                   stride = buffer.componentCount * (int)sizeof(GLbyte);   break;
336                         case GL_UNSIGNED_BYTE:  stride = buffer.componentCount * (int)sizeof(GLubyte);  break;
337
338                         default:
339                                 stride = 0;
340                                 DE_ASSERT(DE_FALSE);
341                 }
342         }
343
344         deUint8* itr = data;
345
346         for (int pos = 0; pos < buffer.count; pos++)
347         {
348                 deUint8* componentItr = itr;
349                 for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
350                 {
351                         switch (buffer.type)
352                         {
353                                 case GL_FLOAT:
354                                 {
355                                         float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
356                                         deMemcpy(componentItr, &v, sizeof(v));
357                                         componentItr += sizeof(v);
358                                         break;
359                                 }
360
361                                 case GL_INT:
362                                 {
363                                         GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
364                                         deMemcpy(componentItr, &v, sizeof(v));
365                                         componentItr += sizeof(v);
366                                         break;
367                                 }
368
369                                 case GL_UNSIGNED_INT:
370                                 {
371                                         GLuint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
372                                         deMemcpy(componentItr, &v, sizeof(v));
373                                         componentItr += sizeof(v);
374                                         break;
375                                 }
376
377                                 case GL_SHORT:
378                                 {
379                                         GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
380                                         deMemcpy(componentItr, &v, sizeof(v));
381                                         componentItr += sizeof(v);
382                                         break;
383                                 }
384
385                                 case GL_UNSIGNED_SHORT:
386                                 {
387                                         GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
388                                         deMemcpy(componentItr, &v, sizeof(v));
389                                         componentItr += sizeof(v);
390                                         break;
391                                 }
392
393                                 case GL_BYTE:
394                                 {
395                                         GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
396                                         deMemcpy(componentItr, &v, sizeof(v));
397                                         componentItr += sizeof(v);
398                                         break;
399                                 }
400
401                                 case GL_UNSIGNED_BYTE:
402                                 {
403                                         GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
404                                         deMemcpy(componentItr, &v, sizeof(v));
405                                         componentItr += sizeof(v);
406                                         break;
407                                 }
408
409                                 default:
410                                         DE_ASSERT(false);
411                         };
412                 }
413
414                 itr += stride;
415         }
416
417         return data;
418 }
419
420 glu::ShaderProgram* VertexArrayObjectTest::createProgram (const VertexArrayState& state)
421 {
422         std::stringstream vertexShaderStream;
423         std::stringstream value;
424
425         vertexShaderStream << "#version 300 es\n";
426
427         for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
428         {
429                 if (state.attributes[attribNdx].integer)
430                         vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
431                 else
432                         vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
433
434                 if (state.attributes[attribNdx].integer)
435                 {
436                         float scale = 0.0f;
437
438                         switch (state.attributes[0].type)
439                         {
440                                 case GL_SHORT:                  scale  = (1.0f/float((1u<<14)-1u));     break;
441                                 case GL_UNSIGNED_SHORT: scale  = (1.0f/float((1u<<15)-1u));     break;
442                                 case GL_INT:                    scale  = (1.0f/float((1u<<30)-1u));     break;
443                                 case GL_UNSIGNED_INT:   scale  = (1.0f/float((1u<<31)-1u));     break;
444                                 case GL_BYTE:                   scale  = (1.0f/float((1u<<6)-1u));      break;
445                                 case GL_UNSIGNED_BYTE:  scale  = (1.0f/float((1u<<7)-1u));      break;
446
447                                 default:
448                                         DE_ASSERT(DE_FALSE);
449                         }
450                         value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
451                 }
452                 else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
453                 {
454                         float scale = 0.0f;
455
456                         switch (state.attributes[0].type)
457                         {
458                                 case GL_SHORT:                  scale  = (0.5f/float((1u<<14)-1u));     break;
459                                 case GL_UNSIGNED_SHORT: scale  = (0.5f/float((1u<<15)-1u));     break;
460                                 case GL_INT:                    scale  = (0.5f/float((1u<<30)-1u));     break;
461                                 case GL_UNSIGNED_INT:   scale  = (0.5f/float((1u<<31)-1u));     break;
462                                 case GL_BYTE:                   scale  = (0.5f/float((1u<<6)-1u));      break;
463                                 case GL_UNSIGNED_BYTE:  scale  = (0.5f/float((1u<<7)-1u));      break;
464
465                                 default:
466                                         DE_ASSERT(DE_FALSE);
467                         }
468                         value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
469                 }
470                 else
471                         value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
472         }
473
474         vertexShaderStream
475                 << "out mediump vec4 v_value;\n"
476                 << "void main (void)\n"
477                 << "{\n"
478                 << "\tv_value = " << value.str() << ";\n";
479
480         if (state.attributes[0].integer)
481         {
482                 float scale = 0.0f;
483
484                 switch (state.attributes[0].type)
485                 {
486                         case GL_SHORT:                  scale  = (1.0f/float((1u<<14)-1u));     break;
487                         case GL_UNSIGNED_SHORT: scale  = (1.0f/float((1u<<15)-1u));     break;
488                         case GL_INT:                    scale  = (1.0f/float((1u<<30)-1u));     break;
489                         case GL_UNSIGNED_INT:   scale  = (1.0f/float((1u<<31)-1u));     break;
490                         case GL_BYTE:                   scale  = (1.0f/float((1u<<6)-1u));      break;
491                         case GL_UNSIGNED_BYTE:  scale  = (1.0f/float((1u<<7)-1u));      break;
492
493                         default:
494                                 DE_ASSERT(DE_FALSE);
495                 }
496
497                 vertexShaderStream
498                         << "\tgl_Position = vec4(" << scale << " * " <<  "vec3(a_attrib0.xyz), 1.0);\n"
499                         << "}";
500         }
501         else
502         {
503                 if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
504                 {
505                         vertexShaderStream
506                                 << "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
507                                 << "}";
508                 }
509                 else
510                 {
511                         float scale = 0.0f;
512
513                         switch (state.attributes[0].type)
514                         {
515                                 case GL_SHORT:                  scale  = (1.0f/float((1u<<14)-1u));     break;
516                                 case GL_UNSIGNED_SHORT: scale  = (1.0f/float((1u<<15)-1u));     break;
517                                 case GL_INT:                    scale  = (1.0f/float((1u<<30)-1u));     break;
518                                 case GL_UNSIGNED_INT:   scale  = (1.0f/float((1u<<31)-1u));     break;
519                                 case GL_BYTE:                   scale  = (1.0f/float((1u<<6)-1u));      break;
520                                 case GL_UNSIGNED_BYTE:  scale  = (1.0f/float((1u<<7)-1u));      break;
521
522                                 default:
523                                         DE_ASSERT(DE_FALSE);
524                         }
525
526                         scale *= 0.5f;
527
528                         vertexShaderStream
529                                 << "\tgl_Position = vec4(" << scale << " * " <<  "a_attrib0.xyz, 1.0);\n"
530                                 << "}";
531                 }
532         }
533
534         const char* fragmentShader =
535         "#version 300 es\n"
536         "in mediump vec4 v_value;\n"
537         "layout(location = 0) out mediump vec4 fragColor;\n"
538         "void main (void)\n"
539         "{\n"
540         "\tfragColor = vec4(v_value.xyz, 1.0);\n"
541         "}";
542
543         return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
544 }
545
546 void VertexArrayObjectTest::setState (const VertexArrayState& state)
547 {
548         GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
549
550         for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
551         {
552                 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
553                 if (state.attributes[attribNdx].enabled)
554                         GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
555                 else
556                         GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
557
558                 if (state.attributes[attribNdx].integer)
559                         GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
560                 else
561                         GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
562
563                 GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
564         }
565 }
566
567 void VertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
568 {
569         GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
570         GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
571
572         if (m_spec.useDrawElements)
573         {
574                 if (state.elementArrayBuffer == 0)
575                 {
576                         if (m_spec.instances == 0)
577                                 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
578                         else
579                                 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
580                 }
581                 else
582                 {
583                         if (m_spec.instances == 0)
584                                 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
585                         else
586                                 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
587                 }
588         }
589         else
590         {
591                 if (m_spec.instances == 0)
592                         GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
593                 else
594                         GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
595         }
596 }
597
598 void VertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
599 {
600         GLuint vao = 0;
601
602         GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
603         GLU_CHECK_CALL(glBindVertexArray(vao));
604         setState(m_spec.vao);
605         GLU_CHECK_CALL(glBindVertexArray(0));
606
607         setState(m_spec.state);
608
609         GLU_CHECK_CALL(glBindVertexArray(vao));
610         GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
611         makeDrawCall(m_spec.vao);
612         glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
613         setState(m_spec.vao);
614         GLU_CHECK_CALL(glBindVertexArray(0));
615
616         GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
617         makeDrawCall(m_spec.state);
618         glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
619 }
620
621 void VertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
622 {
623         setState(m_spec.vao);
624         GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
625         makeDrawCall(m_spec.vao);
626         glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
627
628         setState(m_spec.state);
629         GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
630         makeDrawCall(m_spec.state);
631         glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
632 }
633
634 TestCase::IterateResult VertexArrayObjectTest::iterate (void)
635 {
636         tcu::Surface    vaoReference    (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
637         tcu::Surface    stateReference  (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
638
639         tcu::Surface    vaoResult               (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
640         tcu::Surface    stateResult             (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
641
642         bool                    isOk;
643
644         logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
645         logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
646         genReferences(stateReference, vaoReference);
647         render(stateResult, vaoResult);
648
649         isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
650         isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
651
652         if (isOk)
653         {
654                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
655                 return STOP;
656         }
657         else
658         {
659                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
660                 return STOP;
661         }
662 }
663
664 class MultiVertexArrayObjectTest : public TestCase
665 {
666 public:
667
668                                                         MultiVertexArrayObjectTest      (Context& context, const char* name, const char* description);
669                                                         ~MultiVertexArrayObjectTest     (void);
670         virtual void                    init                                            (void);
671         virtual void                    deinit                                          (void);
672         virtual IterateResult   iterate                                         (void);
673
674 private:
675         Spec                                    m_spec;
676         tcu::TestLog&                   m_log;
677         vector<GLuint>                  m_buffers;
678         glu::ShaderProgram*             m_vaoProgram;
679         glu::ShaderProgram*             m_stateProgram;
680         de::Random                              m_random;
681         deUint8*                                m_indices;
682
683         void                                    logVertexArrayState                     (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
684         deUint8*                                createRandomBufferData          (const BufferSpec& buffer);
685         deUint8*                                generateIndices                         (void);
686         glu::ShaderProgram*             createProgram                           (const VertexArrayState& state);
687         void                                    setState                                        (const VertexArrayState& state);
688         void                                    render                                          (tcu::Surface& vaoResult, tcu::Surface& defaultResult);
689         void                                    makeDrawCall                            (const VertexArrayState& state);
690         void                                    genReferences                           (tcu::Surface& vaoRef, tcu::Surface& defaultRef);
691
692                                                         MultiVertexArrayObjectTest      (const MultiVertexArrayObjectTest&);
693         MultiVertexArrayObjectTest&     operator=                               (const MultiVertexArrayObjectTest&);
694 };
695
696 MultiVertexArrayObjectTest::MultiVertexArrayObjectTest (Context& context, const char* name, const char* description)
697         : TestCase                      (context, name, description)
698         , m_log                         (context.getTestContext().getLog())
699         , m_vaoProgram          (NULL)
700         , m_stateProgram        (NULL)
701         , m_random                      (deStringHash(name))
702         , m_indices                     (NULL)
703 {
704         // Makes zero to zero mapping for buffers
705         m_buffers.push_back(0);
706 }
707
708 MultiVertexArrayObjectTest::~MultiVertexArrayObjectTest (void)
709 {
710 }
711
712 void MultiVertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
713 {
714         std::stringstream message;
715
716         message << msg << "\n";
717         message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
718
719         for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
720         {
721                 message
722                 << "attribute : " << attribNdx << "\n"
723                 << "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") <<  "\n"
724                 << "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size <<  "\n"
725                 << "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride <<  "\n"
726                 << "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type <<  "\n"
727                 << "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") <<  "\n"
728                 << "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") <<  "\n"
729                 << "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor <<  "\n"
730                 << "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset <<  "\n"
731                 << "\t GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] <<  "\n";
732         }
733         log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
734 }
735
736
737 void MultiVertexArrayObjectTest::init (void)
738 {
739         GLint attribCount;
740
741         GLU_CHECK_CALL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribCount));
742
743         m_spec.useDrawElements                  = false;
744         m_spec.instances                                = 0;
745         m_spec.count                                    = 24;
746         m_spec.indexOffset                              = 0;
747         m_spec.indexRangeMin                    = 0;
748         m_spec.indexRangeMax                    = 0;
749         m_spec.indexType                                = GL_NONE;
750         m_spec.indexCount                               = 0;
751         m_spec.vao.elementArrayBuffer   = 0;
752         m_spec.state.elementArrayBuffer = 0;
753
754         for (int attribNdx = 0; attribNdx < attribCount; attribNdx++)
755         {
756                 BufferSpec shortCoordBuffer48 = { 48, 2*384, 4, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
757                 m_spec.buffers.push_back(shortCoordBuffer48);
758
759                 m_spec.state.attributes.push_back(Attribute());
760                 m_spec.state.attributes[attribNdx].enabled              = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
761                 m_spec.state.attributes[attribNdx].size                 = m_random.getInt(2,4);
762                 m_spec.state.attributes[attribNdx].stride               = 2*m_random.getInt(1, 3);
763                 m_spec.state.attributes[attribNdx].type                 = GL_SHORT;
764                 m_spec.state.attributes[attribNdx].integer              = m_random.getBool();
765                 m_spec.state.attributes[attribNdx].divisor              = m_random.getInt(0, 1);
766                 m_spec.state.attributes[attribNdx].offset               = 2*m_random.getInt(0, 2);
767                 m_spec.state.attributes[attribNdx].normalized   = m_random.getBool();
768                 m_spec.state.attributes[attribNdx].bufferNdx    = attribNdx+1;
769
770                 if (attribNdx == 0)
771                 {
772                         m_spec.state.attributes[attribNdx].divisor      = 0;
773                         m_spec.state.attributes[attribNdx].enabled      = GL_TRUE;
774                         m_spec.state.attributes[attribNdx].size         = 2;
775                 }
776
777                 m_spec.vao.attributes.push_back(Attribute());
778                 m_spec.vao.attributes[attribNdx].enabled                = (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
779                 m_spec.vao.attributes[attribNdx].size                   = m_random.getInt(2,4);
780                 m_spec.vao.attributes[attribNdx].stride                 = 2*m_random.getInt(1, 3);
781                 m_spec.vao.attributes[attribNdx].type                   = GL_SHORT;
782                 m_spec.vao.attributes[attribNdx].integer                = m_random.getBool();
783                 m_spec.vao.attributes[attribNdx].divisor                = m_random.getInt(0, 1);
784                 m_spec.vao.attributes[attribNdx].offset                 = 2*m_random.getInt(0, 2);
785                 m_spec.vao.attributes[attribNdx].normalized             = m_random.getBool();
786                 m_spec.vao.attributes[attribNdx].bufferNdx              = attribCount - attribNdx;
787
788                 if (attribNdx == 0)
789                 {
790                         m_spec.vao.attributes[attribNdx].divisor        = 0;
791                         m_spec.vao.attributes[attribNdx].enabled        = GL_TRUE;
792                         m_spec.vao.attributes[attribNdx].size           = 2;
793                 }
794
795         }
796
797         // \note [mika] Index 0 is reserved for 0 buffer
798         for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
799         {
800                 deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
801
802                 try
803                 {
804                         GLuint buffer;
805                         GLU_CHECK_CALL(glGenBuffers(1, &buffer));
806                         m_buffers.push_back(buffer);
807
808                         GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
809                         GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
810                         GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
811
812                 } catch (...) {
813                         delete[] data;
814                         throw;
815                 }
816
817                 delete[] data;
818         }
819
820         m_vaoProgram    = createProgram(m_spec.vao);
821         m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
822         m_log << *m_vaoProgram;
823         m_stateProgram  = createProgram(m_spec.state);
824         m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
825         m_log << *m_stateProgram;
826
827         if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
828                 TCU_FAIL("Failed to compile shaders");
829
830         if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
831                 m_indices = generateIndices();
832 }
833
834 void MultiVertexArrayObjectTest::deinit (void)
835 {
836         GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
837         m_buffers.clear();
838         delete m_vaoProgram;
839         delete m_stateProgram;
840         delete[] m_indices;
841 }
842
843 deUint8* MultiVertexArrayObjectTest::generateIndices (void)
844 {
845         int typeSize = 0;
846         switch (m_spec.indexType)
847         {
848                 case GL_UNSIGNED_INT:   typeSize = sizeof(GLuint);              break;
849                 case GL_UNSIGNED_SHORT: typeSize = sizeof(GLushort);    break;
850                 case GL_UNSIGNED_BYTE:  typeSize = sizeof(GLubyte);             break;
851                 default:
852                         DE_ASSERT(false);
853         }
854
855         deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
856
857         for (int i = 0; i < m_spec.indexCount; i++)
858         {
859                 deUint8* pos = indices + typeSize * i;
860
861                 switch (m_spec.indexType)
862                 {
863                         case GL_UNSIGNED_INT:
864                         {
865                                 GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
866                                 deMemcpy(pos, &v, sizeof(v));
867                                 break;
868                         }
869
870                         case GL_UNSIGNED_SHORT:
871                         {
872                                 GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
873                                 deMemcpy(pos, &v, sizeof(v));
874                                 break;
875                         }
876
877                         case GL_UNSIGNED_BYTE:
878                         {
879                                 GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
880                                 deMemcpy(pos, &v, sizeof(v));
881                                 break;
882                         }
883
884                         default:
885                                 DE_ASSERT(false);
886                 }
887         }
888
889         return indices;
890 }
891
892 deUint8* MultiVertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
893 {
894         deUint8* data = new deUint8[buffer.size];
895
896         int stride;
897
898         if (buffer.stride != 0)
899         {
900                 stride = buffer.stride;
901         }
902         else
903         {
904                 switch (buffer.type)
905                 {
906                         case GL_FLOAT:                  stride = buffer.componentCount * (int)sizeof(GLfloat);  break;
907                         case GL_INT:                    stride = buffer.componentCount * (int)sizeof(GLint);    break;
908                         case GL_UNSIGNED_INT:   stride = buffer.componentCount * (int)sizeof(GLuint);   break;
909                         case GL_SHORT:                  stride = buffer.componentCount * (int)sizeof(GLshort);  break;
910                         case GL_UNSIGNED_SHORT: stride = buffer.componentCount * (int)sizeof(GLushort); break;
911                         case GL_BYTE:                   stride = buffer.componentCount * (int)sizeof(GLbyte);   break;
912                         case GL_UNSIGNED_BYTE:  stride = buffer.componentCount * (int)sizeof(GLubyte);  break;
913
914                         default:
915                                 stride = 0;
916                                 DE_ASSERT(DE_FALSE);
917                 }
918         }
919
920         deUint8* itr = data;
921
922         for (int pos = 0; pos < buffer.count; pos++)
923         {
924                 deUint8* componentItr = itr;
925                 for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
926                 {
927                         switch (buffer.type)
928                         {
929                                 case GL_FLOAT:
930                                 {
931                                         float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
932                                         deMemcpy(componentItr, &v, sizeof(v));
933                                         componentItr += sizeof(v);
934                                         break;
935                                 }
936
937                                 case GL_INT:
938                                 {
939                                         GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
940                                         deMemcpy(componentItr, &v, sizeof(v));
941                                         componentItr += sizeof(v);
942                                         break;
943                                 }
944
945                                 case GL_UNSIGNED_INT:
946                                 {
947                                         GLuint v = (GLuint)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
948                                         deMemcpy(componentItr, &v, sizeof(v));
949                                         componentItr += sizeof(v);
950                                         break;
951                                 }
952
953                                 case GL_SHORT:
954                                 {
955                                         GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
956                                         deMemcpy(componentItr, &v, sizeof(v));
957                                         componentItr += sizeof(v);
958                                         break;
959                                 }
960
961                                 case GL_UNSIGNED_SHORT:
962                                 {
963                                         GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
964                                         deMemcpy(componentItr, &v, sizeof(v));
965                                         componentItr += sizeof(v);
966                                         break;
967                                 }
968
969                                 case GL_BYTE:
970                                 {
971                                         GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
972                                         deMemcpy(componentItr, &v, sizeof(v));
973                                         componentItr += sizeof(v);
974                                         break;
975                                 }
976
977                                 case GL_UNSIGNED_BYTE:
978                                 {
979                                         GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
980                                         deMemcpy(componentItr, &v, sizeof(v));
981                                         componentItr += sizeof(v);
982                                         break;
983                                 }
984
985                                 default:
986                                         DE_ASSERT(false);
987                         };
988                 }
989
990                 itr += stride;
991         }
992
993         return data;
994 }
995
996 glu::ShaderProgram* MultiVertexArrayObjectTest::createProgram (const VertexArrayState& state)
997 {
998         std::stringstream vertexShaderStream;
999         std::stringstream value;
1000
1001         vertexShaderStream << "#version 300 es\n";
1002
1003         for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1004         {
1005                 if (state.attributes[attribNdx].integer)
1006                         vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
1007                 else
1008                         vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
1009
1010                 if (state.attributes[attribNdx].integer)
1011                 {
1012                         float scale = 0.0f;
1013
1014                         switch (state.attributes[0].type)
1015                         {
1016                                 case GL_SHORT:                  scale  = (1.0f/float((1u<<14)-1u));     break;
1017                                 case GL_UNSIGNED_SHORT: scale  = (1.0f/float((1u<<15)-1u));     break;
1018                                 case GL_INT:                    scale  = (1.0f/float((1u<<30)-1u));     break;
1019                                 case GL_UNSIGNED_INT:   scale  = (1.0f/float((1u<<31)-1u));     break;
1020                                 case GL_BYTE:                   scale  = (1.0f/float((1u<<6)-1u));      break;
1021                                 case GL_UNSIGNED_BYTE:  scale  = (1.0f/float((1u<<7)-1u));      break;
1022
1023                                 default:
1024                                         DE_ASSERT(DE_FALSE);
1025                         }
1026                         value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
1027                 }
1028                 else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
1029                 {
1030                         float scale = 0.0f;
1031
1032                         switch (state.attributes[0].type)
1033                         {
1034                                 case GL_SHORT:                  scale  = (0.5f/float((1u<<14)-1u));     break;
1035                                 case GL_UNSIGNED_SHORT: scale  = (0.5f/float((1u<<15)-1u));     break;
1036                                 case GL_INT:                    scale  = (0.5f/float((1u<<30)-1u));     break;
1037                                 case GL_UNSIGNED_INT:   scale  = (0.5f/float((1u<<31)-1u));     break;
1038                                 case GL_BYTE:                   scale  = (0.5f/float((1u<<6)-1u));      break;
1039                                 case GL_UNSIGNED_BYTE:  scale  = (0.5f/float((1u<<7)-1u));      break;
1040
1041                                 default:
1042                                         DE_ASSERT(DE_FALSE);
1043                         }
1044                         value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
1045                 }
1046                 else
1047                         value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
1048         }
1049
1050         vertexShaderStream
1051                 << "out mediump vec4 v_value;\n"
1052                 << "void main (void)\n"
1053                 << "{\n"
1054                 << "\tv_value = " << value.str() << ";\n";
1055
1056         if (state.attributes[0].integer)
1057         {
1058                 float scale = 0.0f;
1059
1060                 switch (state.attributes[0].type)
1061                 {
1062                         case GL_SHORT:                  scale  = (1.0f/float((1u<<14)-1u));     break;
1063                         case GL_UNSIGNED_SHORT: scale  = (1.0f/float((1u<<15)-1u));     break;
1064                         case GL_INT:                    scale  = (1.0f/float((1u<<30)-1u));     break;
1065                         case GL_UNSIGNED_INT:   scale  = (1.0f/float((1u<<31)-1u));     break;
1066                         case GL_BYTE:                   scale  = (1.0f/float((1u<<6)-1u));      break;
1067                         case GL_UNSIGNED_BYTE:  scale  = (1.0f/float((1u<<7)-1u));      break;
1068
1069
1070                         default:
1071                                 DE_ASSERT(DE_FALSE);
1072                 }
1073
1074                 vertexShaderStream
1075                         << "\tgl_Position = vec4(" << scale << " * " <<  "a_attrib0.xyz, 1.0);\n"
1076                         << "}";
1077         }
1078         else
1079         {
1080                 if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
1081                 {
1082                         vertexShaderStream
1083                                 << "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
1084                                 << "}";
1085                 }
1086                 else
1087                 {
1088                         float scale = 0.0f;
1089
1090                         switch (state.attributes[0].type)
1091                         {
1092                                 case GL_SHORT:                  scale  = (1.0f/float((1u<<14)-1u));     break;
1093                                 case GL_UNSIGNED_SHORT: scale  = (1.0f/float((1u<<15)-1u));     break;
1094                                 case GL_INT:                    scale  = (1.0f/float((1u<<30)-1u));     break;
1095                                 case GL_UNSIGNED_INT:   scale  = (1.0f/float((1u<<31)-1u));     break;
1096                                 case GL_BYTE:                   scale  = (1.0f/float((1u<<6)-1u));      break;
1097                                 case GL_UNSIGNED_BYTE:  scale  = (1.0f/float((1u<<7)-1u));      break;
1098
1099                                 default:
1100                                         DE_ASSERT(DE_FALSE);
1101                         }
1102
1103                         scale *= 0.5f;
1104
1105                         vertexShaderStream
1106                                 << "\tgl_Position = vec4(" << scale << " * " <<  "vec3(a_attrib0.xyz), 1.0);\n"
1107                                 << "}";
1108                 }
1109         }
1110
1111         const char* fragmentShader =
1112         "#version 300 es\n"
1113         "in mediump vec4 v_value;\n"
1114         "layout(location = 0) out mediump vec4 fragColor;\n"
1115         "void main (void)\n"
1116         "{\n"
1117         "\tfragColor = vec4(v_value.xyz, 1.0);\n"
1118         "}";
1119
1120         return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
1121 }
1122
1123 void MultiVertexArrayObjectTest::setState (const VertexArrayState& state)
1124 {
1125         GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
1126
1127         for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
1128         {
1129                 GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
1130                 if (state.attributes[attribNdx].enabled)
1131                         GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
1132                 else
1133                         GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
1134
1135                 if (state.attributes[attribNdx].integer)
1136                         GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
1137                 else
1138                         GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
1139
1140                 GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
1141         }
1142 }
1143
1144 void MultiVertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
1145 {
1146         GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
1147         GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
1148
1149         if (m_spec.useDrawElements)
1150         {
1151                 if (state.elementArrayBuffer == 0)
1152                 {
1153                         if (m_spec.instances == 0)
1154                                 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
1155                         else
1156                                 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
1157                 }
1158                 else
1159                 {
1160                         if (m_spec.instances == 0)
1161                                 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
1162                         else
1163                                 GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
1164                 }
1165         }
1166         else
1167         {
1168                 if (m_spec.instances == 0)
1169                         GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
1170                 else
1171                         GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
1172         }
1173 }
1174
1175 void MultiVertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
1176 {
1177         GLuint vao = 0;
1178
1179         GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
1180         GLU_CHECK_CALL(glBindVertexArray(vao));
1181         setState(m_spec.vao);
1182         GLU_CHECK_CALL(glBindVertexArray(0));
1183
1184         setState(m_spec.state);
1185
1186         GLU_CHECK_CALL(glBindVertexArray(vao));
1187         GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1188         makeDrawCall(m_spec.vao);
1189         glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
1190         setState(m_spec.vao);
1191         GLU_CHECK_CALL(glBindVertexArray(0));
1192
1193         GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1194         makeDrawCall(m_spec.state);
1195         glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
1196 }
1197
1198 void MultiVertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
1199 {
1200         setState(m_spec.vao);
1201         GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
1202         makeDrawCall(m_spec.vao);
1203         glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
1204
1205         setState(m_spec.state);
1206         GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
1207         makeDrawCall(m_spec.state);
1208         glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
1209 }
1210
1211 TestCase::IterateResult MultiVertexArrayObjectTest::iterate (void)
1212 {
1213         tcu::Surface    vaoReference    (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1214         tcu::Surface    stateReference  (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1215
1216         tcu::Surface    vaoResult               (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1217         tcu::Surface    stateResult             (m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
1218
1219         bool                    isOk;
1220
1221         logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
1222         logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
1223         genReferences(stateReference, vaoReference);
1224         render(stateResult, vaoResult);
1225
1226         isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
1227         isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
1228
1229         if (isOk)
1230         {
1231                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1232                 return STOP;
1233         }
1234         else
1235         {
1236                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1237                 return STOP;
1238         }
1239 }
1240
1241 VertexArrayObjectTestGroup::VertexArrayObjectTestGroup (Context& context)
1242         : TestCaseGroup(context, "vertex_array_objects", "Vertex array object test cases")
1243 {
1244 }
1245
1246 VertexArrayObjectTestGroup::~VertexArrayObjectTestGroup (void)
1247 {
1248 }
1249
1250 void VertexArrayObjectTestGroup::init (void)
1251 {
1252         BufferSpec floatCoordBuffer48_1 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1253         BufferSpec floatCoordBuffer48_2 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
1254
1255         BufferSpec shortCoordBuffer48 = { 48, 192, 2, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
1256
1257         // Different buffer
1258         {
1259                 Spec spec;
1260
1261                 VertexArrayState state;
1262
1263                 state.attributes.push_back(Attribute());
1264
1265                 state.attributes[0].enabled             = true;
1266                 state.attributes[0].size                = 2;
1267                 state.attributes[0].stride              = 0;
1268                 state.attributes[0].type                = GL_FLOAT;
1269                 state.attributes[0].integer             = GL_FALSE;
1270                 state.attributes[0].divisor             = 0;
1271                 state.attributes[0].offset              = 0;
1272                 state.attributes[0].normalized  = GL_FALSE;
1273
1274                 state.elementArrayBuffer = 0;
1275
1276                 spec.buffers.push_back(floatCoordBuffer48_1);
1277                 spec.buffers.push_back(floatCoordBuffer48_2);
1278
1279                 spec.useDrawElements    = false;
1280                 spec.instances                  = 0;
1281                 spec.count                              = 48;
1282                 spec.vao                                = state;
1283                 spec.state                              = state;
1284                 spec.indexOffset                = 0;
1285                 spec.indexRangeMin              = 0;
1286                 spec.indexRangeMax              = 0;
1287                 spec.indexType                  = GL_NONE;
1288                 spec.indexCount                 = 0;
1289
1290                 spec.state.attributes[0].bufferNdx      = 1;
1291                 spec.vao.attributes[0].bufferNdx        = 2;
1292                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_buffer", "diff_buffer"));
1293         }
1294         // Different size
1295         {
1296                 Spec spec;
1297
1298                 VertexArrayState state;
1299
1300                 state.attributes.push_back(Attribute());
1301
1302                 state.attributes[0].enabled             = true;
1303                 state.attributes[0].size                = 2;
1304                 state.attributes[0].stride              = 0;
1305                 state.attributes[0].type                = GL_FLOAT;
1306                 state.attributes[0].integer             = GL_FALSE;
1307                 state.attributes[0].divisor             = 0;
1308                 state.attributes[0].offset              = 0;
1309                 state.attributes[0].normalized  = GL_FALSE;
1310                 state.attributes[0].bufferNdx   = 1;
1311
1312                 state.elementArrayBuffer = 0;
1313
1314                 spec.buffers.push_back(floatCoordBuffer48_1);
1315
1316                 spec.useDrawElements    = false;
1317                 spec.instances                  = 0;
1318                 spec.count                              = 24;
1319                 spec.vao                                = state;
1320                 spec.state                              = state;
1321                 spec.indexOffset                = 0;
1322                 spec.indexRangeMin              = 0;
1323                 spec.indexRangeMax              = 0;
1324                 spec.indexType                  = GL_NONE;
1325                 spec.indexCount                 = 0;
1326
1327                 spec.state.attributes[0].size           = 2;
1328                 spec.vao.attributes[0].size                     = 3;
1329                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_size", "diff_size"));
1330         }
1331
1332         // Different stride
1333         {
1334                 Spec spec;
1335
1336                 VertexArrayState state;
1337
1338                 state.attributes.push_back(Attribute());
1339
1340                 state.attributes[0].enabled             = true;
1341                 state.attributes[0].size                = 2;
1342                 state.attributes[0].stride              = 0;
1343                 state.attributes[0].type                = GL_SHORT;
1344                 state.attributes[0].integer             = GL_FALSE;
1345                 state.attributes[0].divisor             = 0;
1346                 state.attributes[0].offset              = 0;
1347                 state.attributes[0].normalized  = GL_TRUE;
1348                 state.attributes[0].bufferNdx   = 1;
1349
1350                 state.elementArrayBuffer = 0;
1351
1352                 spec.buffers.push_back(shortCoordBuffer48);
1353
1354                 spec.useDrawElements    = false;
1355                 spec.instances                  = 0;
1356                 spec.count                              = 24;
1357                 spec.vao                                = state;
1358                 spec.state                              = state;
1359                 spec.indexOffset                = 0;
1360                 spec.indexRangeMin              = 0;
1361                 spec.indexRangeMax              = 0;
1362                 spec.indexType                  = GL_NONE;
1363                 spec.indexCount                 = 0;
1364
1365                 spec.vao.attributes[0].stride   = 2;
1366                 spec.state.attributes[0].stride = 4;
1367                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_stride", "diff_stride"));
1368         }
1369
1370         // Different types
1371         {
1372                 Spec spec;
1373
1374                 VertexArrayState state;
1375
1376                 state.attributes.push_back(Attribute());
1377
1378                 state.attributes[0].enabled             = true;
1379                 state.attributes[0].size                = 2;
1380                 state.attributes[0].stride              = 0;
1381                 state.attributes[0].type                = GL_SHORT;
1382                 state.attributes[0].integer             = GL_FALSE;
1383                 state.attributes[0].divisor             = 0;
1384                 state.attributes[0].offset              = 0;
1385                 state.attributes[0].normalized  = GL_TRUE;
1386                 state.attributes[0].bufferNdx   = 1;
1387
1388                 state.elementArrayBuffer = 0;
1389
1390                 spec.buffers.push_back(shortCoordBuffer48);
1391
1392                 spec.useDrawElements    = false;
1393                 spec.instances                  = 0;
1394                 spec.count                              = 24;
1395                 spec.vao                                = state;
1396                 spec.state                              = state;
1397                 spec.indexOffset                = 0;
1398                 spec.indexRangeMin              = 0;
1399                 spec.indexRangeMax              = 0;
1400                 spec.indexType                  = GL_NONE;
1401                 spec.indexCount                 = 0;
1402
1403                 spec.vao.attributes[0].type             = GL_SHORT;
1404                 spec.state.attributes[0].type   = GL_BYTE;
1405                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_type", "diff_type"));
1406         }
1407         // Different "integer"
1408         {
1409                 Spec spec;
1410
1411                 VertexArrayState state;
1412
1413                 state.attributes.push_back(Attribute());
1414
1415                 state.attributes[0].enabled             = true;
1416                 state.attributes[0].size                = 2;
1417                 state.attributes[0].stride              = 0;
1418                 state.attributes[0].type                = GL_BYTE;
1419                 state.attributes[0].integer             = GL_TRUE;
1420                 state.attributes[0].divisor             = 0;
1421                 state.attributes[0].offset              = 0;
1422                 state.attributes[0].normalized  = GL_FALSE;
1423                 state.attributes[0].bufferNdx   = 1;
1424
1425                 state.elementArrayBuffer = 0;
1426
1427                 spec.buffers.push_back(shortCoordBuffer48);
1428
1429                 spec.useDrawElements    = false;
1430                 spec.count                              = 24;
1431                 spec.vao                                = state;
1432                 spec.state                              = state;
1433                 spec.instances                  = 0;
1434                 spec.indexOffset                = 0;
1435                 spec.indexRangeMin              = 0;
1436                 spec.indexRangeMax              = 0;
1437                 spec.indexType                  = GL_NONE;
1438                 spec.indexCount                 = 0;
1439
1440                 spec.state.attributes[0].integer        = GL_FALSE;
1441                 spec.vao.attributes[0].integer          = GL_TRUE;
1442                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_integer", "diff_integer"));
1443         }
1444         // Different divisor
1445         {
1446                 Spec spec;
1447
1448                 VertexArrayState state;
1449
1450                 state.attributes.push_back(Attribute());
1451                 state.attributes.push_back(Attribute());
1452
1453                 state.attributes[0].enabled             = true;
1454                 state.attributes[0].size                = 2;
1455                 state.attributes[0].stride              = 0;
1456                 state.attributes[0].type                = GL_SHORT;
1457                 state.attributes[0].integer             = GL_FALSE;
1458                 state.attributes[0].divisor             = 0;
1459                 state.attributes[0].offset              = 0;
1460                 state.attributes[0].normalized  = GL_TRUE;
1461                 state.attributes[0].bufferNdx   = 1;
1462
1463                 state.attributes[1].enabled             = true;
1464                 state.attributes[1].size                = 4;
1465                 state.attributes[1].stride              = 0;
1466                 state.attributes[1].type                = GL_FLOAT;
1467                 state.attributes[1].integer             = GL_FALSE;
1468                 state.attributes[1].divisor             = 0;
1469                 state.attributes[1].offset              = 0;
1470                 state.attributes[1].normalized  = GL_FALSE;
1471                 state.attributes[1].bufferNdx   = 2;
1472
1473                 state.elementArrayBuffer = 0;
1474
1475                 spec.buffers.push_back(shortCoordBuffer48);
1476                 spec.buffers.push_back(floatCoordBuffer48_1);
1477
1478                 spec.useDrawElements    = false;
1479                 spec.instances                  = 10;
1480                 spec.count                              = 12;
1481                 spec.vao                                = state;
1482                 spec.state                              = state;
1483                 spec.indexOffset                = 0;
1484                 spec.indexRangeMin              = 0;
1485                 spec.indexRangeMax              = 0;
1486                 spec.indexType                  = GL_NONE;
1487                 spec.indexCount                 = 0;
1488
1489                 spec.vao.attributes[1].divisor          = 3;
1490                 spec.state.attributes[1].divisor        = 2;
1491
1492                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_divisor", "diff_divisor"));
1493         }
1494         // Different offset
1495         {
1496                 Spec spec;
1497
1498                 VertexArrayState state;
1499
1500                 state.attributes.push_back(Attribute());
1501
1502                 state.attributes[0].enabled             = true;
1503                 state.attributes[0].size                = 2;
1504                 state.attributes[0].stride              = 0;
1505                 state.attributes[0].type                = GL_SHORT;
1506                 state.attributes[0].integer             = GL_FALSE;
1507                 state.attributes[0].divisor             = 0;
1508                 state.attributes[0].offset              = 0;
1509                 state.attributes[0].normalized  = GL_TRUE;
1510                 state.attributes[0].bufferNdx   = 1;
1511
1512                 state.elementArrayBuffer = 0;
1513
1514                 spec.buffers.push_back(shortCoordBuffer48);
1515
1516                 spec.useDrawElements    = false;
1517                 spec.instances                  = 0;
1518                 spec.count                              = 24;
1519                 spec.vao                                = state;
1520                 spec.state                              = state;
1521                 spec.indexOffset                = 0;
1522                 spec.indexRangeMin              = 0;
1523                 spec.indexRangeMax              = 0;
1524                 spec.indexType                  = GL_NONE;
1525                 spec.indexCount                 = 0;
1526
1527                 spec.vao.attributes[0].offset   = 2;
1528                 spec.state.attributes[0].offset = 4;
1529                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_offset", "diff_offset"));
1530         }
1531         // Different normalize
1532         {
1533                 Spec spec;
1534
1535                 VertexArrayState state;
1536
1537                 state.attributes.push_back(Attribute());
1538
1539                 state.attributes[0].enabled             = true;
1540                 state.attributes[0].size                = 2;
1541                 state.attributes[0].stride              = 0;
1542                 state.attributes[0].type                = GL_SHORT;
1543                 state.attributes[0].integer             = GL_FALSE;
1544                 state.attributes[0].divisor             = 0;
1545                 state.attributes[0].offset              = 0;
1546                 state.attributes[0].normalized  = GL_TRUE;
1547                 state.attributes[0].bufferNdx   = 1;
1548
1549                 state.elementArrayBuffer = 0;
1550
1551                 spec.buffers.push_back(shortCoordBuffer48);
1552
1553                 spec.useDrawElements    = false;
1554                 spec.instances                  = 0;
1555                 spec.count                              = 48;
1556                 spec.vao                                = state;
1557                 spec.state                              = state;
1558                 spec.indexOffset                = 0;
1559                 spec.indexRangeMin              = 0;
1560                 spec.indexRangeMax              = 0;
1561                 spec.indexType                  = GL_NONE;
1562                 spec.indexCount                 = 0;
1563
1564                 spec.vao.attributes[0].normalized       = GL_TRUE;
1565                 spec.state.attributes[0].normalized     = GL_FALSE;;
1566                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_normalize", "diff_normalize"));
1567         }
1568         // DrawElements with buffer / Pointer
1569         {
1570                 Spec spec;
1571
1572                 VertexArrayState state;
1573
1574                 state.attributes.push_back(Attribute());
1575
1576                 state.attributes[0].enabled             = true;
1577                 state.attributes[0].size                = 2;
1578                 state.attributes[0].stride              = 0;
1579                 state.attributes[0].type                = GL_FLOAT;
1580                 state.attributes[0].integer             = GL_FALSE;
1581                 state.attributes[0].divisor             = 0;
1582                 state.attributes[0].offset              = 0;
1583                 state.attributes[0].normalized  = GL_TRUE;
1584                 state.attributes[0].bufferNdx   = 1;
1585
1586                 state.elementArrayBuffer = 0;
1587
1588                 spec.buffers.push_back(floatCoordBuffer48_1);
1589
1590                 BufferSpec indexBuffer = { 24, 192, 1, 0, 0, GL_UNSIGNED_SHORT, 0, 48, 0.0f, 0.0f };
1591                 spec.buffers.push_back(indexBuffer);
1592
1593                 spec.useDrawElements    = true;
1594                 spec.count                              = 24;
1595                 spec.vao                                = state;
1596                 spec.state                              = state;
1597                 spec.instances                  = 0;
1598                 spec.indexOffset                = 0;
1599                 spec.indexRangeMin              = 0;
1600                 spec.indexRangeMax              = 48;
1601                 spec.indexType                  = GL_UNSIGNED_SHORT;
1602                 spec.indexCount                 = 24;
1603
1604                 spec.state.elementArrayBuffer   = 0;
1605                 spec.vao.elementArrayBuffer             = 2;
1606                 addChild(new VertexArrayObjectTest(m_context, spec, "diff_indices", "diff_indices"));
1607         }
1608         // Use all attributes
1609
1610         addChild(new MultiVertexArrayObjectTest(m_context, "all_attributes", "all_attributes"));
1611 }
1612
1613 } // Functional
1614 } // gles3
1615 } // deqp