1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL (ES) 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 GLES Scissor tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "glsScissorTests.hpp" 25 #include "glsTextureTestUtil.hpp" 26 27 #include "deMath.h" 28 #include "deRandom.hpp" 29 #include "deUniquePtr.hpp" 30 31 #include "tcuTestCase.hpp" 32 #include "tcuImageCompare.hpp" 33 #include "tcuVector.hpp" 34 #include "tcuVectorUtil.hpp" 35 #include "tcuTexture.hpp" 36 #include "tcuStringTemplate.hpp" 37 38 #include "gluStrUtil.hpp" 39 #include "gluDrawUtil.hpp" 40 #include "gluPixelTransfer.hpp" 41 #include "gluObjectWrapper.hpp" 42 43 #include "glwEnums.hpp" 44 #include "glwFunctions.hpp" 45 46 #include <map> 47 48 namespace deqp 49 { 50 namespace gls 51 { 52 namespace Functional 53 { 54 namespace 55 { 56 57 using namespace ScissorTestInternal; 58 using namespace glw; // GL types 59 60 using tcu::ConstPixelBufferAccess; 61 using tcu::PixelBufferAccess; 62 using tcu::TestLog; 63 64 using std::vector; 65 using std::string; 66 using std::map; 67 using tcu::Vec3; 68 using tcu::Vec4; 69 using tcu::IVec4; 70 using tcu::UVec4; 71 72 void drawQuad (const glw::Functions& gl, deUint32 program, const Vec3& p0, const Vec3& p1) 73 { 74 // Vertex data. 75 const float hz = (p0.z() + p1.z()) * 0.5f; 76 const float position[] = 77 { 78 p0.x(), p0.y(), p0.z(), 1.0f, 79 p0.x(), p1.y(), hz, 1.0f, 80 p1.x(), p0.y(), hz, 1.0f, 81 p1.x(), p1.y(), p1.z(), 1.0f 82 }; 83 84 const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 }; 85 86 const deInt32 posLoc = gl.getAttribLocation(program, "a_position"); 87 88 gl.useProgram(program); 89 gl.enableVertexAttribArray(posLoc); 90 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]); 91 92 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]); 93 94 gl.disableVertexAttribArray(posLoc); 95 96 } 97 98 void drawPrimitives (const glw::Functions& gl, deUint32 program, const deUint32 type, const vector<float>& vertices, const vector<deUint16>& indices) 99 { 100 const deInt32 posLoc = gl.getAttribLocation(program, "a_position"); 101 102 TCU_CHECK(posLoc >= 0); 103 104 gl.useProgram(program); 105 gl.enableVertexAttribArray(posLoc); 106 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]); 107 108 gl.drawElements(type, GLsizei(indices.size()), GL_UNSIGNED_SHORT, &indices[0]); 109 110 gl.disableVertexAttribArray(posLoc); 111 } 112 113 template<typename T> 114 void clearEdges (const tcu::PixelBufferAccess& access, const T& color, const IVec4& scissorArea) 115 { 116 for (int y = 0; y < access.getHeight(); y++) 117 for (int x = 0; x < access.getWidth(); x++) 118 { 119 if (y < scissorArea.y() || 120 y >= scissorArea.y() + scissorArea.w() || 121 x < scissorArea.x() || 122 x >= scissorArea.x()+ scissorArea.z()) 123 access.setPixel(color, x, y); 124 } 125 } 126 127 glu::ProgramSources genShaders(glu::GLSLVersion version) 128 { 129 const string vtxSource = "${VERSION}\n" 130 "${IN} highp vec4 a_position;\n" 131 "void main(){\n" 132 " gl_Position = a_position;\n" 133 "}\n"; 134 135 const string frgSource = "${VERSION}\n" 136 "${OUT_DECL}" 137 "uniform highp vec4 u_color;\n" 138 "void main(){\n" 139 " ${OUTPUT} = u_color;\n" 140 "}\n"; 141 142 map<string, string> params; 143 144 switch(version) 145 { 146 case glu::GLSL_VERSION_100_ES: 147 params["VERSION"] = "#version 100"; 148 params["IN"] = "attribute"; 149 params["OUT_DECL"] = ""; 150 params["OUTPUT"] = "gl_FragColor"; 151 break; 152 153 case glu::GLSL_VERSION_300_ES: 154 case glu::GLSL_VERSION_310_ES: // Assumed to support 3.0 155 params["VERSION"] = "#version 300 es"; 156 params["IN"] = "in"; 157 params["OUT_DECL"] = "out mediump vec4 f_color;\n"; 158 params["OUTPUT"] = "f_color"; 159 break; 160 161 default: 162 DE_ASSERT(!"Unsupported version"); 163 } 164 165 return glu::makeVtxFragSources(tcu::StringTemplate(vtxSource).specialize(params), tcu::StringTemplate(frgSource).specialize(params)); 166 } 167 168 // Wrapper class, provides iterator & reporting logic 169 class ScissorCase : public tcu::TestCase 170 { 171 public: 172 ScissorCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char *name, const char* desc, const Vec4& scissorArea); 173 virtual ~ScissorCase (void) {} 174 175 virtual IterateResult iterate (void); 176 177 protected: 178 virtual void render (GLuint program, const IVec4& viewport) const = 0; 179 180 glu::RenderContext& m_renderCtx; 181 const Vec4 m_scissorArea; 182 }; 183 184 ScissorCase::ScissorCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char *name, const char* desc, const Vec4& scissorArea) 185 : TestCase (testCtx, name, desc) 186 , m_renderCtx (renderCtx) 187 , m_scissorArea (scissorArea) 188 { 189 } 190 191 ScissorCase::IterateResult ScissorCase::iterate (void) 192 { 193 using TextureTestUtil::RandomViewport; 194 195 const glw::Functions& gl = m_renderCtx.getFunctions(); 196 TestLog& log = m_testCtx.getLog(); 197 const tcu::PixelFormat renderFormat = m_renderCtx.getRenderTarget().getPixelFormat(); 198 const tcu::Vec4 threshold = 0.02f * UVec4(1u << de::max(0, 8 - renderFormat.redBits), 199 1u << de::max(0, 8 - renderFormat.greenBits), 200 1u << de::max(0, 8 - renderFormat.blueBits), 201 1u << de::max(0, 8 - renderFormat.alphaBits)).asFloat(); 202 const glu::ShaderProgram shader (m_renderCtx, genShaders(glu::getContextTypeGLSLVersion(m_renderCtx.getType()))); 203 204 const RandomViewport viewport (m_renderCtx.getRenderTarget(), 256, 256, deStringHash(getName())); 205 const IVec4 relScissorArea (int(m_scissorArea.x()*viewport.width), 206 int(m_scissorArea.y()*viewport.height), 207 int(m_scissorArea.z()*viewport.width), 208 int(m_scissorArea.w()*viewport.height)); 209 const IVec4 absScissorArea (relScissorArea.x() + viewport.x, 210 relScissorArea.y() + viewport.y, 211 relScissorArea.z(), 212 relScissorArea.w()); 213 214 tcu::Surface refImage (viewport.width, viewport.height); 215 tcu::Surface resImage (viewport.width, viewport.height); 216 217 if (!shader.isOk()) 218 { 219 log << shader; 220 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader compile/link failed"); 221 return STOP; 222 } 223 224 log << TestLog::Message << "Viewport area is " << IVec4(viewport.x, viewport.y, viewport.width, viewport.height) << TestLog::EndMessage; 225 log << TestLog::Message << "Scissor area is " << absScissorArea << TestLog::EndMessage; 226 227 // Render reference (no scissors) 228 { 229 log << TestLog::Message << "Rendering reference (scissors disabled)" << TestLog::EndMessage; 230 231 gl.useProgram(shader.getProgram()); 232 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 233 234 gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f); 235 gl.clearDepthf(1.0f); 236 gl.clearStencil(0); 237 gl.disable(GL_DEPTH_TEST); 238 gl.disable(GL_STENCIL_TEST); 239 gl.disable(GL_SCISSOR_TEST); 240 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 241 242 render(shader.getProgram(), IVec4(viewport.x, viewport.y, viewport.width, viewport.height)); 243 244 glu::readPixels(m_renderCtx, viewport.x, viewport.y, refImage.getAccess()); 245 GLU_CHECK_ERROR(gl.getError()); 246 } 247 248 // Render result (scissors) 249 { 250 log << TestLog::Message << "Rendering result (scissors enabled)" << TestLog::EndMessage; 251 252 gl.useProgram(shader.getProgram()); 253 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 254 255 gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f); 256 gl.clearDepthf(1.0f); 257 gl.clearStencil(0); 258 gl.disable(GL_DEPTH_TEST); 259 gl.disable(GL_STENCIL_TEST); 260 gl.disable(GL_SCISSOR_TEST); 261 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 262 263 gl.scissor(absScissorArea.x(), absScissorArea.y(), absScissorArea.z(), absScissorArea.w()); 264 gl.enable(GL_SCISSOR_TEST); 265 266 render(shader.getProgram(), IVec4(viewport.x, viewport.y, viewport.width, viewport.height)); 267 268 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resImage.getAccess()); 269 GLU_CHECK_ERROR(gl.getError()); 270 } 271 272 // Manual 'scissors' for reference image 273 log << TestLog::Message << "Clearing area outside scissor area from reference" << TestLog::EndMessage; 274 clearEdges(refImage.getAccess(), IVec4(32, 64, 128, 255), relScissorArea); 275 276 if (tcu::floatThresholdCompare(log, "ComparisonResult", "Image comparison result", refImage.getAccess(), resImage.getAccess(), threshold, tcu::COMPARE_LOG_RESULT)) 277 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 278 else 279 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 280 281 return STOP; 282 } 283 284 // Tests scissoring with multiple primitive types 285 class ScissorPrimitiveCase : public ScissorCase 286 { 287 public: 288 ScissorPrimitiveCase (tcu::TestContext& testCtx, 289 glu::RenderContext& renderCtx, 290 const char* name, 291 const char* desc, 292 const Vec4& scissorArea, 293 const Vec4& renderArea, 294 PrimitiveType type, 295 int primitiveCount); 296 virtual ~ScissorPrimitiveCase (void){} 297 298 protected: 299 virtual void render (GLuint program, const IVec4& viewport) const; 300 301 private: 302 const Vec4 m_renderArea; 303 const PrimitiveType m_primitiveType; 304 const int m_primitiveCount; 305 }; 306 307 ScissorPrimitiveCase::ScissorPrimitiveCase (tcu::TestContext& testCtx, 308 glu::RenderContext& renderCtx, 309 const char* name, 310 const char* desc, 311 const Vec4& scissorArea, 312 const Vec4& renderArea, 313 PrimitiveType type, 314 int primitiveCount) 315 : ScissorCase (testCtx, renderCtx, name, desc, scissorArea) 316 , m_renderArea (renderArea) 317 , m_primitiveType (type) 318 , m_primitiveCount (primitiveCount) 319 { 320 } 321 322 void ScissorPrimitiveCase::render (GLuint program, const IVec4&) const 323 { 324 const glw::Functions& gl = m_renderCtx.getFunctions(); 325 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0); 326 const Vec4 primitiveArea (m_renderArea.x()*2.0f-1.0f, 327 m_renderArea.x()*2.0f-1.0f, 328 m_renderArea.z()*2.0f, 329 m_renderArea.w()*2.0f); 330 331 static const float quadPositions[] = 332 { 333 0.0f, 1.0f, 334 0.0f, 0.0f, 335 1.0f, 1.0f, 336 1.0f, 0.0f 337 }; 338 static const float triPositions[] = 339 { 340 0.0f, 0.0f, 341 1.0f, 0.0f, 342 0.5f, 1.0f, 343 }; 344 static const float linePositions[] = 345 { 346 0.0f, 0.0f, 347 1.0f, 1.0f 348 }; 349 static const float pointPosition[] = 350 { 351 0.5f, 0.5f 352 }; 353 354 const float* positionSet[] = { pointPosition, linePositions, triPositions, quadPositions }; 355 const int vertexCountSet[]= { 1, 2, 3, 4 }; 356 const int indexCountSet[] = { 1, 2, 3, 6 }; 357 358 const deUint16 baseIndices[] = { 0, 1, 2, 2, 1, 3 }; 359 const float* basePositions = positionSet[m_primitiveType]; 360 const int vertexCount = vertexCountSet[m_primitiveType]; 361 const int indexCount = indexCountSet[m_primitiveType]; 362 363 const float scale = 1.44f/deFloatSqrt(float(m_primitiveCount)*2.0f); // Magic value to roughly fill the render area with primitives at a readable density 364 vector<float> positions (4*vertexCount*m_primitiveCount); 365 vector<deUint16> indices (indexCount*m_primitiveCount); 366 de::Random rng (1234); 367 368 for (int primNdx = 0; primNdx < m_primitiveCount; primNdx++) 369 { 370 const float dx = m_primitiveCount>1 ? rng.getFloat() : 0.0f; 371 const float dy = m_primitiveCount>1 ? rng.getFloat() : 0.0f; 372 373 for (int vertNdx = 0; vertNdx < vertexCount; vertNdx++) 374 { 375 const int ndx = primNdx*4*vertexCount + vertNdx*4; 376 positions[ndx+0] = (basePositions[vertNdx*2 + 0]*scale + dx)*primitiveArea.z() + primitiveArea.x(); 377 positions[ndx+1] = (basePositions[vertNdx*2 + 1]*scale + dy)*primitiveArea.w() + primitiveArea.y(); 378 positions[ndx+2] = 0.2f; 379 positions[ndx+3] = 1.0f; 380 } 381 382 for (int ndx = 0; ndx < indexCount; ndx++) 383 indices[primNdx*indexCount + ndx] = baseIndices[ndx] + primNdx*vertexCount; 384 } 385 386 gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, white.m_data); 387 388 switch (m_primitiveType) 389 { 390 case TRIANGLE: drawPrimitives(gl, program, GL_TRIANGLES, positions, indices); break; 391 case LINE: drawPrimitives(gl, program, GL_LINES, positions, indices); break; 392 case POINT: drawPrimitives(gl, program, GL_POINTS, positions, indices); break; 393 default: DE_ASSERT(false); break; 394 } 395 } 396 397 // Test effect of scissor on default framebuffer clears 398 class ScissorClearCase : public ScissorCase 399 { 400 public: 401 ScissorClearCase (tcu::TestContext& testCtx, 402 glu::RenderContext& renderCtx, 403 const char* name, 404 const char* desc, 405 const Vec4& scissorArea, 406 deUint32 clearMode); 407 virtual ~ScissorClearCase (void) {} 408 409 virtual void init (void); 410 411 protected: 412 virtual void render (GLuint program, const IVec4& viewport) const; 413 414 private: 415 const deUint32 m_clearMode; //!< Combination of the flags accepted by glClear 416 }; 417 418 ScissorClearCase::ScissorClearCase (tcu::TestContext& testCtx, 419 glu::RenderContext& renderCtx, 420 const char* name, 421 const char* desc, 422 const Vec4& scissorArea, 423 deUint32 clearMode) 424 : ScissorCase (testCtx, renderCtx, name, desc, scissorArea) 425 , m_clearMode (clearMode) 426 { 427 } 428 429 void ScissorClearCase::init (void) 430 { 431 if ((m_clearMode & GL_DEPTH_BUFFER_BIT) && m_renderCtx.getRenderTarget().getDepthBits() == 0) 432 throw tcu::NotSupportedError("Cannot clear depth; no depth buffer present", "", __FILE__, __LINE__); 433 else if ((m_clearMode & GL_STENCIL_BUFFER_BIT) && m_renderCtx.getRenderTarget().getStencilBits() == 0) 434 throw tcu::NotSupportedError("Cannot clear stencil; no stencil buffer present", "", __FILE__, __LINE__); 435 } 436 437 void ScissorClearCase::render (GLuint program, const IVec4&) const 438 { 439 const glw::Functions& gl = m_renderCtx.getFunctions(); 440 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0); 441 442 gl.clearColor(0.6f, 0.1f, 0.1f, 1.0); 443 gl.clearDepthf(0.0f); 444 445 if (m_clearMode & GL_DEPTH_BUFFER_BIT) 446 { 447 gl.enable(GL_DEPTH_TEST); 448 gl.depthFunc(GL_GREATER); 449 } 450 451 if (m_clearMode & GL_STENCIL_BUFFER_BIT) 452 { 453 gl.clearStencil(123); 454 gl.enable(GL_STENCIL_TEST); 455 gl.stencilFunc(GL_EQUAL, 123, ~0u); 456 } 457 458 if (m_clearMode & GL_COLOR_BUFFER_BIT) 459 gl.clearColor(0.1f, 0.6f, 0.1f, 1.0); 460 461 gl.clear(m_clearMode); 462 gl.disable(GL_SCISSOR_TEST); 463 464 gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, white.getPtr()); 465 466 if (!(m_clearMode & GL_COLOR_BUFFER_BIT)) 467 drawQuad(gl, program, Vec3(-1.0f, -1.0f, 0.5f), Vec3(1.0f, 1.0f, 0.5f)); 468 469 gl.disable(GL_DEPTH_TEST); 470 gl.disable(GL_STENCIL_TEST); 471 } 472 473 class FramebufferBlitCase : public ScissorCase 474 { 475 public: 476 FramebufferBlitCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, const Vec4& scissorArea); 477 virtual ~FramebufferBlitCase (void) {} 478 479 virtual void init (void); 480 virtual void deinit (void); 481 482 protected: 483 typedef de::MovePtr<glu::Framebuffer> FramebufferP; 484 485 enum {SIZE = 64}; 486 487 virtual void render (GLuint program, const IVec4& viewport) const; 488 489 FramebufferP m_fbo; 490 }; 491 492 FramebufferBlitCase::FramebufferBlitCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, const Vec4& scissorArea) 493 : ScissorCase(testCtx, renderCtx, name, desc, scissorArea) 494 { 495 } 496 497 void FramebufferBlitCase::init (void) 498 { 499 if (m_renderCtx.getRenderTarget().getNumSamples()) 500 throw tcu::NotSupportedError("Cannot blit to multisampled framebuffer", "", __FILE__, __LINE__); 501 502 const glw::Functions& gl = m_renderCtx.getFunctions(); 503 const glu::Renderbuffer colorbuf (gl); 504 const tcu::Vec4 clearColor (1.0f, 0.5, 0.125f, 1.0f); 505 506 m_fbo = FramebufferP(new glu::Framebuffer(gl)); 507 508 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, **m_fbo); 509 510 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorbuf); 511 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SIZE, SIZE); 512 gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorbuf); 513 514 gl.clearBufferfv(GL_COLOR, 0, clearColor.getPtr()); 515 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_renderCtx.getDefaultFramebuffer()); 516 } 517 518 void FramebufferBlitCase::deinit (void) 519 { 520 m_fbo.clear(); 521 } 522 523 void FramebufferBlitCase::render(GLuint program, const IVec4& viewport) const 524 { 525 const glw::Functions& gl = m_renderCtx.getFunctions(); 526 527 const int width = viewport.z(); 528 const int height = viewport.w(); 529 const deInt32 defaultFramebuffer = m_renderCtx.getDefaultFramebuffer(); 530 531 DE_UNREF(program); 532 533 // blit to default framebuffer 534 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo); 535 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebuffer); 536 537 gl.blitFramebuffer(0, 0, SIZE, SIZE, viewport.x(), viewport.y(), viewport.x() + width, viewport.y() + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); 538 539 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebuffer); 540 } 541 542 struct BufferFmtDesc 543 { 544 tcu::TextureFormat texFmt; 545 GLenum colorFmt; 546 }; 547 548 struct Color 549 { 550 enum Type {FLOAT, INT, UINT}; 551 552 Type type; 553 554 union 555 { 556 float f[4]; 557 deInt32 i[4]; 558 deUint32 u[4]; 559 }; 560 561 Color(const float f_[4]) : type(FLOAT) { f[0] = f_[0]; f[1] = f_[1]; f[2] = f_[2]; f[3] = f_[3]; } 562 Color(const deInt32 i_[4]) : type(INT) { i[0] = i_[0]; i[1] = i_[1]; i[2] = i_[2]; i[3] = i_[3]; } 563 Color(const deUint32 u_[4]) : type(UINT) { u[0] = u_[0]; u[1] = u_[1]; u[2] = u_[2]; u[3] = u_[3]; } 564 }; 565 566 class FramebufferClearCase : public tcu::TestCase 567 { 568 public: 569 FramebufferClearCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, ClearType clearType); 570 virtual ~FramebufferClearCase (void) {} 571 572 virtual IterateResult iterate (void); 573 574 private: 575 static void clearBuffers (const glw::Functions& gl, Color color, float depth, int stencil); 576 static Color getBaseColor (const BufferFmtDesc& bufferFmt); 577 static Color getMainColor (const BufferFmtDesc& bufferFmt); 578 static BufferFmtDesc getBufferFormat (ClearType type); 579 580 virtual void render (GLuint program) const; 581 582 glu::RenderContext& m_renderCtx; 583 const ClearType m_clearType; 584 }; 585 586 FramebufferClearCase::FramebufferClearCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, ClearType clearType) 587 : tcu::TestCase (testCtx, name, desc) 588 , m_renderCtx (renderCtx) 589 , m_clearType (clearType) 590 { 591 } 592 593 void FramebufferClearCase::clearBuffers (const glw::Functions& gl, Color color, float depth, int stencil) 594 { 595 switch(color.type) 596 { 597 case Color::FLOAT: gl.clearBufferfv (GL_COLOR, 0, color.f); break; 598 case Color::INT: gl.clearBufferiv (GL_COLOR, 0, color.i); break; 599 case Color::UINT: gl.clearBufferuiv(GL_COLOR, 0, color.u); break; 600 default: 601 DE_ASSERT(false); 602 } 603 604 gl.clearBufferfv(GL_DEPTH, 0, &depth); 605 gl.clearBufferiv(GL_STENCIL, 0, &stencil); 606 } 607 608 FramebufferClearCase::IterateResult FramebufferClearCase::iterate (void) 609 { 610 TestLog& log = m_testCtx.getLog(); 611 const glw::Functions& gl = m_renderCtx.getFunctions(); 612 const glu::ShaderProgram shader (m_renderCtx, genShaders(glu::getContextTypeGLSLVersion(m_renderCtx.getType()))); 613 614 const glu::Framebuffer fbo (gl); 615 const glu::Renderbuffer colorbuf (gl); 616 const glu::Renderbuffer depthbuf (gl); 617 618 const BufferFmtDesc bufferFmt = getBufferFormat(m_clearType); 619 const Color baseColor = getBaseColor(bufferFmt); 620 621 const int width = 64; 622 const int height = 64; 623 624 const IVec4 scissorArea (8, 8, 48, 48); 625 626 vector<deUint8> refData (width*height*bufferFmt.texFmt.getPixelSize()); 627 vector<deUint8> resData (width*height*bufferFmt.texFmt.getPixelSize()); 628 629 tcu::PixelBufferAccess refAccess (bufferFmt.texFmt, width, height, 1, &refData[0]); 630 tcu::PixelBufferAccess resAccess (bufferFmt.texFmt, width, height, 1, &resData[0]); 631 632 if (!shader.isOk()) 633 { 634 log << shader; 635 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader compile/link failed"); 636 return STOP; 637 } 638 639 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 640 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *fbo); 641 642 // Color 643 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorbuf); 644 gl.renderbufferStorage(GL_RENDERBUFFER, bufferFmt.colorFmt, width, height); 645 gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorbuf); 646 647 // Depth/stencil 648 gl.bindRenderbuffer(GL_RENDERBUFFER, *depthbuf); 649 gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); 650 gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *depthbuf); 651 652 log << TestLog::Message << "Scissor area is " << scissorArea << TestLog::EndMessage; 653 654 // Render reference 655 { 656 log << TestLog::Message << "Rendering reference (scissors disabled)" << TestLog::EndMessage; 657 658 gl.useProgram(shader.getProgram()); 659 gl.viewport(0, 0, width, height); 660 661 gl.disable(GL_DEPTH_TEST); 662 gl.disable(GL_STENCIL_TEST); 663 gl.disable(GL_SCISSOR_TEST); 664 665 clearBuffers(gl, baseColor, 1.0f, 0); 666 667 render(shader.getProgram()); 668 669 glu::readPixels(m_renderCtx, 0, 0, refAccess); 670 GLU_CHECK_ERROR(gl.getError()); 671 } 672 673 // Render result 674 { 675 log << TestLog::Message << "Rendering result (scissors enabled)" << TestLog::EndMessage; 676 677 gl.useProgram(shader.getProgram()); 678 gl.viewport(0, 0, width, height); 679 680 gl.disable(GL_DEPTH_TEST); 681 gl.disable(GL_STENCIL_TEST); 682 gl.disable(GL_SCISSOR_TEST); 683 684 clearBuffers(gl, baseColor, 1.0f, 0); 685 686 gl.enable(GL_SCISSOR_TEST); 687 gl.scissor(scissorArea.x(), scissorArea.y(), scissorArea.z(), scissorArea.w()); 688 689 render(shader.getProgram()); 690 691 glu::readPixels(m_renderCtx, 0, 0, resAccess); 692 GLU_CHECK_ERROR(gl.getError()); 693 } 694 695 { 696 bool resultOk = false; 697 698 switch (baseColor.type) 699 { 700 case Color::FLOAT: 701 clearEdges(refAccess, Vec4(baseColor.f[0], baseColor.f[1], baseColor.f[2], baseColor.f[3]), scissorArea); 702 resultOk = tcu::floatThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, Vec4(0.02f, 0.02f, 0.02f, 0.02f), tcu::COMPARE_LOG_RESULT); 703 break; 704 705 case Color::INT: 706 clearEdges(refAccess, IVec4(baseColor.i[0], baseColor.i[1], baseColor.i[2], baseColor.i[3]), scissorArea); 707 resultOk = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, UVec4(2, 2, 2, 2), tcu::COMPARE_LOG_RESULT); 708 break; 709 710 case Color::UINT: 711 clearEdges(refAccess, UVec4(baseColor.u[0], baseColor.u[1], baseColor.u[2], baseColor.u[3]), scissorArea); 712 resultOk = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, UVec4(2, 2, 2, 2), tcu::COMPARE_LOG_RESULT); 713 break; 714 } 715 716 if (resultOk) 717 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 718 else 719 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 720 } 721 722 return STOP; 723 } 724 725 Color FramebufferClearCase::getBaseColor (const BufferFmtDesc& bufferFmt) 726 { 727 const float f[4] = {0.125f, 0.25f, 0.5f, 1.0f}; 728 const deInt32 i[4] = {0, 0, 0, 0}; 729 const deUint32 u[4] = {0, 0, 0, 0}; 730 731 switch(bufferFmt.colorFmt) 732 { 733 case GL_RGBA8: return Color(f); 734 case GL_RGBA8I: return Color(i); 735 case GL_RGBA8UI: return Color(u); 736 default: 737 DE_ASSERT(false); 738 } 739 740 return Color(f); 741 } 742 743 Color FramebufferClearCase::getMainColor (const BufferFmtDesc& bufferFmt) 744 { 745 const float f[4] = {1.0f, 1.0f, 0.5f, 1.0f}; 746 const deInt32 i[4] = {127, -127, 0, 127}; 747 const deUint32 u[4] = {255, 255, 0, 255}; 748 749 switch(bufferFmt.colorFmt) 750 { 751 case GL_RGBA8: return Color(f); 752 case GL_RGBA8I: return Color(i); 753 case GL_RGBA8UI: return Color(u); 754 default: 755 DE_ASSERT(false); 756 } 757 758 return Color(f); 759 } 760 761 BufferFmtDesc FramebufferClearCase::getBufferFormat (ClearType type) 762 { 763 BufferFmtDesc retval; 764 765 switch (type) 766 { 767 case CLEAR_COLOR_FLOAT: 768 retval.colorFmt = GL_RGBA16F; 769 retval.texFmt = tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::HALF_FLOAT); 770 DE_ASSERT(!"Floating point clear not implemented");// \todo [2014-1-23 otto] pixel read format & type, nothing guaranteed, need extension... 771 break; 772 773 case CLEAR_COLOR_INT: 774 retval.colorFmt = GL_RGBA8I; 775 retval.texFmt = tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32); 776 break; 777 778 case CLEAR_COLOR_UINT: 779 retval.colorFmt = GL_RGBA8UI; 780 retval.texFmt = tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32); 781 break; 782 783 default: 784 retval.colorFmt = GL_RGBA8; 785 retval.texFmt = tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8); 786 break; 787 } 788 789 return retval; 790 } 791 792 void FramebufferClearCase::render (GLuint program) const 793 { 794 const glw::Functions& gl = m_renderCtx.getFunctions(); 795 796 const BufferFmtDesc bufferFmt = getBufferFormat(m_clearType); 797 const Color clearColor = getMainColor(bufferFmt); 798 799 const int clearStencil = 123; 800 const float clearDepth = 0.5f; 801 802 switch (m_clearType) 803 { 804 case CLEAR_COLOR_FIXED: gl.clearBufferfv (GL_COLOR, 0, clearColor.f); break; 805 case CLEAR_COLOR_FLOAT: gl.clearBufferfv (GL_COLOR, 0, clearColor.f); break; 806 case CLEAR_COLOR_INT: gl.clearBufferiv (GL_COLOR, 0, clearColor.i); break; 807 case CLEAR_COLOR_UINT: gl.clearBufferuiv(GL_COLOR, 0, clearColor.u); break; 808 case CLEAR_DEPTH: gl.clearBufferfv (GL_DEPTH, 0, &clearDepth); break; 809 case CLEAR_STENCIL: gl.clearBufferiv (GL_STENCIL, 0, &clearStencil); break; 810 case CLEAR_DEPTH_STENCIL: gl.clearBufferfi (GL_DEPTH_STENCIL, 0, clearDepth, clearStencil); break; 811 812 default: 813 DE_ASSERT(false); 814 } 815 816 const bool useDepth = (m_clearType == CLEAR_DEPTH || m_clearType == CLEAR_DEPTH_STENCIL); 817 const bool useStencil = (m_clearType == CLEAR_STENCIL || m_clearType == CLEAR_DEPTH_STENCIL); 818 819 // Render something to expose changes to depth/stencil buffer 820 if (useDepth || useStencil) 821 { 822 if (useDepth) 823 gl.enable(GL_DEPTH_TEST); 824 825 if (useStencil) 826 gl.enable(GL_STENCIL_TEST); 827 828 gl.stencilFunc(GL_EQUAL, clearStencil, ~0u); 829 gl.depthFunc(GL_GREATER); 830 gl.disable(GL_SCISSOR_TEST); 831 832 gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, clearColor.f); 833 drawQuad(gl, program, tcu::Vec3(-1.0f, -1.0f, 0.6f), tcu::Vec3(1.0f, 1.0f, 0.6f)); 834 } 835 } 836 837 } // Anonymous 838 839 namespace ScissorTestInternal 840 { 841 842 tcu::TestNode* createPrimitiveTest (tcu::TestContext& testCtx, 843 glu::RenderContext& renderCtx, 844 const char* name, 845 const char* desc, 846 const Vec4& scissorArea, 847 const Vec4& renderArea, 848 PrimitiveType type, 849 int primitiveCount) 850 { 851 return new ScissorPrimitiveCase(testCtx, renderCtx, name, desc, scissorArea, renderArea, type, primitiveCount); 852 } 853 854 tcu::TestNode* createClearTest (tcu::TestContext& testCtx, 855 glu::RenderContext& renderCtx, 856 const char* name, 857 const char* desc, 858 const Vec4& scissorArea, 859 deUint32 clearMode) 860 { 861 return new ScissorClearCase(testCtx, renderCtx, name, desc, scissorArea, clearMode); 862 } 863 864 tcu::TestNode* createFramebufferClearTest (tcu::TestContext& testCtx, 865 glu::RenderContext& renderCtx, 866 const char* name, 867 const char* desc, 868 ClearType clearType) 869 { 870 return new FramebufferClearCase(testCtx, renderCtx, name, desc, clearType); 871 } 872 873 tcu::TestNode* createFramebufferBlitTest (tcu::TestContext& testCtx, 874 glu::RenderContext& renderCtx, 875 const char* name, 876 const char* desc, 877 const Vec4& scissorArea) 878 { 879 return new FramebufferBlitCase(testCtx, renderCtx, name, desc, scissorArea); 880 } 881 882 } // ScissorTestInternal 883 } // Functional 884 } // gls 885 } // deqp 886