Add sRGB write decode tests
authorMichael Hadley <michael.hadley@mobica.com>
Wed, 8 Mar 2017 13:28:09 +0000 (13:28 +0000)
committerMika Isojärvi <misojarvi@google.com>
Thu, 6 Jul 2017 18:06:22 +0000 (11:06 -0700)
New Tests:
- dEQP-GLES31.functional.fbo.srgb_write_control.*

Change-Id: Ieaaee4c7dc49cc530d8fc42a060e40c706d86e5c

android/cts/master/gles31-master.txt
modules/gles31/functional/CMakeLists.txt
modules/gles31/functional/es31fFboSRGBWriteControlTests.cpp [new file with mode: 0644]
modules/gles31/functional/es31fFboSRGBWriteControlTests.hpp [new file with mode: 0644]
modules/gles31/functional/es31fFunctionalTests.cpp

index b4f78d9..aeebbe3 100644 (file)
@@ -17894,6 +17894,11 @@ dEQP-GLES31.functional.fbo.no_attachments.maximums.size
 dEQP-GLES31.functional.fbo.no_attachments.maximums.samples
 dEQP-GLES31.functional.fbo.no_attachments.maximums.all
 dEQP-GLES31.functional.fbo.completeness.no_attachments
+dEQP-GLES31.functional.fbo.srgb_write_control.framebuffer_srgb_enabled
+dEQP-GLES31.functional.fbo.srgb_write_control.framebuffer_srgb_enabled_col_attach
+dEQP-GLES31.functional.fbo.srgb_write_control.framebuffer_srgb_enabled_blend
+dEQP-GLES31.functional.fbo.srgb_write_control.framebuffer_srgb_enabled_render_target_ignore
+dEQP-GLES31.functional.fbo.srgb_write_control.framebuffer_srgb_enabled_copy_to_linear
 dEQP-GLES31.functional.program_interface_query.buffer_limited_query.resource_name_query
 dEQP-GLES31.functional.program_interface_query.buffer_limited_query.resource_query
 dEQP-GLES31.functional.program_interface_query.uniform.resource_list.default_block.var
