Fix atomic ssbo xor test am: f0fa05e898 am: 14cd264501 am: d4c01761d3 am: d20475d813...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fShaderBuiltinVarTests.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 Shader built-in variable tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fShaderBuiltinVarTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "glsShaderExecUtil.hpp"
27 #include "deRandom.hpp"
28 #include "deString.h"
29 #include "deMath.h"
30 #include "deUniquePtr.hpp"
31 #include "deStringUtil.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuTestCase.hpp"
34 #include "tcuTextureUtil.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuImageCompare.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluDrawUtil.hpp"
39 #include "gluStrUtil.hpp"
40 #include "rrRenderer.hpp"
41 #include "rrFragmentOperations.hpp"
42
43 #include "glwEnums.hpp"
44 #include "glwFunctions.hpp"
45
46 using std::string;
47 using std::vector;
48 using tcu::TestLog;
49
50 namespace deqp
51 {
52 namespace gles3
53 {
54 namespace Functional
55 {
56
57 static int getInteger (const glw::Functions& gl, deUint32 pname)
58 {
59         int value = -1;
60         gl.getIntegerv(pname, &value);
61         GLU_EXPECT_NO_ERROR(gl.getError(), ("glGetIntegerv(" + glu::getGettableStateStr((int)pname).toString() + ")").c_str());
62         return value;
63 }
64
65 template<deUint32 Pname>
66 static int getInteger (const glw::Functions& gl)
67 {
68         return getInteger(gl, Pname);
69 }
70
71 static int getVectorsFromComps (const glw::Functions& gl, deUint32 pname)
72 {
73         int value = -1;
74         gl.getIntegerv(pname, &value);
75         GLU_EXPECT_NO_ERROR(gl.getError(), ("glGetIntegerv(" + glu::getGettableStateStr((int)pname).toString() + ")").c_str());
76         // Accept truncated division. According to the spec, the number of vectors is number of components divided by four, plain and simple.
77         return value/4;
78 }
79
80 template<deUint32 Pname>
81 static int getVectorsFromComps (const glw::Functions& gl)
82 {
83         return getVectorsFromComps(gl, Pname);
84 }
85
86 class ShaderBuiltinConstantCase : public TestCase
87 {
88 public:
89         typedef int (*GetConstantValueFunc) (const glw::Functions& gl);
90
91                                                                 ShaderBuiltinConstantCase       (Context& context, const char* name, const char* desc, const char* varName, GetConstantValueFunc getValue, glu::ShaderType shaderType);
92                                                                 ~ShaderBuiltinConstantCase      (void);
93
94         IterateResult                           iterate                                         (void);
95
96 private:
97         const std::string                       m_varName;
98         const GetConstantValueFunc      m_getValue;
99         const glu::ShaderType           m_shaderType;
100 };
101
102 ShaderBuiltinConstantCase::ShaderBuiltinConstantCase (Context& context, const char* name, const char* desc, const char* varName, GetConstantValueFunc getValue, glu::ShaderType shaderType)
103         : TestCase              (context, name, desc)
104         , m_varName             (varName)
105         , m_getValue    (getValue)
106         , m_shaderType  (shaderType)
107 {
108 }
109
110 ShaderBuiltinConstantCase::~ShaderBuiltinConstantCase (void)
111 {
112 }
113
114 static gls::ShaderExecUtil::ShaderExecutor* createGetConstantExecutor (const glu::RenderContext& renderCtx, glu::ShaderType shaderType, const std::string& varName)
115 {
116         using namespace gls::ShaderExecUtil;
117
118         ShaderSpec      shaderSpec;
119
120         shaderSpec.version      = glu::GLSL_VERSION_300_ES;
121         shaderSpec.source       = string("result = ") + varName + ";\n";
122         shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
123
124         return createExecutor(renderCtx, shaderType, shaderSpec);
125 }
126
127 ShaderBuiltinConstantCase::IterateResult ShaderBuiltinConstantCase::iterate (void)
128 {
129         using namespace gls::ShaderExecUtil;
130
131         const de::UniquePtr<ShaderExecutor>     shaderExecutor  (createGetConstantExecutor(m_context.getRenderContext(), m_shaderType, m_varName));
132         const int                                                       reference               = m_getValue(m_context.getRenderContext().getFunctions());
133         int                                                                     result                  = -1;
134         void* const                                                     outputs                 = &result;
135
136         if (!shaderExecutor->isOk())
137         {
138                 shaderExecutor->log(m_testCtx.getLog());
139                 TCU_FAIL("Compile failed");
140         }
141
142         shaderExecutor->useProgram();
143         shaderExecutor->execute(1, DE_NULL, &outputs);
144
145         m_testCtx.getLog() << TestLog::Integer(m_varName, m_varName, "", QP_KEY_TAG_NONE, result);
146
147         if (result != reference)
148         {
149                 m_testCtx.getLog() << TestLog::Message << "ERROR: Expected " << m_varName << " = " << reference << TestLog::EndMessage
150                                                    << TestLog::Message << "Test shader:" << TestLog::EndMessage;
151                 shaderExecutor->log(m_testCtx.getLog());
152                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid builtin constant value");
153         }
154         else
155                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
156
157         return STOP;
158 }
159
160 namespace
161 {
162
163 struct DepthRangeParams
164 {
165         DepthRangeParams (void)
166                 : zNear (0.0f)
167                 , zFar  (1.0f)
168         {
169         }
170
171         DepthRangeParams (float zNear_, float zFar_)
172                 : zNear (zNear_)
173                 , zFar  (zFar_)
174         {
175         }
176
177         float   zNear;
178         float   zFar;
179 };
180
181 class DepthRangeEvaluator : public gls::ShaderEvaluator
182 {
183 public:
184         DepthRangeEvaluator (const DepthRangeParams& params)
185                 : m_params(params)
186         {
187         }
188
189         void evaluate (gls::ShaderEvalContext& c)
190         {
191                 float zNear     = deFloatClamp(m_params.zNear, 0.0f, 1.0f);
192                 float zFar      = deFloatClamp(m_params.zFar, 0.0f, 1.0f);
193                 float diff      = zFar - zNear;
194                 c.color.xyz() = tcu::Vec3(zNear, zFar, diff*0.5f + 0.5f);
195         }
196
197 private:
198         const DepthRangeParams& m_params;
199 };
200
201 } // anonymous
202
203 class ShaderDepthRangeTest : public gls::ShaderRenderCase
204 {
205 public:
206         ShaderDepthRangeTest (Context& context, const char* name, const char* desc, bool isVertexCase)
207                 : ShaderRenderCase      (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator)
208                 , m_evaluator           (m_depthRange)
209                 , m_iterNdx                     (0)
210         {
211         }
212
213         void init (void)
214         {
215                 static const char* defaultVertSrc =
216                         "#version 300 es\n"
217                         "in highp vec4 a_position;\n"
218                         "void main (void)\n"
219                         "{\n"
220                         "       gl_Position = a_position;\n"
221                         "}\n";
222                 static const char* defaultFragSrc =
223                         "#version 300 es\n"
224                         "in mediump vec4 v_color;\n"
225                         "layout(location = 0) out mediump vec4 o_color;\n\n"
226                         "void main (void)\n"
227                         "{\n"
228                         "       o_color = v_color;\n"
229                         "}\n";
230
231                 // Construct shader.
232                 std::ostringstream src;
233                 src << "#version 300 es\n";
234                 if (m_isVertexCase)
235                         src << "in highp vec4 a_position;\n"
236                                 << "out mediump vec4 v_color;\n";
237                 else
238                         src << "layout(location = 0) out mediump vec4 o_color;\n";
239
240                 src << "void main (void)\n{\n";
241                 src << "\t" << (m_isVertexCase ? "v_color" : "o_color") << " = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff*0.5 + 0.5, 1.0);\n";
242
243                 if (m_isVertexCase)
244                         src << "\tgl_Position = a_position;\n";
245
246                 src << "}\n";
247
248                 m_vertShaderSource              = m_isVertexCase ? src.str()            : defaultVertSrc;
249                 m_fragShaderSource              = m_isVertexCase ? defaultFragSrc       : src.str();
250
251                 gls::ShaderRenderCase::init();
252         }
253
254         IterateResult iterate (void)
255         {
256                 const glw::Functions& gl = m_renderCtx.getFunctions();
257
258                 const DepthRangeParams cases[] =
259                 {
260                         DepthRangeParams(0.0f,  1.0f),
261                         DepthRangeParams(1.5f, -1.0f),
262                         DepthRangeParams(0.7f,  0.3f)
263                 };
264
265                 m_depthRange = cases[m_iterNdx];
266                 m_testCtx.getLog() << tcu::TestLog::Message << "glDepthRangef(" << m_depthRange.zNear << ", " << m_depthRange.zFar << ")" << tcu::TestLog::EndMessage;
267                 gl.depthRangef(m_depthRange.zNear, m_depthRange.zFar);
268                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthRangef()");
269
270                 gls::ShaderRenderCase::iterate();
271                 m_iterNdx += 1;
272
273                 if (m_iterNdx == DE_LENGTH_OF_ARRAY(cases) || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
274                         return STOP;
275                 else
276                         return CONTINUE;
277         }
278
279 private:
280         DepthRangeParams                m_depthRange;
281         DepthRangeEvaluator             m_evaluator;
282         int                                             m_iterNdx;
283 };
284
285 class FragCoordXYZCase : public TestCase
286 {
287 public:
288         FragCoordXYZCase (Context& context)
289                 : TestCase(context, "fragcoord_xyz", "gl_FragCoord.xyz Test")
290         {
291         }
292
293         IterateResult iterate (void)
294         {
295                 TestLog&                                log                     = m_testCtx.getLog();
296                 const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
297                 const int                               width           = m_context.getRenderTarget().getWidth();
298                 const int                               height          = m_context.getRenderTarget().getHeight();
299                 const tcu::RGBA                 threshold       = tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
300                 const tcu::Vec3                 scale           (1.f / float(width), 1.f / float(height), 1.0f);
301
302                 tcu::Surface                    testImg         (width, height);
303                 tcu::Surface                    refImg          (width, height);
304
305                 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
306                         "#version 300 es\n"
307                         "in highp vec4 a_position;\n"
308                         "void main (void)\n"
309                         "{\n"
310                         "       gl_Position = a_position;\n"
311                         "}\n",
312
313                         "#version 300 es\n"
314                         "uniform highp vec3 u_scale;\n"
315                         "layout(location = 0) out mediump vec4 o_color;\n"
316                         "void main (void)\n"
317                         "{\n"
318                         "       o_color = vec4(gl_FragCoord.xyz*u_scale, 1.0);\n"
319                         "}\n"));
320
321                 log << program;
322
323                 if (!program.isOk())
324                         throw tcu::TestError("Compile failed");
325
326                 // Draw with GL.
327                 {
328                         const float positions[] =
329                         {
330                                 -1.0f,  1.0f, -1.0f, 1.0f,
331                                 -1.0f, -1.0f,  0.0f, 1.0f,
332                                  1.0f,  1.0f,  0.0f, 1.0f,
333                                  1.0f, -1.0f,  1.0f, 1.0f
334                         };
335                         const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
336
337                         const int                               scaleLoc        = gl.getUniformLocation(program.getProgram(), "u_scale");
338                         glu::VertexArrayBinding posBinding      = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
339
340                         gl.useProgram(program.getProgram());
341                         gl.uniform3fv(scaleLoc, 1, scale.getPtr());
342
343                         glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
344                                           glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
345
346                         glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
347                         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
348                 }
349
350                 // Draw reference
351                 for (int y = 0; y < refImg.getHeight(); y++)
352                 {
353                         for (int x = 0; x < refImg.getWidth(); x++)
354                         {
355                                 const float                     xf                      = (float(x)+.5f) / float(refImg.getWidth());
356                                 const float                     yf                      = (float(refImg.getHeight()-y-1)+.5f) / float(refImg.getHeight());
357                                 const float                     z                       = (xf + yf) / 2.0f;
358                                 const tcu::Vec3         fragCoord       (float(x)+.5f, float(y)+.5f, z);
359                                 const tcu::Vec3         scaledFC        = fragCoord*scale;
360                                 const tcu::Vec4         color           (scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
361
362                                 refImg.setPixel(x, y, tcu::RGBA(color));
363                         }
364                 }
365
366                 // Compare
367                 {
368                         bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
369                         m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
370                                                                         isOk ? "Pass"                           : "Image comparison failed");
371                 }
372
373                 return STOP;
374         }
375 };
376
377 static inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny)
378 {
379         return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
380 }
381
382 class FragCoordWCase : public TestCase
383 {
384 public:
385         FragCoordWCase (Context& context)
386                 : TestCase(context, "fragcoord_w", "gl_FragCoord.w Test")
387         {
388         }
389
390         IterateResult iterate (void)
391         {
392                 TestLog&                                log                     = m_testCtx.getLog();
393                 const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
394                 const int                               width           = m_context.getRenderTarget().getWidth();
395                 const int                               height          = m_context.getRenderTarget().getHeight();
396                 const tcu::RGBA                 threshold       = tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
397
398                 tcu::Surface                    testImg         (width, height);
399                 tcu::Surface                    refImg          (width, height);
400
401                 const float                             w[4]            = { 1.7f, 2.0f, 1.2f, 1.0f };
402
403                 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
404                         "#version 300 es\n"
405                         "in highp vec4 a_position;\n"
406                         "void main (void)\n"
407                         "{\n"
408                         "       gl_Position = a_position;\n"
409                         "}\n",
410
411                         "#version 300 es\n"
412                         "layout(location = 0) out mediump vec4 o_color;\n"
413                         "void main (void)\n"
414                         "{\n"
415                         "       o_color = vec4(0.0, 1.0/gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
416                         "}\n"));
417
418                 log << program;
419
420                 if (!program.isOk())
421                         throw tcu::TestError("Compile failed");
422
423                 // Draw with GL.
424                 {
425                         const float positions[] =
426                         {
427                                 -w[0],  w[0], 0.0f, w[0],
428                                 -w[1], -w[1], 0.0f, w[1],
429                                  w[2],  w[2], 0.0f, w[2],
430                                  w[3], -w[3], 0.0f, w[3]
431                         };
432                         const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
433
434                         glu::VertexArrayBinding posBinding      = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
435
436                         gl.useProgram(program.getProgram());
437
438                         glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
439                                           glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
440
441                         glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
442                         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
443                 }
444
445                 // Draw reference
446                 for (int y = 0; y < refImg.getHeight(); y++)
447                 {
448                         for (int x = 0; x < refImg.getWidth(); x++)
449                         {
450                                 const float                     xf                      = (float(x)+.5f) / float(refImg.getWidth());
451                                 const float                     yf                      = (float(refImg.getHeight()-y-1)+.5f) / float(refImg.getHeight());
452                                 const float                     oow                     = ((xf + yf) < 1.0f)
453                                                                                                 ? projectedTriInterpolate(tcu::Vec3(w[0], w[1], w[2]), tcu::Vec3(w[0], w[1], w[2]), xf, yf)
454                                                                                                 : projectedTriInterpolate(tcu::Vec3(w[3], w[2], w[1]), tcu::Vec3(w[3], w[2], w[1]), 1.0f-xf, 1.0f-yf);
455                                 const tcu::Vec4         color           (0.0f, oow - 1.0f, 0.0f, 1.0f);
456
457                                 refImg.setPixel(x, y, tcu::RGBA(color));
458                         }
459                 }
460
461                 // Compare
462                 {
463                         bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
464                         m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
465                                                                         isOk ? "Pass"                           : "Image comparison failed");
466                 }
467
468                 return STOP;
469         }
470 };
471
472 class PointCoordCase : public TestCase
473 {
474 public:
475         PointCoordCase (Context& context)
476                 : TestCase(context, "pointcoord", "gl_PointCoord Test")
477         {
478         }
479
480         IterateResult iterate (void)
481         {
482                 TestLog&                                log                     = m_testCtx.getLog();
483                 const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
484                 const int                               width           = de::min(256, m_context.getRenderTarget().getWidth());
485                 const int                               height          = de::min(256, m_context.getRenderTarget().getHeight());
486                 const float                             threshold       = 0.02f;
487
488                 const int                               numPoints       = 8;
489
490                 vector<tcu::Vec3>               coords          (numPoints);
491                 float                                   pointSizeRange[2]       = { 0.0f, 0.0f };
492
493                 de::Random                              rnd                     (0x145fa);
494                 tcu::Surface                    testImg         (width, height);
495                 tcu::Surface                    refImg          (width, height);
496
497                 gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, &pointSizeRange[0]);
498                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE)");
499
500                 if (pointSizeRange[0] <= 0.0f || pointSizeRange[1] <= 0.0f || pointSizeRange[1] < pointSizeRange[0])
501                         throw tcu::TestError("Invalid GL_ALIASED_POINT_SIZE_RANGE");
502
503                 // Compute coordinates.
504                 {
505
506                         for (vector<tcu::Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
507                         {
508                                 coord->x() = rnd.getFloat(-0.9f, 0.9f);
509                                 coord->y() = rnd.getFloat(-0.9f, 0.9f);
510                                 coord->z() = rnd.getFloat(pointSizeRange[0], pointSizeRange[1]);
511                         }
512                 }
513
514                 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
515                         "#version 300 es\n"
516                         "in highp vec3 a_positionSize;\n"
517                         "void main (void)\n"
518                         "{\n"
519                         "       gl_Position = vec4(a_positionSize.xy, 0.0, 1.0);\n"
520                         "       gl_PointSize = a_positionSize.z;\n"
521                         "}\n",
522
523                         "#version 300 es\n"
524                         "layout(location = 0) out mediump vec4 o_color;\n"
525                         "void main (void)\n"
526                         "{\n"
527                         "       o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
528                         "}\n"));
529
530                 log << program;
531
532                 if (!program.isOk())
533                         throw tcu::TestError("Compile failed");
534
535                 // Draw with GL.
536                 {
537                         glu::VertexArrayBinding posBinding      = glu::va::Float("a_positionSize", 3, (int)coords.size(), 0, (const float*)&coords[0]);
538                         const int                               viewportX       = rnd.getInt(0, m_context.getRenderTarget().getWidth()-width);
539                         const int                               viewportY       = rnd.getInt(0, m_context.getRenderTarget().getHeight()-height);
540
541                         gl.viewport(viewportX, viewportY, width, height);
542                         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
543                         gl.clear(GL_COLOR_BUFFER_BIT);
544
545                         gl.useProgram(program.getProgram());
546
547                         glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
548                                           glu::pr::Points((int)coords.size()));
549
550                         glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
551                         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
552                 }
553
554                 // Draw reference
555                 tcu::clear(refImg.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
556                 for (vector<tcu::Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
557                 {
558                         const int       x0              = deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) - pointIter->z()*0.5f);
559                         const int       y0              = deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) - pointIter->z()*0.5f);
560                         const int       x1              = deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) + pointIter->z()*0.5f);
561                         const int       y1              = deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) + pointIter->z()*0.5f);
562                         const int       w               = x1-x0;
563                         const int       h               = y1-y0;
564
565                         for (int yo = 0; yo < h; yo++)
566                         {
567                                 for (int xo = 0; xo < w; xo++)
568                                 {
569                                         const float                     xf              = (float(xo)+0.5f) / float(w);
570                                         const float                     yf              = (float(h-yo-1)+0.5f) / float(h);
571                                         const tcu::Vec4         color   (xf, yf, 0.0f, 1.0f);
572                                         const int                       dx              = x0+xo;
573                                         const int                       dy              = y0+yo;
574
575                                         if (de::inBounds(dx, 0, refImg.getWidth()) && de::inBounds(dy, 0, refImg.getHeight()))
576                                                 refImg.setPixel(dx, dy, tcu::RGBA(color));
577                                 }
578                         }
579                 }
580
581                 // Compare
582                 {
583                         bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
584                         m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
585                                                                         isOk ? "Pass"                           : "Image comparison failed");
586                 }
587
588                 return STOP;
589         }
590 };
591
592 class FrontFacingCase : public TestCase
593 {
594 public:
595         FrontFacingCase (Context& context)
596                 : TestCase(context, "frontfacing", "gl_FrontFacing Test")
597         {
598         }
599
600         IterateResult iterate (void)
601         {
602                 // Test case renders two adjecent quads, where left is has front-facing
603                 // triagles and right back-facing. Color is selected based on gl_FrontFacing
604                 // value.
605
606                 TestLog&                                log                     = m_testCtx.getLog();
607                 const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
608                 de::Random                              rnd                     (0x89f2c);
609                 const int                               width           = de::min(64, m_context.getRenderTarget().getWidth());
610                 const int                               height          = de::min(64, m_context.getRenderTarget().getHeight());
611                 const int                               viewportX       = rnd.getInt(0, m_context.getRenderTarget().getWidth()-width);
612                 const int                               viewportY       = rnd.getInt(0, m_context.getRenderTarget().getHeight()-height);
613                 const tcu::RGBA                 threshold       = tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
614
615                 tcu::Surface                    testImg         (width, height);
616                 tcu::Surface                    refImg          (width, height);
617
618                 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
619                         "#version 300 es\n"
620                         "in highp vec4 a_position;\n"
621                         "void main (void)\n"
622                         "{\n"
623                         "       gl_Position = a_position;\n"
624                         "}\n",
625
626                         "#version 300 es\n"
627                         "layout(location = 0) out mediump vec4 o_color;\n"
628                         "void main (void)\n"
629                         "{\n"
630                         "       if (gl_FrontFacing)\n"
631                         "               o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
632                         "       else\n"
633                         "               o_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
634                         "}\n"));
635
636                 log << program;
637
638                 if (!program.isOk())
639                         throw tcu::TestError("Compile failed");
640
641                 // Draw with GL.
642                 {
643                         const float positions[] =
644                         {
645                                 -1.0f,  1.0f, 0.0f, 1.0f,
646                                 -1.0f, -1.0f, 0.0f, 1.0f,
647                                  1.0f,  1.0f, 0.0f, 1.0f,
648                                  1.0f, -1.0f, 0.0f, 1.0f
649                         };
650                         const deUint16 indicesCCW[]     = { 0, 1, 2, 2, 1, 3 };
651                         const deUint16 indicesCW[]      = { 2, 1, 0, 3, 1, 2 };
652
653                         glu::VertexArrayBinding posBinding      = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
654
655                         gl.useProgram(program.getProgram());
656
657                         gl.viewport(viewportX, viewportY, width/2, height);
658                         glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
659                                           glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0]));
660
661                         gl.viewport(viewportX + width/2, viewportY, width-width/2, height);
662                         glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
663                                           glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0]));
664
665                         glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
666                         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
667                 }
668
669                 // Draw reference
670                 for (int y = 0; y < refImg.getHeight(); y++)
671                 {
672                         for (int x = 0; x < refImg.getWidth()/2; x++)
673                                 refImg.setPixel(x, y, tcu::RGBA::green());
674
675                         for (int x = refImg.getWidth()/2; x < refImg.getWidth(); x++)
676                                 refImg.setPixel(x, y, tcu::RGBA::blue());
677                 }
678
679                 // Compare
680                 {
681                         bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
682                         m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
683                                                                         isOk ? "Pass"                           : "Image comparison failed");
684                 }
685
686                 return STOP;
687         }
688 };
689
690 // VertexIDCase
691
692 class VertexIDCase : public TestCase
693 {
694 public:
695                                                 VertexIDCase                    (Context& context);
696                                                 ~VertexIDCase                   (void);
697
698         void                            init                                    (void);
699         void                            deinit                                  (void);
700         IterateResult           iterate                                 (void);
701
702 private:
703         enum
704         {
705                 MAX_VERTICES = 8*3      //!< 8 triangles, totals 24 vertices
706         };
707
708         void                            renderReference                 (const tcu::PixelBufferAccess& dst, const int numVertices, const deUint16* const indices, const tcu::Vec4* const positions, const tcu::Vec4* const colors);
709
710         glu::ShaderProgram*     m_program;
711         deUint32                        m_positionBuffer;
712         deUint32                        m_elementBuffer;
713
714         vector<tcu::Vec4>       m_positions;
715         vector<tcu::Vec4>       m_colors;
716         int                                     m_viewportW;
717         int                                     m_viewportH;
718
719         int                                     m_iterNdx;
720 };
721
722 VertexIDCase::VertexIDCase (Context& context)
723         : TestCase                      (context, "vertex_id",  "gl_VertexID Test")
724         , m_program                     (DE_NULL)
725         , m_positionBuffer      (0)
726         , m_elementBuffer       (0)
727         , m_viewportW           (0)
728         , m_viewportH           (0)
729         , m_iterNdx                     (0)
730 {
731 }
732
733 VertexIDCase::~VertexIDCase (void)
734 {
735         VertexIDCase::deinit();
736 }
737
738 void VertexIDCase::init (void)
739 {
740         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
741         const int                               width           = m_context.getRenderTarget().getWidth();
742         const int                               height          = m_context.getRenderTarget().getHeight();
743
744         const int                               quadWidth       = 32;
745         const int                               quadHeight      = 32;
746
747         if (width < quadWidth)
748                 throw tcu::NotSupportedError("Too small render target");
749
750         const int                               maxQuadsX       = width/quadWidth;
751         const int                               numVertices     = MAX_VERTICES;
752
753         const int                               numQuads        = numVertices/6 + (numVertices%6 != 0 ? 1 : 0);
754         const int                               viewportW       = de::min(numQuads, maxQuadsX)*quadWidth;
755         const int                               viewportH       = (numQuads/maxQuadsX + (numQuads%maxQuadsX != 0 ? 1 : 0))*quadHeight;
756
757         if (viewportH > height)
758                 throw tcu::NotSupportedError("Too small render target");
759
760         DE_ASSERT(viewportW <= width && viewportH <= height);
761
762         DE_ASSERT(!m_program);
763         m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
764                 "#version 300 es\n"
765                 "in highp vec4 a_position;\n"
766                 "out mediump vec4 v_color;\n"
767                 "uniform highp vec4 u_colors[24];\n"
768                 "void main (void)\n"
769                 "{\n"
770                 "       gl_Position = a_position;\n"
771                 "       v_color = u_colors[gl_VertexID];\n"
772                 "}\n",
773
774                 "#version 300 es\n"
775                 "in mediump vec4 v_color;\n"
776                 "layout(location = 0) out mediump vec4 o_color;\n"
777                 "void main (void)\n"
778                 "{\n"
779                 "       o_color = v_color;\n"
780                 "}\n"));
781
782         m_testCtx.getLog() << *m_program;
783
784         if (!m_program->isOk())
785         {
786                 delete m_program;
787                 m_program = DE_NULL;
788                 throw tcu::TestError("Compile failed");
789         }
790
791         gl.genBuffers(1, &m_positionBuffer);
792         gl.genBuffers(1, &m_elementBuffer);
793
794         // Set colors (in dynamic memory to save static data space).
795         m_colors.resize(numVertices);
796         m_colors[ 0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
797         m_colors[ 1] = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
798         m_colors[ 2] = tcu::Vec4(0.0f, 0.5f, 1.0f, 1.0f);
799         m_colors[ 3] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
800         m_colors[ 4] = tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f);
801         m_colors[ 5] = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f);
802         m_colors[ 6] = tcu::Vec4(0.5f, 0.0f, 1.0f, 1.0f);
803         m_colors[ 7] = tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f);
804         m_colors[ 8] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
805         m_colors[ 9] = tcu::Vec4(0.5f, 1.0f, 0.0f, 1.0f);
806         m_colors[10] = tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f);
807         m_colors[11] = tcu::Vec4(0.5f, 1.0f, 1.0f, 1.0f);
808         m_colors[12] = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
809         m_colors[13] = tcu::Vec4(1.0f, 0.0f, 0.5f, 1.0f);
810         m_colors[14] = tcu::Vec4(0.0f, 0.5f, 0.5f, 1.0f);
811         m_colors[15] = tcu::Vec4(1.0f, 1.0f, 0.5f, 1.0f);
812         m_colors[16] = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f);
813         m_colors[17] = tcu::Vec4(1.0f, 0.5f, 0.0f, 1.0f);
814         m_colors[18] = tcu::Vec4(0.0f, 1.0f, 0.5f, 1.0f);
815         m_colors[19] = tcu::Vec4(1.0f, 0.5f, 1.0f, 1.0f);
816         m_colors[20] = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
817         m_colors[21] = tcu::Vec4(1.0f, 0.5f, 0.5f, 1.0f);
818         m_colors[22] = tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f);
819         m_colors[23] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
820
821         // Compute positions.
822         m_positions.resize(numVertices);
823         DE_ASSERT(numVertices%3 == 0);
824         for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx += 3)
825         {
826                 const float     h                       = 2.0f * float(quadHeight)/float(viewportH);
827                 const float     w                       = 2.0f * float(quadWidth)/float(viewportW);
828
829                 const int       triNdx          = vtxNdx/3;
830                 const int       quadNdx         = triNdx/2;
831                 const int       quadY           = quadNdx/maxQuadsX;
832                 const int       quadX           = quadNdx%maxQuadsX;
833
834                 const float     x0                      = -1.0f + float(quadX)*w;
835                 const float     y0                      = -1.0f + float(quadY)*h;
836
837                 if (triNdx%2 == 0)
838                 {
839                         m_positions[vtxNdx+0] = tcu::Vec4(x0,   y0,   0.0f, 1.0f);
840                         m_positions[vtxNdx+1] = tcu::Vec4(x0+w, y0+h, 0.0f, 1.0f);
841                         m_positions[vtxNdx+2] = tcu::Vec4(x0,   y0+h, 0.0f, 1.0f);
842                 }
843                 else
844                 {
845                         m_positions[vtxNdx+0] = tcu::Vec4(x0+w, y0+h, 0.0f, 1.0f);
846                         m_positions[vtxNdx+1] = tcu::Vec4(x0,   y0,   0.0f, 1.0f);
847                         m_positions[vtxNdx+2] = tcu::Vec4(x0+w, y0,   0.0f, 1.0f);
848                 }
849         }
850
851         m_viewportW     = viewportW;
852         m_viewportH     = viewportH;
853         m_iterNdx       = 0;
854
855         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
856 }
857
858 void VertexIDCase::deinit (void)
859 {
860         delete m_program;
861         m_program = DE_NULL;
862
863         if (m_positionBuffer)
864         {
865                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_positionBuffer);
866                 m_positionBuffer = 0;
867         }
868
869         if (m_elementBuffer)
870         {
871                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuffer);
872                 m_elementBuffer = 0;
873         }
874
875         m_positions.clear();
876         m_colors.clear();
877 }
878
879 class VertexIDReferenceShader : public rr::VertexShader, public rr::FragmentShader
880 {
881 public:
882         enum
883         {
884                 VARYINGLOC_COLOR = 0
885         };
886
887         VertexIDReferenceShader ()
888                 : rr::VertexShader      (2, 1)          // color and pos in => color out
889                 , rr::FragmentShader(1, 1)              // color in => color out
890         {
891                 this->rr::VertexShader::m_inputs[0].type                = rr::GENERICVECTYPE_FLOAT;
892                 this->rr::VertexShader::m_inputs[1].type                = rr::GENERICVECTYPE_FLOAT;
893
894                 this->rr::VertexShader::m_outputs[0].type               = rr::GENERICVECTYPE_FLOAT;
895                 this->rr::VertexShader::m_outputs[0].flatshade  = false;
896
897                 this->rr::FragmentShader::m_inputs[0].type              = rr::GENERICVECTYPE_FLOAT;
898                 this->rr::FragmentShader::m_inputs[0].flatshade = false;
899
900                 this->rr::FragmentShader::m_outputs[0].type             = rr::GENERICVECTYPE_FLOAT;
901         }
902
903         void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
904         {
905                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
906                 {
907                         const int positionAttrLoc = 0;
908                         const int colorAttrLoc = 1;
909
910                         rr::VertexPacket& packet = *packets[packetNdx];
911
912                         // Transform to position
913                         packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx);
914
915                         // Pass color to FS
916                         packet.outputs[VARYINGLOC_COLOR] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx);
917                 }
918         }
919
920         void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
921         {
922                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
923                 {
924                         rr::FragmentPacket& packet = packets[packetNdx];
925
926                         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
927                                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, VARYINGLOC_COLOR, fragNdx));
928                 }
929         }
930 };
931
932 void VertexIDCase::renderReference (const tcu::PixelBufferAccess& dst, const int numVertices, const deUint16* const indices, const tcu::Vec4* const positions, const tcu::Vec4* const colors)
933 {
934         const rr::Renderer                              referenceRenderer;
935         const rr::RenderState                   referenceState          ((rr::ViewportState)(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst)));
936         const rr::RenderTarget                  referenceTarget         (rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst));
937         const VertexIDReferenceShader   referenceShader;
938               rr::VertexAttrib                  attribs[2];
939
940         attribs[0].type                         = rr::VERTEXATTRIBTYPE_FLOAT;
941         attribs[0].size                         = 4;
942         attribs[0].stride                       = 0;
943         attribs[0].instanceDivisor      = 0;
944         attribs[0].pointer                      = positions;
945
946         attribs[1].type                         = rr::VERTEXATTRIBTYPE_FLOAT;
947         attribs[1].size                         = 4;
948         attribs[1].stride                       = 0;
949         attribs[1].instanceDivisor      = 0;
950         attribs[1].pointer                      = colors;
951
952         referenceRenderer.draw(
953                 rr::DrawCommand(
954                         referenceState,
955                         referenceTarget,
956                         rr::Program(&referenceShader, &referenceShader),
957                         2,
958                         attribs,
959                         rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, numVertices, rr::DrawIndices(indices))));
960 }
961
962 VertexIDCase::IterateResult VertexIDCase::iterate (void)
963 {
964         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
965         const int                               width           = m_context.getRenderTarget().getWidth();
966         const int                               height          = m_context.getRenderTarget().getHeight();
967         const int                               viewportW       = m_viewportW;
968         const int                               viewportH       = m_viewportH;
969
970         const float                             threshold       = 0.02f;
971
972         de::Random                              rnd                     (0xcf23ab1 ^ deInt32Hash(m_iterNdx));
973         tcu::Surface                    refImg          (viewportW, viewportH);
974         tcu::Surface                    testImg         (viewportW, viewportH);
975
976         const int                               viewportX       = rnd.getInt(0, width-viewportW);
977         const int                               viewportY       = rnd.getInt(0, height-viewportH);
978
979         const int                               posLoc          = gl.getAttribLocation(m_program->getProgram(), "a_position");
980         const int                               colorsLoc       = gl.getUniformLocation(m_program->getProgram(), "u_colors[0]");
981         const tcu::Vec4                 clearColor      (0.0f, 0.0f, 0.0f, 1.0f);
982
983         // Setup common state.
984         gl.viewport                                     (viewportX, viewportY, viewportW, viewportH);
985         gl.useProgram                           (m_program->getProgram());
986         gl.bindBuffer                           (GL_ARRAY_BUFFER, m_positionBuffer);
987         gl.enableVertexAttribArray      (posLoc);
988         gl.vertexAttribPointer          (posLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
989         gl.uniform4fv                           (colorsLoc, (int)m_colors.size(), (const float*)&m_colors[0]);
990
991         // Clear render target to black.
992         gl.clearColor   (clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
993         gl.clear                (GL_COLOR_BUFFER_BIT);
994
995         tcu::clear(refImg.getAccess(), clearColor);
996
997         if (m_iterNdx == 0)
998         {
999                 tcu::ScopedLogSection   logSection      (m_testCtx.getLog(), "Iter0", "glDrawArrays()");
1000                 vector<deUint16>                indices         (m_positions.size());
1001
1002                 gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size()*sizeof(tcu::Vec4)), &m_positions[0], GL_DYNAMIC_DRAW);
1003                 gl.drawArrays(GL_TRIANGLES, 0, (int)m_positions.size());
1004
1005                 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
1006                 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1007
1008                 // Reference indices
1009                 for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1010                         indices[ndx] = (deUint16)ndx;
1011
1012                 renderReference(refImg.getAccess(), (int)m_positions.size(), &indices[0], &m_positions[0], &m_colors[0]);
1013         }
1014         else if (m_iterNdx == 1)
1015         {
1016                 tcu::ScopedLogSection   logSection      (m_testCtx.getLog(), "Iter1", "glDrawElements(), indices in client-side array");
1017                 vector<deUint16>                indices         (m_positions.size());
1018                 vector<tcu::Vec4>               mappedPos       (m_positions.size());
1019
1020                 // Compute initial indices and suffle
1021                 for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1022                         indices[ndx] = (deUint16)ndx;
1023                 rnd.shuffle(indices.begin(), indices.end());
1024
1025                 // Use indices to re-map positions.
1026                 for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1027                         mappedPos[indices[ndx]] = m_positions[ndx];
1028
1029                 gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size()*sizeof(tcu::Vec4)), &mappedPos[0], GL_DYNAMIC_DRAW);
1030                 gl.drawElements(GL_TRIANGLES, (int)indices.size(), GL_UNSIGNED_SHORT, &indices[0]);
1031
1032                 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
1033                 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1034
1035                 renderReference(refImg.getAccess(), (int)indices.size(), &indices[0], &mappedPos[0], &m_colors[0]);
1036         }
1037         else if (m_iterNdx == 2)
1038         {
1039                 tcu::ScopedLogSection   logSection      (m_testCtx.getLog(), "Iter2", "glDrawElements(), indices in buffer");
1040                 vector<deUint16>                indices         (m_positions.size());
1041                 vector<tcu::Vec4>               mappedPos       (m_positions.size());
1042
1043                 // Compute initial indices and suffle
1044                 for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1045                         indices[ndx] = (deUint16)ndx;
1046                 rnd.shuffle(indices.begin(), indices.end());
1047
1048                 // Use indices to re-map positions.
1049                 for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1050                         mappedPos[indices[ndx]] = m_positions[ndx];
1051
1052                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer);
1053                 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (int)(indices.size()*sizeof(deUint16)), &indices[0], GL_DYNAMIC_DRAW);
1054
1055                 gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size()*sizeof(tcu::Vec4)), &mappedPos[0], GL_DYNAMIC_DRAW);
1056                 gl.drawElements(GL_TRIANGLES, (int)indices.size(), GL_UNSIGNED_SHORT, DE_NULL);
1057
1058                 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
1059                 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1060
1061                 tcu::clear(refImg.getAccess(), clearColor);
1062                 renderReference(refImg.getAccess(), (int)indices.size(), &indices[0], &mappedPos[0], &m_colors[0]);
1063         }
1064         else
1065                 DE_ASSERT(false);
1066
1067         if (!tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT))
1068                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
1069
1070         m_iterNdx += 1;
1071         return (m_iterNdx < 3) ? CONTINUE : STOP;
1072 }
1073
1074 ShaderBuiltinVarTests::ShaderBuiltinVarTests (Context& context)
1075         : TestCaseGroup(context, "builtin_variable", "Built-in Variable Tests")
1076 {
1077 }
1078
1079 ShaderBuiltinVarTests::~ShaderBuiltinVarTests (void)
1080 {
1081 }
1082
1083 void ShaderBuiltinVarTests::init (void)
1084 {
1085         // Builtin constants.
1086
1087         static const struct
1088         {
1089                 const char*                                                                                     caseName;
1090                 const char*                                                                                     varName;
1091                 ShaderBuiltinConstantCase::GetConstantValueFunc         getValue;
1092         } builtinConstants[] =
1093         {
1094                 // GLES 2.
1095
1096                 { "max_vertex_attribs",                                 "gl_MaxVertexAttribs",                          getInteger<GL_MAX_VERTEX_ATTRIBS>                                               },
1097                 { "max_vertex_uniform_vectors",                 "gl_MaxVertexUniformVectors",           getInteger<GL_MAX_VERTEX_UNIFORM_VECTORS>                               },
1098                 { "max_fragment_uniform_vectors",               "gl_MaxFragmentUniformVectors",         getInteger<GL_MAX_FRAGMENT_UNIFORM_VECTORS>                             },
1099                 { "max_texture_image_units",                    "gl_MaxTextureImageUnits",                      getInteger<GL_MAX_TEXTURE_IMAGE_UNITS>                                  },
1100                 { "max_vertex_texture_image_units",             "gl_MaxVertexTextureImageUnits",        getInteger<GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS>                   },
1101                 { "max_combined_texture_image_units",   "gl_MaxCombinedTextureImageUnits",      getInteger<GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS>                 },
1102                 { "max_draw_buffers",                                   "gl_MaxDrawBuffers",                            getInteger<GL_MAX_DRAW_BUFFERS>                                                 },
1103
1104                 // GLES 3.
1105
1106                 { "max_vertex_output_vectors",                  "gl_MaxVertexOutputVectors",            getVectorsFromComps<GL_MAX_VERTEX_OUTPUT_COMPONENTS>    },
1107                 { "max_fragment_input_vectors",                 "gl_MaxFragmentInputVectors",           getVectorsFromComps<GL_MAX_FRAGMENT_INPUT_COMPONENTS>   },
1108                 { "min_program_texel_offset",                   "gl_MinProgramTexelOffset",                     getInteger<GL_MIN_PROGRAM_TEXEL_OFFSET>                                 },
1109                 { "max_program_texel_offset",                   "gl_MaxProgramTexelOffset",                     getInteger<GL_MAX_PROGRAM_TEXEL_OFFSET>                                 }
1110         };
1111
1112         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtinConstants); ndx++)
1113         {
1114                 const char* const                                                                               caseName        = builtinConstants[ndx].caseName;
1115                 const char* const                                                                               varName         = builtinConstants[ndx].varName;
1116                 const ShaderBuiltinConstantCase::GetConstantValueFunc   getValue        = builtinConstants[ndx].getValue;
1117
1118                 addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_vertex").c_str(),       varName, varName, getValue, glu::SHADERTYPE_VERTEX));
1119                 addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_fragment").c_str(),     varName, varName, getValue, glu::SHADERTYPE_FRAGMENT));
1120         }
1121
1122         addChild(new ShaderDepthRangeTest(m_context, "depth_range_vertex",              "gl_DepthRange", true));
1123         addChild(new ShaderDepthRangeTest(m_context, "depth_range_fragment",    "gl_DepthRange", false));
1124
1125         // Vertex shader builtin variables.
1126         addChild(new VertexIDCase               (m_context));
1127         // \todo [2013-03-20 pyry] gl_InstanceID -- tested in instancing tests quite thoroughly.
1128
1129         // Fragment shader builtin variables.
1130
1131         addChild(new FragCoordXYZCase   (m_context));
1132         addChild(new FragCoordWCase             (m_context));
1133         addChild(new PointCoordCase             (m_context));
1134         addChild(new FrontFacingCase    (m_context));
1135 }
1136
1137 } // Functional
1138 } // gles3
1139 } // deqp