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 void init (void); 67 68 private: 69 std::string m_varName; 70 deUint32 m_paramName; 71 }; 72 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 80 ShaderBuiltinConstantCase::~ShaderBuiltinConstantCase (void) 81 { 82 } 83 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 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 { 148 DepthRangeParams (void) 149 : zNear (0.0f) 150 , zFar (1.0f) 151 { 152 } 153 154 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: 167 DepthRangeEvaluator (const DepthRangeParams& params) 168 : m_params(params) 169 { 170 } 171 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: 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 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 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: 265 FragCoordXYZCase (Context& context) 266 : TestCase(context, "fragcoord_xyz", "gl_FragCoord.xyz Test") 267 { 268 } 269 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 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: 359 FragCoordWCase (Context& context) 360 : TestCase(context, "fragcoord_w", "gl_FragCoord.w Test") 361 { 362 } 363 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: 446 PointCoordCase (Context& context) 447 : TestCase(context, "pointcoord", "gl_PointCoord Test") 448 { 449 } 450 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: 563 FrontFacingCase (Context& context) 564 : TestCase(context, "frontfacing", "gl_FrontFacing Test") 565 { 566 } 567 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 655 ShaderBuiltinVarTests::ShaderBuiltinVarTests (Context& context) 656 : TestCaseGroup(context, "builtin_variable", "Built-in Variable Tests") 657 { 658 } 659 660 ShaderBuiltinVarTests::~ShaderBuiltinVarTests (void) 661 { 662 } 663 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