1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2017 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 FBO sRGB tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fFboSRGBWriteControlTests.hpp" 25 #include "es31fFboTestUtil.hpp" 26 #include "gluTextureUtil.hpp" 27 #include "gluContextInfo.hpp" 28 #include "tcuTestLog.hpp" 29 #include "glwEnums.hpp" 30 #include "sglrContextUtil.hpp" 31 #include "glwFunctions.hpp" 32 #include "deUniquePtr.hpp" 33 #include "deSharedPtr.hpp" 34 #include "gluObjectWrapper.hpp" 35 #include "gluPixelTransfer.hpp" 36 #include "glsTextureTestUtil.hpp" 37 #include "tcuVectorUtil.hpp" 38 #include "gluStrUtil.hpp" 39 40 namespace deqp 41 { 42 namespace gles31 43 { 44 namespace Functional 45 { 46 namespace 47 { 48 49 tcu::Vec4 getTestColorLinear (void) 50 { 51 return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f); 52 } 53 54 tcu::Vec4 getTestColorSRGB (void) 55 { 56 return linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f)); 57 } 58 59 tcu::Vec4 getTestColorBlank (void) 60 { 61 return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); 62 } 63 64 tcu::Vec4 getEpsilonError (void) 65 { 66 return tcu::Vec4(0.005f); 67 } 68 69 enum QueryType 70 { 71 QUERYTYPE_ISENABLED = 0, 72 QUERYTYPE_BOOLEAN, 73 QUERYTYPE_FLOAT, 74 QUERYTYPE_INT, 75 QUERYTYPE_INT64, 76 QUERYTYPE_LAST 77 }; 78 79 enum DataType 80 { 81 DATATYPE_BOOLEAN = 0, 82 DATATYPE_FLOAT, 83 DATATYPE_INT, 84 DATATYPE_INT64, 85 }; 86 87 enum FramebufferSRGB 88 { 89 FRAMEBUFFERSRGB_ENABLED = 0, 90 FRAMEBUFFERSRGB_DISABLED 91 }; 92 93 enum FramebufferBlend 94 { 95 FRAMEBUFFERBLEND_ENABLED = 0, 96 FRAMEBUFFERBLEND_DISABLED 97 }; 98 99 enum TextureSourcesType 100 { 101 TEXTURESOURCESTYPE_RGBA = 0, 102 TEXTURESOURCESTYPE_SRGBA, 103 TEXTURESOURCESTYPE_BOTH, 104 TEXTURESOURCESTYPE_NONE 105 }; 106 107 enum FboType 108 { 109 FBOTYPE_SOURCE = 0, 110 FBOTYPE_DESTINATION 111 }; 112 113 enum RendererTask 114 { 115 RENDERERTASK_DRAW = 0, 116 RENDERERTASK_COPY 117 }; 118 119 enum SamplingType 120 { 121 SAMPLINGTYPE_TEXTURE = 0, 122 SAMPLINGTYPE_TEXTURE_LOD, 123 SAMPLINGTYPE_TEXTURE_GRAD, 124 SAMPLINGTYPE_TEXTURE_OFFSET, 125 SAMPLINGTYPE_TEXTURE_PROJ, 126 }; 127 128 namespace TestTextureSizes 129 { 130 const int WIDTH = 128; 131 const int HEIGHT = 128; 132 } // global test texture sizes 133 134 namespace SampligTypeCount 135 { 136 const int MAX = 5; 137 } // global max number of sampling types 138 139 std::string buildSamplingPassType (const int samplerTotal) 140 { 141 std::ostringstream shaderFragment; 142 143 const SamplingType samplingTypeList [] = 144 { 145 SAMPLINGTYPE_TEXTURE, SAMPLINGTYPE_TEXTURE_LOD, SAMPLINGTYPE_TEXTURE_GRAD, SAMPLINGTYPE_TEXTURE_OFFSET, SAMPLINGTYPE_TEXTURE_PROJ 146 } ; 147 148 for (int samplerTypeIdx = 0; samplerTypeIdx < DE_LENGTH_OF_ARRAY(samplingTypeList); samplerTypeIdx++) 149 { 150 shaderFragment 151 << " if (uFunctionType == " << samplerTypeIdx << ") \n" 152 << " { \n"; 153 154 for (int samplerIdx = 0; samplerIdx < samplerTotal; samplerIdx++) 155 { 156 switch (static_cast<SamplingType>(samplerTypeIdx)) 157 { 158 case SAMPLINGTYPE_TEXTURE: 159 { 160 shaderFragment 161 << " texelColor" << samplerIdx << " = texture(uTexture" << samplerIdx << ", vs_aTexCoord); \n"; 162 break; 163 } 164 case SAMPLINGTYPE_TEXTURE_LOD: 165 { 166 shaderFragment 167 << " texelColor" << samplerIdx << " = textureLod(uTexture" << samplerIdx << ", vs_aTexCoord, 0.0f); \n"; 168 break; 169 } 170 case SAMPLINGTYPE_TEXTURE_GRAD: 171 { 172 shaderFragment 173 << " texelColor" << samplerIdx << " = textureGrad(uTexture" << samplerIdx << ", vs_aTexCoord, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)); \n"; 174 break; 175 } 176 case SAMPLINGTYPE_TEXTURE_OFFSET: 177 { 178 shaderFragment 179 << " texelColor" << samplerIdx << " = textureOffset(uTexture" << samplerIdx << ", vs_aTexCoord, ivec2(0.0f, 0.0f)); \n"; 180 break; 181 } 182 case SAMPLINGTYPE_TEXTURE_PROJ: 183 { 184 shaderFragment 185 << " texelColor" << samplerIdx << " = textureProj(uTexture" << samplerIdx << ", vec3(vs_aTexCoord, 1.0f)); \n"; 186 break; 187 } 188 default: 189 DE_FATAL("Error: sampling type unrecognised"); 190 } 191 } 192 193 shaderFragment 194 << " } \n"; 195 } 196 197 return shaderFragment.str(); 198 } 199 200 void logColor (Context& context, const std::string& colorLogMessage, const tcu::Vec4 resultColor) 201 { 202 tcu::TestLog& log = context.getTestContext().getLog(); 203 std::ostringstream message; 204 205 message << colorLogMessage << " = (" << resultColor.x() << ", " << resultColor.y() << ", " << resultColor.z() << ", " << resultColor.w() << ")"; 206 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 207 } 208 209 struct TestFunction 210 { 211 explicit TestFunction (const bool hasFunctionValue) 212 : hasFunction (hasFunctionValue) {} 213 TestFunction (const char* const functionNameValue, const char* const functionDefinition) 214 : hasFunction (true) 215 , functionName (functionNameValue) 216 , functionDefintion (functionDefinition) {} 217 ~TestFunction (void) {} 218 219 bool hasFunction; 220 const char* functionName; 221 const char* functionDefintion; 222 }; 223 224 TestFunction getFunctionBlendLinearToSRGBCheck (void) 225 { 226 const char* const functionName = "blendPlusLinearToSRGB"; 227 228 const char* const functionDefinition = 229 "mediump vec4 blendPlusLinearToSRGB(in mediump vec4 colorSrc, in mediump vec4 colorDst) \n" 230 "{ \n" 231 " const int MAX_VECTOR_SIZE = 4; \n" 232 " mediump vec4 colorConverted; \n" 233 " mediump vec4 colorBlended; \n" 234 " for (int idx = 0; idx < MAX_VECTOR_SIZE; idx++) \n" 235 " { \n" 236 " if (uBlendFunctionType == 0) \n" 237 " { \n" 238 " colorBlended[idx] = (colorSrc[idx] * uFactorSrc) + colorDst[idx] * uFactorDst; \n" 239 " } \n" 240 " if (uBlendFunctionType == 1) \n" 241 " { \n" 242 " colorBlended[idx] = (colorSrc[idx] * uFactorSrc) - (colorDst[idx] * uFactorDst); \n" 243 " } \n" 244 "if (uBlendFunctionType == 2) \n" 245 " { \n" 246 " colorBlended[idx] = (colorDst[idx] * uFactorDst) - (colorSrc[idx] * uFactorSrc); \n" 247 " } \n" 248 " if (colorBlended[idx] < 0.0031308f) \n" 249 " { \n" 250 " colorConverted[idx] = 12.92f * colorBlended[idx]; \n" 251 " } \n" 252 " else \n" 253 " { \n" 254 " colorConverted[idx] = 1.055f * pow(colorBlended[idx], 0.41666f) - 0.055f; \n" 255 " } \n" 256 " } \n" 257 " return colorConverted; \n" 258 "} \n"; 259 260 TestFunction testFunction(functionName, functionDefinition); 261 262 return testFunction; 263 } 264 265 struct FBOConfig 266 { 267 FBOConfig (const deUint32 textureInternalFormatValue, 268 const tcu::Vec4 textureColorValue, 269 const deUint32 fboTargetTypeValue, 270 const deUint32 fboColorAttachmentValue, 271 const FboType fboTypeValue) 272 : textureInternalFormat (textureInternalFormatValue) 273 , textureColor (textureColorValue) 274 , fboTargetType (fboTargetTypeValue) 275 , fboColorAttachment (fboColorAttachmentValue) 276 , fboType (fboTypeValue) {} 277 ~FBOConfig (void) {} 278 279 deUint32 textureInternalFormat; 280 tcu::Vec4 textureColor; 281 deUint32 fboTargetType; 282 deUint32 fboColorAttachment; 283 FboType fboType; 284 }; 285 286 struct BlendConfig 287 { 288 deUint32 equation; 289 deUint32 funcSrc; 290 deUint32 funcDst; 291 }; 292 293 std::vector<BlendConfig> getBlendingConfigList (void) 294 { 295 BlendConfig blendConfigs[12]; 296 297 // add function permutations 298 blendConfigs[0].equation = GL_FUNC_ADD; 299 blendConfigs[1].equation = GL_FUNC_ADD; 300 blendConfigs[2].equation = GL_FUNC_ADD; 301 blendConfigs[3].equation = GL_FUNC_ADD; 302 303 blendConfigs[0].funcSrc = GL_ONE; 304 blendConfigs[0].funcDst = GL_ONE; 305 blendConfigs[1].funcSrc = GL_ONE; 306 blendConfigs[1].funcDst = GL_ZERO; 307 blendConfigs[2].funcSrc = GL_ZERO; 308 blendConfigs[2].funcDst = GL_ONE; 309 blendConfigs[3].funcSrc = GL_ZERO; 310 blendConfigs[3].funcDst = GL_ZERO; 311 312 // subtract function permutations 313 blendConfigs[4].equation = GL_FUNC_SUBTRACT; 314 blendConfigs[5].equation = GL_FUNC_SUBTRACT; 315 blendConfigs[6].equation = GL_FUNC_SUBTRACT; 316 blendConfigs[7].equation = GL_FUNC_SUBTRACT; 317 318 blendConfigs[4].funcSrc = GL_ONE; 319 blendConfigs[4].funcDst = GL_ONE; 320 blendConfigs[5].funcSrc = GL_ONE; 321 blendConfigs[5].funcDst = GL_ZERO; 322 blendConfigs[6].funcSrc = GL_ZERO; 323 blendConfigs[6].funcDst = GL_ONE; 324 blendConfigs[7].funcSrc = GL_ZERO; 325 blendConfigs[7].funcDst = GL_ZERO; 326 327 // reverse subtract function permutations 328 blendConfigs[8].equation = GL_FUNC_REVERSE_SUBTRACT; 329 blendConfigs[9].equation = GL_FUNC_REVERSE_SUBTRACT; 330 blendConfigs[10].equation = GL_FUNC_REVERSE_SUBTRACT; 331 blendConfigs[11].equation = GL_FUNC_REVERSE_SUBTRACT; 332 333 blendConfigs[8].funcSrc = GL_ONE; 334 blendConfigs[8].funcDst = GL_ONE; 335 blendConfigs[9].funcSrc = GL_ONE; 336 blendConfigs[9].funcDst = GL_ZERO; 337 blendConfigs[10].funcSrc = GL_ZERO; 338 blendConfigs[10].funcDst = GL_ONE; 339 blendConfigs[11].funcSrc = GL_ZERO; 340 blendConfigs[11].funcDst = GL_ZERO; 341 342 std::vector<BlendConfig> configList(blendConfigs, blendConfigs + DE_LENGTH_OF_ARRAY(blendConfigs)); 343 344 return configList; 345 } 346 347 struct TestRenderPassConfig 348 { 349 TestRenderPassConfig (void) 350 : testFunction (false) {} 351 352 TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue, 353 FBOConfig fboConfigListValue, 354 const FramebufferSRGB framebufferSRGBValue, 355 const FramebufferBlend framebufferBendValue, 356 const RendererTask rendererTaskValue) 357 : textureSourcesType (textureSourcesTypeValue) 358 , framebufferSRGB (framebufferSRGBValue) 359 , frameBufferBlend (framebufferBendValue) 360 , testFunction (false) 361 , rendererTask (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);} 362 363 TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue, 364 FBOConfig fboConfigListValue, 365 const FramebufferSRGB framebufferSRGBValue, 366 const FramebufferBlend framebufferBendValue, 367 TestFunction testFunctionValue, 368 const RendererTask rendererTaskValue) 369 : textureSourcesType (textureSourcesTypeValue) 370 , framebufferSRGB (framebufferSRGBValue) 371 , frameBufferBlend (framebufferBendValue) 372 , testFunction (testFunctionValue) 373 , rendererTask (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);} 374 375 TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue, 376 std::vector<FBOConfig> fboConfigListValue, 377 const FramebufferSRGB framebufferSRGBValue, 378 const FramebufferBlend framebufferBendValue, 379 TestFunction testFunctionValue, 380 const RendererTask rendererTaskValue) 381 : textureSourcesType (textureSourcesTypeValue) 382 , fboConfigList (fboConfigListValue) 383 , framebufferSRGB (framebufferSRGBValue) 384 , frameBufferBlend (framebufferBendValue) 385 , testFunction (testFunctionValue) 386 , rendererTask (rendererTaskValue) {} 387 388 ~TestRenderPassConfig (void) {} 389 390 TextureSourcesType textureSourcesType; 391 std::vector<FBOConfig> fboConfigList; 392 FramebufferSRGB framebufferSRGB; 393 FramebufferBlend frameBufferBlend; 394 TestFunction testFunction; 395 RendererTask rendererTask; 396 }; 397 398 class TestVertexData 399 { 400 public: 401 TestVertexData (Context& context); 402 ~TestVertexData (void); 403 404 void init (void); 405 406 void bind (void) const; 407 void unbind (void) const; 408 409 private: 410 const glw::Functions* m_gl; 411 std::vector<float> m_data; 412 glw::GLuint m_vboHandle; 413 glw::GLuint m_vaoHandle; 414 }; 415 416 TestVertexData::TestVertexData (Context& context) 417 : m_gl (&context.getRenderContext().getFunctions()) 418 { 419 const glw::GLfloat vertexData[] = 420 { 421 // position // texcoord 422 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left corner 423 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right corner 424 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner 425 426 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left corner 427 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner 428 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f // bottom left corner 429 }; 430 431 m_data.resize(DE_LENGTH_OF_ARRAY(vertexData)); 432 for (int idx = 0; idx < (int)m_data.size(); idx++) 433 m_data[idx] = vertexData[idx]; 434 435 m_gl->genVertexArrays(1, &m_vaoHandle); 436 m_gl->bindVertexArray(m_vaoHandle); 437 438 m_gl->genBuffers(1, &m_vboHandle); 439 m_gl->bindBuffer(GL_ARRAY_BUFFER, m_vboHandle); 440 441 m_gl->bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)(m_data.size() * sizeof(glw::GLfloat)), &m_data[0], GL_STATIC_DRAW); 442 443 m_gl->enableVertexAttribArray(0); 444 m_gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0); 445 m_gl->enableVertexAttribArray(1); 446 m_gl->vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT))); 447 448 m_gl->bindVertexArray(0); 449 m_gl->bindBuffer(GL_ARRAY_BUFFER, 0); 450 GLU_EXPECT_NO_ERROR(m_gl->getError(), "gl error during vertex data setup"); 451 } 452 453 TestVertexData::~TestVertexData (void) 454 { 455 m_gl->deleteBuffers(1, &m_vboHandle); 456 m_gl->deleteVertexArrays(1, &m_vaoHandle); 457 } 458 459 void TestVertexData::bind (void) const 460 { 461 m_gl->bindVertexArray(m_vaoHandle); 462 } 463 464 void TestVertexData::unbind (void) const 465 { 466 m_gl->bindVertexArray(0); 467 } 468 469 class TestTexture2D 470 { 471 public: 472 TestTexture2D (Context& context, const deUint32 internalFormatValue, const deUint32 transferFormatValue, const deUint32 transferTypeValue, const tcu::Vec4 imageColorValue, const int idx); 473 ~TestTexture2D (void); 474 475 int getTextureUnit (void) const; 476 deUint32 getHandle (void) const; 477 int getIdx (void) const; 478 479 void bind (const int textureUnit); 480 void unbind (void) const; 481 482 private: 483 const glw::Functions* m_gl; 484 glw::GLuint m_handle; 485 const deUint32 m_internalFormat; 486 tcu::TextureFormat m_transferFormat; 487 int m_width; 488 int m_height; 489 tcu::TextureLevel m_imageData; 490 int m_textureUnit; 491 const int m_idx; 492 }; 493 494 TestTexture2D::TestTexture2D (Context& context, const deUint32 internalFormat, const deUint32 transferFormat, const deUint32 transferType, const tcu::Vec4 imageColor, const int idx) 495 : m_gl (&context.getRenderContext().getFunctions()) 496 , m_internalFormat (internalFormat) 497 , m_transferFormat (tcu::TextureFormat(glu::mapGLTransferFormat(transferFormat, transferType))) 498 , m_width (TestTextureSizes::WIDTH) 499 , m_height (TestTextureSizes::HEIGHT) 500 , m_imageData (tcu::TextureLevel(glu::mapGLInternalFormat(internalFormat), m_width, m_height, 1)) 501 , m_idx (idx) 502 { 503 // fill image data with a solid test color 504 tcu::clear(m_imageData.getAccess(), tcu::Vec4(0.0f)); 505 for (int py = 0; py < m_imageData.getHeight(); py++) 506 { 507 for (int px = 0; px < m_imageData.getWidth(); px++) 508 m_imageData.getAccess().setPixel(imageColor, px, py); 509 } 510 511 m_gl->genTextures(1, &m_handle); 512 513 m_gl->bindTexture(GL_TEXTURE_2D, m_handle); 514 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 515 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 516 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 517 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 518 519 m_gl->texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFormat, transferType, m_imageData.getAccess().getDataPtr()); 520 521 m_gl->bindTexture(GL_TEXTURE_2D, 0); 522 } 523 524 TestTexture2D::~TestTexture2D (void) 525 { 526 m_gl->deleteTextures(1, &m_handle); 527 } 528 529 int TestTexture2D::getTextureUnit (void) const 530 { 531 return m_textureUnit; 532 } 533 534 deUint32 TestTexture2D::getHandle (void) const 535 { 536 return m_handle; 537 } 538 539 int TestTexture2D::getIdx (void) const 540 { 541 return m_idx; 542 } 543 544 void TestTexture2D::bind (const int textureUnit) 545 { 546 m_textureUnit = textureUnit; 547 m_gl->activeTexture(GL_TEXTURE0 + m_textureUnit); 548 m_gl->bindTexture(GL_TEXTURE_2D, m_handle); 549 } 550 551 void TestTexture2D::unbind (void) const 552 { 553 m_gl->bindTexture(GL_TEXTURE_2D, 0); 554 } 555 556 class TestFramebuffer 557 { 558 public: 559 TestFramebuffer (void); 560 TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx); 561 ~TestFramebuffer (void); 562 563 void setTargetType (const deUint32 targetType); 564 565 FboType getType (void) const; 566 deUint32 getHandle (void) const; 567 deUint32 getColorAttachment (void) const; 568 int getIdx (void) const; 569 deUint32 getTargetType (void) const; 570 571 void bind (void); 572 void unbind (void); 573 574 typedef de::UniquePtr<glu::Framebuffer> fboUniquePtr; 575 576 private: 577 const glw::Functions* m_gl; 578 fboUniquePtr m_referenceSource; 579 deUint32 m_targetType; 580 bool m_bound; 581 bool m_isSRGB; 582 FboType m_type; 583 const int m_idx; 584 deUint32 m_colorAttachment; 585 }; 586 587 TestFramebuffer::TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx) 588 : m_gl (&context.getRenderContext().getFunctions()) 589 , m_referenceSource (new glu::Framebuffer(context.getRenderContext())) 590 , m_targetType (targetType) 591 , m_bound (false) 592 , m_isSRGB (isSRGB) 593 , m_type (fboType) 594 , m_idx (idx) 595 , m_colorAttachment (colorAttachment) 596 { 597 m_gl->bindFramebuffer(m_targetType, **m_referenceSource); 598 599 m_gl->framebufferTexture2D(m_targetType, m_colorAttachment, GL_TEXTURE_2D, textureAttachmentHandle, 0); 600 601 TCU_CHECK(m_gl->checkFramebufferStatus(m_targetType) == GL_FRAMEBUFFER_COMPLETE); 602 603 if (targetType == GL_DRAW_BUFFER) 604 { 605 glw::GLuint textureAttachments[] = {m_colorAttachment}; 606 m_gl->drawBuffers(DE_LENGTH_OF_ARRAY(textureAttachments), textureAttachments); 607 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glDrawBuffer()"); 608 } 609 610 if (targetType == GL_READ_BUFFER) 611 { 612 m_gl->readBuffer(m_colorAttachment); 613 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glReadBuffer()"); 614 } 615 616 m_gl->bindFramebuffer(m_targetType, 0); 617 } 618 619 TestFramebuffer::~TestFramebuffer (void) 620 { 621 } 622 623 void TestFramebuffer::setTargetType (const deUint32 targetType) 624 { 625 m_targetType = targetType; 626 } 627 628 FboType TestFramebuffer::getType (void) const 629 { 630 return m_type; 631 } 632 633 deUint32 TestFramebuffer::getHandle (void) const 634 { 635 return **m_referenceSource; 636 } 637 638 deUint32 TestFramebuffer::getColorAttachment (void) const 639 { 640 return m_colorAttachment; 641 } 642 643 int TestFramebuffer::getIdx (void) const 644 { 645 return m_idx; 646 } 647 648 deUint32 TestFramebuffer::getTargetType (void) const 649 { 650 return m_targetType; 651 } 652 653 void TestFramebuffer::bind (void) 654 { 655 if (!m_bound) 656 { 657 m_gl->bindFramebuffer(m_targetType, **m_referenceSource); 658 m_bound = true; 659 } 660 } 661 662 void TestFramebuffer::unbind (void) 663 { 664 if (m_bound) 665 { 666 m_gl->bindFramebuffer(m_targetType, 0); 667 m_bound = false; 668 } 669 } 670 671 class TestShaderProgram 672 { 673 public: 674 TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction); 675 ~TestShaderProgram (void); 676 677 glw::GLuint getHandle (void) const; 678 int getSamplerTotal (void) const; 679 680 void use (void) const; 681 void unuse (void) const; 682 683 glu::ShaderProgramInfo getLogInfo (void); 684 685 private: 686 const glw::Functions* m_gl; 687 de::MovePtr<glu::ShaderProgram> m_referenceSource; 688 const int m_samplerTotal; 689 const int m_shaderStagesTotal; 690 }; 691 692 TestShaderProgram::TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction) 693 : m_gl (&context.getRenderContext().getFunctions()) 694 , m_samplerTotal (samplerTotal) 695 , m_shaderStagesTotal (2) 696 { 697 std::ostringstream shaderFragment; 698 699 const char* const shaderVertex = 700 "#version 310 es \n" 701 "layout (location = 0) in mediump vec3 aPosition; \n" 702 "layout (location = 1) in mediump vec2 aTexCoord; \n" 703 "out mediump vec2 vs_aTexCoord; \n" 704 "void main () \n" 705 "{ \n" 706 " gl_Position = vec4(aPosition, 1.0f); \n" 707 " vs_aTexCoord = aTexCoord; \n" 708 "} \n"; 709 710 shaderFragment 711 << "#version 310 es \n" 712 << "in mediump vec2 vs_aTexCoord; \n" 713 << "layout (location = 0) out mediump vec4 fs_aColor0; \n"; 714 715 for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++) 716 shaderFragment 717 << "uniform sampler2D uTexture" << samplerIdx << "; \n"; 718 719 shaderFragment 720 << "uniform int uFunctionType; \n"; 721 722 if (testFunction.hasFunction) 723 shaderFragment 724 << "uniform int uBlendFunctionType; \n" 725 << "uniform mediump float uFactorSrc; \n" 726 << "uniform mediump float uFactorDst; \n" 727 << testFunction.functionDefintion; 728 729 shaderFragment 730 << "void main () \n" 731 << "{ \n"; 732 733 for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++) 734 shaderFragment 735 <<" mediump vec4 texelColor" << samplerIdx << " = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n"; 736 737 shaderFragment 738 << buildSamplingPassType(m_samplerTotal); 739 740 if (testFunction.hasFunction) 741 shaderFragment 742 << " fs_aColor0 = " << testFunction.functionName << "(texelColor0, texelColor1); \n"; 743 else 744 shaderFragment 745 << " fs_aColor0 = texelColor0; \n"; 746 747 shaderFragment 748 << "} \n"; 749 750 m_referenceSource = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(context.getRenderContext(), glu::makeVtxFragSources(shaderVertex, shaderFragment.str()))); 751 if (!m_referenceSource->isOk()) 752 { 753 tcu::TestLog& log = context.getTestContext().getLog(); 754 log << this->getLogInfo(); 755 TCU_FAIL("Failed to compile shaders and link program"); 756 } 757 } 758 759 TestShaderProgram::~TestShaderProgram (void) 760 { 761 m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL); 762 m_referenceSource.clear(); 763 } 764 765 deUint32 TestShaderProgram::getHandle (void) const 766 { 767 return m_referenceSource->getProgram(); 768 } 769 770 int TestShaderProgram::getSamplerTotal (void) const 771 { 772 return m_samplerTotal; 773 } 774 775 void TestShaderProgram::use (void) const 776 { 777 m_gl->useProgram(this->getHandle()); 778 } 779 780 void TestShaderProgram::unuse (void) const 781 { 782 m_gl->useProgram(0); 783 } 784 785 glu::ShaderProgramInfo TestShaderProgram::getLogInfo (void) 786 { 787 glu::ShaderProgramInfo buildInfo; 788 789 // log shader program info. Only vertex and fragment shaders included 790 buildInfo.program = m_referenceSource->getProgramInfo(); 791 for (int shaderIdx = 0; shaderIdx < m_shaderStagesTotal; shaderIdx++) 792 { 793 glu::ShaderInfo shaderInfo = m_referenceSource->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0); 794 buildInfo.shaders.push_back(shaderInfo); 795 } 796 return buildInfo; 797 } 798 799 class Renderer 800 { 801 public: 802 Renderer (Context& context); 803 ~Renderer (void); 804 805 void init (const TestRenderPassConfig& renderPassConfig, const int renderpass); 806 void deinit (void); 807 808 void setSamplingType (const SamplingType samplerIdx); 809 void setBlendIteration (const int blendIteration); 810 void setFramebufferBlend (const bool blend); 811 void setFramebufferSRGB (const bool sRGB); 812 813 std::vector<tcu::Vec4> getResultsPreDraw (void) const; 814 std::vector<tcu::Vec4> getResultsPostDraw (void) const; 815 int getBlendConfigCount (void) const; 816 glu::ShaderProgramInfo getShaderProgramInfo (void); 817 818 void copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy); 819 void draw (void); 820 void storeShaderProgramInfo (void); 821 void logShaderProgramInfo (void); 822 823 typedef de::SharedPtr<TestTexture2D> TextureSp; 824 typedef de::SharedPtr<TestFramebuffer> FboSp; 825 826 private: 827 void createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList); 828 void setShaderProgramSamplingType (const int samplerIdx); 829 void setShaderBlendFunctionType (void); 830 void setShaderBlendSrcDstValues (void); 831 void bindActiveTexturesSamplers (void); 832 void bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired); 833 void unbindAllSourceTextures (void); 834 void bindFramebuffer (const int framebufferIdx); 835 void unbindFramebuffer (const int framebufferIdx); 836 void enableFramebufferSRGB (void); 837 void enableFramebufferBlend (void); 838 bool isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const; 839 void readTexels (const int px, const int py, const deUint32 attachment, tcu::Vec4& texelData); 840 void logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const; 841 842 // renderer specific constants initialized during constructor 843 Context& m_context; 844 const TestVertexData m_vertexData; 845 const int m_textureSourceTotal; 846 847 // additional resources monitored by the renderer 848 std::vector<BlendConfig> m_blendConfigList; 849 std::vector<TextureSp> m_textureSourceList; 850 TestRenderPassConfig m_renderPassConfig; 851 std::vector<TextureSp> m_fboTextureList; 852 TestShaderProgram* m_shaderProgram; 853 std::vector<FboSp> m_framebufferList; 854 std::vector<tcu::Vec4> m_resultsListPreDraw; 855 std::vector<tcu::Vec4> m_resultsListPostDraw; 856 857 // mutable state variables (internal access only) 858 bool m_hasShaderProgramInfo; 859 int m_renderPass; 860 int m_samplersRequired; 861 bool m_hasFunction; 862 bool m_blittingEnabled; 863 glu::ShaderProgramInfo m_shaderProgramInfo; 864 865 // mutable state variables (external access via setters) 866 SamplingType m_samplingType; 867 int m_blendIteration; 868 bool m_framebufferBlendEnabled; 869 bool m_framebufferSRGBEnabled; 870 }; 871 872 Renderer::Renderer (Context& context) 873 : m_context (context) 874 , m_vertexData (context) 875 , m_textureSourceTotal (2) 876 , m_blendConfigList (getBlendingConfigList()) 877 , m_hasShaderProgramInfo (false) 878 { 879 TextureSp textureLinear(new TestTexture2D(m_context, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 0)); 880 m_textureSourceList.push_back(textureLinear); 881 882 TextureSp textureSRGB(new TestTexture2D(m_context, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 1)); 883 m_textureSourceList.push_back(textureSRGB); 884 } 885 886 Renderer::~Renderer (void) 887 { 888 m_textureSourceList.clear(); 889 this->deinit(); 890 } 891 892 void Renderer::init (const TestRenderPassConfig& renderPassConfig, const int renderpass) 893 { 894 m_renderPassConfig = renderPassConfig; 895 m_renderPass = renderpass; 896 897 this->createFBOwithColorAttachment(m_renderPassConfig.fboConfigList); 898 899 if (m_renderPassConfig.textureSourcesType != TEXTURESOURCESTYPE_NONE) 900 { 901 if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_RGBA || m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_SRGBA) 902 m_samplersRequired = 1; 903 else if (m_renderPassConfig.textureSourcesType ==TEXTURESOURCESTYPE_BOTH ) 904 m_samplersRequired = 2; 905 else 906 DE_FATAL("Error: Texture source required not recognised"); 907 908 m_shaderProgram = new TestShaderProgram(m_context, m_samplersRequired, m_renderPassConfig.testFunction); 909 m_hasFunction = m_renderPassConfig.testFunction.hasFunction; 910 } 911 else 912 m_shaderProgram = DE_NULL; 913 } 914 915 void Renderer::deinit (void) 916 { 917 if (m_shaderProgram != DE_NULL) 918 { 919 delete m_shaderProgram; 920 m_shaderProgram = DE_NULL; 921 } 922 923 m_fboTextureList.clear(); 924 m_framebufferList.clear(); 925 } 926 927 void Renderer::setSamplingType (const SamplingType samplingType) 928 { 929 m_samplingType = samplingType; 930 } 931 932 void Renderer::setBlendIteration (const int blendIteration) 933 { 934 m_blendIteration = blendIteration; 935 } 936 937 void Renderer::setFramebufferBlend (const bool blend) 938 { 939 m_framebufferBlendEnabled = blend; 940 } 941 942 void Renderer::setFramebufferSRGB (const bool sRGB) 943 { 944 m_framebufferSRGBEnabled = sRGB; 945 } 946 947 std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const 948 { 949 return m_resultsListPreDraw; 950 } 951 952 std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const 953 { 954 return m_resultsListPostDraw; 955 } 956 957 int Renderer::getBlendConfigCount (void) const 958 { 959 return (int)m_blendConfigList.size(); 960 } 961 962 void Renderer::copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy) 963 { 964 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 965 int fboSrcIdx = -1; 966 int fboDstIdx = -1; 967 deUint32 fboSrcColAttachment = GL_NONE; 968 deUint32 fboDstColAttachment = GL_NONE; 969 970 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 971 this->bindFramebuffer(idx); 972 973 // cache fbo attachments and idx locations 974 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 975 { 976 if (m_framebufferList[idx]->getType() == FBOTYPE_SOURCE) 977 { 978 fboSrcIdx = m_framebufferList[idx]->getIdx(); 979 fboSrcColAttachment = m_framebufferList[fboSrcIdx]->getColorAttachment(); 980 } 981 if (m_framebufferList[idx]->getType() == FBOTYPE_DESTINATION) 982 { 983 fboDstIdx = m_framebufferList[idx]->getIdx(); 984 fboDstColAttachment = m_framebufferList[fboDstIdx]->getColorAttachment(); 985 } 986 } 987 988 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 989 m_framebufferList[idx]->unbind(); 990 991 // store texel data from both src and dst before performing the copy 992 m_resultsListPreDraw.resize(2); 993 m_framebufferList[fboSrcIdx]->bind(); 994 this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPreDraw[0]); 995 m_framebufferList[fboSrcIdx]->unbind(); 996 m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER); 997 m_framebufferList[fboDstIdx]->bind(); 998 this->readTexels(0, 0, fboDstColAttachment, m_resultsListPreDraw[1]); 999 m_framebufferList[fboDstIdx]->unbind(); 1000 m_framebufferList[fboDstIdx]->setTargetType(GL_DRAW_FRAMEBUFFER); 1001 1002 m_framebufferList[fboSrcIdx]->bind(); 1003 m_framebufferList[fboDstIdx]->bind(); 1004 1005 this->enableFramebufferSRGB(); 1006 this->enableFramebufferBlend(); 1007 1008 gl.blitFramebuffer( srcPx, srcPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT, 1009 dstPx, dstPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT, 1010 GL_COLOR_BUFFER_BIT, GL_NEAREST); 1011 1012 m_resultsListPostDraw.resize(2); 1013 this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPostDraw[0]); 1014 m_framebufferList[fboSrcIdx]->unbind(); 1015 m_framebufferList[fboDstIdx]->unbind(); 1016 1017 m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER); 1018 m_framebufferList[fboDstIdx]->bind(); 1019 this->readTexels(0, 0, fboDstColAttachment, m_resultsListPostDraw[1]); 1020 m_framebufferList[fboDstIdx]->unbind(); 1021 } 1022 1023 void Renderer::draw (void) 1024 { 1025 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1026 1027 if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_NONE) 1028 DE_FATAL("Error: Attempted to draw with no texture sources"); 1029 1030 // resize results storage with each render pass 1031 m_resultsListPreDraw.resize(m_renderPass + 1); 1032 m_resultsListPostDraw.resize(m_renderPass + 1); 1033 1034 m_shaderProgram->use(); 1035 m_vertexData.bind(); 1036 1037 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 1038 this->bindFramebuffer(idx); 1039 1040 this->bindAllRequiredSourceTextures(m_renderPassConfig.textureSourcesType); 1041 this->bindActiveTexturesSamplers(); 1042 1043 this->enableFramebufferSRGB(); 1044 this->enableFramebufferBlend(); 1045 1046 this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPreDraw[m_renderPass]); 1047 this->setShaderProgramSamplingType(m_samplingType); 1048 if (m_hasFunction) 1049 { 1050 this->setShaderBlendFunctionType(); 1051 this->setShaderBlendSrcDstValues(); 1052 } 1053 1054 gl.drawArrays(GL_TRIANGLES, 0, 6); 1055 1056 this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPostDraw[m_renderPass]); 1057 this->logState(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_samplingType); 1058 1059 this->unbindAllSourceTextures(); 1060 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 1061 this->unbindFramebuffer(idx); 1062 m_vertexData.unbind(); 1063 m_shaderProgram->unuse(); 1064 } 1065 1066 void Renderer::storeShaderProgramInfo (void) 1067 { 1068 m_shaderProgramInfo = m_shaderProgram->getLogInfo(); 1069 m_hasShaderProgramInfo = true; 1070 } 1071 1072 void Renderer::logShaderProgramInfo (void) 1073 { 1074 tcu::TestLog& log = m_context.getTestContext().getLog(); 1075 1076 if (m_hasShaderProgramInfo) 1077 log << m_shaderProgramInfo; 1078 } 1079 1080 void Renderer::createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList) 1081 { 1082 const int size = (int)fboConfigList.size(); 1083 for (int idx = 0; idx < size; idx++) 1084 { 1085 TextureSp texture(new TestTexture2D(m_context, fboConfigList[idx].textureInternalFormat, GL_RGBA, GL_UNSIGNED_BYTE, fboConfigList[idx].textureColor, idx)); 1086 m_fboTextureList.push_back(texture); 1087 1088 bool isSRGB; 1089 if (fboConfigList[idx].textureInternalFormat == GL_SRGB8_ALPHA8) 1090 isSRGB = true; 1091 else 1092 isSRGB = false; 1093 1094 FboSp framebuffer(new TestFramebuffer(m_context, fboConfigList[idx].fboTargetType, fboConfigList[idx].fboColorAttachment, texture->getHandle(), isSRGB, fboConfigList[idx].fboType, idx)); 1095 m_framebufferList.push_back(framebuffer); 1096 } 1097 } 1098 1099 void Renderer::setShaderProgramSamplingType (const int samplerIdx) 1100 { 1101 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1102 1103 glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFunctionType"); 1104 DE_ASSERT(location != (glw::GLuint)-1); 1105 gl.uniform1i(location, samplerIdx); 1106 } 1107 1108 void Renderer::setShaderBlendFunctionType (void) 1109 { 1110 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1111 1112 int function = -1; 1113 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD) 1114 function = 0; 1115 else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT) 1116 function = 1; 1117 else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT) 1118 function = 2; 1119 else 1120 DE_FATAL("Error: Blend function not recognised"); 1121 1122 glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uBlendFunctionType"); 1123 DE_ASSERT(location != (glw::GLuint)-1); 1124 gl.uniform1i(location, function); 1125 } 1126 1127 void Renderer::setShaderBlendSrcDstValues (void) 1128 { 1129 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1130 1131 float funcSrc; 1132 if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE) 1133 funcSrc = 1.0f; 1134 else 1135 funcSrc = 0.0f; 1136 1137 float funcDst; 1138 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE) 1139 funcDst = 1.0f; 1140 else 1141 funcDst = 0.0f; 1142 1143 glw::GLuint locationSrc = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorSrc"); 1144 gl.uniform1f(locationSrc, funcSrc); 1145 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()"); 1146 1147 glw::GLuint locationDst = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorDst"); 1148 gl.uniform1f(locationDst, funcDst); 1149 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()"); 1150 } 1151 1152 void Renderer::bindActiveTexturesSamplers (void) 1153 { 1154 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1155 1156 for (int idx = 0; idx < m_samplersRequired; idx++) 1157 { 1158 std::ostringstream stream; 1159 stream << "uTexture" << idx; 1160 std::string uniformName(stream.str()); 1161 glw::GLint location = gl.getUniformLocation(m_shaderProgram->getHandle(), uniformName.c_str()); 1162 DE_ASSERT(location != -1); 1163 gl.uniform1i(location, m_textureSourceList[idx]->getTextureUnit()); 1164 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation()"); 1165 } 1166 } 1167 1168 void Renderer::bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired) 1169 { 1170 if (texturesRequired == TEXTURESOURCESTYPE_RGBA) 1171 m_textureSourceList[0]->bind(0); 1172 else if (texturesRequired == TEXTURESOURCESTYPE_SRGBA) 1173 m_textureSourceList[1]->bind(0); 1174 else if (texturesRequired == TEXTURESOURCESTYPE_BOTH) 1175 { 1176 m_textureSourceList[0]->bind(0); 1177 m_textureSourceList[1]->bind(1); 1178 } 1179 else 1180 DE_FATAL("Error: Invalid sources requested in bind all"); 1181 } 1182 1183 void Renderer::unbindAllSourceTextures (void) 1184 { 1185 for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++) 1186 m_textureSourceList[idx]->unbind(); 1187 } 1188 1189 void Renderer::bindFramebuffer (const int framebufferIdx) 1190 { 1191 m_framebufferList[framebufferIdx]->bind(); 1192 } 1193 1194 void Renderer::unbindFramebuffer (const int framebufferIdx) 1195 { 1196 m_framebufferList[framebufferIdx]->unbind(); 1197 } 1198 1199 void Renderer::enableFramebufferSRGB (void) 1200 { 1201 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1202 1203 if (m_framebufferSRGBEnabled) 1204 gl.enable(GL_FRAMEBUFFER_SRGB); 1205 else 1206 gl.disable(GL_FRAMEBUFFER_SRGB); 1207 } 1208 1209 void Renderer::enableFramebufferBlend (void) 1210 { 1211 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1212 tcu::TestLog& log = m_context.getTestContext().getLog(); 1213 std::ostringstream message; 1214 1215 message << "Blend settings = "; 1216 1217 if (m_framebufferBlendEnabled) 1218 { 1219 gl.enable(GL_BLEND); 1220 gl.blendEquation(m_blendConfigList[m_blendIteration].equation); 1221 gl.blendFunc(m_blendConfigList[m_blendIteration].funcSrc, m_blendConfigList[m_blendIteration].funcDst); 1222 1223 std::string equation, src, dst; 1224 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD) 1225 equation = "GL_FUNC_ADD"; 1226 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT) 1227 equation = "GL_FUNC_SUBTRACT"; 1228 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT) 1229 equation = "GL_FUNC_REVERSE_SUBTRACT"; 1230 if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE) 1231 src = "GL_ONE"; 1232 else 1233 src = "GL_ZERO"; 1234 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE) 1235 dst = "GL_ONE"; 1236 else 1237 dst = "GL_ZERO"; 1238 1239 message << "Enabled: equation = " << equation << ", func src = " << src << ", func dst = " << dst; 1240 } 1241 else 1242 { 1243 gl.disable(GL_BLEND); 1244 message << "Disabled"; 1245 } 1246 1247 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1248 } 1249 1250 bool Renderer::isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const 1251 { 1252 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1253 glw::GLint encodingType; 1254 1255 gl.getFramebufferAttachmentParameteriv(targetType, attachment, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encodingType); 1256 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedFramebufferAttachmentParameteriv()"); 1257 1258 switch (static_cast<glw::GLenum>(encodingType)) 1259 { 1260 case GL_SRGB: 1261 { 1262 return true; 1263 break; 1264 } 1265 case GL_LINEAR: 1266 { 1267 return false; 1268 break; 1269 } 1270 default: 1271 { 1272 DE_FATAL("Error: Color attachment format not recognised"); 1273 return false; 1274 } 1275 } 1276 } 1277 1278 void Renderer::readTexels (const int px, const int py, const deUint32 mode, tcu::Vec4& texelData) 1279 { 1280 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1281 tcu::TextureLevel textureRead; 1282 1283 // ensure result sampling coordinates are within range of the result color attachment 1284 DE_ASSERT((px >= 0) && (px < m_context.getRenderTarget().getWidth())); 1285 DE_ASSERT((py >= 0) && (py < m_context.getRenderTarget().getHeight())); 1286 1287 gl.readBuffer(mode); 1288 textureRead.setStorage(glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE), TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT); 1289 glu::readPixels(m_context.getRenderContext(), px, py, textureRead.getAccess()); 1290 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()"); 1291 texelData = textureRead.getAccess().getPixel(px, py); 1292 } 1293 1294 void Renderer::logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const 1295 { 1296 tcu::TestLog& log = m_context.getTestContext().getLog(); 1297 std::ostringstream message; 1298 1299 bool fboAttachmentSRGB = this->isFramebufferAttachmentSRGB(targetType, attachment); 1300 message.str(""); 1301 message << "getFramebufferAttachmentParameteriv() check = "; 1302 if (fboAttachmentSRGB) 1303 message << "GL_SRGB"; 1304 else 1305 message << "GL_LINEAR"; 1306 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1307 1308 message.str(""); 1309 message << "Framebuffer color attachment value BEFORE draw call"; 1310 logColor(m_context, message.str(), m_resultsListPreDraw[m_renderPass]); 1311 1312 message.str(""); 1313 message << "Framebuffer color attachment value AFTER draw call"; 1314 logColor(m_context, message.str(), m_resultsListPostDraw[m_renderPass]); 1315 1316 message.str(""); 1317 message << "Sampling type = "; 1318 std::string type; 1319 if (samplingType == 0) 1320 type = "texture()"; 1321 else if (samplingType == 1) 1322 type = "textureLOD()"; 1323 else if (samplingType == 2) 1324 type = "textureGrad()"; 1325 else if (samplingType == 3) 1326 type = "textureOffset()"; 1327 else if (samplingType == 4) 1328 type = "textureProj()"; 1329 else 1330 DE_FATAL("Error: Sampling type unregonised"); 1331 message << type; 1332 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1333 1334 message.str(""); 1335 if (m_framebufferSRGBEnabled) 1336 message << "Framebuffer SRGB = enabled"; 1337 else 1338 message << "Framebuffer SRGB = disabled"; 1339 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1340 } 1341 1342 class FboSRGBTestCase : public TestCase 1343 { 1344 public: 1345 FboSRGBTestCase (Context& context, const char* const name, const char* const desc); 1346 ~FboSRGBTestCase (void); 1347 1348 void init (void); 1349 void deinit (void); 1350 IterateResult iterate (void); 1351 1352 void setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList); 1353 1354 virtual void setupTest (void) = 0; 1355 virtual bool verifyResult (void) = 0; 1356 1357 protected: 1358 bool m_hasTestConfig; 1359 std::vector<TestRenderPassConfig> m_renderPassConfigList; 1360 bool m_testcaseRequiresBlend; 1361 std::vector<tcu::Vec4> m_resultsPreDraw; 1362 std::vector<tcu::Vec4> m_resultsPostDraw; 1363 1364 private: 1365 FboSRGBTestCase (const FboSRGBTestCase&); 1366 FboSRGBTestCase& operator= (const FboSRGBTestCase&); 1367 }; 1368 1369 FboSRGBTestCase::FboSRGBTestCase (Context& context, const char* const name, const char* const desc) 1370 : TestCase (context, name, desc) 1371 , m_hasTestConfig (false) 1372 { 1373 } 1374 1375 FboSRGBTestCase::~FboSRGBTestCase (void) 1376 { 1377 FboSRGBTestCase::deinit(); 1378 } 1379 1380 void FboSRGBTestCase::init (void) 1381 { 1382 // extensions requirements for test 1383 if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2))) 1384 TCU_THROW(NotSupportedError, "Test requires a context version equal or higher than 3.2"); 1385 1386 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) 1387 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control"); 1388 1389 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode")) 1390 TCU_THROW(NotSupportedError, "Test requires GL_EXT_texture_sRGB_decode extension"); 1391 } 1392 1393 void FboSRGBTestCase::deinit (void) 1394 { 1395 } 1396 1397 FboSRGBTestCase::IterateResult FboSRGBTestCase::iterate (void) 1398 { 1399 this->setupTest(); 1400 1401 DE_ASSERT(m_hasTestConfig && "Error: Renderer was not supplied a test config"); 1402 1403 Renderer renderer(m_context); 1404 1405 // loop through each sampling type 1406 for (int samplingIdx = 0; samplingIdx < SampligTypeCount::MAX; samplingIdx++) 1407 { 1408 renderer.setSamplingType(static_cast<SamplingType>(samplingIdx)); 1409 1410 // loop through each blend configuration 1411 const int blendCount = renderer.getBlendConfigCount(); 1412 for (int blendIdx = 0; blendIdx < blendCount; blendIdx++) 1413 { 1414 // loop through each render pass 1415 const int renderPassCount = (int)m_renderPassConfigList.size(); 1416 for (int renderPassIdx = 0; renderPassIdx < renderPassCount; renderPassIdx++) 1417 { 1418 TestRenderPassConfig renderPassConfig = m_renderPassConfigList[renderPassIdx]; 1419 1420 renderer.init(renderPassConfig, renderPassIdx); 1421 1422 if (blendIdx == 0 && renderPassConfig.rendererTask == RENDERERTASK_DRAW) 1423 renderer.storeShaderProgramInfo(); 1424 1425 if (renderPassConfig.frameBufferBlend == FRAMEBUFFERBLEND_ENABLED) 1426 { 1427 renderer.setBlendIteration(blendIdx); 1428 renderer.setFramebufferBlend(true); 1429 } 1430 else 1431 renderer.setFramebufferBlend(false); 1432 1433 if (renderPassConfig.framebufferSRGB == FRAMEBUFFERSRGB_ENABLED) 1434 renderer.setFramebufferSRGB(true); 1435 else 1436 renderer.setFramebufferSRGB(false); 1437 1438 if (renderPassConfig.rendererTask == RENDERERTASK_DRAW) 1439 renderer.draw(); 1440 else if (renderPassConfig.rendererTask == RENDERERTASK_COPY) 1441 renderer.copyFrameBufferTexture(0, 0, 0, 0); 1442 else 1443 DE_FATAL("Error: render task not recognised"); 1444 1445 renderer.deinit(); 1446 1447 } // render passes 1448 1449 m_resultsPreDraw = renderer.getResultsPreDraw(); 1450 m_resultsPostDraw = renderer.getResultsPostDraw(); 1451 1452 bool testPassed = this->verifyResult(); 1453 if (testPassed) 1454 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1455 else 1456 { 1457 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed"); 1458 renderer.logShaderProgramInfo(); 1459 return STOP; 1460 } 1461 1462 if (!m_testcaseRequiresBlend) 1463 break; 1464 } // blend configs 1465 1466 renderer.logShaderProgramInfo(); 1467 } // sampling types 1468 1469 return STOP; 1470 } 1471 1472 void FboSRGBTestCase::setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList) 1473 { 1474 m_renderPassConfigList = renderPassConfigList; 1475 m_hasTestConfig = true; 1476 1477 for (int idx = 0; idx < (int)renderPassConfigList.size(); idx++) 1478 { 1479 if (renderPassConfigList[idx].frameBufferBlend == FRAMEBUFFERBLEND_ENABLED) 1480 { 1481 m_testcaseRequiresBlend = true; 1482 return; 1483 } 1484 } 1485 m_testcaseRequiresBlend = false; 1486 } 1487 1488 class FboSRGBQueryCase : public TestCase 1489 { 1490 public: 1491 FboSRGBQueryCase (Context& context, const char* const name, const char* const description); 1492 ~FboSRGBQueryCase (void); 1493 1494 void init (void); 1495 void deinit (void); 1496 IterateResult iterate (void); 1497 }; 1498 1499 FboSRGBQueryCase::FboSRGBQueryCase (Context& context, const char* const name, const char* const description) 1500 : TestCase (context, name, description) 1501 { 1502 } 1503 1504 FboSRGBQueryCase::~FboSRGBQueryCase (void) 1505 { 1506 FboSRGBQueryCase::deinit(); 1507 } 1508 1509 void FboSRGBQueryCase::init (void) 1510 { 1511 // extension requirements for test 1512 if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) 1513 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control or a context version equal or higher than 3.2"); 1514 } 1515 1516 void FboSRGBQueryCase::deinit (void) 1517 { 1518 } 1519 1520 FboSRGBQueryCase::IterateResult FboSRGBQueryCase::iterate (void) 1521 { 1522 // TEST INFO: 1523 // API tests which check when querying FRAMEBUFFER_SRGB_EXT capability returns the correct information when using glEnabled() or glDisabled() 1524 1525 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1526 tcu::TestLog& log = m_context.getTestContext().getLog(); 1527 const char* const msgPart = ", after disabling = "; 1528 1529 for (int idx = 0; idx < static_cast<int>(QUERYTYPE_LAST); idx++) 1530 { 1531 std::ostringstream message; 1532 bool pass = false; 1533 1534 message << std::string("Results: After Enabling = "); 1535 1536 gl.enable(GL_FRAMEBUFFER_SRGB); 1537 1538 switch (static_cast<QueryType>(idx)) 1539 { 1540 case QUERYTYPE_ISENABLED: 1541 { 1542 glw::GLboolean enabled[2]; 1543 enabled[0] = gl.isEnabled(GL_FRAMEBUFFER_SRGB); 1544 gl.disable(GL_FRAMEBUFFER_SRGB); 1545 enabled[1] = gl.isEnabled(GL_FRAMEBUFFER_SRGB); 1546 1547 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1548 pass = (enabled[0] && !(enabled[1])) ? true : false; 1549 break; 1550 } 1551 case QUERYTYPE_BOOLEAN: 1552 { 1553 glw::GLboolean enabled[2]; 1554 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[0]); 1555 gl.disable(GL_FRAMEBUFFER_SRGB); 1556 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[1]); 1557 1558 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1559 pass = (enabled[0] && !(enabled[1])) ? true : false; 1560 break; 1561 } 1562 case QUERYTYPE_FLOAT: 1563 { 1564 glw::GLfloat enabled[2]; 1565 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[0]); 1566 gl.disable(GL_FRAMEBUFFER_SRGB); 1567 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[1]); 1568 1569 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1570 pass = ((int)enabled[0] && !((int)enabled[1])) ? true : false; 1571 break; 1572 } 1573 case QUERYTYPE_INT: 1574 { 1575 glw::GLint enabled[2]; 1576 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[0]); 1577 gl.disable(GL_FRAMEBUFFER_SRGB); 1578 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[1]); 1579 1580 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1581 pass = (enabled[0] && !(enabled[1])) ? true : false; 1582 break; 1583 } 1584 case QUERYTYPE_INT64: 1585 { 1586 glw::GLint64 enabled[2]; 1587 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[0]); 1588 gl.disable(GL_FRAMEBUFFER_SRGB); 1589 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[1]); 1590 1591 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1592 pass = (enabled[0] && !(enabled[1])) ? true : false; 1593 break; 1594 } 1595 default: 1596 DE_FATAL("Error: Datatype not recognised"); 1597 } 1598 1599 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1600 1601 if (pass) 1602 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1603 else 1604 { 1605 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed"); 1606 return STOP; 1607 } 1608 } 1609 return STOP; 1610 } 1611 1612 class FboSRGBColAttachCase : public FboSRGBTestCase 1613 { 1614 public: 1615 FboSRGBColAttachCase (Context& context, const char* const name, const char* const description) 1616 : FboSRGBTestCase (context, name, description) {} 1617 ~FboSRGBColAttachCase (void) {} 1618 1619 void setupTest (void); 1620 bool verifyResult (void); 1621 }; 1622 1623 void FboSRGBColAttachCase::setupTest (void) 1624 { 1625 // TEST INFO: 1626 // Check if FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING set to SRGB and FRAMEBUFFER_SRGB_EXT enabled, destination colors are converted from SRGB to linear 1627 // before and after blending, finally the result is converted back to SRGB for storage 1628 1629 // NOTE: 1630 // if fbo pre-draw color set to linaer, color values get linearlized "twice" 1631 // (0.2f, 0.3f, 0.4f, 1.0f) when sampled i.e. converted in shader = (0.0331048f, 0.073239f, 0.132868f) 1632 // resulting in the follolwing blending equation (0.2f, 0.3f, 0.4f 1.0f) + (0.0331048, 0.073239, 0.132868) = (0.521569f, 0.647059f, 0.756863f, 1.0f) 1633 1634 FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE); 1635 FBOConfig fboConfig1 = FBOConfig(GL_RGBA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE); 1636 1637 const TestRenderPassConfig renderPassConfigs[] = 1638 { 1639 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_ENABLED, RENDERERTASK_DRAW), 1640 TestRenderPassConfig(TEXTURESOURCESTYPE_BOTH, fboConfig1, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, getFunctionBlendLinearToSRGBCheck(), RENDERERTASK_DRAW) 1641 }; 1642 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1643 1644 this->setTestConfig(renderPassConfigList); 1645 } 1646 1647 bool FboSRGBColAttachCase::verifyResult (void) 1648 { 1649 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], m_resultsPostDraw[1]))) 1650 return true; 1651 else 1652 return false; 1653 } 1654 1655 class FboSRGBToggleBlendCase : public FboSRGBTestCase 1656 { 1657 public: 1658 FboSRGBToggleBlendCase (Context& context, const char* const name, const char* const description) 1659 : FboSRGBTestCase (context, name, description) {} 1660 ~FboSRGBToggleBlendCase (void) {} 1661 1662 void setupTest (void); 1663 bool verifyResult (void); 1664 }; 1665 1666 void FboSRGBToggleBlendCase::setupTest (void) 1667 { 1668 // TEST INFO: 1669 // Test to check if changing FRAMEBUFFER_SRGB_EXT from enabled to disabled. Enabled should produce SRGB color whilst disabled 1670 // should produce linear color. Test conducted with blending disabled. 1671 1672 FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION); 1673 1674 const TestRenderPassConfig renderPassConfigs[] = 1675 { 1676 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW), 1677 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW) 1678 }; 1679 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1680 1681 this->setTestConfig(renderPassConfigList); 1682 } 1683 1684 bool FboSRGBToggleBlendCase::verifyResult (void) 1685 { 1686 if (tcu::boolAny(tcu::greaterThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError()))) 1687 return true; 1688 else 1689 return false; 1690 } 1691 1692 class FboSRGBRenderTargetIgnoreCase : public FboSRGBTestCase 1693 { 1694 public: 1695 FboSRGBRenderTargetIgnoreCase (Context& context, const char* const name, const char* const description) 1696 : FboSRGBTestCase (context, name, description) {} 1697 ~FboSRGBRenderTargetIgnoreCase (void) {} 1698 1699 void setupTest (void); 1700 bool verifyResult (void); 1701 }; 1702 1703 void FboSRGBRenderTargetIgnoreCase::setupTest (void) 1704 { 1705 // TEST INFO: 1706 // Check if render targets that are non-RGB ignore the state of GL_FRAMEBUFFER_SRGB_EXT. Rendering to an fbo with non-sRGB color 1707 // attachment should ignore color space conversion, producing linear color. 1708 1709 FBOConfig fboConfig0 = FBOConfig(GL_RGBA8, getTestColorBlank(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION); 1710 1711 const TestRenderPassConfig renderPassConfigs[] = 1712 { 1713 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW) 1714 1715 }; 1716 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1717 1718 this->setTestConfig(renderPassConfigList); 1719 } 1720 1721 bool FboSRGBRenderTargetIgnoreCase::verifyResult (void) 1722 { 1723 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], getTestColorLinear()))) 1724 return true; 1725 else 1726 return false; 1727 } 1728 1729 class FboSRGBCopyToLinearCase : public FboSRGBTestCase 1730 { 1731 public: 1732 FboSRGBCopyToLinearCase (Context& context, const char* const name, const char* const description) 1733 : FboSRGBTestCase (context, name, description) {} 1734 ~FboSRGBCopyToLinearCase (void) {} 1735 1736 void setupTest (void); 1737 bool verifyResult (void); 1738 }; 1739 1740 void FboSRGBCopyToLinearCase::setupTest (void) 1741 { 1742 // TEST INFO: 1743 // Check if copying from an fbo with an sRGB color attachment to an fbo with a linear color attachment with FRAMEBUFFER_EXT enabled results in 1744 // an sRGB to linear conversion 1745 1746 FBOConfig fboConfigs[] = 1747 { 1748 FBOConfig(GL_SRGB8_ALPHA8, getTestColorSRGB(), GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE), 1749 FBOConfig(GL_RGBA8, getTestColorBlank(), GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION) 1750 }; 1751 std::vector<FBOConfig> fboConfigList(fboConfigs, fboConfigs + DE_LENGTH_OF_ARRAY(fboConfigs)); 1752 1753 const TestRenderPassConfig renderPassConfigs[] = 1754 { 1755 TestRenderPassConfig(TEXTURESOURCESTYPE_NONE, fboConfigList, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_COPY) 1756 }; 1757 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1758 1759 this->setTestConfig(renderPassConfigList); 1760 } 1761 1762 bool FboSRGBCopyToLinearCase::verifyResult (void) 1763 { 1764 logColor(m_context, "pre-copy source fbo color values", m_resultsPreDraw[0]); 1765 logColor(m_context, "pre-copy destination fbo color values", m_resultsPreDraw[1]); 1766 logColor(m_context, "post-copy source fbo color values", m_resultsPostDraw[0]); 1767 logColor(m_context, "post-copy destination fbo color values", m_resultsPostDraw[1]); 1768 1769 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[1] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[1], getTestColorLinear()))) 1770 return true; 1771 else 1772 return false; 1773 } 1774 1775 class FboSRGBUnsupportedEnumCase : public TestCase 1776 { 1777 public: 1778 FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description); 1779 ~FboSRGBUnsupportedEnumCase (void); 1780 1781 void init (void); 1782 void deinit (void); 1783 bool isInvalidEnum (std::string functionName); 1784 IterateResult iterate (void); 1785 }; 1786 1787 FboSRGBUnsupportedEnumCase::FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description) 1788 : TestCase (context, name, description) 1789 { 1790 } 1791 1792 FboSRGBUnsupportedEnumCase::~FboSRGBUnsupportedEnumCase (void) 1793 { 1794 FboSRGBUnsupportedEnumCase::deinit(); 1795 } 1796 1797 void FboSRGBUnsupportedEnumCase::init (void) 1798 { 1799 // extension requirements for test 1800 if (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) || m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) 1801 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control to be unsupported and a context version less than 3.2"); 1802 } 1803 1804 void FboSRGBUnsupportedEnumCase::deinit (void) 1805 { 1806 } 1807 1808 bool FboSRGBUnsupportedEnumCase::isInvalidEnum (std::string functionName) 1809 { 1810 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1811 tcu::TestLog& log = m_context.getTestContext().getLog(); 1812 bool isOk = true; 1813 glw::GLenum error = GL_NO_ERROR; 1814 1815 log << tcu::TestLog::Message << "Checking call to " << functionName << tcu::TestLog::EndMessage; 1816 1817 error = gl.getError(); 1818 1819 if (error != GL_INVALID_ENUM) 1820 { 1821 log << tcu::TestLog::Message << " returned wrong value [" << glu::getErrorStr(error) << ", expected " << glu::getErrorStr(GL_INVALID_ENUM) << "]" << tcu::TestLog::EndMessage; 1822 isOk = false; 1823 } 1824 1825 return isOk; 1826 } 1827 1828 FboSRGBUnsupportedEnumCase::IterateResult FboSRGBUnsupportedEnumCase::iterate (void) 1829 { 1830 // TEST INFO: 1831 // API tests that check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported 1832 1833 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1834 bool allPass = true; 1835 glw::GLboolean bEnabled = GL_FALSE; 1836 glw::GLfloat fEnabled = 0; 1837 glw::GLint iEnabled = 0; 1838 glw::GLint64 lEnabled = 0; 1839 1840 m_context.getTestContext().getLog() << tcu::TestLog::Message 1841 << "Check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported\n\n" 1842 << tcu::TestLog::EndMessage; 1843 1844 gl.enable(GL_FRAMEBUFFER_SRGB); 1845 allPass &= isInvalidEnum("glEnable()"); 1846 1847 gl.disable(GL_FRAMEBUFFER_SRGB); 1848 allPass &= isInvalidEnum("glDisable()"); 1849 1850 gl.isEnabled(GL_FRAMEBUFFER_SRGB); 1851 allPass &= isInvalidEnum("glIsEnabled()"); 1852 1853 gl.getBooleanv(GL_FRAMEBUFFER_SRGB, &bEnabled); 1854 allPass &= isInvalidEnum("glGetBooleanv()"); 1855 1856 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &fEnabled); 1857 allPass &= isInvalidEnum("glGetFloatv()"); 1858 1859 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &iEnabled); 1860 allPass &= isInvalidEnum("glGetIntegerv()"); 1861 1862 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &lEnabled); 1863 allPass &= isInvalidEnum("glGetInteger64v()"); 1864 1865 if (allPass) 1866 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1867 else 1868 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1869 1870 return STOP; 1871 } 1872 1873 } // anonymous 1874 1875 FboSRGBWriteControlTests::FboSRGBWriteControlTests (Context& context) 1876 : TestCaseGroup (context, "srgb_write_control", "Colorbuffer tests") 1877 { 1878 } 1879 1880 FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void) 1881 { 1882 } 1883 1884 void FboSRGBWriteControlTests::init (void) 1885 { 1886 this->addChild(new FboSRGBQueryCase (m_context, "framebuffer_srgb_enabled", "srgb enable framebuffer")); 1887 this->addChild(new FboSRGBColAttachCase (m_context, "framebuffer_srgb_enabled_col_attach", "srgb enable color attachment and framebuffer")); 1888 this->addChild(new FboSRGBToggleBlendCase (m_context, "framebuffer_srgb_enabled_blend", "toggle framebuffer srgb settings with blend disabled")); 1889 this->addChild(new FboSRGBRenderTargetIgnoreCase (m_context, "framebuffer_srgb_enabled_render_target_ignore", "enable framebuffer srgb, non-srgb render target should ignore")); 1890 this->addChild(new FboSRGBCopyToLinearCase (m_context, "framebuffer_srgb_enabled_copy_to_linear", "no conversion when blittering between framebuffer srgb and linear")); 1891 1892 // negative 1893 this->addChild(new FboSRGBUnsupportedEnumCase (m_context, "framebuffer_srgb_unsupported_enum", "check error codes for query functions when extension is not supported")); 1894 } 1895 1896 } 1897 } // gles31 1898 } // deqp 1899