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