/*------------------------------------------------------------------------- * OpenGL Conformance Test Suite * ----------------------------- * * Copyright (c) 2021 Google Inc. * Copyright (c) 2021 The Khronos Group Inc. * * 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 glcCompressedFormatTests.cpp * \brief Tests for OpenGL ES 3.1 and 3.2 compressed image formats */ /*-------------------------------------------------------------------*/ #include "glcCompressedFormatTests.hpp" #include "gluDefs.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include "gluShaderProgram.hpp" #include "gluPixelTransfer.hpp" #include "gluStrUtil.hpp" #include "tcuResource.hpp" #include "tcuSurface.hpp" #include "tcuImageCompare.hpp" #include "tcuTestLog.hpp" #include "tcuStringTemplate.hpp" #include "deUniquePtr.hpp" #include #include #include #include #include #include namespace glcts { namespace { using namespace glw; using namespace glu; using namespace tcu; using namespace std; struct FormatInfo { ApiType minApi; const char* name; GLenum internalFormat; GLenum format; GLenum sizedFormat; bool issRGB; IVec2 blockSize; }; const ApiType gles31 = ApiType::es(3, 1); const ApiType gles32 = ApiType::es(3, 2); // List of compressed texture formats (table 8.17) const FormatInfo compressedFormats[] = { // ETC (table C.2) // minApi, name , internalFormat , format , sizedFormat , issRGB , blockSize { gles31, "r11_eac" , GL_COMPRESSED_R11_EAC , GL_RED , GL_R8 , false , { 4, 4 } }, { gles31, "signed_r11_eac" , GL_COMPRESSED_SIGNED_R11_EAC , GL_RED , GL_R8 , false , { 4, 4 } }, { gles31, "rg11_eac" , GL_COMPRESSED_RG11_EAC , GL_RG , GL_RG8 , false , { 4, 4 } }, { gles31, "signed_rg11_eac" , GL_COMPRESSED_SIGNED_RG11_EAC , GL_RG , GL_RG8 , false , { 4, 4 } }, { gles31, "rgb8_etc2" , GL_COMPRESSED_RGB8_ETC2 , GL_RGB , GL_RGB8 , false , { 4, 4 } }, { gles31, "srgb8_etc2" , GL_COMPRESSED_SRGB8_ETC2 , GL_RGB , GL_SRGB8 , true , { 4, 4 } }, { gles31, "rgb8_punchthrough_alpha1_etc2" , GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_RGBA , GL_RGBA8 , false , { 4, 4 } }, { gles31, "srgb8_punchthrough_alpha1_etc2" , GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 4, 4 } }, { gles31, "rgba8_etc2_eac" , GL_COMPRESSED_RGBA8_ETC2_EAC , GL_RGBA , GL_RGBA8 , false , { 4, 4 } }, { gles31, "srgb8_alpha8_etc2_eac" , GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 4, 4 } }, // ASTC (table C.1) // minApi, name , internalFormat , format , sizedFormat , issRGB , blockSize { gles32, "rgba_astc_4x4" , GL_COMPRESSED_RGBA_ASTC_4x4 , GL_RGBA , GL_RGBA8 , false , { 4, 4 } }, { gles32, "rgba_astc_5x4" , GL_COMPRESSED_RGBA_ASTC_5x4 , GL_RGBA , GL_RGBA8 , false , { 5, 4 } }, { gles32, "rgba_astc_5x5" , GL_COMPRESSED_RGBA_ASTC_5x5 , GL_RGBA , GL_RGBA8 , false , { 5, 5 } }, { gles32, "rgba_astc_6x5" , GL_COMPRESSED_RGBA_ASTC_6x5 , GL_RGBA , GL_RGBA8 , false , { 6, 5 } }, { gles32, "rgba_astc_6x6" , GL_COMPRESSED_RGBA_ASTC_6x6 , GL_RGBA , GL_RGBA8 , false , { 6, 6 } }, { gles32, "rgba_astc_8x5" , GL_COMPRESSED_RGBA_ASTC_8x5 , GL_RGBA , GL_RGBA8 , false , { 8, 5 } }, { gles32, "rgba_astc_8x6" , GL_COMPRESSED_RGBA_ASTC_8x6 , GL_RGBA , GL_RGBA8 , false , { 8, 6 } }, { gles32, "rgba_astc_8x8" , GL_COMPRESSED_RGBA_ASTC_8x8 , GL_RGBA , GL_RGBA8 , false , { 8, 8 } }, { gles32, "rgba_astc_10x5" , GL_COMPRESSED_RGBA_ASTC_10x5 , GL_RGBA , GL_RGBA8 , false , { 10, 5 } }, { gles32, "rgba_astc_10x6" , GL_COMPRESSED_RGBA_ASTC_10x6 , GL_RGBA , GL_RGBA8 , false , { 10, 6 } }, { gles32, "rgba_astc_10x8" , GL_COMPRESSED_RGBA_ASTC_10x8 , GL_RGBA , GL_RGBA8 , false , { 10, 8 } }, { gles32, "rgba_astc_10x10" , GL_COMPRESSED_RGBA_ASTC_10x10 , GL_RGBA , GL_RGBA8 , false , { 10, 10 } }, { gles32, "rgba_astc_12x10" , GL_COMPRESSED_RGBA_ASTC_12x10 , GL_RGBA , GL_RGBA8 , false , { 12, 10 } }, { gles32, "rgba_astc_12x12" , GL_COMPRESSED_RGBA_ASTC_12x12 , GL_RGBA , GL_RGBA8 , false , { 12, 12 } }, { gles32, "srgb8_alpha8_astc_4x4" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 4, 4 } }, { gles32, "srgb8_alpha8_astc_5x4" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 5, 4 } }, { gles32, "srgb8_alpha8_astc_5x5" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 5, 5 } }, { gles32, "srgb8_alpha8_astc_6x5" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 6, 5 } }, { gles32, "srgb8_alpha8_astc_6x6" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 6, 6 } }, { gles32, "srgb8_alpha8_astc_8x5" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 8, 5 } }, { gles32, "srgb8_alpha8_astc_8x6" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 8, 6 } }, { gles32, "srgb8_alpha8_astc_8x8" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 8, 8 } }, { gles32, "srgb8_alpha8_astc_10x5" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 10, 5 } }, { gles32, "srgb8_alpha8_astc_10x6" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 10, 6 } }, { gles32, "srgb8_alpha8_astc_10x8" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 10, 8 } }, { gles32, "srgb8_alpha8_astc_10x10" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 10, 10 } }, { gles32, "srgb8_alpha8_astc_12x10" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 12, 10 } }, { gles32, "srgb8_alpha8_astc_12x12" , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 , GL_RGBA , GL_SRGB8_ALPHA8 , true , { 12, 12 } }, }; struct UnsizedFormatInfo { GLenum format; GLenum dataType; }; const map unsizedFormats = { { GL_RGBA32UI , { GL_RGBA_INTEGER , GL_UNSIGNED_INT } }, { GL_RGBA32I , { GL_RGBA_INTEGER , GL_INT } }, { GL_RGBA32F , { GL_RGBA , GL_FLOAT } }, { GL_RGBA16F , { GL_RGBA , GL_FLOAT } }, { GL_RG32F , { GL_RG , GL_FLOAT } }, { GL_RGBA16UI , { GL_RGBA_INTEGER , GL_UNSIGNED_SHORT } }, { GL_RG32UI , { GL_RG_INTEGER , GL_UNSIGNED_INT } }, { GL_RGBA16I , { GL_RGBA_INTEGER , GL_SHORT } }, { GL_RG32I , { GL_RG_INTEGER , GL_INT } } }; const vector, vector>> copyFormats = { // Table 16.3 - copy between compressed and uncompressed // 128bit texel / block size { { GL_RGBA32UI, GL_RGBA32I, GL_RGBA32F }, { GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12, } }, // 64bit texel / block size { { GL_RGBA16F, GL_RG32F, GL_RGBA16UI, GL_RG32UI, GL_RGBA16I, GL_RG32I }, { GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 } }, // Table 16.4 - only entries for compressed formats are included { { GL_COMPRESSED_R11_EAC , GL_COMPRESSED_SIGNED_R11_EAC }, {} }, { { GL_COMPRESSED_RG11_EAC , GL_COMPRESSED_SIGNED_RG11_EAC }, {} }, { { GL_COMPRESSED_RGB8_ETC2 , GL_COMPRESSED_SRGB8_ETC2 }, {} }, { { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 }, {} }, { { GL_COMPRESSED_RGBA8_ETC2_EAC , GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC }, {} }, { { GL_COMPRESSED_RGBA_ASTC_4x4 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_5x4 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_5x5 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_6x5 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_6x6 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_8x5 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_8x6 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_8x8 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_10x5 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_10x6 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_10x8 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_10x10 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_12x10 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 }, {} }, { { GL_COMPRESSED_RGBA_ASTC_12x12 , GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 }, {} } }; #include "glcCompressedFormatTests_data.inl" const float vertexPositions[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, }; const float vertexTexCoords[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, }; const char* vertexShader = "${VERSION}\n" "in highp vec4 in_position;\n" "in highp vec2 in_texCoord;\n" "out highp vec2 v_texCoord;\n" "void main (void)\n" "{\n" " gl_Position = in_position;\n" " v_texCoord = in_texCoord;\n" "}\n"; const char* fragmentShader = "${VERSION}\n" "uniform highp vec4 offset;\n" "uniform highp vec4 scale;\n" "uniform highp sampler2D sampler;\n" "in highp vec2 v_texCoord;\n" "layout(location = 0) out highp vec4 out_color;\n" "void main (void)\n" "{\n" " out_color = texture(sampler, v_texCoord) * scale + offset;\n" "}\n"; struct OffsetInfo { Vec4 offset; Vec4 scale; }; const OffsetInfo defaultOffset { { 0.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }; const map offsets = { { GL_COMPRESSED_SIGNED_R11_EAC , { { 0.5f, 0.0f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f, 1.0f } } }, { GL_COMPRESSED_SIGNED_RG11_EAC , { { 0.5f, 0.5f, 0.0f, 0.0f }, { 0.5f, 0.5f, 0.0f, 1.0f } } } }; class SharedData { public: explicit SharedData (deqp::Context& context); virtual ~SharedData (); void init(); void deinit(); GLuint programId() const; GLuint texId(int index) const; GLuint vaoId() const; GLuint offsetLoc() const; GLuint scaleLoc() const; private: deqp::Context& m_context; size_t m_initCount; vector m_texIds; shared_ptr m_program; GLuint m_vaoId; GLuint m_vboIds[2]; GLuint m_offsetLoc; GLuint m_scaleLoc; SharedData (const SharedData& other) = delete; SharedData& operator= (const SharedData& other) = delete; }; SharedData::SharedData (deqp::Context& context) : m_context(context) , m_initCount(0) { } SharedData::~SharedData () { DE_ASSERT(m_initCount <= 0); } void SharedData::init () { ++m_initCount; if (m_initCount > 1) return; const auto& gl = m_context.getRenderContext().getFunctions(); // program const bool supportsES32 = contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); const auto glslVersion = getGLSLVersionDeclaration(supportsES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES); const auto args = map { { "VERSION", glslVersion } }; const auto vs = StringTemplate(vertexShader).specialize(args); const auto fs = StringTemplate(fragmentShader).specialize(args); m_program = make_shared(m_context.getRenderContext(), ProgramSources() << glu::VertexSource(vs) << glu::FragmentSource(fs)); if (!m_program->isOk()) throw runtime_error("Compiling shader program failed"); const auto program = m_program->getProgram(); const auto positionLoc = gl.getAttribLocation(program, "in_position"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed"); const auto texCoordLoc = gl.getAttribLocation(program, "in_texCoord"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed"); m_offsetLoc = gl.getUniformLocation(program, "offset"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed"); m_scaleLoc = gl.getUniformLocation(program, "scale"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed"); // buffers gl.genBuffers(DE_LENGTH_OF_ARRAY(m_vboIds), m_vboIds); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexTexCoords), vertexTexCoords, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); gl.bindBuffer(GL_ARRAY_BUFFER, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); // vertex array objects gl.genVertexArrays(1, &m_vaoId); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed"); gl.bindVertexArray(m_vaoId); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed"); gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); gl.enableVertexAttribArray(positionLoc); GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed"); gl.vertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed"); gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); gl.enableVertexAttribArray(texCoordLoc); GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed"); gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed"); gl.bindVertexArray(0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed"); } void SharedData::deinit () { DE_ASSERT(m_initCount > 0); --m_initCount; if (m_initCount > 0) return; const auto& gl = m_context.getRenderContext().getFunctions(); gl.deleteBuffers(1, &m_vaoId); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed"); gl.deleteBuffers(DE_LENGTH_OF_ARRAY(m_vboIds), m_vboIds); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed"); gl.deleteTextures(m_texIds.size(), m_texIds.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed"); } GLuint SharedData::programId () const { return m_program->getProgram(); } GLuint SharedData::texId (int index) const { return m_texIds[index]; } GLuint SharedData::vaoId () const { return m_vaoId; } GLuint SharedData::offsetLoc () const { return m_offsetLoc; } GLuint SharedData::scaleLoc () const { return m_scaleLoc; } struct { const GLsizei width = 8; const GLsizei height = 8; const GLsizei depth = 6; const vector data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; } invalidTexture; struct ApiTestContext { TestLog& log; const glw::Functions& gl; vector& texIds; vector& bufferIds; const Archive& archive; void bindTexture(GLenum target, GLuint texId); }; void ApiTestContext::bindTexture (GLenum target, GLuint texId) { gl.bindTexture(target, texId); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed"); } typedef function ApiCaseFn; struct ApiCaseStep { ApiCaseFn code; GLenum expectedError; }; typedef function&)> ApiCaseStepGeneratorFn; struct ApiCaseParams { ApiType minApi; string name; string description; size_t texIdsCount; size_t bufferIdsCount; vector steps; ApiCaseStepGeneratorFn stepsGenerator; }; const GLenum cubemapFaces[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, }; struct ImageInfo { GLuint width; GLuint height; vector data; }; ImageInfo loadImage (const Archive& archive, GLenum format, size_t imageIndex) { const auto data = imageData.find(format); if (data == imageData.end()) { ostringstream msg; msg << "No image data found for format: " << format; TCU_FAIL(msg.str().c_str()); } if (imageIndex >= data->second.size()) { ostringstream msg; msg << "Image index out of range for format: " << format << " index: " << imageIndex; TCU_FAIL(msg.str().c_str()); } const de::UniquePtr resource (archive.getResource(data->second[imageIndex].path.c_str())); if (!resource || resource->getSize() <= 0) TCU_FAIL("Failed to read file: "+data->second[imageIndex].path); ImageInfo result; result.width = data->second[imageIndex].width; result.height = data->second[imageIndex].height; const auto size = resource->getSize(); result.data.resize(size); resource->setPosition(0); resource->read(result.data.data(), size); return result; } void setTextureParameters (const glw::Functions& gl, GLenum target) { gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed"); gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed"); gl.texParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed"); gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed"); const auto repeatMode = GL_CLAMP_TO_EDGE; gl.texParameteri(target, GL_TEXTURE_WRAP_S, repeatMode); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed"); gl.texParameteri(target, GL_TEXTURE_WRAP_T, repeatMode); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed"); gl.texParameteri(target, GL_TEXTURE_WRAP_R, repeatMode); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed"); } ApiCaseParams apiTests[] = { { gles31, // ApiType minApi; "invalid_target", // string name; "Invalid texture target for compressed format", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_3D, context.texIds[0]); }, GL_NO_ERROR }, { [](ApiTestContext& context) { context.gl.compressedTexImage2D(GL_TEXTURE_3D, 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width, invalidTexture.height, 0, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_ENUM }, { [](ApiTestContext& context) { context.gl.compressedTexSubImage2D(GL_TEXTURE_3D, 0, 0, 0, invalidTexture.width, invalidTexture.height, GL_COMPRESSED_RGB8_ETC2, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_ENUM }, }, DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator; }, { gles31, // ApiType minApi; "invalid_width_or_height", // string name; "Different values for width and height for cubemap texture target", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR } }, [](deqp::Context&, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { steps.push_back( { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR }); for(size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapFaces); ++i) { steps.push_back( { [i](ApiTestContext& context) { context.gl.compressedTexImage2D(cubemapFaces[i], 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width - i % 2, invalidTexture.height - (i + 1) % 2, 0, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_VALUE }); steps.push_back( { [i](ApiTestContext& context) { const auto format = GL_COMPRESSED_RGB8_ETC2; const GLsizei blockSize = 4; const GLsizei blockDataSize = 8; const auto data = loadImage(context.archive, format, 0); const auto& gl = context.gl; gl.compressedTexImage2D(cubemapFaces[i], 0, format, data.width, data.height, 0, data.data.size(), data.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); const auto updateWidth = invalidTexture.width - (i % 2) * blockSize; const auto updateHeight = invalidTexture.height - ((i + 1) % 2) * blockSize; const auto updateDataSize = (updateWidth / blockSize) * (updateHeight / blockSize) * blockDataSize; DE_ASSERT(updateDataSize <= invalidTexture.data.size()); context.gl.compressedTexSubImage2D(cubemapFaces[i], 0, 0, 0, updateWidth, updateHeight, format, updateDataSize, invalidTexture.data.data()); }, GL_NO_ERROR }); } } }, { gles32, // ApiType minApi; "invalid_width_or_height_array", // string name; "Different values for width and height for cubemap texture target", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR }, { [](ApiTestContext& context) { context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width - 1, invalidTexture.height, 6, 0, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_VALUE } }, DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator; }, { gles31, // ApiType minApi; "invalid_size_value_negative", // string name; "Negative width, height or imageSize for compressed texture image", // string description; 3, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context& testContext, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { auto format = GL_COMPRESSED_RGB8_ETC2; const auto data = loadImage(testContext.getTestContext().getArchive(), format, 0); steps.push_back( { [format, data](ApiTestContext& context) { DE_ASSERT(context.texIds.size() >= 3); context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, -1, 0, data.data.size(), data.data.data()); }, GL_INVALID_VALUE }); steps.push_back( { [format, data](ApiTestContext& context) { context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, data.data.size(), data.data.data()); }, GL_NO_ERROR }); steps.push_back( { [format, data](ApiTestContext& context) { context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data.width, -1, format, data.data.size(), data.data.data()); }, GL_INVALID_VALUE }); steps.push_back( { [format, data](ApiTestContext& context) { DE_ASSERT(context.texIds.size() >= 3); context.bindTexture(GL_TEXTURE_2D, context.texIds[1]); context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, -276, data.height, 0, data.data.size(), data.data.data()); }, GL_INVALID_VALUE }); steps.push_back( { [format, data](ApiTestContext& context) { context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, data.data.size(), data.data.data()); }, GL_NO_ERROR }); steps.push_back( { [format, data](ApiTestContext& context) { context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, -276, data.height, format, data.data.size(), data.data.data()); }, GL_INVALID_VALUE }); steps.push_back( { [format, data](ApiTestContext& context) { DE_ASSERT(context.texIds.size() >= 3); context.bindTexture(GL_TEXTURE_2D, context.texIds[2]); context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, -66543, data.data.data()); }, GL_INVALID_VALUE }); steps.push_back( { [format, data](ApiTestContext& context) { context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, data.data.size(), data.data.data()); }, GL_NO_ERROR }); steps.push_back( { [format, data](ApiTestContext& context) { context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data.width, data.height, format, -66543, data.data.data()); }, GL_INVALID_VALUE }); } }, { gles31, // ApiType minApi; "invalid_border_nonzero", // string name; "Non zero border values are not supported", // string description; 2, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width, invalidTexture.height, 1, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_VALUE }, }, [](deqp::Context&, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(size_t j = 0; j < DE_LENGTH_OF_ARRAY(cubemapFaces); ++j) steps.push_back( { [j](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[1]); context.gl.compressedTexImage2D(cubemapFaces[j], 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width, invalidTexture.height, 1, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_VALUE }); }, }, { gles32, // ApiType minApi; "invalid_border_nonzero_array", // string name; "Non zero border values are not supported", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width, invalidTexture.height, invalidTexture.depth, 1, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_VALUE }, }, DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator; }, { gles31, // ApiType minApi; "invalid_format_mismatch", // string name; "Subimage format differs from previously specified texture format", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { const auto& gl = context.gl; const auto format0 = GL_COMPRESSED_RGB8_ETC2; const auto data0 = loadImage(context.archive, format0, 0); const auto format1 = GL_COMPRESSED_R11_EAC; const auto data1 = loadImage(context.archive, format1, 0); DE_ASSERT(data0.width == data1.width && data0.height == data1.height); context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format0, data0.width, data0.height, 0, data0.data.size(), data0.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data1.width, data1.height, format1, data1.data.size(), data1.data.data()); }, GL_INVALID_OPERATION }, }, DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator; }, { gles31, // ApiType minApi; "invalid_target_3d", // string name; "Invalid texture target for compressed texture", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context& testContext, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i) { if (!contextSupports(testContext.getRenderContext().getType(), compressedFormats[i].minApi)) continue; const auto data = loadImage(testContext.getTestContext().getArchive(), compressedFormats[i].internalFormat, 0); steps.push_back( { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); }, GL_NO_ERROR }); steps.push_back( { [i, data](ApiTestContext& context) { context.gl.compressedTexImage3D(GL_TEXTURE_2D, 0, compressedFormats[i].internalFormat, data.width, data.height, 1, 0, data.data.size(), data.data.data()); }, GL_INVALID_ENUM }); steps.push_back( { [i, data](ApiTestContext& context) { context.gl.compressedTexSubImage3D(GL_TEXTURE_2D, 0, 0, 0, 0, data.width, data.height, 1, compressedFormats[i].internalFormat, data.data.size(), data.data.data()); }, GL_INVALID_ENUM }); } } }, { gles31, // ApiType minApi; "texstorage_accepts_compressed_format", // string name; "TexStorage should accept compressed format", // string description; DE_LENGTH_OF_ARRAY(compressedFormats), // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context& testContext, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i) { if (!contextSupports(testContext.getRenderContext().getType(), compressedFormats[i].minApi)) continue; steps.push_back( { [i](ApiTestContext& context) { const auto& gl = context.gl; const size_t textureWidth = 240; const size_t textureHeight = 240; context.bindTexture(GL_TEXTURE_2D, context.texIds[i]); gl.texStorage2D(GL_TEXTURE_2D, 1, compressedFormats[i].internalFormat, textureWidth, textureHeight); }, GL_NO_ERROR }); } } }, { gles31, // ApiType minApi; "invalid_teximage_with_compressed_format", // string name; "TexImage should not accept compressed format", // string description; 2, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context& testContext, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i) { const auto format = compressedFormats[i]; if (!contextSupports(testContext.getRenderContext().getType(), format.minApi)) continue; const auto data = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0); steps.push_back( { [format, data](ApiTestContext& context) { const auto& gl = context.gl; context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.texImage2D(GL_TEXTURE_2D, 0, format.internalFormat, data.width, data.height, 0, format.format, GL_UNSIGNED_BYTE, data.data.data()); }, GL_INVALID_VALUE }); steps.push_back( { [format, data](ApiTestContext& context) { const auto& gl = context.gl; context.bindTexture(GL_TEXTURE_3D, context.texIds[1]); gl.texImage3D(GL_TEXTURE_3D, 0, format.internalFormat, data.width, data.height, 1, 0, format.format, GL_UNSIGNED_BYTE, data.data.data()); }, GL_INVALID_VALUE }); } } }, { gles31, // ApiType minApi; "invalid_format", // string name; "Uncompressed internal format for compressed texture", // string description; 2, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_2D, context.texIds[1]); }, GL_NO_ERROR }, { [](ApiTestContext& context) { context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, invalidTexture.width, invalidTexture.height, 0, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_ENUM }, { [](ApiTestContext& context) { context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, invalidTexture.width, invalidTexture.height, GL_RGB, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_OPERATION }, { [](ApiTestContext& context) { const GLenum format = GL_COMPRESSED_RGB8_ETC2; const auto data = loadImage(context.archive, format, 0); const auto& gl = context.gl; gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, data.data.size(), data.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, invalidTexture.width, invalidTexture.height, GL_RGB, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_OPERATION }, { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR } }, [](deqp::Context&, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(size_t j = 0; j < DE_LENGTH_OF_ARRAY(cubemapFaces); ++j) { steps.push_back( { [j](ApiTestContext& context) { context.gl.compressedTexImage2D(cubemapFaces[j], 0, GL_RGB, invalidTexture.width, invalidTexture.height, 0, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_ENUM }); steps.push_back( { [j](ApiTestContext& context) { const GLenum format = GL_COMPRESSED_RGB8_ETC2; const auto data = loadImage(context.archive, format, 0); const auto& gl = context.gl; gl.compressedTexImage2D(cubemapFaces[j], 0, format, data.width, data.height, 0, data.data.size(), data.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); context.gl.compressedTexSubImage2D(cubemapFaces[j], 0, 0, 0, invalidTexture.width, invalidTexture.height, GL_RGB, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_OPERATION }); } } }, { gles32, // ApiType minApi; "invalid_format_array", // string name; "Uncompressed internal format for compressed texture", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR }, { [](ApiTestContext& context) { context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGB, invalidTexture.width, invalidTexture.height, 6, 0, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_ENUM }, { [](ApiTestContext& context) { const GLenum format = GL_COMPRESSED_RGB8_ETC2; const auto data = loadImage(context.archive, format, 0); const auto& gl = context.gl; vector arrayData; arrayData.reserve(6 * data.data.size()); for(size_t k = 0; k < 6; ++k) std::copy(data.data.begin(), data.data.end(), std::back_inserter(arrayData)); context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, format, data.width, data.height, 6, 0, arrayData.size(), arrayData.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage3D() failed"); context.gl.compressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, invalidTexture.width, invalidTexture.height, 6, GL_RGB, invalidTexture.data.size(), invalidTexture.data.data());context.gl.compressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, invalidTexture.width, invalidTexture.height, 6, GL_RGB, invalidTexture.data.size(), invalidTexture.data.data()); }, GL_INVALID_OPERATION } }, DE_NULL // ApiCaseStepGeneratorFn stepsGenerator; }, { gles31, // ApiType minApi; "invalid_too_small_unpack_buffer", // string name; "Pixel unpack buffer with not enough space for required texture data", // string description; 1, // size_t texIdsCount; 1, // size_t bufferIdsCount; { // vector steps; { [](ApiTestContext& context) { const GLenum format = GL_COMPRESSED_RGB8_ETC2; const auto data = loadImage(context.archive, format, 0); const auto& gl = context.gl; context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, context.bufferIds[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); gl.bufferData(GL_PIXEL_UNPACK_BUFFER, data.data.size() / 2, data.data.data(), GL_STATIC_READ); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, data.data.size(), 0); }, GL_INVALID_OPERATION }, { [](ApiTestContext& context) { const GLenum format = GL_COMPRESSED_RGB8_ETC2; const auto data = loadImage(context.archive, format, 0); const auto& gl = context.gl; context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, data.data.size(), data.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, context.bufferIds[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); gl.bufferData(GL_PIXEL_UNPACK_BUFFER, data.data.size() / 2, data.data.data(), GL_STATIC_READ); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data.width, data.height, format, data.data.size(), 0); }, GL_INVALID_OPERATION } }, DE_NULL // ApiCaseStepGeneratorFn stepsGenerator; }, { gles31, // ApiType minApi; "invalid_inconsistent_data_size", // string name; "Data size is not consistent with texture internal format and dimensions", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context& testContext, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i) { const auto& format = compressedFormats[i]; if (!contextSupports(testContext.getRenderContext().getType(), format.minApi)) continue; const auto data0 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0); const auto data1 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 1); steps.push_back( { [format, data0](ApiTestContext& context) { const auto& gl = context.gl; context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format.internalFormat, data0.width - 12, data0.height - 12, 0, data0.data.size(), data0.data.data()); }, GL_INVALID_VALUE }); } } }, { gles32, // ApiType minApi; "invalid_inconsistent_data_size_array", // string name; "Data size is not consistent with texture internal format and dimensions", // string description; 2, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context& testContext, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i) { const auto& format = compressedFormats[i]; if (!contextSupports(testContext.getRenderContext().getType(), format.minApi)) continue; const auto data0 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0); const auto data1 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 1); steps.push_back( { [format, data0](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR }); for(size_t j = 0; j < DE_LENGTH_OF_ARRAY(cubemapFaces); ++j) steps.push_back( { [j, format, data0](ApiTestContext& context) { context.gl.compressedTexImage2D(cubemapFaces[j], 0, format.internalFormat, data0.width, data0.height, 0, data0.data.size(), data0.data.data()); }, GL_NO_ERROR }); steps.push_back( { [format, data0](ApiTestContext& context) { vector arrayData; arrayData.reserve(6 * data0.data.size()); for(size_t k = 0; k < 6; ++k) std::copy(data0.data.begin(), data0.data.end(), std::back_inserter(arrayData)); context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[1]); context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, format.internalFormat, data0.width, data0.height, 6, 0, arrayData.size(), arrayData.data()); }, GL_NO_ERROR }); steps.push_back( { [format, data1](ApiTestContext& context) { context.gl.compressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, data1.width, data1.height, 1, format.internalFormat, data1.data.size() - 1, data1.data.data()); }, GL_INVALID_VALUE }); } } }, { gles31, // ApiType minApi; "invalid_offset_or_size", // string name; "Offset or image size not aligned with block size", // string description; 1, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context& testContext, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i) { const auto& format = compressedFormats[i]; if (!contextSupports(testContext.getRenderContext().getType(), format.minApi)) continue; const auto data0 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0); const auto data1 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 1); steps.push_back( { [format, data0](ApiTestContext& context) { context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format.internalFormat, data0.width, data0.height, 0, data0.data.size(), data0.data.data()); }, GL_NO_ERROR }); steps.push_back( { [format, data1](ApiTestContext& context) { context.gl.compressedTexImage2D(GL_TEXTURE_2D, 1, format.internalFormat, data1.width, data1.height, 0, data1.data.size(), data1.data.data()); }, GL_NO_ERROR }); steps.push_back( { [format, data1](ApiTestContext& context) { context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, format.blockSize.x() - 2, 0, data1.width, data1.height, format.internalFormat, data1.data.size(), data1.data.data()); }, GL_INVALID_OPERATION }); steps.push_back( { [format, data1](ApiTestContext& context) { context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, format.blockSize.y() - 2, data1.width, data1.height, format.internalFormat, data1.data.size(), data1.data.data()); }, GL_INVALID_OPERATION }); } } }, { gles32, // ApiType minApi; "copy_compressed_to_uncompressed", // string name; "Copying pixels from compressed to uncompressed texture", // string description; 2, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context&, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(const auto& format : copyFormats) { if (format.second.empty()) continue; for(const auto& uncompressedFormat : format.first) { for(const auto& compressedFormat : format.second) { steps.push_back( { [uncompressedFormat, compressedFormat](ApiTestContext& context) { const auto& gl = context.gl; const auto& image = imageData.at(compressedFormat); const auto& unsizedInfo = unsizedFormats.at(uncompressedFormat); const auto textureData = loadImage(context.archive, compressedFormat, 0); const auto compressedInfo = find_if(begin(compressedFormats), end(compressedFormats), [compressedFormat](const FormatInfo& fmt) { return fmt.internalFormat == compressedFormat; }); DE_ASSERT((GLsizei)textureData.width == image[0].width && (GLsizei)textureData.height == image[0].height); DE_ASSERT(compressedInfo != end(compressedFormats)); const auto targetWidth = image[0].width / compressedInfo->blockSize[0]; const auto targetHeight = image[0].height / compressedInfo->blockSize[1]; context.log << TestLog::Message << "Copying from " << getTextureFormatStr(compressedFormat).toString() << " " << image[0].width << "x" << image[0].height << " to " << getTextureFormatStr(uncompressedFormat).toString() << " " << targetWidth << "x" << targetHeight << TestLog::EndMessage; context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.texImage2D(GL_TEXTURE_2D, 0, uncompressedFormat, targetWidth, targetHeight, 0, unsizedInfo.format, unsizedInfo.dataType, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() failed"); setTextureParameters(context.gl, GL_TEXTURE_2D); context.bindTexture(GL_TEXTURE_2D, context.texIds[1]); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, compressedFormat, image[0].width, image[0].height, 0, textureData.data.size(), textureData.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); setTextureParameters(context.gl, GL_TEXTURE_2D); context.bindTexture(GL_TEXTURE_2D, 0); gl.copyImageSubData(context.texIds[1], GL_TEXTURE_2D, 0, 0, 0, 0, context.texIds[0], GL_TEXTURE_2D, 0, 0, 0, 0, image[0].width, image[0].height, 1); }, GL_NO_ERROR }); } } } } }, { gles32, // ApiType minApi; "copy_uncompressed_to_compressed", // string name; "Copying pixels from uncompressed to compressed texture", // string description; 2, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context&, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(const auto& format : copyFormats) { if (format.second.empty()) continue; for(const auto& uncompressedFormat : format.first) { for(const auto& compressedFormat : format.second) { steps.push_back( { [uncompressedFormat, compressedFormat](ApiTestContext& context) { const auto& gl = context.gl; const auto& image = imageData.at(compressedFormat); const auto& unsizedInfo = unsizedFormats.at(uncompressedFormat); const auto textureData = loadImage(context.archive, compressedFormat, 0); const auto compressedInfo = find_if(begin(compressedFormats), end(compressedFormats), [compressedFormat](const FormatInfo& fmt) { return fmt.internalFormat == compressedFormat; }); DE_ASSERT(compressedInfo != end(compressedFormats)); const auto sourceWidth = image[0].width / compressedInfo->blockSize[0]; const auto sourceHeight = image[0].height / compressedInfo->blockSize[1]; DE_ASSERT((GLsizei)textureData.width == image[0].width && (GLsizei)textureData.height == image[0].height); context.log << TestLog::Message << "Copying from " << getTextureFormatStr(uncompressedFormat).toString() << " " << sourceWidth << "x" << sourceHeight << " to " << getTextureFormatStr(compressedFormat).toString() << " " << image[0].width << "x" << image[0].height << TestLog::EndMessage; context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.texImage2D(GL_TEXTURE_2D, 0, uncompressedFormat, sourceWidth, sourceHeight, 0, unsizedInfo.format, unsizedInfo.dataType, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() failed"); setTextureParameters(context.gl, GL_TEXTURE_2D); context.bindTexture(GL_TEXTURE_2D, context.texIds[1]); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, compressedFormat, image[0].width, image[0].height, 0, textureData.data.size(), textureData.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); setTextureParameters(context.gl, GL_TEXTURE_2D); context.bindTexture(GL_TEXTURE_2D, 0); gl.copyImageSubData(context.texIds[0], GL_TEXTURE_2D, 0, 0, 0, 0, context.texIds[1], GL_TEXTURE_2D, 0, 0, 0, 0, sourceWidth, sourceHeight, 1); }, GL_NO_ERROR }); } } } } }, { gles32, // ApiType minApi; "copy_compressed_to_compressed", // string name; "Copying of pixels between compatible compressed texture formats", // string description; 2, // size_t texIdsCount; 0, // size_t bufferIdsCount; {}, // vector steps; [](deqp::Context&, vector& steps) // ApiCaseStepGeneratorFn stepsGenerator; { for(const auto& format : copyFormats) { if (!format.second.empty()) continue; for(const auto& format0 : format.first) { for(const auto& format1 : format.first) { steps.push_back( { [format0, format1](ApiTestContext& context) { const auto& gl = context.gl; const auto image0 = loadImage(context.archive, format0, 0); const auto image1 = loadImage(context.archive, format1, 1); DE_ASSERT(image0.width == 2 * image1.width && image0.height == 2 * image1.height); context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format0, image0.width, image0.height, 0, image0.data.size(), image0.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); setTextureParameters(context.gl, GL_TEXTURE_2D); context.bindTexture(GL_TEXTURE_2D, context.texIds[1]); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format1, image1.width, image1.height, 0, image1.data.size(), image1.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); setTextureParameters(context.gl, GL_TEXTURE_2D); context.bindTexture(GL_TEXTURE_2D, 0); gl.copyImageSubData(context.texIds[1], GL_TEXTURE_2D, 0, 0, 0, 0, context.texIds[0], GL_TEXTURE_2D, 0, 0, 0, 0, image1.width, image1.height, 1); }, GL_NO_ERROR }); } } } } } }; class CompressedApiTest : public deqp::TestCase { public: explicit CompressedApiTest (deqp::Context& context, const ApiCaseParams& params); virtual ~CompressedApiTest (); virtual void init (void) override; virtual void deinit (void) override; virtual IterateResult iterate (void) override; private: ApiCaseParams m_params; vector m_texIds; vector m_bufferIds; }; CompressedApiTest::CompressedApiTest (deqp::Context& context, const ApiCaseParams& params) : deqp::TestCase(context, params.name.c_str(), params.description.c_str()) , m_params(params) { } CompressedApiTest::~CompressedApiTest () { } void CompressedApiTest::init (void) { const auto& gl = m_context.getRenderContext().getFunctions(); if (m_params.texIdsCount > 0) { m_texIds.resize(m_params.texIdsCount); gl.genTextures(m_texIds.size(), m_texIds.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); m_bufferIds.resize(m_params.bufferIdsCount); gl.genBuffers(m_bufferIds.size(), m_bufferIds.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); } } void CompressedApiTest::deinit (void) { const auto& gl = m_context.getRenderContext().getFunctions(); if (!m_bufferIds.empty()) { gl.deleteBuffers(m_bufferIds.size(), m_bufferIds.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed"); m_bufferIds.erase(m_bufferIds.begin(), m_bufferIds.end()); } if (!m_texIds.empty()) { gl.deleteTextures(m_texIds.size(), m_texIds.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed"); m_texIds.erase(m_texIds.begin(), m_texIds.end()); } } CompressedApiTest::IterateResult CompressedApiTest::iterate (void) { const auto& gl = m_context.getRenderContext().getFunctions(); ApiTestContext caseContext = { m_context.getTestContext().getLog(), gl, m_texIds, m_bufferIds, m_context.getTestContext().getArchive() }; vector steps (m_params.steps); if (m_params.stepsGenerator) m_params.stepsGenerator(m_context, steps); size_t stepIndex = 0; for(const auto& step : steps) { step.code(caseContext); const auto errorCode = gl.getError(); if (errorCode != step.expectedError) { ostringstream msg; msg << "Got wrong error code: " << glu::getErrorStr(errorCode) << ", expected: " << glu::getErrorStr(step.expectedError) << " after step " << stepIndex; TCU_FAIL(msg.str().c_str()); } ++stepIndex; } m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); return IterateResult::STOP; } class CompressedFormatTest : public deqp::TestCase { public: CompressedFormatTest (deqp::Context& context, shared_ptr data, const FormatInfo& format); virtual ~CompressedFormatTest (); virtual void init (void); virtual void deinit (void); virtual IterateResult iterate (void); private: Surface drawTestImage (const glw::Functions& gl, GLuint texId, GLsizei width, GLsizei height); shared_ptr m_data; const FormatInfo& formatInfo; }; CompressedFormatTest::CompressedFormatTest (deqp::Context& context, shared_ptr data, const FormatInfo& format) : deqp::TestCase(context, format.name, "Test rendering of compressed format ") , m_data(data) , formatInfo(format) { } CompressedFormatTest::~CompressedFormatTest () { } void CompressedFormatTest::init (void) { m_data->init(); } void CompressedFormatTest::deinit (void) { m_data->deinit(); } Surface CompressedFormatTest::drawTestImage (const glw::Functions& gl, GLuint texId, GLsizei width, GLsizei height) { gl.clearColor(1.0f, 0.2f, 1.0f, 1.0f); gl.clear(GL_COLOR_BUFFER_BIT); GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() failed"); gl.disable(GL_BLEND); GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() failed"); gl.bindTexture(GL_TEXTURE_2D, texId); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed"); gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); gl.bindTexture(GL_TEXTURE_2D, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed"); Surface result(width, height); readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); return result; } CompressedFormatTest::IterateResult CompressedFormatTest::iterate (void) { const auto& archive = m_context.getTestContext().getArchive(); const auto image0 = loadImage(archive, formatInfo.internalFormat, 0); const auto image1 = loadImage(archive, formatInfo.internalFormat, 1); const auto image2 = loadImage(archive, formatInfo.internalFormat, 2); DE_ASSERT(image0.width == 2 * image1.width && image0.height == 2 * image1.height && image0.width % 4 == 0 && image0.height % 4 == 0 && image0.width == image2.width && image0.height == image2.height); const auto& gl = m_context.getRenderContext().getFunctions(); GLuint texIds[2]; gl.genTextures(DE_LENGTH_OF_ARRAY(texIds), texIds); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); GLuint fboId; gl.genFramebuffers(1, &fboId); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed"); GLuint rboId; gl.genRenderbuffers(1, &rboId); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers() failed"); gl.bindRenderbuffer(GL_RENDERBUFFER, rboId); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed"); const GLenum bufferFormats[2][2] = { { GL_RGB8 , GL_SRGB8_ALPHA8 }, { GL_RGBA8 , GL_SRGB8_ALPHA8 } }; const bool hasAlpha = formatInfo.format == GL_RGBA; gl.renderbufferStorage(GL_RENDERBUFFER, bufferFormats[hasAlpha][formatInfo.issRGB], image0.width, image0.height); GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage() failed"); gl.bindRenderbuffer(GL_RENDERBUFFER, 0); gl.bindFramebuffer(GL_FRAMEBUFFER, fboId); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed"); gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboId); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer() failed"); gl.viewport(0,0, image0.width, image0.height); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed"); gl.useProgram(m_data->programId()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed"); gl.uniform4fv(m_data->offsetLoc(), 1, defaultOffset.offset.getPtr()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed"); gl.uniform4fv(m_data->scaleLoc(), 1, defaultOffset.scale.getPtr()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed"); gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GLU_EXPECT_NO_ERROR(gl.getError(), "glBlendFunc() failed"); gl.disable(GL_BLEND); GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() failed"); // reference image gl.bindTexture(GL_TEXTURE_2D, texIds[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed"); gl.texImage2D(GL_TEXTURE_2D, 0, formatInfo.sizedFormat, image2.width, image2.height, 0, formatInfo.format, GL_UNSIGNED_BYTE, image2.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() failed"); setTextureParameters(gl, GL_TEXTURE_2D); // compressed image gl.bindTexture(GL_TEXTURE_2D, texIds[1]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed"); gl.compressedTexImage2D(GL_TEXTURE_2D, 0, formatInfo.internalFormat, image0.width, image0.height, 0, image0.data.size(), image0.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed"); gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image1.width, image1.height, formatInfo.internalFormat, image1.data.size(), image1.data.data()); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexSubImage2D() failed"); setTextureParameters(gl, GL_TEXTURE_2D); gl.bindTexture(GL_TEXTURE_2D, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed"); gl.bindVertexArray(m_data->vaoId()); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed"); gl.useProgram(m_data->programId()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed"); gl.uniform4fv(m_data->offsetLoc(), 1, defaultOffset.offset.getPtr()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed"); gl.uniform4fv(m_data->scaleLoc(), 1, defaultOffset.scale.getPtr()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed"); const auto referenceImage = drawTestImage(gl, texIds[0], image0.width, image0.height); const auto& offsetIt = offsets.find(formatInfo.internalFormat); const auto& offset = offsetIt != offsets.end() ? offsetIt->second : defaultOffset; gl.uniform4fv(m_data->offsetLoc(), 1, offset.offset.getPtr()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed"); gl.uniform4fv(m_data->scaleLoc(), 1, offset.scale.getPtr()); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed"); const auto compressedImage = drawTestImage(gl, texIds[1], image0.width, image0.height); gl.disable(GL_BLEND); GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() failed"); gl.bindTexture(GL_TEXTURE_2D, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindtexture() failed"); gl.deleteRenderbuffers(1, &rboId); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteRenderbuffers() failed"); gl.deleteTextures(DE_LENGTH_OF_ARRAY(texIds), texIds); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed"); gl.deleteFramebuffers(1, &fboId); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers() failed"); if (!fuzzyCompare(m_testCtx.getLog(), "compressed_vs_uncompressed", "Image comparison result", referenceImage, compressedImage, 0.0f, CompareLogMode::COMPARE_LOG_ON_ERROR)) TCU_FAIL("Rendered image comparison failed."); m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); return IterateResult::STOP; } } // CompressedFormatTests::CompressedFormatTests (deqp::Context& context) : deqp::TestCaseGroup(context, "compressed_format", "Tests for compressed image formats") { } CompressedFormatTests::~CompressedFormatTests (void) { } void CompressedFormatTests::init (void) { const auto apiGroup = new TestCaseGroup(m_context, "api", "Api call return values"); addChild(apiGroup); for(const auto& apiCase : apiTests) if (glu::contextSupports(m_context.getRenderContext().getType(), apiCase.minApi)) apiGroup->addChild(new CompressedApiTest(m_context, apiCase)); const auto formatGroup = new TestCaseGroup(m_context, "format", "Compressed format textures"); addChild(formatGroup); const auto sharedData = make_shared(m_context); for(const auto& formatInfo : compressedFormats) if (glu::contextSupports(m_context.getRenderContext().getType(), formatInfo.minApi)) formatGroup->addChild(new CompressedFormatTest(m_context, sharedData, formatInfo)); } } // glcts