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