1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 "es2fShaderBuiltinVarTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "deRandom.hpp"
27 #include "deString.h"
28 #include "deMath.h"
29 #include "deStringUtil.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuTestCase.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuRenderTarget.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "gluPixelTransfer.hpp"
36 #include "gluDrawUtil.hpp"
37
38 #include "glwEnums.hpp"
39 #include "glwFunctions.hpp"
40
41 using std::string;
42 using std::vector;
43 using tcu::TestLog;
44
45 namespace deqp
46 {
47 namespace gles2
48 {
49 namespace Functional
50 {
51
52 const float builtinConstScale = 4.0f;
53
evalBuiltinConstant(gls::ShaderEvalContext & c)54 void evalBuiltinConstant (gls::ShaderEvalContext& c)
55 {
56 bool isOk = 0 == (int)(deFloatFloor(c.coords.x() * builtinConstScale) + 0.05f);
57 c.color = isOk ? tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f) : tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
58 }
59
60 class ShaderBuiltinConstantCase : public gls::ShaderRenderCase
61 {
62 public:
63 ShaderBuiltinConstantCase (Context& context, const char* name, const char* desc, const char* varName, deUint32 paramName, bool isVertexCase);
64 ~ShaderBuiltinConstantCase (void);
65
66 void init (void);
67
68 private:
69 std::string m_varName;
70 deUint32 m_paramName;
71 };
72
ShaderBuiltinConstantCase(Context & context,const char * name,const char * desc,const char * varName,deUint32 paramName,bool isVertexCase)73 ShaderBuiltinConstantCase::ShaderBuiltinConstantCase (Context& context, const char* name, const char* desc, const char* varName, deUint32 paramName, bool isVertexCase)
74 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, evalBuiltinConstant)
75 , m_varName (varName)
76 , m_paramName (paramName)
77 {
78 }
79
~ShaderBuiltinConstantCase(void)80 ShaderBuiltinConstantCase::~ShaderBuiltinConstantCase (void)
81 {
82 }
83
getConstRefValue(const char * varName)84 static int getConstRefValue (const char* varName)
85 {
86 if (deStringEqual(varName, "gl_MaxDrawBuffers"))
87 return 1;
88 else
89 {
90 DE_ASSERT(DE_FALSE);
91 return 0;
92 }
93 }
94
init(void)95 void ShaderBuiltinConstantCase::init (void)
96 {
97 int refValue = m_paramName != GL_NONE ? m_ctxInfo.getInt(m_paramName) : getConstRefValue(m_varName.c_str());
98 m_testCtx.getLog() << tcu::TestLog::Message << m_varName << " = " << refValue << tcu::TestLog::EndMessage;
99
100 static const char* defaultVertSrc =
101 "attribute highp vec4 a_position;\n"
102 "attribute highp vec4 a_coords;\n"
103 "varying mediump vec4 v_coords;\n\n"
104 "void main (void)\n"
105 "{\n"
106 " v_coords = a_coords;\n"
107 " gl_Position = a_position;\n"
108 "}\n";
109 static const char* defaultFragSrc =
110 "varying mediump vec4 v_color;\n\n"
111 "void main (void)\n"
112 "{\n"
113 " gl_FragColor = v_color;\n"
114 "}\n";
115
116 // Construct shader.
117 std::ostringstream src;
118 if (m_isVertexCase)
119 {
120 src << "attribute highp vec4 a_position;\n"
121 << "attribute highp vec4 a_coords;\n"
122 << "varying mediump vec4 v_color;\n";
123 }
124 else
125 src << "varying mediump vec4 v_coords;\n";
126
127 src << "void main (void)\n{\n";
128
129 src << "\tbool isOk = " << m_varName << " == (" << refValue << " + int(floor(" << (m_isVertexCase ? "a_coords" : "v_coords") << ".x * " << de::floatToString(builtinConstScale, 1) << ") + 0.05));\n";
130 src << "\t" << (m_isVertexCase ? "v_color" : "gl_FragColor") << " = isOk ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n";
131
132 if (m_isVertexCase)
133 src << "\tgl_Position = a_position;\n";
134
135 src << "}\n";
136
137 m_vertShaderSource = m_isVertexCase ? src.str() : defaultVertSrc;
138 m_fragShaderSource = m_isVertexCase ? defaultFragSrc : src.str();
139
140 gls::ShaderRenderCase::init();
141 }
142
143 namespace
144 {
145
146 struct DepthRangeParams
147 {
DepthRangeParamsdeqp::gles2::Functional::__anone95c6a420111::DepthRangeParams148 DepthRangeParams (void)
149 : zNear (0.0f)
150 , zFar (1.0f)
151 {
152 }
153
DepthRangeParamsdeqp::gles2::Functional::__anone95c6a420111::DepthRangeParams154 DepthRangeParams (float zNear_, float zFar_)
155 : zNear (zNear_)
156 , zFar (zFar_)
157 {
158 }
159
160 float zNear;
161 float zFar;
162 };
163
164 class DepthRangeEvaluator : public gls::ShaderEvaluator
165 {
166 public:
DepthRangeEvaluator(const DepthRangeParams & params)167 DepthRangeEvaluator (const DepthRangeParams& params)
168 : m_params(params)
169 {
170 }
171
evaluate(gls::ShaderEvalContext & c)172 void evaluate (gls::ShaderEvalContext& c)
173 {
174 float zNear = deFloatClamp(m_params.zNear, 0.0f, 1.0f);
175 float zFar = deFloatClamp(m_params.zFar, 0.0f, 1.0f);
176 float diff = zFar - zNear;
177 c.color.xyz() = tcu::Vec3(zNear, zFar, diff*0.5f + 0.5f);
178 }
179
180 private:
181 const DepthRangeParams& m_params;
182 };
183
184 } // anonymous
185
186 class ShaderDepthRangeTest : public gls::ShaderRenderCase
187 {
188 public:
ShaderDepthRangeTest(Context & context,const char * name,const char * desc,bool isVertexCase)189 ShaderDepthRangeTest (Context& context, const char* name, const char* desc, bool isVertexCase)
190 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator)
191 , m_evaluator (m_depthRange)
192 , m_iterNdx (0)
193 {
194 }
195
init(void)196 void init (void)
197 {
198 static const char* defaultVertSrc =
199 "attribute highp vec4 a_position;\n"
200 "void main (void)\n"
201 "{\n"
202 " gl_Position = a_position;\n"
203 "}\n";
204 static const char* defaultFragSrc =
205 "varying mediump vec4 v_color;\n\n"
206 "void main (void)\n"
207 "{\n"
208 " gl_FragColor = v_color;\n"
209 "}\n";
210
211 // Construct shader.
212 std::ostringstream src;
213 if (m_isVertexCase)
214 src << "attribute highp vec4 a_position;\n"
215 << "varying mediump vec4 v_color;\n";
216
217 src << "void main (void)\n{\n";
218 src << "\t" << (m_isVertexCase ? "v_color" : "gl_FragColor") << " = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff*0.5 + 0.5, 1.0);\n";
219
220 if (m_isVertexCase)
221 src << "\tgl_Position = a_position;\n";
222
223 src << "}\n";
224
225 m_vertShaderSource = m_isVertexCase ? src.str() : defaultVertSrc;
226 m_fragShaderSource = m_isVertexCase ? defaultFragSrc : src.str();
227
228 gls::ShaderRenderCase::init();
229 }
230
iterate(void)231 IterateResult iterate (void)
232 {
233 const glw::Functions& gl = m_renderCtx.getFunctions();
234
235 const DepthRangeParams cases[] =
236 {
237 DepthRangeParams(0.0f, 1.0f),
238 DepthRangeParams(1.5f, -1.0f),
239 DepthRangeParams(0.7f, 0.3f)
240 };
241
242 m_depthRange = cases[m_iterNdx];
243 m_testCtx.getLog() << tcu::TestLog::Message << "glDepthRangef(" << m_depthRange.zNear << ", " << m_depthRange.zFar << ")" << tcu::TestLog::EndMessage;
244 gl.depthRangef(m_depthRange.zNear, m_depthRange.zFar);
245 GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthRangef()");
246
247 gls::ShaderRenderCase::iterate();
248 m_iterNdx += 1;
249
250 if (m_iterNdx == DE_LENGTH_OF_ARRAY(cases) || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
251 return STOP;
252 else
253 return CONTINUE;
254 }
255
256 private:
257 DepthRangeParams m_depthRange;
258 DepthRangeEvaluator m_evaluator;
259 int m_iterNdx;
260 };
261
262 class FragCoordXYZCase : public TestCase
263 {
264 public:
FragCoordXYZCase(Context & context)265 FragCoordXYZCase (Context& context)
266 : TestCase(context, "fragcoord_xyz", "gl_FragCoord.xyz Test")
267 {
268 }
269
iterate(void)270 IterateResult iterate (void)
271 {
272 TestLog& log = m_testCtx.getLog();
273 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
274 const int width = m_context.getRenderTarget().getWidth();
275 const int height = m_context.getRenderTarget().getHeight();
276 const tcu::RGBA threshold = tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
277 const tcu::Vec3 scale (1.f / float(width), 1.f / float(height), 1.0f);
278
279 tcu::Surface testImg (width, height);
280 tcu::Surface refImg (width, height);
281
282 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
283 "attribute highp vec4 a_position;\n"
284 "void main (void)\n"
285 "{\n"
286 " gl_Position = a_position;\n"
287 "}\n",
288
289 "uniform mediump vec3 u_scale;\n"
290 "void main (void)\n"
291 "{\n"
292 " gl_FragColor = vec4(gl_FragCoord.xyz*u_scale, 1.0);\n"
293 "}\n"));
294
295 log << program;
296
297 if (!program.isOk())
298 throw tcu::TestError("Compile failed");
299
300 // Draw with GL.
301 {
302 const float positions[] =
303 {
304 -1.0f, 1.0f, -1.0f, 1.0f,
305 -1.0f, -1.0f, 0.0f, 1.0f,
306 1.0f, 1.0f, 0.0f, 1.0f,
307 1.0f, -1.0f, 1.0f, 1.0f
308 };
309 const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
310
311 const int scaleLoc = gl.getUniformLocation(program.getProgram(), "u_scale");
312 glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
313
314 gl.useProgram(program.getProgram());
315 gl.uniform3fv(scaleLoc, 1, scale.getPtr());
316
317 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
318 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
319
320 glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
321 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
322 }
323
324 // Draw reference
325 for (int y = 0; y < refImg.getHeight(); y++)
326 {
327 for (int x = 0; x < refImg.getWidth(); x++)
328 {
329 const float xf = (float(x)+.5f) / float(refImg.getWidth());
330 const float yf = (float(refImg.getHeight()-y-1)+.5f) / float(refImg.getHeight());
331 const float z = (xf + yf) / 2.0f;
332 const tcu::Vec3 fragCoord (float(x)+.5f, float(y)+.5f, z);
333 const tcu::Vec3 scaledFC = fragCoord*scale;
334 const tcu::Vec4 color (scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
335
336 refImg.setPixel(x, y, tcu::RGBA(color));
337 }
338 }
339
340 // Compare
341 {
342 bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
343 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
344 isOk ? "Pass" : "Image comparison failed");
345 }
346
347 return STOP;
348 }
349 };
350
projectedTriInterpolate(const tcu::Vec3 & s,const tcu::Vec3 & w,float nx,float ny)351 static inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny)
352 {
353 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]);
354 }
355
356 class FragCoordWCase : public TestCase
357 {
358 public:
FragCoordWCase(Context & context)359 FragCoordWCase (Context& context)
360 : TestCase(context, "fragcoord_w", "gl_FragCoord.w Test")
361 {
362 }
363
iterate(void)364 IterateResult iterate (void)
365 {
366 TestLog& log = m_testCtx.getLog();
367 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
368 const int width = m_context.getRenderTarget().getWidth();
369 const int height = m_context.getRenderTarget().getHeight();
370 const tcu::RGBA threshold = tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
371
372 tcu::Surface testImg (width, height);
373 tcu::Surface refImg (width, height);
374
375 const float w[4] = { 1.7f, 2.0f, 1.2f, 1.0f };
376
377 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
378 "attribute highp vec4 a_position;\n"
379 "void main (void)\n"
380 "{\n"
381 " gl_Position = a_position;\n"
382 "}\n",
383
384 "void main (void)\n"
385 "{\n"
386 " gl_FragColor = vec4(0.0, 1.0/gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
387 "}\n"));
388
389 log << program;
390
391 if (!program.isOk())
392 throw tcu::TestError("Compile failed");
393
394 // Draw with GL.
395 {
396 const float positions[] =
397 {
398 -w[0], w[0], 0.0f, w[0],
399 -w[1], -w[1], 0.0f, w[1],
400 w[2], w[2], 0.0f, w[2],
401 w[3], -w[3], 0.0f, w[3]
402 };
403 const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
404
405 glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
406
407 gl.useProgram(program.getProgram());
408
409 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
410 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
411
412 glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
413 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
414 }
415
416 // Draw reference
417 for (int y = 0; y < refImg.getHeight(); y++)
418 {
419 for (int x = 0; x < refImg.getWidth(); x++)
420 {
421 const float xf = (float(x)+.5f) / float(refImg.getWidth());
422 const float yf = (float(refImg.getHeight()-y-1)+.5f) / float(refImg.getHeight());
423 const float oow = ((xf + yf) < 1.0f)
424 ? projectedTriInterpolate(tcu::Vec3(w[0], w[1], w[2]), tcu::Vec3(w[0], w[1], w[2]), xf, yf)
425 : projectedTriInterpolate(tcu::Vec3(w[3], w[2], w[1]), tcu::Vec3(w[3], w[2], w[1]), 1.0f-xf, 1.0f-yf);
426 const tcu::Vec4 color (0.0f, oow - 1.0f, 0.0f, 1.0f);
427
428 refImg.setPixel(x, y, tcu::RGBA(color));
429 }
430 }
431
432 // Compare
433 {
434 bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
435 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
436 isOk ? "Pass" : "Image comparison failed");
437 }
438
439 return STOP;
440 }
441 };
442
443 class PointCoordCase : public TestCase
444 {
445 public:
PointCoordCase(Context & context)446 PointCoordCase (Context& context)
447 : TestCase(context, "pointcoord", "gl_PointCoord Test")
448 {
449 }
450
iterate(void)451 IterateResult iterate (void)
452 {
453 TestLog& log = m_testCtx.getLog();
454 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
455 const int width = de::min(256, m_context.getRenderTarget().getWidth());
456 const int height = de::min(256, m_context.getRenderTarget().getHeight());
457 const float threshold = 0.02f;
458
459 const int numPoints = 8;
460
461 vector<tcu::Vec3> coords (numPoints);
462 float pointSizeRange[2] = { 0.0f, 0.0f };
463
464 de::Random rnd (0x145fa);
465 tcu::Surface testImg (width, height);
466 tcu::Surface refImg (width, height);
467
468 gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, &pointSizeRange[0]);
469 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE)");
470
471 if (pointSizeRange[0] <= 0.0f || pointSizeRange[1] <= 0.0f || pointSizeRange[1] < pointSizeRange[0])
472 throw tcu::TestError("Invalid GL_ALIASED_POINT_SIZE_RANGE");
473
474 // Compute coordinates.
475 {
476
477 for (vector<tcu::Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
478 {
479 coord->x() = rnd.getFloat(-0.9f, 0.9f);
480 coord->y() = rnd.getFloat(-0.9f, 0.9f);
481 coord->z() = rnd.getFloat(pointSizeRange[0], pointSizeRange[1]);
482 }
483 }
484
485 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
486 "attribute highp vec3 a_positionSize;\n"
487 "void main (void)\n"
488 "{\n"
489 " gl_Position = vec4(a_positionSize.xy, 0.0, 1.0);\n"
490 " gl_PointSize = a_positionSize.z;\n"
491 "}\n",
492
493 "void main (void)\n"
494 "{\n"
495 " gl_FragColor = vec4(gl_PointCoord, 0.0, 1.0);\n"
496 "}\n"));
497
498 log << program;
499
500 if (!program.isOk())
501 throw tcu::TestError("Compile failed");
502
503 // Draw with GL.
504 {
505 glu::VertexArrayBinding posBinding = glu::va::Float("a_positionSize", 3, (int)coords.size(), 0, (const float*)&coords[0]);
506 const int viewportX = rnd.getInt(0, m_context.getRenderTarget().getWidth()-width);
507 const int viewportY = rnd.getInt(0, m_context.getRenderTarget().getHeight()-height);
508
509 gl.viewport(viewportX, viewportY, width, height);
510 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
511 gl.clear(GL_COLOR_BUFFER_BIT);
512
513 gl.useProgram(program.getProgram());
514
515 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
516 glu::pr::Points((int)coords.size()));
517
518 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
519 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
520 }
521
522 // Draw reference
523 tcu::clear(refImg.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
524 for (vector<tcu::Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
525 {
526 const int x0 = deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) - pointIter->z()*0.5f);
527 const int y0 = deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) - pointIter->z()*0.5f);
528 const int x1 = deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) + pointIter->z()*0.5f);
529 const int y1 = deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) + pointIter->z()*0.5f);
530 const int w = x1-x0;
531 const int h = y1-y0;
532
533 for (int yo = 0; yo < h; yo++)
534 {
535 for (int xo = 0; xo < w; xo++)
536 {
537 const float xf = float(xo+0.5f) / float(w);
538 const float yf = float((h-yo-1)+0.5f) / float(h);
539 const tcu::Vec4 color (xf, yf, 0.0f, 1.0f);
540 const int dx = x0+xo;
541 const int dy = y0+yo;
542
543 if (de::inBounds(dx, 0, refImg.getWidth()) && de::inBounds(dy, 0, refImg.getHeight()))
544 refImg.setPixel(dx, dy, tcu::RGBA(color));
545 }
546 }
547 }
548
549 // Compare
550 {
551 bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
552 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
553 isOk ? "Pass" : "Image comparison failed");
554 }
555
556 return STOP;
557 }
558 };
559
560 class FrontFacingCase : public TestCase
561 {
562 public:
FrontFacingCase(Context & context)563 FrontFacingCase (Context& context)
564 : TestCase(context, "frontfacing", "gl_FrontFacing Test")
565 {
566 }
567
iterate(void)568 IterateResult iterate (void)
569 {
570 // Test case renders two adjecent quads, where left is has front-facing
571 // triagles and right back-facing. Color is selected based on gl_FrontFacing
572 // value.
573
574 TestLog& log = m_testCtx.getLog();
575 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
576 de::Random rnd (0x89f2c);
577 const int width = de::min(64, m_context.getRenderTarget().getWidth());
578 const int height = de::min(64, m_context.getRenderTarget().getHeight());
579 const int viewportX = rnd.getInt(0, m_context.getRenderTarget().getWidth()-width);
580 const int viewportY = rnd.getInt(0, m_context.getRenderTarget().getHeight()-height);
581 const tcu::RGBA threshold = tcu::RGBA(1,1,1,1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
582
583 tcu::Surface testImg (width, height);
584 tcu::Surface refImg (width, height);
585
586 const glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(
587 "attribute highp vec4 a_position;\n"
588 "void main (void)\n"
589 "{\n"
590 " gl_Position = a_position;\n"
591 "}\n",
592
593 "void main (void)\n"
594 "{\n"
595 " if (gl_FrontFacing)\n"
596 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
597 " else\n"
598 " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
599 "}\n"));
600
601 log << program;
602
603 if (!program.isOk())
604 throw tcu::TestError("Compile failed");
605
606 // Draw with GL.
607 {
608 const float positions[] =
609 {
610 -1.0f, 1.0f, 0.0f, 1.0f,
611 -1.0f, -1.0f, 0.0f, 1.0f,
612 1.0f, 1.0f, 0.0f, 1.0f,
613 1.0f, -1.0f, 0.0f, 1.0f
614 };
615 const deUint16 indicesCCW[] = { 0, 1, 2, 2, 1, 3 };
616 const deUint16 indicesCW[] = { 2, 1, 0, 3, 1, 2 };
617
618 glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
619
620 gl.useProgram(program.getProgram());
621
622 gl.viewport(viewportX, viewportY, width/2, height);
623 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
624 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0]));
625
626 gl.viewport(viewportX + width/2, viewportY, width-width/2, height);
627 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
628 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0]));
629
630 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
631 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
632 }
633
634 // Draw reference
635 for (int y = 0; y < refImg.getHeight(); y++)
636 {
637 for (int x = 0; x < refImg.getWidth()/2; x++)
638 refImg.setPixel(x, y, tcu::RGBA::green);
639
640 for (int x = refImg.getWidth()/2; x < refImg.getWidth(); x++)
641 refImg.setPixel(x, y, tcu::RGBA::blue);
642 }
643
644 // Compare
645 {
646 bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT);
647 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
648 isOk ? "Pass" : "Image comparison failed");
649 }
650
651 return STOP;
652 }
653 };
654
ShaderBuiltinVarTests(Context & context)655 ShaderBuiltinVarTests::ShaderBuiltinVarTests (Context& context)
656 : TestCaseGroup(context, "builtin_variable", "Built-in Variable Tests")
657 {
658 }
659
~ShaderBuiltinVarTests(void)660 ShaderBuiltinVarTests::~ShaderBuiltinVarTests (void)
661 {
662 }
663
init(void)664 void ShaderBuiltinVarTests::init (void)
665 {
666 // Builtin constants.
667
668 static const struct
669 {
670 const char* caseName;
671 const char* varName;
672 deUint32 paramName;
673 } builtinConstants[] =
674 {
675 { "max_vertex_attribs", "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
676 { "max_vertex_uniform_vectors", "gl_MaxVertexUniformVectors", GL_MAX_VERTEX_UNIFORM_VECTORS },
677 { "max_fragment_uniform_vectors", "gl_MaxFragmentUniformVectors", GL_MAX_FRAGMENT_UNIFORM_VECTORS },
678 { "max_varying_vectors", "gl_MaxVaryingVectors", GL_MAX_VARYING_VECTORS },
679 { "max_texture_image_units", "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
680 { "max_vertex_texture_image_units", "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
681 { "max_combined_texture_image_units", "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
682 { "max_draw_buffers", "gl_MaxDrawBuffers", GL_NONE }
683 };
684
685 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtinConstants); ndx++)
686 {
687 const char* caseName = builtinConstants[ndx].caseName;
688 const char* varName = builtinConstants[ndx].varName;
689 deUint32 paramName = builtinConstants[ndx].paramName;
690
691 addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_vertex").c_str(), varName, varName, paramName, true));
692 addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_fragment").c_str(), varName, varName, paramName, false));
693 }
694
695 addChild(new ShaderDepthRangeTest(m_context, "depth_range_vertex", "gl_DepthRange", true));
696 addChild(new ShaderDepthRangeTest(m_context, "depth_range_fragment", "gl_DepthRange", false));
697
698 // Fragment shader builtin variables.
699
700 addChild(new FragCoordXYZCase (m_context));
701 addChild(new FragCoordWCase (m_context));
702 addChild(new PointCoordCase (m_context));
703 addChild(new FrontFacingCase (m_context));
704 }
705
706 } // Functional
707 } // gles2
708 } // deqp
709