index 2f2429e..0454747 100644 (file)
@@ -71,6 +71,8 @@ set(DEQP_GLES31_FUNCTIONAL_SRCS
        es31fFboTestCase.hpp
        es31fFboTestUtil.cpp
        es31fFboTestUtil.hpp
+       es31fFboSRGBWriteControlTests.cpp
+       es31fFboSRGBWriteControlTests.hpp
        es31fTextureFilteringTests.cpp
        es31fTextureFilteringTests.hpp
        es31fTextureFormatTests.hpp
diff --git a/modules/gles31/functional/es31fFboSRGBWriteControlTests.cpp b/modules/gles31/functional/es31fFboSRGBWriteControlTests.cpp
new file mode 100644 (file)
index 0000000..bd913ec
--- /dev/null
@@ -0,0 +1,1796 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief FBO sRGB tests.
+*//*--------------------------------------------------------------------*/
+
+#include "es31fFboSRGBWriteControlTests.hpp"
+#include "es31fFboTestUtil.hpp"
+#include "gluTextureUtil.hpp"
+#include "gluContextInfo.hpp"
+#include "tcuTestLog.hpp"
+#include "glwEnums.hpp"
+#include "sglrContextUtil.hpp"
+#include "glwFunctions.hpp"
+#include "deUniquePtr.hpp"
+#include "deSharedPtr.hpp"
+#include "gluObjectWrapper.hpp"
+#include "gluPixelTransfer.hpp"
+#include "glsTextureTestUtil.hpp"
+#include "tcuVectorUtil.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+tcu::Vec4 getTestColorLinear (void)
+{
+       return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
+}
+
+tcu::Vec4 getTestColorSRGB (void)
+{
+       return linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
+}
+
+tcu::Vec4 getTestColorBlank (void)
+{
+       return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+}
+
+tcu::Vec4 getEpsilonError (void)
+{
+       return tcu::Vec4(0.005f);
+}
+
+enum QueryType
+{
+       QUERYTYPE_ISENABLED = 0,
+       QUERYTYPE_BOOLEAN,
+       QUERYTYPE_FLOAT,
+       QUERYTYPE_INT,
+       QUERYTYPE_INT64,
+       QUERYTYPE_LAST
+};
+
+enum DataType
+{
+       DATATYPE_BOOLEAN = 0,
+       DATATYPE_FLOAT,
+       DATATYPE_INT,
+       DATATYPE_INT64,
+};
+
+enum FramebufferSRGB
+{
+       FRAMEBUFFERSRGB_ENABLED = 0,
+       FRAMEBUFFERSRGB_DISABLED
+};
+
+enum FramebufferBlend
+{
+       FRAMEBUFFERBLEND_ENABLED = 0,
+       FRAMEBUFFERBLEND_DISABLED
+};
+
+enum TextureSourcesType
+{
+       TEXTURESOURCESTYPE_RGBA         = 0,
+       TEXTURESOURCESTYPE_SRGBA,
+       TEXTURESOURCESTYPE_BOTH,
+       TEXTURESOURCESTYPE_NONE
+};
+
+enum FboType
+{
+       FBOTYPE_SOURCE                  = 0,
+       FBOTYPE_DESTINATION
+};
+
+enum RendererTask
+{
+       RENDERERTASK_DRAW = 0,
+       RENDERERTASK_COPY
+};
+
+enum SamplingType
+{
+       SAMPLINGTYPE_TEXTURE                    = 0,
+       SAMPLINGTYPE_TEXTURE_LOD,
+       SAMPLINGTYPE_TEXTURE_GRAD,
+       SAMPLINGTYPE_TEXTURE_OFFSET,
+       SAMPLINGTYPE_TEXTURE_PROJ,
+};
+
+namespace TestTextureSizes
+{
+       const int WIDTH = 128;
+       const int HEIGHT = 128;
+} // global test texture sizes
+
+namespace SampligTypeCount
+{
+       const int MAX = 5;
+} // global max number of sampling types
+
+std::string buildSamplingPassType (const int samplerTotal)
+{
+       std::ostringstream      shaderFragment;
+
+       const SamplingType      samplingTypeList [] =
+       {
+               SAMPLINGTYPE_TEXTURE, SAMPLINGTYPE_TEXTURE_LOD, SAMPLINGTYPE_TEXTURE_GRAD, SAMPLINGTYPE_TEXTURE_OFFSET, SAMPLINGTYPE_TEXTURE_PROJ
+       } ;
+
+       for (int samplerTypeIdx = 0; samplerTypeIdx < DE_LENGTH_OF_ARRAY(samplingTypeList); samplerTypeIdx++)
+       {
+               shaderFragment
+                       << "    if (uFunctionType == " << samplerTypeIdx << ") \n"
+                       << "    { \n";
+
+               for (int samplerIdx = 0; samplerIdx < samplerTotal; samplerIdx++)
+               {
+                       switch (static_cast<SamplingType>(samplerTypeIdx))
+                       {
+                               case SAMPLINGTYPE_TEXTURE:
+                               {
+                                       shaderFragment
+                                               << "            texelColor" << samplerIdx << " = texture(uTexture" << samplerIdx << ", vs_aTexCoord); \n";
+                                       break;
+                               }
+                               case SAMPLINGTYPE_TEXTURE_LOD:
+                               {
+                                       shaderFragment
+                                               << "            texelColor" << samplerIdx << " = textureLod(uTexture" << samplerIdx << ", vs_aTexCoord, 0.0f); \n";
+                                       break;
+                               }
+                               case SAMPLINGTYPE_TEXTURE_GRAD:
+                               {
+                                       shaderFragment
+                                               << "            texelColor" << samplerIdx << " = textureGrad(uTexture" << samplerIdx << ", vs_aTexCoord, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)); \n";
+                                       break;
+                               }
+                               case SAMPLINGTYPE_TEXTURE_OFFSET:
+                               {
+                                       shaderFragment
+                                               << "            texelColor" << samplerIdx << " = textureOffset(uTexture" << samplerIdx << ", vs_aTexCoord, ivec2(0.0f, 0.0f)); \n";
+                                       break;
+                               }
+                               case SAMPLINGTYPE_TEXTURE_PROJ:
+                               {
+                                       shaderFragment
+                                               << "            texelColor" << samplerIdx << " = textureProj(uTexture" << samplerIdx << ", vec3(vs_aTexCoord, 1.0f)); \n";
+                                       break;
+                               }
+                               default:
+                                       DE_FATAL("Error: sampling type unrecognised");
+                       }
+               }
+
+               shaderFragment
+                       << "    } \n";
+       }
+
+       return shaderFragment.str();
+}
+
+void logColor (Context& context, const std::string& colorLogMessage, const tcu::Vec4 resultColor)
+{
+       tcu::TestLog&                   log             = context.getTestContext().getLog();
+       std::ostringstream              message;
+
+       message << colorLogMessage << " = (" << resultColor.x() << ", " << resultColor.y() << ", " << resultColor.z() << ", " << resultColor.w() << ")";
+               log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+}
+
+struct TestFunction
+{
+       explicit TestFunction   (const bool hasFunctionValue)
+               : hasFunction           (hasFunctionValue) {}
+       TestFunction                    (const char* const functionNameValue, const char* const functionDefinition)
+               : hasFunction           (true)
+               , functionName          (functionNameValue)
+               , functionDefintion     (functionDefinition) {}
+       ~TestFunction                   (void) {}
+
+       bool                    hasFunction;
+       const char*             functionName;
+       const char*             functionDefintion;
+};
+
+TestFunction getFunctionBlendLinearToSRGBCheck (void)
+{
+       const char* const functionName = "blendPlusLinearToSRGB";
+
+       const char* const functionDefinition =
+               "mediump vec4 blendPlusLinearToSRGB(in mediump vec4 colorSrc, in mediump vec4 colorDst) \n"
+               "{ \n"
+               "       const int MAX_VECTOR_SIZE = 4; \n"
+               "       mediump vec4 colorConverted; \n"
+               "       mediump vec4 colorBlended; \n"
+               "       for (int idx = 0; idx < MAX_VECTOR_SIZE; idx++) \n"
+               "       { \n"
+               "               if (uBlendFunctionType == 0) \n"
+               "               { \n"
+               "                       colorBlended[idx] = (colorSrc[idx] * uFactorSrc) + colorDst[idx] * uFactorDst; \n"
+               "               } \n"
+               "               if (uBlendFunctionType == 1) \n"
+               "               { \n"
+               "                       colorBlended[idx] = (colorSrc[idx] * uFactorSrc) - (colorDst[idx] * uFactorDst); \n"
+               "               } \n"
+                               "if (uBlendFunctionType == 2) \n"
+               "               { \n"
+               "                       colorBlended[idx] = (colorDst[idx] * uFactorDst) - (colorSrc[idx] * uFactorSrc); \n"
+               "               } \n"
+               "               if (colorBlended[idx] < 0.0031308f) \n"
+               "               { \n"
+               "                       colorConverted[idx] = 12.92f * colorBlended[idx]; \n"
+               "               } \n"
+               "               else \n"
+               "               { \n"
+               "                       colorConverted[idx] = 1.055f * pow(colorBlended[idx], 0.41666f) - 0.055f; \n"
+               "               } \n"
+               "       } \n"
+               "       return colorConverted; \n"
+               "} \n";
+
+       TestFunction testFunction(functionName, functionDefinition);
+
+       return testFunction;
+}
+
+struct FBOConfig
+{
+       FBOConfig                                       (const deUint32 textureInternalFormatValue,
+                                                                const tcu::Vec4 textureColorValue,
+                                                                const deUint32 fboTargetTypeValue,
+                                                                const deUint32 fboColorAttachmentValue,
+                                                                const FboType fboTypeValue)
+               : textureInternalFormat (textureInternalFormatValue)
+               , textureColor                  (textureColorValue)
+               , fboTargetType                 (fboTargetTypeValue)
+               , fboColorAttachment    (fboColorAttachmentValue)
+               , fboType                               (fboTypeValue) {}
+       ~FBOConfig                                      (void) {}
+
+       deUint32        textureInternalFormat;
+       tcu::Vec4       textureColor;
+       deUint32        fboTargetType;
+       deUint32        fboColorAttachment;
+       FboType         fboType;
+};
+
+struct BlendConfig
+{
+       deUint32        equation;
+       deUint32        funcSrc;
+       deUint32        funcDst;
+};
+
+std::vector<BlendConfig> getBlendingConfigList (void)
+{
+       BlendConfig blendConfigs[12];
+
+       // add function permutations
+       blendConfigs[0].equation = GL_FUNC_ADD;
+       blendConfigs[1].equation = GL_FUNC_ADD;
+       blendConfigs[2].equation = GL_FUNC_ADD;
+       blendConfigs[3].equation = GL_FUNC_ADD;
+
+       blendConfigs[0].funcSrc = GL_ONE;
+       blendConfigs[0].funcDst = GL_ONE;
+       blendConfigs[1].funcSrc = GL_ONE;
+       blendConfigs[1].funcDst = GL_ZERO;
+       blendConfigs[2].funcSrc = GL_ZERO;
+       blendConfigs[2].funcDst = GL_ONE;
+       blendConfigs[3].funcSrc = GL_ZERO;
+       blendConfigs[3].funcDst = GL_ZERO;
+
+       // subtract function permutations
+       blendConfigs[4].equation = GL_FUNC_SUBTRACT;
+       blendConfigs[5].equation = GL_FUNC_SUBTRACT;
+       blendConfigs[6].equation = GL_FUNC_SUBTRACT;
+       blendConfigs[7].equation = GL_FUNC_SUBTRACT;
+
+       blendConfigs[4].funcSrc = GL_ONE;
+       blendConfigs[4].funcDst = GL_ONE;
+       blendConfigs[5].funcSrc = GL_ONE;
+       blendConfigs[5].funcDst = GL_ZERO;
+       blendConfigs[6].funcSrc = GL_ZERO;
+       blendConfigs[6].funcDst = GL_ONE;
+       blendConfigs[7].funcSrc = GL_ZERO;
+       blendConfigs[7].funcDst = GL_ZERO;
+
+       // reverse subtract function permutations
+       blendConfigs[8].equation = GL_FUNC_REVERSE_SUBTRACT;
+       blendConfigs[9].equation = GL_FUNC_REVERSE_SUBTRACT;
+       blendConfigs[10].equation = GL_FUNC_REVERSE_SUBTRACT;
+       blendConfigs[11].equation = GL_FUNC_REVERSE_SUBTRACT;
+
+       blendConfigs[8].funcSrc = GL_ONE;
+       blendConfigs[8].funcDst = GL_ONE;
+       blendConfigs[9].funcSrc = GL_ONE;
+       blendConfigs[9].funcDst = GL_ZERO;
+       blendConfigs[10].funcSrc = GL_ZERO;
+       blendConfigs[10].funcDst = GL_ONE;
+       blendConfigs[11].funcSrc = GL_ZERO;
+       blendConfigs[11].funcDst = GL_ZERO;
+
+       std::vector<BlendConfig> configList(blendConfigs, blendConfigs + DE_LENGTH_OF_ARRAY(blendConfigs));
+
+       return configList;
+}
+
+struct TestRenderPassConfig
+{
+       TestRenderPassConfig            (void)
+               : testFunction                  (false) {}
+
+       TestRenderPassConfig            (const TextureSourcesType textureSourcesTypeValue,
+                                                               FBOConfig fboConfigListValue,
+                                                               const FramebufferSRGB framebufferSRGBValue,
+                                                               const FramebufferBlend framebufferBendValue,
+                                                               const RendererTask rendererTaskValue)
+               : textureSourcesType    (textureSourcesTypeValue)
+               , framebufferSRGB               (framebufferSRGBValue)
+               , frameBufferBlend              (framebufferBendValue)
+               , testFunction                  (false)
+               , rendererTask                  (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
+
+       TestRenderPassConfig            (const TextureSourcesType textureSourcesTypeValue,
+                                                               FBOConfig fboConfigListValue,
+                                                               const FramebufferSRGB framebufferSRGBValue,
+                                                               const FramebufferBlend framebufferBendValue,
+                                                               TestFunction testFunctionValue,
+                                                               const RendererTask rendererTaskValue)
+               : textureSourcesType    (textureSourcesTypeValue)
+               , framebufferSRGB               (framebufferSRGBValue)
+               , frameBufferBlend              (framebufferBendValue)
+               , testFunction                  (testFunctionValue)
+               , rendererTask                  (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
+
+       TestRenderPassConfig            (const TextureSourcesType textureSourcesTypeValue,
+                                                               std::vector<FBOConfig> fboConfigListValue,
+                                                               const FramebufferSRGB framebufferSRGBValue,
+                                                               const FramebufferBlend framebufferBendValue,
+                                                               TestFunction testFunctionValue,
+                                                               const RendererTask rendererTaskValue)
+               : textureSourcesType    (textureSourcesTypeValue)
+               , fboConfigList                 (fboConfigListValue)
+               , framebufferSRGB               (framebufferSRGBValue)
+               , frameBufferBlend              (framebufferBendValue)
+               , testFunction                  (testFunctionValue)
+               , rendererTask                  (rendererTaskValue) {}
+
+       ~TestRenderPassConfig           (void) {}
+
+       TextureSourcesType              textureSourcesType;
+       std::vector<FBOConfig>  fboConfigList;
+       FramebufferSRGB                 framebufferSRGB;
+       FramebufferBlend                frameBufferBlend;
+       TestFunction                    testFunction;
+       RendererTask                    rendererTask;
+};
+
+class TestVertexData
+{
+public:
+                                                       TestVertexData          (Context& context);
+                                                       ~TestVertexData         (void);
+
+       void                                    init                            (void);
+
+       void                                    bind                            (void) const;
+       void                                    unbind                          (void) const;
+
+private:
+       const glw::Functions*   m_gl;
+       std::vector<float>              m_data;
+       glw::GLuint                             m_vboHandle;
+       glw::GLuint                             m_vaoHandle;
+};
+
+TestVertexData::TestVertexData (Context& context)
+       : m_gl                                          (&context.getRenderContext().getFunctions())
+{
+       const glw::GLfloat              vertexData[]    =
+       {
+               // position                             // texcoord
+               -1.0f, -1.0f, 0.0f,             0.0f, 0.0f, // bottom left corner
+                1.0f, -1.0f, 0.0f,             1.0f, 0.0f, // bottom right corner
+                1.0f,  1.0f, 0.0f,             1.0f, 1.0f, // Top right corner
+
+               -1.0f,  1.0f, 0.0f,             0.0f, 1.0f, // top left corner
+                1.0f,  1.0f, 0.0f,             1.0f, 1.0f, // Top right corner
+               -1.0f, -1.0f, 0.0f,             0.0f, 0.0f  // bottom left corner
+       };
+
+       m_data.resize(DE_LENGTH_OF_ARRAY(vertexData));
+       for (int idx = 0; idx < (int)m_data.size(); idx++)
+               m_data[idx] = vertexData[idx];
+
+       m_gl->genVertexArrays(1, &m_vaoHandle);
+       m_gl->bindVertexArray(m_vaoHandle);
+
+       m_gl->genBuffers(1, &m_vboHandle);
+       m_gl->bindBuffer(GL_ARRAY_BUFFER, m_vboHandle);
+
+       m_gl->bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)(m_data.size() * sizeof(glw::GLfloat)), &m_data[0], GL_STATIC_DRAW);
+
+       m_gl->enableVertexAttribArray(0);
+       m_gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
+       m_gl->enableVertexAttribArray(1);
+       m_gl->vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
+
+       m_gl->bindVertexArray(0);
+       m_gl->bindBuffer(GL_ARRAY_BUFFER, 0);
+       GLU_EXPECT_NO_ERROR(m_gl->getError(), "gl error during vertex data setup");
+}
+
+TestVertexData::~TestVertexData (void)
+{
+       m_gl->deleteBuffers(1, &m_vboHandle);
+       m_gl->deleteVertexArrays(1, &m_vaoHandle);
+}
+
+void TestVertexData::bind (void) const
+{
+       m_gl->bindVertexArray(m_vaoHandle);
+}
+
+void TestVertexData::unbind (void) const
+{
+       m_gl->bindVertexArray(0);
+}
+
+class TestTexture2D
+{
+public:
+                                                               TestTexture2D           (Context& context, const deUint32 internalFormatValue, const deUint32 transferFormatValue, const deUint32 transferTypeValue, const tcu::Vec4 imageColorValue, const int idx);
+                                                               ~TestTexture2D          (void);
+
+       int                                                     getTextureUnit          (void) const;
+       deUint32                                        getHandle                       (void) const;
+       int                                                     getIdx                          (void) const;
+
+       void                                            bind                            (const int textureUnit);
+       void                                            unbind                          (void) const;
+
+private:
+       const glw::Functions*           m_gl;
+       glw::GLuint                                     m_handle;
+       const deUint32                          m_internalFormat;
+       tcu::TextureFormat                      m_transferFormat;
+       int                                                     m_width;
+       int                                                     m_height;
+       tcu::TextureLevel                       m_imageData;
+       int                                                     m_textureUnit;
+       const int                                       m_idx;
+};
+
+TestTexture2D::TestTexture2D   (Context& context, const deUint32 internalFormat, const deUint32 transferFormat, const deUint32 transferType, const tcu::Vec4 imageColor, const int idx)
+       : m_gl                                          (&context.getRenderContext().getFunctions())
+       , m_internalFormat                      (internalFormat)
+       , m_transferFormat                      (tcu::TextureFormat(glu::mapGLTransferFormat(transferFormat, transferType)))
+       , m_width                                       (TestTextureSizes::WIDTH)
+       , m_height                                      (TestTextureSizes::HEIGHT)
+       , m_imageData                           (tcu::TextureLevel(glu::mapGLInternalFormat(internalFormat), m_width, m_height, 1))
+       , m_idx                                         (idx)
+{
+       // fill image data with a solid test color
+       tcu::clear(m_imageData.getAccess(), tcu::Vec4(0.0f));
+       for (int py = 0; py < m_imageData.getHeight(); py++)
+       {
+               for (int px = 0; px < m_imageData.getWidth(); px++)
+                       m_imageData.getAccess().setPixel(imageColor, px, py);
+       }
+
+       m_gl->genTextures(1, &m_handle);
+
+       m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
+       m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_WRAP_S,              GL_MIRRORED_REPEAT);
+       m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_WRAP_T,              GL_MIRRORED_REPEAT);
+       m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_MIN_FILTER,  GL_NEAREST);
+       m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_MAG_FILTER,  GL_NEAREST);
+
+       m_gl->texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFormat, transferType, m_imageData.getAccess().getDataPtr());
+
+       m_gl->bindTexture(GL_TEXTURE_2D, 0);
+}
+
+TestTexture2D::~TestTexture2D (void)
+{
+       m_gl->deleteTextures(1, &m_handle);
+}
+
+int TestTexture2D::getTextureUnit (void) const
+{
+       return m_textureUnit;
+}
+
+deUint32 TestTexture2D::getHandle (void) const
+{
+       return m_handle;
+}
+
+int TestTexture2D::getIdx (void) const
+{
+       return m_idx;
+}
+
+void TestTexture2D::bind (const int textureUnit)
+{
+       m_textureUnit = textureUnit;
+       m_gl->activeTexture(GL_TEXTURE0 + m_textureUnit);
+       m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
+}
+
+void TestTexture2D::unbind (void) const
+{
+       m_gl->bindTexture(GL_TEXTURE_2D, 0);
+}
+
+class TestFramebuffer
+{
+public:
+                                                                                               TestFramebuffer                 (void);
+                                                                                               TestFramebuffer                 (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx);
+                                                                                               ~TestFramebuffer                (void);
+
+       void                                                                            setTargetType                   (const deUint32 targetType);
+
+       FboType                                                                         getType                                 (void) const;
+       deUint32                                                                        getHandle                               (void) const;
+       deUint32                                                                        getColorAttachment              (void) const;
+       int                                                                                     getIdx                                  (void) const;
+       deUint32                                                                        getTargetType                   (void) const;
+
+       void                                                                            bind                                    (void);
+       void                                                                            unbind                                  (void);
+
+       typedef de::UniquePtr<glu::Framebuffer>         fboUniquePtr;
+
+private:
+       const glw::Functions*                                           m_gl;
+       fboUniquePtr                                                            m_referenceSource;
+       deUint32                                                                        m_targetType;
+       bool                                                                            m_bound;
+       bool                                                                            m_isSRGB;
+       FboType                                                                         m_type;
+       const int                                                                       m_idx;
+       deUint32                                                                        m_colorAttachment;
+};
+
+TestFramebuffer::TestFramebuffer       (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx)
+       : m_gl                                                  (&context.getRenderContext().getFunctions())
+       , m_referenceSource                             (new glu::Framebuffer(context.getRenderContext()))
+       , m_targetType                                  (targetType)
+       , m_bound                                               (false)
+       , m_isSRGB                                              (isSRGB)
+       , m_type                                                (fboType)
+       , m_idx                                                 (idx)
+       , m_colorAttachment                             (colorAttachment)
+{
+       m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
+
+       m_gl->framebufferTexture2D(m_targetType, m_colorAttachment, GL_TEXTURE_2D, textureAttachmentHandle, 0);
+
+       TCU_CHECK(m_gl->checkFramebufferStatus(m_targetType) == GL_FRAMEBUFFER_COMPLETE);
+
+       if (targetType == GL_DRAW_BUFFER)
+       {
+               glw::GLuint textureAttachments[] = {m_colorAttachment};
+               m_gl->drawBuffers(DE_LENGTH_OF_ARRAY(textureAttachments), textureAttachments);
+               GLU_EXPECT_NO_ERROR(m_gl->getError(), "glDrawBuffer()");
+       }
+
+       if (targetType == GL_READ_BUFFER)
+       {
+               m_gl->readBuffer(m_colorAttachment);
+               GLU_EXPECT_NO_ERROR(m_gl->getError(), "glReadBuffer()");
+       }
+
+       m_gl->bindFramebuffer(m_targetType, 0);
+}
+
+TestFramebuffer::~TestFramebuffer (void)
+{
+}
+
+void TestFramebuffer::setTargetType (const deUint32 targetType)
+{
+       m_targetType = targetType;
+}
+
+FboType TestFramebuffer::getType (void) const
+{
+       return m_type;
+}
+
+deUint32 TestFramebuffer::getHandle (void) const
+{
+       return **m_referenceSource;
+}
+
+deUint32 TestFramebuffer::getColorAttachment (void) const
+{
+       return m_colorAttachment;
+}
+
+int TestFramebuffer::getIdx (void) const
+{
+       return m_idx;
+}
+
+deUint32 TestFramebuffer::getTargetType (void) const
+{
+       return m_targetType;
+}
+
+void TestFramebuffer::bind (void)
+{
+       if (!m_bound)
+       {
+               m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
+               m_bound = true;
+       }
+}
+
+void TestFramebuffer::unbind (void)
+{
+       if (m_bound)
+       {
+               m_gl->bindFramebuffer(m_targetType, 0);
+               m_bound = false;
+       }
+}
+
+class TestShaderProgram
+{
+public:
+                                                                               TestShaderProgram               (Context& context, const int samplerTotal, TestFunction testFunction);
+                                                                               ~TestShaderProgram              (void);
+
+       glw::GLuint                                                     getHandle                               (void) const;
+       int                                                                     getSamplerTotal                 (void) const;
+
+       void                                                            use                                             (void) const;
+       void                                                            unuse                                   (void) const;
+
+       glu::ShaderProgramInfo                          getLogInfo                              (void);
+
+private:
+       const glw::Functions*                           m_gl;
+       de::MovePtr<glu::ShaderProgram>         m_referenceSource;
+       const int                                                       m_samplerTotal;
+       const int                                                       m_shaderStagesTotal;
+};
+
+TestShaderProgram::TestShaderProgram   (Context& context, const int samplerTotal, TestFunction testFunction)
+       : m_gl                                                          (&context.getRenderContext().getFunctions())
+       , m_samplerTotal                                        (samplerTotal)
+       , m_shaderStagesTotal                           (2)
+{
+       std::ostringstream              shaderFragment;
+
+       const char* const shaderVertex =
+               "#version 310 es \n"
+               "layout (location = 0) in mediump vec3 aPosition; \n"
+               "layout (location = 1) in mediump vec2 aTexCoord; \n"
+               "out mediump vec2 vs_aTexCoord; \n"
+               "void main () \n"
+               "{ \n"
+               "       gl_Position = vec4(aPosition, 1.0f); \n"
+               "       vs_aTexCoord = aTexCoord; \n"
+               "} \n";
+
+       shaderFragment
+               << "#version 310 es \n"
+               << "in mediump vec2 vs_aTexCoord; \n"
+               << "layout (location = 0) out mediump vec4 fs_aColor0; \n";
+
+       for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
+               shaderFragment
+                       << "uniform sampler2D uTexture" << samplerIdx << "; \n";
+
+       shaderFragment
+               << "uniform int uFunctionType; \n";
+
+       if (testFunction.hasFunction)
+               shaderFragment
+               << "uniform int uBlendFunctionType; \n"
+               << "uniform mediump float uFactorSrc; \n"
+               << "uniform mediump float uFactorDst; \n"
+                       << testFunction.functionDefintion;
+
+       shaderFragment
+               << "void main () \n"
+               << "{ \n";
+
+       for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
+               shaderFragment
+                       <<"     mediump vec4 texelColor" << samplerIdx << " = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n";
+
+       shaderFragment
+               << buildSamplingPassType(m_samplerTotal);
+
+       if (testFunction.hasFunction)
+               shaderFragment
+                       << "    fs_aColor0 = " << testFunction.functionName << "(texelColor0, texelColor1); \n";
+       else
+               shaderFragment
+                       << "    fs_aColor0 = texelColor0; \n";
+
+       shaderFragment
+               << "} \n";
+
+       m_referenceSource = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(context.getRenderContext(), glu::makeVtxFragSources(shaderVertex, shaderFragment.str())));
+       if (!m_referenceSource->isOk())
+       {
+               tcu::TestLog& log = context.getTestContext().getLog();
+               log << this->getLogInfo();
+               TCU_FAIL("Failed to compile shaders and link program");
+       }
+}
+
+TestShaderProgram::~TestShaderProgram (void)
+{
+       m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL);
+       m_referenceSource.clear();
+}
+
+deUint32 TestShaderProgram::getHandle (void) const
+{
+       return m_referenceSource->getProgram();
+}
+
+int TestShaderProgram::getSamplerTotal (void) const
+{
+       return m_samplerTotal;
+}
+
+void TestShaderProgram::use (void) const
+{
+       m_gl->useProgram(this->getHandle());
+}
+
+void TestShaderProgram::unuse (void) const
+{
+       m_gl->useProgram(0);
+}
+
+glu::ShaderProgramInfo TestShaderProgram::getLogInfo (void)
+{
+       glu::ShaderProgramInfo  buildInfo;
+
+       // log shader program info. Only vertex and fragment shaders included
+       buildInfo.program = m_referenceSource->getProgramInfo();
+       for (int shaderIdx = 0; shaderIdx < m_shaderStagesTotal; shaderIdx++)
+       {
+               glu::ShaderInfo shaderInfo = m_referenceSource->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
+               buildInfo.shaders.push_back(shaderInfo);
+       }
+       return buildInfo;
+}
+
+class Renderer
+{
+public:
+                                                                                       Renderer                                                (Context& context);
+                                                                                       ~Renderer                                               (void);
+
+       void                                                                    init                                                    (const TestRenderPassConfig& renderPassConfig, const int renderpass);
+       void                                                                    deinit                                                  (void);
+
+       void                                                                    setSamplingType                                 (const SamplingType samplerIdx);
+       void                                                                    setBlendIteration                               (const int blendIteration);
+       void                                                                    setFramebufferBlend                             (const bool blend);
+       void                                                                    setFramebufferSRGB                              (const bool sRGB);
+
+       std::vector<tcu::Vec4>                                  getResultsPreDraw                               (void) const;
+       std::vector<tcu::Vec4>                                  getResultsPostDraw                              (void) const;
+       int                                                                             getBlendConfigCount                             (void) const;
+       glu::ShaderProgramInfo                                  getShaderProgramInfo                    (void);
+
+       void                                                                    copyFrameBufferTexture                  (const int srcPx, const int srcPy, const int dstPx, const int dstPy);
+       void                                                                    draw                                                    (void);
+       void                                                                    storeShaderProgramInfo                  (void);
+       void                                                                    logShaderProgramInfo                    (void);
+
+       typedef de::SharedPtr<TestTexture2D>    TextureSp;
+       typedef de::SharedPtr<TestFramebuffer>  FboSp;
+
+private:
+       void                                                                    createFBOwithColorAttachment    (const std::vector<FBOConfig> fboConfigList);
+       void                                                                    setShaderProgramSamplingType    (const int samplerIdx);
+       void                                                                    setShaderBlendFunctionType              (void);
+       void                                                                    setShaderBlendSrcDstValues              (void);
+       void                                                                    bindActiveTexturesSamplers              (void);
+       void                                                                    bindAllRequiredSourceTextures   (const TextureSourcesType texturesRequired);
+       void                                                                    unbindAllSourceTextures                 (void);
+       void                                                                    bindFramebuffer                                 (const int framebufferIdx);
+       void                                                                    unbindFramebuffer                               (const int framebufferIdx);
+       void                                                                    enableFramebufferSRGB                   (void);
+       void                                                                    enableFramebufferBlend                  (void);
+       bool                                                                    isFramebufferAttachmentSRGB             (const deUint32 targetType, const deUint32 attachment) const;
+       void                                                                    readTexels                                              (const int px, const int py, const deUint32 attachment, tcu::Vec4& texelData);
+       void                                                                    logState                                                (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const;
+
+       // renderer specific constants initialized during constructor
+       Context&                                                                m_context;
+       const TestVertexData                                    m_vertexData;
+       const int                                                               m_textureSourceTotal;
+
+       // additional resources monitored by the renderer
+       std::vector<BlendConfig>                                m_blendConfigList;
+       std::vector<TextureSp>                                  m_textureSourceList;
+       TestRenderPassConfig                                    m_renderPassConfig;
+       std::vector<TextureSp>                                  m_fboTextureList;
+       TestShaderProgram*                                              m_shaderProgram;
+       std::vector<FboSp>                                              m_framebufferList;
+       std::vector<tcu::Vec4>                                  m_resultsListPreDraw;
+       std::vector<tcu::Vec4>                                  m_resultsListPostDraw;
+
+       // mutable state variables (internal access only)
+       bool                                                                    m_hasShaderProgramInfo;
+       int                                                                             m_renderPass;
+       int                                                                             m_samplersRequired;
+       bool                                                                    m_hasFunction;
+       bool                                                                    m_blittingEnabled;
+       glu::ShaderProgramInfo                                  m_shaderProgramInfo;
+
+       // mutable state variables (external access via setters)
+       SamplingType                                                    m_samplingType;
+       int                                                                             m_blendIteration;
+       bool                                                                    m_framebufferBlendEnabled;
+       bool                                                                    m_framebufferSRGBEnabled;
+};
+
+Renderer::Renderer                             (Context& context)
+       : m_context                                     (context)
+       , m_vertexData                          (context)
+       , m_textureSourceTotal          (2)
+       , m_blendConfigList                     (getBlendingConfigList())
+       , m_hasShaderProgramInfo        (false)
+{
+       TextureSp textureLinear(new TestTexture2D(m_context, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 0));
+       m_textureSourceList.push_back(textureLinear);
+
+       TextureSp textureSRGB(new TestTexture2D(m_context, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 1));
+       m_textureSourceList.push_back(textureSRGB);
+}
+
+Renderer::~Renderer (void)
+{
+       m_textureSourceList.clear();
+       this->deinit();
+}
+
+void Renderer::init (const TestRenderPassConfig& renderPassConfig, const int renderpass)
+{
+       m_renderPassConfig = renderPassConfig;
+       m_renderPass = renderpass;
+
+       this->createFBOwithColorAttachment(m_renderPassConfig.fboConfigList);
+
+       if (m_renderPassConfig.textureSourcesType != TEXTURESOURCESTYPE_NONE)
+       {
+               if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_RGBA || m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_SRGBA)
+                       m_samplersRequired = 1;
+               else if (m_renderPassConfig.textureSourcesType ==TEXTURESOURCESTYPE_BOTH )
+                       m_samplersRequired = 2;
+               else
+                       DE_FATAL("Error: Texture source required not recognised");
+
+               m_shaderProgram = new TestShaderProgram(m_context, m_samplersRequired, m_renderPassConfig.testFunction);
+               m_hasFunction = m_renderPassConfig.testFunction.hasFunction;
+       }
+       else
+               m_shaderProgram = DE_NULL;
+}
+
+void Renderer::deinit (void)
+{
+       if (m_shaderProgram != DE_NULL)
+       {
+               delete m_shaderProgram;
+               m_shaderProgram = DE_NULL;
+       }
+
+       m_fboTextureList.clear();
+       m_framebufferList.clear();
+}
+
+void Renderer::setSamplingType (const SamplingType samplingType)
+{
+       m_samplingType = samplingType;
+}
+
+void Renderer::setBlendIteration (const int blendIteration)
+{
+       m_blendIteration = blendIteration;
+}
+
+void Renderer::setFramebufferBlend (const bool blend)
+{
+       m_framebufferBlendEnabled = blend;
+}
+
+void Renderer::setFramebufferSRGB (const bool sRGB)
+{
+       m_framebufferSRGBEnabled = sRGB;
+}
+
+std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const
+{
+       return m_resultsListPreDraw;
+}
+
+std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const
+{
+       return m_resultsListPostDraw;
+}
+
+int Renderer::getBlendConfigCount (void) const
+{
+       return (int)m_blendConfigList.size();
+}
+
+void Renderer::copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy)
+{
+       const glw::Functions&   gl                                              = m_context.getRenderContext().getFunctions();
+       int                                             fboSrcIdx                               = -1;
+       int                                             fboDstIdx                               = -1;
+       deUint32                                fboSrcColAttachment             = GL_NONE;
+       deUint32                                fboDstColAttachment             = GL_NONE;
+
+       for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
+               this->bindFramebuffer(idx);
+
+       // cache fbo attachments and idx locations
+       for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
+       {
+               if (m_framebufferList[idx]->getType() == FBOTYPE_SOURCE)
+               {
+                       fboSrcIdx = m_framebufferList[idx]->getIdx();
+                       fboSrcColAttachment = m_framebufferList[fboSrcIdx]->getColorAttachment();
+               }
+               if (m_framebufferList[idx]->getType() == FBOTYPE_DESTINATION)
+               {
+                       fboDstIdx = m_framebufferList[idx]->getIdx();
+                       fboDstColAttachment = m_framebufferList[fboDstIdx]->getColorAttachment();
+               }
+       }
+
+       for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
+               m_framebufferList[idx]->unbind();
+
+       // store texel data from both src and dst before performing the copy
+       m_resultsListPreDraw.resize(2);
+       m_framebufferList[fboSrcIdx]->bind();
+       this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPreDraw[0]);
+       m_framebufferList[fboSrcIdx]->unbind();
+       m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
+       m_framebufferList[fboDstIdx]->bind();
+       this->readTexels(0, 0, fboDstColAttachment, m_resultsListPreDraw[1]);
+       m_framebufferList[fboDstIdx]->unbind();
+       m_framebufferList[fboDstIdx]->setTargetType(GL_DRAW_FRAMEBUFFER);
+
+       m_framebufferList[fboSrcIdx]->bind();
+       m_framebufferList[fboDstIdx]->bind();
+
+       this->enableFramebufferSRGB();
+       this->enableFramebufferBlend();
+
+       gl.blitFramebuffer(     srcPx, srcPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
+                                               dstPx, dstPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
+                                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+       m_resultsListPostDraw.resize(2);
+       this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPostDraw[0]);
+       m_framebufferList[fboSrcIdx]->unbind();
+       m_framebufferList[fboDstIdx]->unbind();
+
+       m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
+       m_framebufferList[fboDstIdx]->bind();
+       this->readTexels(0, 0, fboDstColAttachment, m_resultsListPostDraw[1]);
+       m_framebufferList[fboDstIdx]->unbind();
+}
+
+void Renderer::draw (void)
+{
+       const glw::Functions&   gl = m_context.getRenderContext().getFunctions();
+
+       if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_NONE)
+               DE_FATAL("Error: Attempted to draw with no texture sources");
+
+       // resize results storage with each render pass
+       m_resultsListPreDraw.resize(m_renderPass + 1);
+       m_resultsListPostDraw.resize(m_renderPass + 1);
+
+       m_shaderProgram->use();
+       m_vertexData.bind();
+
+       for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
+               this->bindFramebuffer(idx);
+
+       this->bindAllRequiredSourceTextures(m_renderPassConfig.textureSourcesType);
+       this->bindActiveTexturesSamplers();
+
+       this->enableFramebufferSRGB();
+       this->enableFramebufferBlend();
+
+       this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPreDraw[m_renderPass]);
+       this->setShaderProgramSamplingType(m_samplingType);
+       if (m_hasFunction)
+       {
+               this->setShaderBlendFunctionType();
+               this->setShaderBlendSrcDstValues();
+       }
+
+       gl.drawArrays(GL_TRIANGLES, 0, 6);
+
+       this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPostDraw[m_renderPass]);
+       this->logState(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_samplingType);
+
+       this->unbindAllSourceTextures();
+       for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
+               this->unbindFramebuffer(idx);
+       m_vertexData.unbind();
+       m_shaderProgram->unuse();
+}
+
+void Renderer::storeShaderProgramInfo (void)
+{
+       m_shaderProgramInfo = m_shaderProgram->getLogInfo();
+       m_hasShaderProgramInfo = true;
+}
+
+void Renderer::logShaderProgramInfo (void)
+{
+       tcu::TestLog& log = m_context.getTestContext().getLog();
+
+       if (m_hasShaderProgramInfo)
+               log << m_shaderProgramInfo;
+}
+
+void Renderer::createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList)
+{
+       const int size = (int)fboConfigList.size();
+       for (int idx = 0; idx < size; idx++)
+       {
+               TextureSp texture(new TestTexture2D(m_context, fboConfigList[idx].textureInternalFormat, GL_RGBA, GL_UNSIGNED_BYTE, fboConfigList[idx].textureColor, idx));
+               m_fboTextureList.push_back(texture);
+
+               bool isSRGB;
+               if (fboConfigList[idx].textureInternalFormat == GL_SRGB8_ALPHA8)
+                       isSRGB = true;
+               else
+                       isSRGB = false;
+
+               FboSp framebuffer(new TestFramebuffer(m_context, fboConfigList[idx].fboTargetType, fboConfigList[idx].fboColorAttachment, texture->getHandle(), isSRGB, fboConfigList[idx].fboType, idx));
+               m_framebufferList.push_back(framebuffer);
+       }
+}
+
+void Renderer::setShaderProgramSamplingType (const int samplerIdx)
+{
+       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+       glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFunctionType");
+       DE_ASSERT(location != (glw::GLuint)-1);
+       gl.uniform1i(location, samplerIdx);
+}
+
+void Renderer::setShaderBlendFunctionType (void)
+{
+       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+       int function = -1;
+       if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
+               function = 0;
+       else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
+               function = 1;
+       else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
+               function = 2;
+       else
+               DE_FATAL("Error: Blend function not recognised");
+
+       glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uBlendFunctionType");
+       DE_ASSERT(location != (glw::GLuint)-1);
+       gl.uniform1i(location, function);
+}
+
+void Renderer::setShaderBlendSrcDstValues (void)
+{
+       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+       float funcSrc;
+       if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
+               funcSrc = 1.0f;
+       else
+               funcSrc = 0.0f;
+
+       float funcDst;
+               if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
+               funcDst = 1.0f;
+       else
+               funcDst = 0.0f;
+
+       glw::GLuint locationSrc = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorSrc");
+       gl.uniform1f(locationSrc, funcSrc);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
+
+       glw::GLuint locationDst = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorDst");
+       gl.uniform1f(locationDst, funcDst);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
+}
+
+void Renderer::bindActiveTexturesSamplers (void)
+{
+       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+       for (int idx = 0; idx < m_samplersRequired; idx++)
+       {
+               std::ostringstream stream;
+               stream << "uTexture" << idx;
+               std::string uniformName(stream.str());
+               glw::GLint location = gl.getUniformLocation(m_shaderProgram->getHandle(), uniformName.c_str());
+               DE_ASSERT(location != -1);
+               gl.uniform1i(location, m_textureSourceList[idx]->getTextureUnit());
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation()");
+       }
+}
+
+void Renderer::bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired)
+{
+       if (texturesRequired == TEXTURESOURCESTYPE_RGBA)
+               m_textureSourceList[0]->bind(0);
+       else if (texturesRequired == TEXTURESOURCESTYPE_SRGBA)
+               m_textureSourceList[1]->bind(0);
+       else if (texturesRequired == TEXTURESOURCESTYPE_BOTH)
+       {
+               m_textureSourceList[0]->bind(0);
+               m_textureSourceList[1]->bind(1);
+       }
+       else
+               DE_FATAL("Error: Invalid sources requested in bind all");
+}
+
+void Renderer::unbindAllSourceTextures (void)
+{
+       for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++)
+               m_textureSourceList[idx]->unbind();
+}
+
+void Renderer::bindFramebuffer (const int framebufferIdx)
+{
+       m_framebufferList[framebufferIdx]->bind();
+}
+
+void Renderer::unbindFramebuffer (const int framebufferIdx)
+{
+       m_framebufferList[framebufferIdx]->unbind();
+}
+
+void Renderer::enableFramebufferSRGB (void)
+{
+       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+       if (m_framebufferSRGBEnabled)
+               gl.enable(GL_FRAMEBUFFER_SRGB);
+       else
+               gl.disable(GL_FRAMEBUFFER_SRGB);
+}
+
+void Renderer::enableFramebufferBlend (void)
+{
+       const glw::Functions&   gl      = m_context.getRenderContext().getFunctions();
+       tcu::TestLog&                   log     = m_context.getTestContext().getLog();
+       std::ostringstream              message;
+
+       message << "Blend settings = ";
+
+       if (m_framebufferBlendEnabled)
+       {
+               gl.enable(GL_BLEND);
+               gl.blendEquation(m_blendConfigList[m_blendIteration].equation);
+               gl.blendFunc(m_blendConfigList[m_blendIteration].funcSrc, m_blendConfigList[m_blendIteration].funcDst);
+
+               std::string equation, src, dst;
+               if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
+                       equation = "GL_FUNC_ADD";
+               if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
+                       equation = "GL_FUNC_SUBTRACT";
+               if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
+                       equation = "GL_FUNC_REVERSE_SUBTRACT";
+               if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
+                       src = "GL_ONE";
+               else
+                       src = "GL_ZERO";
+               if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
+                       dst = "GL_ONE";
+               else
+                       dst = "GL_ZERO";
+
+               message << "Enabled: equation = " << equation << ", func src = " << src << ", func dst = " << dst;
+       }
+       else
+       {
+               gl.disable(GL_BLEND);
+               message << "Disabled";
+       }
+
+       log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+}
+
+bool Renderer::isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const
+{
+       const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
+       glw::GLint                              encodingType;
+
+       gl.getFramebufferAttachmentParameteriv(targetType, attachment, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encodingType);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedFramebufferAttachmentParameteriv()");
+
+       switch (static_cast<glw::GLenum>(encodingType))
+       {
+               case GL_SRGB:
+               {
+                       return true;
+                       break;
+               }
+               case GL_LINEAR:
+               {
+                       return false;
+                       break;
+               }
+               default:
+               {
+                       DE_FATAL("Error: Color attachment format not recognised");
+                       return false;
+               }
+       }
+}
+
+void Renderer::readTexels (const int px, const int py, const deUint32 mode, tcu::Vec4& texelData)
+{
+       const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
+       tcu::TextureLevel               textureRead;
+
+       // ensure result sampling coordinates are within range of the result color attachment
+       DE_ASSERT((px >= 0) && (px < m_context.getRenderTarget().getWidth()));
+       DE_ASSERT((py >= 0) && (py < m_context.getRenderTarget().getHeight()));
+
+       gl.readBuffer(mode);
+       textureRead.setStorage(glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE), TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT);
+       glu::readPixels(m_context.getRenderContext(), px, py, textureRead.getAccess());
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
+       texelData = textureRead.getAccess().getPixel(px, py);
+}
+
+void Renderer::logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const
+{
+       tcu::TestLog&                   log                                     = m_context.getTestContext().getLog();
+       std::ostringstream              message;
+
+       bool fboAttachmentSRGB = this->isFramebufferAttachmentSRGB(targetType, attachment);
+       message.str("");
+       message << "getFramebufferAttachmentParameteriv() check = ";
+       if (fboAttachmentSRGB)
+               message << "GL_SRGB";
+       else
+               message << "GL_LINEAR";
+       log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+
+       message.str("");
+       message << "Framebuffer color attachment value BEFORE draw call";
+       logColor(m_context, message.str(), m_resultsListPreDraw[m_renderPass]);
+
+       message.str("");
+       message << "Framebuffer color attachment value AFTER draw call";
+       logColor(m_context, message.str(), m_resultsListPostDraw[m_renderPass]);
+
+       message.str("");
+       message << "Sampling type = ";
+       std::string type;
+       if (samplingType == 0)
+               type = "texture()";
+       else if (samplingType == 1)
+               type = "textureLOD()";
+       else if (samplingType == 2)
+               type = "textureGrad()";
+       else if (samplingType == 3)
+               type = "textureOffset()";
+       else if (samplingType == 4)
+               type = "textureProj()";
+       else
+               DE_FATAL("Error: Sampling type unregonised");
+       message << type;
+       log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+
+       message.str("");
+       if (m_framebufferSRGBEnabled)
+               message << "Framebuffer SRGB = enabled";
+       else
+               message << "Framebuffer SRGB = disabled";
+       log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+}
+
+class FboSRGBTestCase : public TestCase
+{
+public:
+                                                                                       FboSRGBTestCase                         (Context& context, const char* const name, const char* const desc);
+                                                                                       ~FboSRGBTestCase                        (void);
+
+       void                                                                    init                                            (void);
+       void                                                                    deinit                                          (void);
+       IterateResult                                                   iterate                                         (void);
+
+       void                                                                    setTestConfig                           (std::vector<TestRenderPassConfig> renderPassConfigList);
+
+       virtual void                                                    setupTest                                       (void) = 0;
+       virtual bool                                                    verifyResult                            (void) = 0;
+
+protected:
+       bool                                                                    m_hasTestConfig;
+       std::vector<TestRenderPassConfig>               m_renderPassConfigList;
+       bool                                                                    m_testcaseRequiresBlend;
+       std::vector<tcu::Vec4>                                  m_resultsPreDraw;
+       std::vector<tcu::Vec4>                                  m_resultsPostDraw;
+
+private:
+                                                                                       FboSRGBTestCase                         (const FboSRGBTestCase&);
+       FboSRGBTestCase&                                                operator=                                       (const FboSRGBTestCase&);
+};
+
+FboSRGBTestCase::FboSRGBTestCase       (Context& context, const char* const name, const char* const desc)
+       : TestCase                                              (context, name, desc)
+       , m_hasTestConfig                               (false)
+{
+}
+
+FboSRGBTestCase::~FboSRGBTestCase (void)
+{
+       FboSRGBTestCase::deinit();
+}
+
+void FboSRGBTestCase::init (void)
+{
+       // extensions requirements for test
+       if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
+               TCU_THROW(NotSupportedError, "Test requires a context version equal or higher than 3.2");
+
+       if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
+               TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control");
+
+       if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode"))
+               TCU_THROW(NotSupportedError, "Test requires GL_EXT_texture_sRGB_decode extension");
+}
+
+void FboSRGBTestCase::deinit (void)
+{
+}
+
+FboSRGBTestCase::IterateResult FboSRGBTestCase::iterate (void)
+{
+       this->setupTest();
+
+       DE_ASSERT(m_hasTestConfig && "Error: Renderer was not supplied a test config");
+
+       Renderer renderer(m_context);
+
+       // loop through each sampling type
+       for (int samplingIdx = 0; samplingIdx < SampligTypeCount::MAX; samplingIdx++)
+       {
+               renderer.setSamplingType(static_cast<SamplingType>(samplingIdx));
+
+               // loop through each blend configuration
+               const int blendCount = renderer.getBlendConfigCount();
+               for (int blendIdx = 0; blendIdx < blendCount; blendIdx++)
+               {
+                       // loop through each render pass
+                       const int renderPassCount = (int)m_renderPassConfigList.size();
+                       for (int renderPassIdx = 0; renderPassIdx < renderPassCount; renderPassIdx++)
+                       {
+                               TestRenderPassConfig renderPassConfig = m_renderPassConfigList[renderPassIdx];
+
+                               renderer.init(renderPassConfig, renderPassIdx);
+
+                               if (blendIdx == 0 && renderPassConfig.rendererTask == RENDERERTASK_DRAW)
+                                       renderer.storeShaderProgramInfo();
+
+                               if (renderPassConfig.frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
+                               {
+                                       renderer.setBlendIteration(blendIdx);
+                                       renderer.setFramebufferBlend(true);
+                               }
+                               else
+                                       renderer.setFramebufferBlend(false);
+
+                               if (renderPassConfig.framebufferSRGB == FRAMEBUFFERSRGB_ENABLED)
+                                       renderer.setFramebufferSRGB(true);
+                               else
+                                       renderer.setFramebufferSRGB(false);
+
+                               if (renderPassConfig.rendererTask == RENDERERTASK_DRAW)
+                                       renderer.draw();
+                               else if (renderPassConfig.rendererTask == RENDERERTASK_COPY)
+                                       renderer.copyFrameBufferTexture(0, 0, 0, 0);
+                               else
+                                       DE_FATAL("Error: render task not recognised");
+
+                               renderer.deinit();
+
+                       } // render passes
+
+                       m_resultsPreDraw = renderer.getResultsPreDraw();
+                       m_resultsPostDraw = renderer.getResultsPostDraw();
+
+                       bool testPassed = this->verifyResult();
+                       if (testPassed)
+                               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+                       else
+                       {
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
+                               renderer.logShaderProgramInfo();
+                               return STOP;
+                       }
+
+                       if (!m_testcaseRequiresBlend)
+                               break;
+               } // blend configs
+
+               renderer.logShaderProgramInfo();
+       } // sampling types
+
+       return STOP;
+}
+
+void FboSRGBTestCase::setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList)
+{
+       m_renderPassConfigList = renderPassConfigList;
+       m_hasTestConfig = true;
+
+       for (int idx = 0; idx < (int)renderPassConfigList.size(); idx++)
+       {
+               if (renderPassConfigList[idx].frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
+               {
+                       m_testcaseRequiresBlend = true;
+                       return;
+               }
+       }
+       m_testcaseRequiresBlend = false;
+}
+
+class FboSRGBQueryCase : public TestCase
+{
+public:
+                                       FboSRGBQueryCase        (Context& context, const char* const name, const char* const description);
+                                       ~FboSRGBQueryCase       (void);
+
+       void                    init                            (void);
+       void                    deinit                          (void);
+       IterateResult   iterate                         (void);
+};
+
+FboSRGBQueryCase::FboSRGBQueryCase     (Context& context, const char* const name, const char* const description)
+       : TestCase                                              (context, name, description)
+{
+}
+
+FboSRGBQueryCase::~FboSRGBQueryCase (void)
+{
+       FboSRGBQueryCase::deinit();
+}
+
+void FboSRGBQueryCase::init (void)
+{
+       // extension requirements for test
+       if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
+               TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control or a context version equal or higher than 3.2");
+}
+
+void FboSRGBQueryCase::deinit (void)
+{
+}
+
+FboSRGBQueryCase::IterateResult FboSRGBQueryCase::iterate (void)
+{
+       // TEST INFO:
+       // API tests which check when querying FRAMEBUFFER_SRGB_EXT capability returns the correct information when using glEnabled() or glDisabled()
+
+       const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
+       tcu::TestLog&                   log             = m_context.getTestContext().getLog();
+       const char*     const           msgPart = ", after disabling = ";
+
+       for (int idx = 0; idx < static_cast<int>(QUERYTYPE_LAST); idx++)
+       {
+               std::ostringstream      message;
+               bool                            pass            = false;
+
+               message << std::string("Results: After Enabling = ");
+
+               gl.enable(GL_FRAMEBUFFER_SRGB);
+
+               switch (static_cast<QueryType>(idx))
+               {
+                       case QUERYTYPE_ISENABLED:
+                       {
+                               glw::GLboolean enabled[2];
+                               enabled[0] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
+                               gl.disable(GL_FRAMEBUFFER_SRGB);
+                               enabled[1] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
+
+                               message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
+                               pass = (enabled[0] && !(enabled[1])) ? true : false;
+                               break;
+                       }
+                       case QUERYTYPE_BOOLEAN:
+                       {
+                               glw::GLboolean enabled[2];
+                               gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[0]);
+                               gl.disable(GL_FRAMEBUFFER_SRGB);
+                               gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[1]);
+
+                               message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
+                               pass = (enabled[0] && !(enabled[1])) ? true : false;
+                               break;
+                       }
+                       case QUERYTYPE_FLOAT:
+                       {
+                               glw::GLfloat enabled[2];
+                               gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
+                               gl.disable(GL_FRAMEBUFFER_SRGB);
+                               gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
+
+                               message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
+                               pass = ((int)enabled[0] && !((int)enabled[1])) ? true : false;
+                               break;
+                       }
+                       case QUERYTYPE_INT:
+                       {
+                               glw::GLint enabled[2];
+                               gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
+                               gl.disable(GL_FRAMEBUFFER_SRGB);
+                               gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
+
+                               message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
+                               pass = (enabled[0] && !(enabled[1])) ? true : false;
+                               break;
+                       }
+                       case QUERYTYPE_INT64:
+                       {
+                               glw::GLint64 enabled[2];
+                               gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[0]);
+                               gl.disable(GL_FRAMEBUFFER_SRGB);
+                               gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[1]);
+
+                               message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
+                               pass = (enabled[0] && !(enabled[1])) ? true : false;
+                               break;
+                       }
+                       default:
+                               DE_FATAL("Error: Datatype not recognised");
+               }
+
+               log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+
+               if (pass)
+                       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+               else
+               {
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
+                       return STOP;
+               }
+       }
+       return STOP;
+}
+
+class FboSRGBColAttachCase : public FboSRGBTestCase
+{
+public:
+                       FboSRGBColAttachCase    (Context& context, const char* const name, const char* const description)
+                               : FboSRGBTestCase       (context, name, description) {}
+                       ~FboSRGBColAttachCase   (void) {}
+
+       void    setupTest                               (void);
+       bool    verifyResult                    (void);
+};
+
+void FboSRGBColAttachCase::setupTest (void)
+{
+       // TEST INFO:
+       // Check if FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING  set to SRGB and FRAMEBUFFER_SRGB_EXT enabled, destination colors are converted from SRGB to linear
+       // before and after blending, finally the result is converted back to SRGB for storage
+
+       // NOTE:
+       // if fbo pre-draw color set to linaer, color values get linearlized "twice"
+       // (0.2f, 0.3f, 0.4f, 1.0f) when sampled i.e. converted in shader = (0.0331048f, 0.073239f, 0.132868f)
+       // 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)
+
+       FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
+       FBOConfig fboConfig1 = FBOConfig(GL_RGBA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
+
+       const TestRenderPassConfig renderPassConfigs[] =
+       {
+               TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_ENABLED, RENDERERTASK_DRAW),
+               TestRenderPassConfig(TEXTURESOURCESTYPE_BOTH, fboConfig1, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, getFunctionBlendLinearToSRGBCheck(), RENDERERTASK_DRAW)
+       };
+       std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
+
+       this->setTestConfig(renderPassConfigList);
+}
+
+bool FboSRGBColAttachCase::verifyResult (void)
+{
+       if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], m_resultsPostDraw[1])))
+               return true;
+       else
+               return false;
+}
+
+class FboSRGBToggleBlendCase : public FboSRGBTestCase
+{
+public:
+                       FboSRGBToggleBlendCase          (Context& context, const char* const name, const char* const description)
+                               : FboSRGBTestCase               (context, name, description) {}
+                       ~FboSRGBToggleBlendCase         (void) {}
+
+       void    setupTest                                       (void);
+       bool    verifyResult                            (void);
+};
+
+void FboSRGBToggleBlendCase::setupTest (void)
+{
+       //      TEST INFO:
+       //      Test to check if changing FRAMEBUFFER_SRGB_EXT from enabled to disabled. Enabled should produce SRGB color whilst disabled
+       //      should produce linear color. Test conducted with blending disabled.
+
+       FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
+
+       const TestRenderPassConfig renderPassConfigs[] =
+       {
+               TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW),
+               TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
+       };
+       std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
+
+       this->setTestConfig(renderPassConfigList);
+}
+
+bool FboSRGBToggleBlendCase::verifyResult (void)
+{
+       if (tcu::boolAny(tcu::greaterThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())))
+               return true;
+       else
+               return false;
+}
+
+class FboSRGBRenderTargetIgnoreCase : public FboSRGBTestCase
+{
+public:
+                       FboSRGBRenderTargetIgnoreCase           (Context& context, const char* const name, const char* const description)
+                               : FboSRGBTestCase                               (context, name, description) {}
+                       ~FboSRGBRenderTargetIgnoreCase          (void) {}
+
+       void    setupTest                                                       (void);
+       bool    verifyResult                                            (void);
+};
+
+void FboSRGBRenderTargetIgnoreCase::setupTest (void)
+{
+       // TEST INFO:
+       // Check if render targets that are non-RGB ignore the state of GL_FRAMEBUFFER_SRGB_EXT. Rendering to an fbo with non-sRGB color
+       // attachment should ignore color space conversion, producing linear color.
+
+       FBOConfig fboConfig0 = FBOConfig(GL_RGBA8, getTestColorBlank(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
+
+       const TestRenderPassConfig renderPassConfigs[] =
+       {
+               TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
+
+       };
+       std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
+
+       this->setTestConfig(renderPassConfigList);
+}
+
+bool FboSRGBRenderTargetIgnoreCase::verifyResult (void)
+{
+       if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], getTestColorLinear())))
+               return true;
+       else
+               return false;
+}
+
+class FboSRGBCopyToLinearCase : public FboSRGBTestCase
+{
+public:
+                       FboSRGBCopyToLinearCase         (Context& context, const char* const name, const char* const description)
+                               : FboSRGBTestCase               (context, name, description) {}
+                       ~FboSRGBCopyToLinearCase        (void) {}
+
+       void    setupTest                                       (void);
+       bool    verifyResult                            (void);
+};
+
+void FboSRGBCopyToLinearCase::setupTest (void)
+{
+       // TEST INFO:
+       // 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
+       // an sRGB to linear conversion
+
+       FBOConfig fboConfigs[] =
+       {
+               FBOConfig(GL_SRGB8_ALPHA8, getTestColorSRGB(), GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE),
+               FBOConfig(GL_RGBA8, getTestColorBlank(), GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION)
+       };
+       std::vector<FBOConfig> fboConfigList(fboConfigs, fboConfigs + DE_LENGTH_OF_ARRAY(fboConfigs));
+
+       const TestRenderPassConfig renderPassConfigs[] =
+       {
+               TestRenderPassConfig(TEXTURESOURCESTYPE_NONE, fboConfigList, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_COPY)
+       };
+       std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
+
+       this->setTestConfig(renderPassConfigList);
+}
+
+bool FboSRGBCopyToLinearCase::verifyResult (void)
+{
+       logColor(m_context, "pre-copy source fbo color values", m_resultsPreDraw[0]);
+       logColor(m_context, "pre-copy destination fbo color values", m_resultsPreDraw[1]);
+       logColor(m_context, "post-copy source fbo color values", m_resultsPostDraw[0]);
+       logColor(m_context, "post-copy destination fbo color values", m_resultsPostDraw[1]);
+
+       if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[1] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[1], getTestColorLinear())))
+               return true;
+       else
+               return false;
+}
+
+} // anonymous
+
+FboSRGBWriteControlTests::FboSRGBWriteControlTests     (Context& context)
+       : TestCaseGroup                 (context, "srgb_write_control", "Colorbuffer tests")
+{
+}
+
+FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void)
+{
+}
+
+void FboSRGBWriteControlTests::init (void)
+{
+       this->addChild(new FboSRGBQueryCase                                     (m_context, "framebuffer_srgb_enabled",                                                 "srgb enable framebuffer"));
+       this->addChild(new FboSRGBColAttachCase                         (m_context, "framebuffer_srgb_enabled_col_attach",                              "srgb enable color attachment and framebuffer"));
+       this->addChild(new FboSRGBToggleBlendCase                       (m_context, "framebuffer_srgb_enabled_blend",                                   "toggle framebuffer srgb settings with blend disabled"));
+       this->addChild(new FboSRGBRenderTargetIgnoreCase        (m_context, "framebuffer_srgb_enabled_render_target_ignore",    "enable framebuffer srgb, non-srgb render target should ignore"));
+       this->addChild(new FboSRGBCopyToLinearCase                      (m_context, "framebuffer_srgb_enabled_copy_to_linear",                  "no conversion when blittering between framebuffer srgb and linear"));
+}
+
+}
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fFboSRGBWriteControlTests.hpp b/modules/gles31/functional/es31fFboSRGBWriteControlTests.hpp
new file mode 100644 (file)
index 0000000..a4e0f17
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _ES31FFBOSRGBWRITECONTROLTESTS_HPP
+#define _ES31FFBOSRGBWRITECONTROLTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief FBO sRGB tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class FboSRGBWriteControlTests  : public TestCaseGroup
+{
+public:
+                                                               FboSRGBWriteControlTests        (Context& context);
+                                                               ~FboSRGBWriteControlTests       (void);
+
+       void                                            init                                            (void);
+
+private:
+                                                               FboSRGBWriteControlTests        (const FboSRGBWriteControlTests & other);
+       FboSRGBWriteControlTests&       operator=                                       (const FboSRGBWriteControlTests & other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FFBOSRGBWRITECONTROLTESTS_HPP
\ No newline at end of file
index b2bdac6..8e2a3c6 100644 (file)
@@ -76,6 +76,7 @@
 #include "es31fDebugTests.hpp"
 #include "es31fFboColorbufferTests.hpp"
 #include "es31fFboNoAttachmentTests.hpp"
+#include "es31fFboSRGBWriteControlTests.hpp"
 #include "es31fProgramInterfaceQueryTests.hpp"
 #include "es31fTextureGatherTests.hpp"
 #include "es31fTextureFormatTests.hpp"
@@ -294,6 +295,7 @@ public:
                addChild(new FboColorTests                                              (m_context));
                addChild(createFboNoAttachmentTests                             (m_context));
                addChild(createFboNoAttachmentCompletenessTests (m_context));
+               addChild(new FboSRGBWriteControlTests                   (m_context));
        }
 };