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); 473 ~TestTexture2D (void); 474 475 int getTextureUnit (void) const; 476 deUint32 getHandle (void) const; 477 478 void bind (const int textureUnit); 479 void unbind (void) const; 480 481 private: 482 const glw::Functions* m_gl; 483 glw::GLuint m_handle; 484 const deUint32 m_internalFormat; 485 tcu::TextureFormat m_transferFormat; 486 int m_width; 487 int m_height; 488 tcu::TextureLevel m_imageData; 489 int m_textureUnit; 490 }; 491 492 TestTexture2D::TestTexture2D (Context& context, const deUint32 internalFormat, const deUint32 transferFormat, const deUint32 transferType, const tcu::Vec4 imageColor) 493 : m_gl (&context.getRenderContext().getFunctions()) 494 , m_internalFormat (internalFormat) 495 , m_transferFormat (tcu::TextureFormat(glu::mapGLTransferFormat(transferFormat, transferType))) 496 , m_width (TestTextureSizes::WIDTH) 497 , m_height (TestTextureSizes::HEIGHT) 498 , m_imageData (tcu::TextureLevel(glu::mapGLInternalFormat(internalFormat), m_width, m_height, 1)) 499 { 500 // fill image data with a solid test color 501 tcu::clear(m_imageData.getAccess(), tcu::Vec4(0.0f)); 502 for (int py = 0; py < m_imageData.getHeight(); py++) 503 { 504 for (int px = 0; px < m_imageData.getWidth(); px++) 505 m_imageData.getAccess().setPixel(imageColor, px, py); 506 } 507 508 m_gl->genTextures(1, &m_handle); 509 510 m_gl->bindTexture(GL_TEXTURE_2D, m_handle); 511 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 512 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 513 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 514 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 515 516 m_gl->texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFormat, transferType, m_imageData.getAccess().getDataPtr()); 517 518 m_gl->bindTexture(GL_TEXTURE_2D, 0); 519 } 520 521 TestTexture2D::~TestTexture2D (void) 522 { 523 m_gl->deleteTextures(1, &m_handle); 524 } 525 526 int TestTexture2D::getTextureUnit (void) const 527 { 528 return m_textureUnit; 529 } 530 531 deUint32 TestTexture2D::getHandle (void) const 532 { 533 return m_handle; 534 } 535 536 void TestTexture2D::bind (const int textureUnit) 537 { 538 m_textureUnit = textureUnit; 539 m_gl->activeTexture(GL_TEXTURE0 + m_textureUnit); 540 m_gl->bindTexture(GL_TEXTURE_2D, m_handle); 541 } 542 543 void TestTexture2D::unbind (void) const 544 { 545 m_gl->bindTexture(GL_TEXTURE_2D, 0); 546 } 547 548 class TestFramebuffer 549 { 550 public: 551 TestFramebuffer (void); 552 TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx); 553 ~TestFramebuffer (void); 554 555 void setTargetType (const deUint32 targetType); 556 557 FboType getType (void) const; 558 deUint32 getColorAttachment (void) const; 559 int getIdx (void) const; 560 561 void bind (void); 562 void unbind (void); 563 564 typedef de::UniquePtr<glu::Framebuffer> fboUniquePtr; 565 566 private: 567 const glw::Functions* m_gl; 568 fboUniquePtr m_referenceSource; 569 deUint32 m_targetType; 570 bool m_bound; 571 bool m_isSRGB; 572 FboType m_type; 573 const int m_idx; 574 deUint32 m_colorAttachment; 575 }; 576 577 TestFramebuffer::TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx) 578 : m_gl (&context.getRenderContext().getFunctions()) 579 , m_referenceSource (new glu::Framebuffer(context.getRenderContext())) 580 , m_targetType (targetType) 581 , m_bound (false) 582 , m_isSRGB (isSRGB) 583 , m_type (fboType) 584 , m_idx (idx) 585 , m_colorAttachment (colorAttachment) 586 { 587 m_gl->bindFramebuffer(m_targetType, **m_referenceSource); 588 589 m_gl->framebufferTexture2D(m_targetType, m_colorAttachment, GL_TEXTURE_2D, textureAttachmentHandle, 0); 590 591 TCU_CHECK(m_gl->checkFramebufferStatus(m_targetType) == GL_FRAMEBUFFER_COMPLETE); 592 593 if (targetType == GL_DRAW_BUFFER) 594 { 595 glw::GLuint textureAttachments[] = {m_colorAttachment}; 596 m_gl->drawBuffers(DE_LENGTH_OF_ARRAY(textureAttachments), textureAttachments); 597 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glDrawBuffer()"); 598 } 599 600 if (targetType == GL_READ_BUFFER) 601 { 602 m_gl->readBuffer(m_colorAttachment); 603 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glReadBuffer()"); 604 } 605 606 m_gl->bindFramebuffer(m_targetType, 0); 607 } 608 609 TestFramebuffer::~TestFramebuffer (void) 610 { 611 } 612 613 void TestFramebuffer::setTargetType (const deUint32 targetType) 614 { 615 m_targetType = targetType; 616 } 617 618 FboType TestFramebuffer::getType (void) const 619 { 620 return m_type; 621 } 622 623 deUint32 TestFramebuffer::getColorAttachment (void) const 624 { 625 return m_colorAttachment; 626 } 627 628 int TestFramebuffer::getIdx (void) const 629 { 630 return m_idx; 631 } 632 633 void TestFramebuffer::bind (void) 634 { 635 if (!m_bound) 636 { 637 m_gl->bindFramebuffer(m_targetType, **m_referenceSource); 638 m_bound = true; 639 } 640 } 641 642 void TestFramebuffer::unbind (void) 643 { 644 if (m_bound) 645 { 646 m_gl->bindFramebuffer(m_targetType, 0); 647 m_bound = false; 648 } 649 } 650 651 class TestShaderProgram 652 { 653 public: 654 TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction); 655 ~TestShaderProgram (void); 656 657 glw::GLuint getHandle (void) const; 658 659 void use (void) const; 660 void unuse (void) const; 661 662 glu::ShaderProgramInfo getLogInfo (void); 663 664 private: 665 const glw::Functions* m_gl; 666 de::MovePtr<glu::ShaderProgram> m_referenceSource; 667 const int m_samplerTotal; 668 const int m_shaderStagesTotal; 669 }; 670 671 TestShaderProgram::TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction) 672 : m_gl (&context.getRenderContext().getFunctions()) 673 , m_samplerTotal (samplerTotal) 674 , m_shaderStagesTotal (2) 675 { 676 std::ostringstream shaderFragment; 677 678 const char* const shaderVertex = 679 "#version 310 es \n" 680 "layout (location = 0) in mediump vec3 aPosition; \n" 681 "layout (location = 1) in mediump vec2 aTexCoord; \n" 682 "out mediump vec2 vs_aTexCoord; \n" 683 "void main () \n" 684 "{ \n" 685 " gl_Position = vec4(aPosition, 1.0f); \n" 686 " vs_aTexCoord = aTexCoord; \n" 687 "} \n"; 688 689 shaderFragment 690 << "#version 310 es \n" 691 << "in mediump vec2 vs_aTexCoord; \n" 692 << "layout (location = 0) out mediump vec4 fs_aColor0; \n"; 693 694 for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++) 695 shaderFragment 696 << "uniform sampler2D uTexture" << samplerIdx << "; \n"; 697 698 shaderFragment 699 << "uniform int uFunctionType; \n"; 700 701 if (testFunction.hasFunction) 702 shaderFragment 703 << "uniform int uBlendFunctionType; \n" 704 << "uniform mediump float uFactorSrc; \n" 705 << "uniform mediump float uFactorDst; \n" 706 << testFunction.functionDefintion; 707 708 shaderFragment 709 << "void main () \n" 710 << "{ \n"; 711 712 for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++) 713 shaderFragment 714 <<" mediump vec4 texelColor" << samplerIdx << " = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n"; 715 716 shaderFragment 717 << buildSamplingPassType(m_samplerTotal); 718 719 if (testFunction.hasFunction) 720 shaderFragment 721 << " fs_aColor0 = " << testFunction.functionName << "(texelColor0, texelColor1); \n"; 722 else 723 shaderFragment 724 << " fs_aColor0 = texelColor0; \n"; 725 726 shaderFragment 727 << "} \n"; 728 729 m_referenceSource = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(context.getRenderContext(), glu::makeVtxFragSources(shaderVertex, shaderFragment.str()))); 730 if (!m_referenceSource->isOk()) 731 { 732 tcu::TestLog& log = context.getTestContext().getLog(); 733 log << this->getLogInfo(); 734 TCU_FAIL("Failed to compile shaders and link program"); 735 } 736 } 737 738 TestShaderProgram::~TestShaderProgram (void) 739 { 740 m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL); 741 m_referenceSource.clear(); 742 } 743 744 deUint32 TestShaderProgram::getHandle (void) const 745 { 746 return m_referenceSource->getProgram(); 747 } 748 749 void TestShaderProgram::use (void) const 750 { 751 m_gl->useProgram(this->getHandle()); 752 } 753 754 void TestShaderProgram::unuse (void) const 755 { 756 m_gl->useProgram(0); 757 } 758 759 glu::ShaderProgramInfo TestShaderProgram::getLogInfo (void) 760 { 761 glu::ShaderProgramInfo buildInfo; 762 763 // log shader program info. Only vertex and fragment shaders included 764 buildInfo.program = m_referenceSource->getProgramInfo(); 765 for (int shaderIdx = 0; shaderIdx < m_shaderStagesTotal; shaderIdx++) 766 { 767 glu::ShaderInfo shaderInfo = m_referenceSource->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0); 768 buildInfo.shaders.push_back(shaderInfo); 769 } 770 return buildInfo; 771 } 772 773 class Renderer 774 { 775 public: 776 Renderer (Context& context); 777 ~Renderer (void); 778 779 void init (const TestRenderPassConfig& renderPassConfig, const int renderpass); 780 void deinit (void); 781 782 void setSamplingType (const SamplingType samplerIdx); 783 void setBlendIteration (const int blendIteration); 784 void setFramebufferBlend (const bool blend); 785 void setFramebufferSRGB (const bool sRGB); 786 787 std::vector<tcu::Vec4> getResultsPreDraw (void) const; 788 std::vector<tcu::Vec4> getResultsPostDraw (void) const; 789 int getBlendConfigCount (void) const; 790 glu::ShaderProgramInfo getShaderProgramInfo (void); 791 792 void copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy); 793 void draw (void); 794 void storeShaderProgramInfo (void); 795 void logShaderProgramInfo (void); 796 797 typedef de::SharedPtr<TestTexture2D> TextureSp; 798 typedef de::SharedPtr<TestFramebuffer> FboSp; 799 800 private: 801 void createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList); 802 void setShaderProgramSamplingType (const int samplerIdx); 803 void setShaderBlendFunctionType (void); 804 void setShaderBlendSrcDstValues (void); 805 void bindActiveTexturesSamplers (void); 806 void bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired); 807 void unbindAllSourceTextures (void); 808 void bindFramebuffer (const int framebufferIdx); 809 void unbindFramebuffer (const int framebufferIdx); 810 void enableFramebufferSRGB (void); 811 void enableFramebufferBlend (void); 812 bool isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const; 813 void readTexels (const int px, const int py, const deUint32 attachment, tcu::Vec4& texelData); 814 void logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const; 815 816 // renderer specific constants initialized during constructor 817 Context& m_context; 818 const TestVertexData m_vertexData; 819 const int m_textureSourceTotal; 820 821 // additional resources monitored by the renderer 822 std::vector<BlendConfig> m_blendConfigList; 823 std::vector<TextureSp> m_textureSourceList; 824 TestRenderPassConfig m_renderPassConfig; 825 std::vector<TextureSp> m_fboTextureList; 826 TestShaderProgram* m_shaderProgram; 827 std::vector<FboSp> m_framebufferList; 828 std::vector<tcu::Vec4> m_resultsListPreDraw; 829 std::vector<tcu::Vec4> m_resultsListPostDraw; 830 831 // mutable state variables (internal access only) 832 bool m_hasShaderProgramInfo; 833 int m_renderPass; 834 int m_samplersRequired; 835 bool m_hasFunction; 836 bool m_blittingEnabled; 837 glu::ShaderProgramInfo m_shaderProgramInfo; 838 839 // mutable state variables (external access via setters) 840 SamplingType m_samplingType; 841 int m_blendIteration; 842 bool m_framebufferBlendEnabled; 843 bool m_framebufferSRGBEnabled; 844 }; 845 846 Renderer::Renderer (Context& context) 847 : m_context (context) 848 , m_vertexData (context) 849 , m_textureSourceTotal (2) 850 , m_blendConfigList (getBlendingConfigList()) 851 , m_hasShaderProgramInfo (false) 852 { 853 TextureSp textureLinear(new TestTexture2D(m_context, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear())); 854 m_textureSourceList.push_back(textureLinear); 855 856 TextureSp textureSRGB(new TestTexture2D(m_context, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear())); 857 m_textureSourceList.push_back(textureSRGB); 858 } 859 860 Renderer::~Renderer (void) 861 { 862 m_textureSourceList.clear(); 863 this->deinit(); 864 } 865 866 void Renderer::init (const TestRenderPassConfig& renderPassConfig, const int renderpass) 867 { 868 m_renderPassConfig = renderPassConfig; 869 m_renderPass = renderpass; 870 871 this->createFBOwithColorAttachment(m_renderPassConfig.fboConfigList); 872 873 if (m_renderPassConfig.textureSourcesType != TEXTURESOURCESTYPE_NONE) 874 { 875 if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_RGBA || m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_SRGBA) 876 m_samplersRequired = 1; 877 else if (m_renderPassConfig.textureSourcesType ==TEXTURESOURCESTYPE_BOTH ) 878 m_samplersRequired = 2; 879 else 880 DE_FATAL("Error: Texture source required not recognised"); 881 882 m_shaderProgram = new TestShaderProgram(m_context, m_samplersRequired, m_renderPassConfig.testFunction); 883 m_hasFunction = m_renderPassConfig.testFunction.hasFunction; 884 } 885 else 886 m_shaderProgram = DE_NULL; 887 } 888 889 void Renderer::deinit (void) 890 { 891 if (m_shaderProgram != DE_NULL) 892 { 893 delete m_shaderProgram; 894 m_shaderProgram = DE_NULL; 895 } 896 897 m_fboTextureList.clear(); 898 m_framebufferList.clear(); 899 } 900 901 void Renderer::setSamplingType (const SamplingType samplingType) 902 { 903 m_samplingType = samplingType; 904 } 905 906 void Renderer::setBlendIteration (const int blendIteration) 907 { 908 m_blendIteration = blendIteration; 909 } 910 911 void Renderer::setFramebufferBlend (const bool blend) 912 { 913 m_framebufferBlendEnabled = blend; 914 } 915 916 void Renderer::setFramebufferSRGB (const bool sRGB) 917 { 918 m_framebufferSRGBEnabled = sRGB; 919 } 920 921 std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const 922 { 923 return m_resultsListPreDraw; 924 } 925 926 std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const 927 { 928 return m_resultsListPostDraw; 929 } 930 931 int Renderer::getBlendConfigCount (void) const 932 { 933 return (int)m_blendConfigList.size(); 934 } 935 936 void Renderer::copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy) 937 { 938 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 939 int fboSrcIdx = -1; 940 int fboDstIdx = -1; 941 deUint32 fboSrcColAttachment = GL_NONE; 942 deUint32 fboDstColAttachment = GL_NONE; 943 944 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 945 this->bindFramebuffer(idx); 946 947 // cache fbo attachments and idx locations 948 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 949 { 950 if (m_framebufferList[idx]->getType() == FBOTYPE_SOURCE) 951 { 952 fboSrcIdx = m_framebufferList[idx]->getIdx(); 953 fboSrcColAttachment = m_framebufferList[fboSrcIdx]->getColorAttachment(); 954 } 955 if (m_framebufferList[idx]->getType() == FBOTYPE_DESTINATION) 956 { 957 fboDstIdx = m_framebufferList[idx]->getIdx(); 958 fboDstColAttachment = m_framebufferList[fboDstIdx]->getColorAttachment(); 959 } 960 } 961 962 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 963 m_framebufferList[idx]->unbind(); 964 965 // store texel data from both src and dst before performing the copy 966 m_resultsListPreDraw.resize(2); 967 m_framebufferList[fboSrcIdx]->bind(); 968 this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPreDraw[0]); 969 m_framebufferList[fboSrcIdx]->unbind(); 970 m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER); 971 m_framebufferList[fboDstIdx]->bind(); 972 this->readTexels(0, 0, fboDstColAttachment, m_resultsListPreDraw[1]); 973 m_framebufferList[fboDstIdx]->unbind(); 974 m_framebufferList[fboDstIdx]->setTargetType(GL_DRAW_FRAMEBUFFER); 975 976 m_framebufferList[fboSrcIdx]->bind(); 977 m_framebufferList[fboDstIdx]->bind(); 978 979 this->enableFramebufferSRGB(); 980 this->enableFramebufferBlend(); 981 982 gl.blitFramebuffer( srcPx, srcPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT, 983 dstPx, dstPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT, 984 GL_COLOR_BUFFER_BIT, GL_NEAREST); 985 986 m_resultsListPostDraw.resize(2); 987 this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPostDraw[0]); 988 m_framebufferList[fboSrcIdx]->unbind(); 989 m_framebufferList[fboDstIdx]->unbind(); 990 991 m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER); 992 m_framebufferList[fboDstIdx]->bind(); 993 this->readTexels(0, 0, fboDstColAttachment, m_resultsListPostDraw[1]); 994 m_framebufferList[fboDstIdx]->unbind(); 995 } 996 997 void Renderer::draw (void) 998 { 999 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1000 1001 if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_NONE) 1002 DE_FATAL("Error: Attempted to draw with no texture sources"); 1003 1004 // resize results storage with each render pass 1005 m_resultsListPreDraw.resize(m_renderPass + 1); 1006 m_resultsListPostDraw.resize(m_renderPass + 1); 1007 1008 m_shaderProgram->use(); 1009 m_vertexData.bind(); 1010 1011 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 1012 this->bindFramebuffer(idx); 1013 1014 this->bindAllRequiredSourceTextures(m_renderPassConfig.textureSourcesType); 1015 this->bindActiveTexturesSamplers(); 1016 1017 this->enableFramebufferSRGB(); 1018 this->enableFramebufferBlend(); 1019 1020 this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPreDraw[m_renderPass]); 1021 this->setShaderProgramSamplingType(m_samplingType); 1022 if (m_hasFunction) 1023 { 1024 this->setShaderBlendFunctionType(); 1025 this->setShaderBlendSrcDstValues(); 1026 } 1027 1028 gl.drawArrays(GL_TRIANGLES, 0, 6); 1029 1030 this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPostDraw[m_renderPass]); 1031 this->logState(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_samplingType); 1032 1033 this->unbindAllSourceTextures(); 1034 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) 1035 this->unbindFramebuffer(idx); 1036 m_vertexData.unbind(); 1037 m_shaderProgram->unuse(); 1038 } 1039 1040 void Renderer::storeShaderProgramInfo (void) 1041 { 1042 m_shaderProgramInfo = m_shaderProgram->getLogInfo(); 1043 m_hasShaderProgramInfo = true; 1044 } 1045 1046 void Renderer::logShaderProgramInfo (void) 1047 { 1048 tcu::TestLog& log = m_context.getTestContext().getLog(); 1049 1050 if (m_hasShaderProgramInfo) 1051 log << m_shaderProgramInfo; 1052 } 1053 1054 void Renderer::createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList) 1055 { 1056 const int size = (int)fboConfigList.size(); 1057 for (int idx = 0; idx < size; idx++) 1058 { 1059 TextureSp texture(new TestTexture2D(m_context, fboConfigList[idx].textureInternalFormat, GL_RGBA, GL_UNSIGNED_BYTE, fboConfigList[idx].textureColor)); 1060 m_fboTextureList.push_back(texture); 1061 1062 bool isSRGB; 1063 if (fboConfigList[idx].textureInternalFormat == GL_SRGB8_ALPHA8) 1064 isSRGB = true; 1065 else 1066 isSRGB = false; 1067 1068 FboSp framebuffer(new TestFramebuffer(m_context, fboConfigList[idx].fboTargetType, fboConfigList[idx].fboColorAttachment, texture->getHandle(), isSRGB, fboConfigList[idx].fboType, idx)); 1069 m_framebufferList.push_back(framebuffer); 1070 } 1071 } 1072 1073 void Renderer::setShaderProgramSamplingType (const int samplerIdx) 1074 { 1075 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1076 1077 glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFunctionType"); 1078 DE_ASSERT(location != (glw::GLuint)-1); 1079 gl.uniform1i(location, samplerIdx); 1080 } 1081 1082 void Renderer::setShaderBlendFunctionType (void) 1083 { 1084 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1085 1086 int function = -1; 1087 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD) 1088 function = 0; 1089 else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT) 1090 function = 1; 1091 else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT) 1092 function = 2; 1093 else 1094 DE_FATAL("Error: Blend function not recognised"); 1095 1096 glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uBlendFunctionType"); 1097 DE_ASSERT(location != (glw::GLuint)-1); 1098 gl.uniform1i(location, function); 1099 } 1100 1101 void Renderer::setShaderBlendSrcDstValues (void) 1102 { 1103 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1104 1105 float funcSrc; 1106 if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE) 1107 funcSrc = 1.0f; 1108 else 1109 funcSrc = 0.0f; 1110 1111 float funcDst; 1112 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE) 1113 funcDst = 1.0f; 1114 else 1115 funcDst = 0.0f; 1116 1117 glw::GLuint locationSrc = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorSrc"); 1118 gl.uniform1f(locationSrc, funcSrc); 1119 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()"); 1120 1121 glw::GLuint locationDst = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorDst"); 1122 gl.uniform1f(locationDst, funcDst); 1123 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()"); 1124 } 1125 1126 void Renderer::bindActiveTexturesSamplers (void) 1127 { 1128 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1129 1130 for (int idx = 0; idx < m_samplersRequired; idx++) 1131 { 1132 std::ostringstream stream; 1133 stream << "uTexture" << idx; 1134 std::string uniformName(stream.str()); 1135 glw::GLint location = gl.getUniformLocation(m_shaderProgram->getHandle(), uniformName.c_str()); 1136 DE_ASSERT(location != -1); 1137 gl.uniform1i(location, m_textureSourceList[idx]->getTextureUnit()); 1138 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation()"); 1139 } 1140 } 1141 1142 void Renderer::bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired) 1143 { 1144 if (texturesRequired == TEXTURESOURCESTYPE_RGBA) 1145 m_textureSourceList[0]->bind(0); 1146 else if (texturesRequired == TEXTURESOURCESTYPE_SRGBA) 1147 m_textureSourceList[1]->bind(0); 1148 else if (texturesRequired == TEXTURESOURCESTYPE_BOTH) 1149 { 1150 m_textureSourceList[0]->bind(0); 1151 m_textureSourceList[1]->bind(1); 1152 } 1153 else 1154 DE_FATAL("Error: Invalid sources requested in bind all"); 1155 } 1156 1157 void Renderer::unbindAllSourceTextures (void) 1158 { 1159 for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++) 1160 m_textureSourceList[idx]->unbind(); 1161 } 1162 1163 void Renderer::bindFramebuffer (const int framebufferIdx) 1164 { 1165 m_framebufferList[framebufferIdx]->bind(); 1166 } 1167 1168 void Renderer::unbindFramebuffer (const int framebufferIdx) 1169 { 1170 m_framebufferList[framebufferIdx]->unbind(); 1171 } 1172 1173 void Renderer::enableFramebufferSRGB (void) 1174 { 1175 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1176 1177 if (m_framebufferSRGBEnabled) 1178 gl.enable(GL_FRAMEBUFFER_SRGB); 1179 else 1180 gl.disable(GL_FRAMEBUFFER_SRGB); 1181 } 1182 1183 void Renderer::enableFramebufferBlend (void) 1184 { 1185 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1186 tcu::TestLog& log = m_context.getTestContext().getLog(); 1187 std::ostringstream message; 1188 1189 message << "Blend settings = "; 1190 1191 if (m_framebufferBlendEnabled) 1192 { 1193 gl.enable(GL_BLEND); 1194 gl.blendEquation(m_blendConfigList[m_blendIteration].equation); 1195 gl.blendFunc(m_blendConfigList[m_blendIteration].funcSrc, m_blendConfigList[m_blendIteration].funcDst); 1196 1197 std::string equation, src, dst; 1198 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD) 1199 equation = "GL_FUNC_ADD"; 1200 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT) 1201 equation = "GL_FUNC_SUBTRACT"; 1202 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT) 1203 equation = "GL_FUNC_REVERSE_SUBTRACT"; 1204 if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE) 1205 src = "GL_ONE"; 1206 else 1207 src = "GL_ZERO"; 1208 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE) 1209 dst = "GL_ONE"; 1210 else 1211 dst = "GL_ZERO"; 1212 1213 message << "Enabled: equation = " << equation << ", func src = " << src << ", func dst = " << dst; 1214 } 1215 else 1216 { 1217 gl.disable(GL_BLEND); 1218 message << "Disabled"; 1219 } 1220 1221 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1222 } 1223 1224 bool Renderer::isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const 1225 { 1226 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1227 glw::GLint encodingType; 1228 1229 gl.getFramebufferAttachmentParameteriv(targetType, attachment, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encodingType); 1230 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedFramebufferAttachmentParameteriv()"); 1231 1232 switch (static_cast<glw::GLenum>(encodingType)) 1233 { 1234 case GL_SRGB: 1235 { 1236 return true; 1237 break; 1238 } 1239 case GL_LINEAR: 1240 { 1241 return false; 1242 break; 1243 } 1244 default: 1245 { 1246 DE_FATAL("Error: Color attachment format not recognised"); 1247 return false; 1248 } 1249 } 1250 } 1251 1252 void Renderer::readTexels (const int px, const int py, const deUint32 mode, tcu::Vec4& texelData) 1253 { 1254 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1255 tcu::TextureLevel textureRead; 1256 1257 // ensure result sampling coordinates are within range of the result color attachment 1258 DE_ASSERT((px >= 0) && (px < m_context.getRenderTarget().getWidth())); 1259 DE_ASSERT((py >= 0) && (py < m_context.getRenderTarget().getHeight())); 1260 1261 gl.readBuffer(mode); 1262 textureRead.setStorage(glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE), TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT); 1263 glu::readPixels(m_context.getRenderContext(), px, py, textureRead.getAccess()); 1264 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()"); 1265 texelData = textureRead.getAccess().getPixel(px, py); 1266 } 1267 1268 void Renderer::logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const 1269 { 1270 tcu::TestLog& log = m_context.getTestContext().getLog(); 1271 std::ostringstream message; 1272 1273 bool fboAttachmentSRGB = this->isFramebufferAttachmentSRGB(targetType, attachment); 1274 message.str(""); 1275 message << "getFramebufferAttachmentParameteriv() check = "; 1276 if (fboAttachmentSRGB) 1277 message << "GL_SRGB"; 1278 else 1279 message << "GL_LINEAR"; 1280 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1281 1282 message.str(""); 1283 message << "Framebuffer color attachment value BEFORE draw call"; 1284 logColor(m_context, message.str(), m_resultsListPreDraw[m_renderPass]); 1285 1286 message.str(""); 1287 message << "Framebuffer color attachment value AFTER draw call"; 1288 logColor(m_context, message.str(), m_resultsListPostDraw[m_renderPass]); 1289 1290 message.str(""); 1291 message << "Sampling type = "; 1292 std::string type; 1293 if (samplingType == 0) 1294 type = "texture()"; 1295 else if (samplingType == 1) 1296 type = "textureLOD()"; 1297 else if (samplingType == 2) 1298 type = "textureGrad()"; 1299 else if (samplingType == 3) 1300 type = "textureOffset()"; 1301 else if (samplingType == 4) 1302 type = "textureProj()"; 1303 else 1304 DE_FATAL("Error: Sampling type unregonised"); 1305 message << type; 1306 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1307 1308 message.str(""); 1309 if (m_framebufferSRGBEnabled) 1310 message << "Framebuffer SRGB = enabled"; 1311 else 1312 message << "Framebuffer SRGB = disabled"; 1313 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1314 } 1315 1316 class FboSRGBTestCase : public TestCase 1317 { 1318 public: 1319 FboSRGBTestCase (Context& context, const char* const name, const char* const desc); 1320 ~FboSRGBTestCase (void); 1321 1322 void init (void); 1323 void deinit (void); 1324 IterateResult iterate (void); 1325 1326 void setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList); 1327 1328 virtual void setupTest (void) = 0; 1329 virtual bool verifyResult (void) = 0; 1330 1331 protected: 1332 bool m_hasTestConfig; 1333 std::vector<TestRenderPassConfig> m_renderPassConfigList; 1334 bool m_testcaseRequiresBlend; 1335 std::vector<tcu::Vec4> m_resultsPreDraw; 1336 std::vector<tcu::Vec4> m_resultsPostDraw; 1337 1338 private: 1339 FboSRGBTestCase (const FboSRGBTestCase&); 1340 FboSRGBTestCase& operator= (const FboSRGBTestCase&); 1341 }; 1342 1343 FboSRGBTestCase::FboSRGBTestCase (Context& context, const char* const name, const char* const desc) 1344 : TestCase (context, name, desc) 1345 , m_hasTestConfig (false) 1346 { 1347 } 1348 1349 FboSRGBTestCase::~FboSRGBTestCase (void) 1350 { 1351 FboSRGBTestCase::deinit(); 1352 } 1353 1354 void FboSRGBTestCase::init (void) 1355 { 1356 // extensions requirements for test 1357 if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2))) 1358 TCU_THROW(NotSupportedError, "Test requires a context version equal or higher than 3.2"); 1359 1360 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) 1361 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control"); 1362 1363 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode")) 1364 TCU_THROW(NotSupportedError, "Test requires GL_EXT_texture_sRGB_decode extension"); 1365 } 1366 1367 void FboSRGBTestCase::deinit (void) 1368 { 1369 } 1370 1371 FboSRGBTestCase::IterateResult FboSRGBTestCase::iterate (void) 1372 { 1373 this->setupTest(); 1374 1375 DE_ASSERT(m_hasTestConfig && "Error: Renderer was not supplied a test config"); 1376 1377 Renderer renderer(m_context); 1378 1379 // loop through each sampling type 1380 for (int samplingIdx = 0; samplingIdx < SampligTypeCount::MAX; samplingIdx++) 1381 { 1382 renderer.setSamplingType(static_cast<SamplingType>(samplingIdx)); 1383 1384 // loop through each blend configuration 1385 const int blendCount = renderer.getBlendConfigCount(); 1386 for (int blendIdx = 0; blendIdx < blendCount; blendIdx++) 1387 { 1388 // loop through each render pass 1389 const int renderPassCount = (int)m_renderPassConfigList.size(); 1390 for (int renderPassIdx = 0; renderPassIdx < renderPassCount; renderPassIdx++) 1391 { 1392 TestRenderPassConfig renderPassConfig = m_renderPassConfigList[renderPassIdx]; 1393 1394 renderer.init(renderPassConfig, renderPassIdx); 1395 1396 if (blendIdx == 0 && renderPassConfig.rendererTask == RENDERERTASK_DRAW) 1397 renderer.storeShaderProgramInfo(); 1398 1399 if (renderPassConfig.frameBufferBlend == FRAMEBUFFERBLEND_ENABLED) 1400 { 1401 renderer.setBlendIteration(blendIdx); 1402 renderer.setFramebufferBlend(true); 1403 } 1404 else 1405 renderer.setFramebufferBlend(false); 1406 1407 if (renderPassConfig.framebufferSRGB == FRAMEBUFFERSRGB_ENABLED) 1408 renderer.setFramebufferSRGB(true); 1409 else 1410 renderer.setFramebufferSRGB(false); 1411 1412 if (renderPassConfig.rendererTask == RENDERERTASK_DRAW) 1413 renderer.draw(); 1414 else if (renderPassConfig.rendererTask == RENDERERTASK_COPY) 1415 renderer.copyFrameBufferTexture(0, 0, 0, 0); 1416 else 1417 DE_FATAL("Error: render task not recognised"); 1418 1419 renderer.deinit(); 1420 1421 } // render passes 1422 1423 m_resultsPreDraw = renderer.getResultsPreDraw(); 1424 m_resultsPostDraw = renderer.getResultsPostDraw(); 1425 1426 bool testPassed = this->verifyResult(); 1427 if (testPassed) 1428 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1429 else 1430 { 1431 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed"); 1432 renderer.logShaderProgramInfo(); 1433 return STOP; 1434 } 1435 1436 if (!m_testcaseRequiresBlend) 1437 break; 1438 } // blend configs 1439 1440 renderer.logShaderProgramInfo(); 1441 } // sampling types 1442 1443 return STOP; 1444 } 1445 1446 void FboSRGBTestCase::setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList) 1447 { 1448 m_renderPassConfigList = renderPassConfigList; 1449 m_hasTestConfig = true; 1450 1451 for (int idx = 0; idx < (int)renderPassConfigList.size(); idx++) 1452 { 1453 if (renderPassConfigList[idx].frameBufferBlend == FRAMEBUFFERBLEND_ENABLED) 1454 { 1455 m_testcaseRequiresBlend = true; 1456 return; 1457 } 1458 } 1459 m_testcaseRequiresBlend = false; 1460 } 1461 1462 class FboSRGBQueryCase : public TestCase 1463 { 1464 public: 1465 FboSRGBQueryCase (Context& context, const char* const name, const char* const description); 1466 ~FboSRGBQueryCase (void); 1467 1468 void init (void); 1469 void deinit (void); 1470 IterateResult iterate (void); 1471 }; 1472 1473 FboSRGBQueryCase::FboSRGBQueryCase (Context& context, const char* const name, const char* const description) 1474 : TestCase (context, name, description) 1475 { 1476 } 1477 1478 FboSRGBQueryCase::~FboSRGBQueryCase (void) 1479 { 1480 FboSRGBQueryCase::deinit(); 1481 } 1482 1483 void FboSRGBQueryCase::init (void) 1484 { 1485 // extension requirements for test 1486 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) 1487 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control"); 1488 } 1489 1490 void FboSRGBQueryCase::deinit (void) 1491 { 1492 } 1493 1494 FboSRGBQueryCase::IterateResult FboSRGBQueryCase::iterate (void) 1495 { 1496 // TEST INFO: 1497 // API tests which check when querying FRAMEBUFFER_SRGB_EXT capability returns the correct information when using glEnabled() or glDisabled() 1498 1499 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1500 tcu::TestLog& log = m_context.getTestContext().getLog(); 1501 const char* const msgPart = ", after disabling = "; 1502 1503 for (int idx = 0; idx < static_cast<int>(QUERYTYPE_LAST); idx++) 1504 { 1505 std::ostringstream message; 1506 bool pass = false; 1507 1508 message << std::string("Results: After Enabling = "); 1509 1510 gl.enable(GL_FRAMEBUFFER_SRGB); 1511 1512 switch (static_cast<QueryType>(idx)) 1513 { 1514 case QUERYTYPE_ISENABLED: 1515 { 1516 glw::GLboolean enabled[2]; 1517 enabled[0] = gl.isEnabled(GL_FRAMEBUFFER_SRGB); 1518 gl.disable(GL_FRAMEBUFFER_SRGB); 1519 enabled[1] = gl.isEnabled(GL_FRAMEBUFFER_SRGB); 1520 1521 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1522 pass = (enabled[0] && !(enabled[1])) ? true : false; 1523 break; 1524 } 1525 case QUERYTYPE_BOOLEAN: 1526 { 1527 glw::GLboolean enabled[2]; 1528 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[0]); 1529 gl.disable(GL_FRAMEBUFFER_SRGB); 1530 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[1]); 1531 1532 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1533 pass = (enabled[0] && !(enabled[1])) ? true : false; 1534 break; 1535 } 1536 case QUERYTYPE_FLOAT: 1537 { 1538 glw::GLfloat enabled[2]; 1539 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[0]); 1540 gl.disable(GL_FRAMEBUFFER_SRGB); 1541 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[1]); 1542 1543 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1544 pass = ((int)enabled[0] && !((int)enabled[1])) ? true : false; 1545 break; 1546 } 1547 case QUERYTYPE_INT: 1548 { 1549 glw::GLint enabled[2]; 1550 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[0]); 1551 gl.disable(GL_FRAMEBUFFER_SRGB); 1552 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[1]); 1553 1554 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1555 pass = (enabled[0] && !(enabled[1])) ? true : false; 1556 break; 1557 } 1558 case QUERYTYPE_INT64: 1559 { 1560 glw::GLint64 enabled[2]; 1561 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[0]); 1562 gl.disable(GL_FRAMEBUFFER_SRGB); 1563 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[1]); 1564 1565 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); 1566 pass = (enabled[0] && !(enabled[1])) ? true : false; 1567 break; 1568 } 1569 default: 1570 DE_FATAL("Error: Datatype not recognised"); 1571 } 1572 1573 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; 1574 1575 if (pass) 1576 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1577 else 1578 { 1579 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed"); 1580 return STOP; 1581 } 1582 } 1583 return STOP; 1584 } 1585 1586 class FboSRGBColAttachCase : public FboSRGBTestCase 1587 { 1588 public: 1589 FboSRGBColAttachCase (Context& context, const char* const name, const char* const description) 1590 : FboSRGBTestCase (context, name, description) {} 1591 ~FboSRGBColAttachCase (void) {} 1592 1593 void setupTest (void); 1594 bool verifyResult (void); 1595 }; 1596 1597 void FboSRGBColAttachCase::setupTest (void) 1598 { 1599 // TEST INFO: 1600 // Check if FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING set to SRGB and FRAMEBUFFER_SRGB_EXT enabled, destination colors are converted from SRGB to linear 1601 // before and after blending, finally the result is converted back to SRGB for storage 1602 1603 // NOTE: 1604 // if fbo pre-draw color set to linaer, color values get linearlized "twice" 1605 // (0.2f, 0.3f, 0.4f, 1.0f) when sampled i.e. converted in shader = (0.0331048f, 0.073239f, 0.132868f) 1606 // 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) 1607 1608 FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE); 1609 FBOConfig fboConfig1 = FBOConfig(GL_RGBA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE); 1610 1611 const TestRenderPassConfig renderPassConfigs[] = 1612 { 1613 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_ENABLED, RENDERERTASK_DRAW), 1614 TestRenderPassConfig(TEXTURESOURCESTYPE_BOTH, fboConfig1, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, getFunctionBlendLinearToSRGBCheck(), RENDERERTASK_DRAW) 1615 }; 1616 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1617 1618 this->setTestConfig(renderPassConfigList); 1619 } 1620 1621 bool FboSRGBColAttachCase::verifyResult (void) 1622 { 1623 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], m_resultsPostDraw[1]))) 1624 return true; 1625 else 1626 return false; 1627 } 1628 1629 class FboSRGBToggleBlendCase : public FboSRGBTestCase 1630 { 1631 public: 1632 FboSRGBToggleBlendCase (Context& context, const char* const name, const char* const description) 1633 : FboSRGBTestCase (context, name, description) {} 1634 ~FboSRGBToggleBlendCase (void) {} 1635 1636 void setupTest (void); 1637 bool verifyResult (void); 1638 }; 1639 1640 void FboSRGBToggleBlendCase::setupTest (void) 1641 { 1642 // TEST INFO: 1643 // Test to check if changing FRAMEBUFFER_SRGB_EXT from enabled to disabled. Enabled should produce SRGB color whilst disabled 1644 // should produce linear color. Test conducted with blending disabled. 1645 1646 FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION); 1647 1648 const TestRenderPassConfig renderPassConfigs[] = 1649 { 1650 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW), 1651 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW) 1652 }; 1653 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1654 1655 this->setTestConfig(renderPassConfigList); 1656 } 1657 1658 bool FboSRGBToggleBlendCase::verifyResult (void) 1659 { 1660 if (tcu::boolAny(tcu::greaterThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError()))) 1661 return true; 1662 else 1663 return false; 1664 } 1665 1666 class FboSRGBRenderTargetIgnoreCase : public FboSRGBTestCase 1667 { 1668 public: 1669 FboSRGBRenderTargetIgnoreCase (Context& context, const char* const name, const char* const description) 1670 : FboSRGBTestCase (context, name, description) {} 1671 ~FboSRGBRenderTargetIgnoreCase (void) {} 1672 1673 void setupTest (void); 1674 bool verifyResult (void); 1675 }; 1676 1677 void FboSRGBRenderTargetIgnoreCase::setupTest (void) 1678 { 1679 // TEST INFO: 1680 // Check if render targets that are non-RGB ignore the state of GL_FRAMEBUFFER_SRGB_EXT. Rendering to an fbo with non-sRGB color 1681 // attachment should ignore color space conversion, producing linear color. 1682 1683 FBOConfig fboConfig0 = FBOConfig(GL_RGBA8, getTestColorBlank(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION); 1684 1685 const TestRenderPassConfig renderPassConfigs[] = 1686 { 1687 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW) 1688 1689 }; 1690 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1691 1692 this->setTestConfig(renderPassConfigList); 1693 } 1694 1695 bool FboSRGBRenderTargetIgnoreCase::verifyResult (void) 1696 { 1697 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], getTestColorLinear()))) 1698 return true; 1699 else 1700 return false; 1701 } 1702 1703 class FboSRGBCopyToLinearCase : public FboSRGBTestCase 1704 { 1705 public: 1706 FboSRGBCopyToLinearCase (Context& context, const char* const name, const char* const description) 1707 : FboSRGBTestCase (context, name, description) {} 1708 ~FboSRGBCopyToLinearCase (void) {} 1709 1710 void setupTest (void); 1711 bool verifyResult (void); 1712 }; 1713 1714 void FboSRGBCopyToLinearCase::setupTest (void) 1715 { 1716 // TEST INFO: 1717 // 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 1718 // an sRGB to linear conversion 1719 1720 FBOConfig fboConfigs[] = 1721 { 1722 FBOConfig(GL_SRGB8_ALPHA8, getTestColorSRGB(), GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE), 1723 FBOConfig(GL_RGBA8, getTestColorBlank(), GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION) 1724 }; 1725 std::vector<FBOConfig> fboConfigList(fboConfigs, fboConfigs + DE_LENGTH_OF_ARRAY(fboConfigs)); 1726 1727 const TestRenderPassConfig renderPassConfigs[] = 1728 { 1729 TestRenderPassConfig(TEXTURESOURCESTYPE_NONE, fboConfigList, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_COPY) 1730 }; 1731 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); 1732 1733 this->setTestConfig(renderPassConfigList); 1734 } 1735 1736 bool FboSRGBCopyToLinearCase::verifyResult (void) 1737 { 1738 logColor(m_context, "pre-copy source fbo color values", m_resultsPreDraw[0]); 1739 logColor(m_context, "pre-copy destination fbo color values", m_resultsPreDraw[1]); 1740 logColor(m_context, "post-copy source fbo color values", m_resultsPostDraw[0]); 1741 logColor(m_context, "post-copy destination fbo color values", m_resultsPostDraw[1]); 1742 1743 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[1] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[1], getTestColorLinear()))) 1744 return true; 1745 else 1746 return false; 1747 } 1748 1749 class FboSRGBUnsupportedEnumCase : public TestCase 1750 { 1751 public: 1752 FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description); 1753 ~FboSRGBUnsupportedEnumCase (void); 1754 1755 void init (void); 1756 void deinit (void); 1757 bool isInvalidEnum (std::string functionName); 1758 IterateResult iterate (void); 1759 }; 1760 1761 FboSRGBUnsupportedEnumCase::FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description) 1762 : TestCase (context, name, description) 1763 { 1764 } 1765 1766 FboSRGBUnsupportedEnumCase::~FboSRGBUnsupportedEnumCase (void) 1767 { 1768 FboSRGBUnsupportedEnumCase::deinit(); 1769 } 1770 1771 void FboSRGBUnsupportedEnumCase::init (void) 1772 { 1773 // extension requirements for test 1774 if (m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) 1775 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control to be unsupported"); 1776 } 1777 1778 void FboSRGBUnsupportedEnumCase::deinit (void) 1779 { 1780 } 1781 1782 bool FboSRGBUnsupportedEnumCase::isInvalidEnum (std::string functionName) 1783 { 1784 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1785 tcu::TestLog& log = m_context.getTestContext().getLog(); 1786 bool isOk = true; 1787 glw::GLenum error = GL_NO_ERROR; 1788 1789 log << tcu::TestLog::Message << "Checking call to " << functionName << tcu::TestLog::EndMessage; 1790 1791 error = gl.getError(); 1792 1793 if (error != GL_INVALID_ENUM) 1794 { 1795 log << tcu::TestLog::Message << " returned wrong value [" << glu::getErrorStr(error) << ", expected " << glu::getErrorStr(GL_INVALID_ENUM) << "]" << tcu::TestLog::EndMessage; 1796 isOk = false; 1797 } 1798 1799 return isOk; 1800 } 1801 1802 FboSRGBUnsupportedEnumCase::IterateResult FboSRGBUnsupportedEnumCase::iterate (void) 1803 { 1804 // TEST INFO: 1805 // API tests that check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported 1806 1807 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1808 bool allPass = true; 1809 glw::GLboolean bEnabled = GL_FALSE; 1810 glw::GLfloat fEnabled = 0; 1811 glw::GLint iEnabled = 0; 1812 glw::GLint64 lEnabled = 0; 1813 1814 m_context.getTestContext().getLog() << tcu::TestLog::Message 1815 << "Check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported\n\n" 1816 << tcu::TestLog::EndMessage; 1817 1818 gl.enable(GL_FRAMEBUFFER_SRGB); 1819 allPass &= isInvalidEnum("glEnable()"); 1820 1821 gl.disable(GL_FRAMEBUFFER_SRGB); 1822 allPass &= isInvalidEnum("glDisable()"); 1823 1824 gl.isEnabled(GL_FRAMEBUFFER_SRGB); 1825 allPass &= isInvalidEnum("glIsEnabled()"); 1826 1827 gl.getBooleanv(GL_FRAMEBUFFER_SRGB, &bEnabled); 1828 allPass &= isInvalidEnum("glGetBooleanv()"); 1829 1830 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &fEnabled); 1831 allPass &= isInvalidEnum("glGetFloatv()"); 1832 1833 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &iEnabled); 1834 allPass &= isInvalidEnum("glGetIntegerv()"); 1835 1836 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &lEnabled); 1837 allPass &= isInvalidEnum("glGetInteger64v()"); 1838 1839 if (allPass) 1840 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1841 else 1842 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1843 1844 return STOP; 1845 } 1846 1847 } // anonymous 1848 1849 FboSRGBWriteControlTests::FboSRGBWriteControlTests (Context& context) 1850 : TestCaseGroup (context, "srgb_write_control", "Colorbuffer tests") 1851 { 1852 } 1853 1854 FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void) 1855 { 1856 } 1857 1858 void FboSRGBWriteControlTests::init (void) 1859 { 1860 this->addChild(new FboSRGBQueryCase (m_context, "framebuffer_srgb_enabled", "srgb enable framebuffer")); 1861 this->addChild(new FboSRGBColAttachCase (m_context, "framebuffer_srgb_enabled_col_attach", "srgb enable color attachment and framebuffer")); 1862 this->addChild(new FboSRGBToggleBlendCase (m_context, "framebuffer_srgb_enabled_blend", "toggle framebuffer srgb settings with blend disabled")); 1863 this->addChild(new FboSRGBRenderTargetIgnoreCase (m_context, "framebuffer_srgb_enabled_render_target_ignore", "enable framebuffer srgb, non-srgb render target should ignore")); 1864 this->addChild(new FboSRGBCopyToLinearCase (m_context, "framebuffer_srgb_enabled_copy_to_linear", "no conversion when blittering between framebuffer srgb and linear")); 1865 1866 // negative 1867 this->addChild(new FboSRGBUnsupportedEnumCase (m_context, "framebuffer_srgb_unsupported_enum", "check error codes for query functions when extension is not supported")); 1868 } 1869 1870 } 1871 } // gles31 1872 } // deqp 1873