/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 2.0 Module * ------------------------------------------------- * * Copyright 2014 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 Texture specification tests. * * \todo [pyry] Following tests are missing: * - Specify mipmap incomplete texture, use without mipmaps, re-specify * as complete and render. * - Randomly re-specify levels to eventually reach mipmap-complete texture. *//*--------------------------------------------------------------------*/ #include "es2fTextureSpecificationTests.hpp" #include "tcuTestLog.hpp" #include "tcuImageCompare.hpp" #include "gluTextureUtil.hpp" #include "sglrContextUtil.hpp" #include "sglrContextWrapper.hpp" #include "sglrGLContext.hpp" #include "sglrReferenceContext.hpp" #include "glsTextureTestUtil.hpp" #include "tcuTextureUtil.hpp" #include "tcuFormatUtil.hpp" #include "tcuVectorUtil.hpp" #include "deRandom.hpp" #include "deStringUtil.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" namespace deqp { namespace gles2 { namespace Functional { using std::string; using std::vector; using std::pair; using tcu::TestLog; using tcu::Vec4; using tcu::IVec4; using tcu::UVec4; tcu::TextureFormat mapGLUnsizedInternalFormat (deUint32 internalFormat) { using tcu::TextureFormat; switch (internalFormat) { case GL_ALPHA: return TextureFormat(TextureFormat::A, TextureFormat::UNORM_INT8); case GL_LUMINANCE: return TextureFormat(TextureFormat::L, TextureFormat::UNORM_INT8); case GL_LUMINANCE_ALPHA: return TextureFormat(TextureFormat::LA, TextureFormat::UNORM_INT8); case GL_RGB: return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8); case GL_RGBA: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8); default: throw tcu::InternalError(string("Can't map GL unsized internal format (") + tcu::toHex(internalFormat).toString() + ") to texture format"); } } template static tcu::Vector randomVector (de::Random& rnd, const tcu::Vector& minVal = tcu::Vector(0.0f), const tcu::Vector& maxVal = tcu::Vector(1.0f)) { tcu::Vector res; for (int ndx = 0; ndx < Size; ndx++) res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]); return res; } static tcu::IVec4 getPixelFormatCompareDepth (const tcu::PixelFormat& pixelFormat, tcu::TextureFormat textureFormat) { switch (textureFormat.order) { case tcu::TextureFormat::L: case tcu::TextureFormat::LA: return tcu::IVec4(pixelFormat.redBits, pixelFormat.redBits, pixelFormat.redBits, pixelFormat.alphaBits); default: return tcu::IVec4(pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits); } } static tcu::UVec4 computeCompareThreshold (const tcu::PixelFormat& pixelFormat, tcu::TextureFormat textureFormat) { const IVec4 texFormatBits = tcu::getTextureFormatBitDepth(textureFormat); const IVec4 pixelFormatBits = getPixelFormatCompareDepth(pixelFormat, textureFormat); const IVec4 accurateFmtBits = min(pixelFormatBits, texFormatBits); const IVec4 compareBits = select(accurateFmtBits, IVec4(8), greaterThan(accurateFmtBits, IVec4(0))) - 1; return (IVec4(1) << (8-compareBits)).asUint(); } class GradientShader : public sglr::ShaderProgram { public: GradientShader (void) : ShaderProgram(sglr::pdec::ShaderProgramDeclaration() << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT) << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n" "attribute mediump vec2 a_coord;\n" "varying mediump vec2 v_coord;\n" "void main (void)\n" "{\n" " gl_Position = a_position;\n" " v_coord = a_coord;\n" "}\n") << sglr::pdec::FragmentSource("varying mediump vec2 v_coord;\n" "void main (void)\n" "{\n" " mediump float x = v_coord.x;\n" " mediump float y = v_coord.y;\n" " mediump float f0 = (x + y) * 0.5;\n" " mediump float f1 = 0.5 + (x - y) * 0.5;\n" " gl_FragColor = vec4(f0, f1, 1.0-f0, 1.0-f1);\n" "}\n")) { } void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const { for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) { rr::VertexPacket& packet = *packets[packetNdx]; packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx); packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx); } } void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const { for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) for (int fragNdx = 0; fragNdx < 4; ++fragNdx) { const tcu::Vec4 coord = rr::readTriangleVarying(packets[packetNdx], context, 0, fragNdx); const float x = coord.x(); const float y = coord.y(); const float f0 = (x + y) * 0.5f; const float f1 = 0.5f + (x - y) * 0.5f; rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(f0, f1, 1.0f-f0, 1.0f-f1)); } } }; class Tex2DShader : public sglr::ShaderProgram { public: Tex2DShader (void) : ShaderProgram(sglr::pdec::ShaderProgramDeclaration() << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT) << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D) << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n" "attribute mediump vec2 a_coord;\n" "varying mediump vec2 v_coord;\n" "void main (void)\n" "{\n" " gl_Position = a_position;\n" " v_coord = a_coord;\n" "}\n") << sglr::pdec::FragmentSource("uniform sampler2D u_sampler0;\n" "varying mediump vec2 v_coord;\n" "void main (void)\n" "{\n" " gl_FragColor = texture2D(u_sampler0, v_coord);\n" "}\n")) { } void setUniforms (sglr::Context& ctx, deUint32 program) const { ctx.useProgram(program); ctx.uniform1i(ctx.getUniformLocation(program, "u_sampler0"), 0); } void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const { for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) { rr::VertexPacket& packet = *packets[packetNdx]; packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx); packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx); } } void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const { tcu::Vec2 texCoords[4]; tcu::Vec4 colors[4]; for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) { // setup tex coords for (int fragNdx = 0; fragNdx < 4; ++fragNdx) { const tcu::Vec4 coord = rr::readTriangleVarying(packets[packetNdx], context, 0, fragNdx); texCoords[fragNdx] = tcu::Vec2(coord.x(), coord.y()); } // Sample m_uniforms[0].sampler.tex2D->sample4(colors, texCoords); // Write out for (int fragNdx = 0; fragNdx < 4; ++fragNdx) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, colors[fragNdx]); } } }; static const char* s_cubeSwizzles[] = { "vec3(-1, -y, +x)", "vec3(+1, -y, -x)", "vec3(+x, -1, -y)", "vec3(+x, +1, +y)", "vec3(-x, -y, -1)", "vec3(+x, -y, +1)" }; class TexCubeShader : public sglr::ShaderProgram { public: TexCubeShader (tcu::CubeFace face) : ShaderProgram(sglr::pdec::ShaderProgramDeclaration() << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT) << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_CUBE) << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n" "attribute mediump vec2 a_coord;\n" "varying mediump vec2 v_coord;\n" "void main (void)\n" "{\n" " gl_Position = a_position;\n" " v_coord = a_coord;\n" "}\n") << sglr::pdec::FragmentSource(string("") + "uniform samplerCube u_sampler0;\n" "varying mediump vec2 v_coord;\n" "void main (void)\n" "{\n" " mediump float x = v_coord.x*2.0 - 1.0;\n" " mediump float y = v_coord.y*2.0 - 1.0;\n" " gl_FragColor = textureCube(u_sampler0, " + s_cubeSwizzles[face] + ");\n" "}\n")) , m_face(face) { } void setUniforms (sglr::Context& ctx, deUint32 program) const { ctx.useProgram(program); ctx.uniform1i(ctx.getUniformLocation(program, "u_sampler0"), 0); } void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const { for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) { rr::VertexPacket& packet = *packets[packetNdx]; packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx); packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx); } } void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const { tcu::Vec3 texCoords[4]; tcu::Vec4 colors[4]; for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) { // setup tex coords for (int fragNdx = 0; fragNdx < 4; ++fragNdx) { const tcu::Vec4 coord = rr::readTriangleVarying(packets[packetNdx], context, 0, fragNdx); const float x = coord.x()*2.0f - 1.0f; const float y = coord.y()*2.0f - 1.0f; // Swizzle tex coords switch (m_face) { case tcu::CUBEFACE_NEGATIVE_X: texCoords[fragNdx] = tcu::Vec3(-1.0f, -y, +x); break; case tcu::CUBEFACE_POSITIVE_X: texCoords[fragNdx] = tcu::Vec3(+1.0f, -y, -x); break; case tcu::CUBEFACE_NEGATIVE_Y: texCoords[fragNdx] = tcu::Vec3( +x, -1.0f, -y); break; case tcu::CUBEFACE_POSITIVE_Y: texCoords[fragNdx] = tcu::Vec3( +x, +1.0f, +y); break; case tcu::CUBEFACE_NEGATIVE_Z: texCoords[fragNdx] = tcu::Vec3( -x, -y, -1.0f); break; case tcu::CUBEFACE_POSITIVE_Z: texCoords[fragNdx] = tcu::Vec3( +x, -y, +1.0f); break; default: DE_ASSERT(false); } } // Sample m_uniforms[0].sampler.texCube->sample4(colors, texCoords); // Write out for (int fragNdx = 0; fragNdx < 4; ++fragNdx) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, colors[fragNdx]); } } private: tcu::CubeFace m_face; }; enum TextureType { TEXTURETYPE_2D = 0, TEXTURETYPE_CUBE, TEXTURETYPE_LAST }; enum Flags { MIPMAPS = (1<<0) }; static const deUint32 s_cubeMapFaces[] = { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, }; class TextureSpecCase : public TestCase, public sglr::ContextWrapper { public: TextureSpecCase (Context& context, const char* name, const char* desc, const TextureType type, const tcu::TextureFormat format, const deUint32 flags, int width, int height); ~TextureSpecCase (void); IterateResult iterate (void); protected: virtual void createTexture (void) = DE_NULL; const TextureType m_texType; const tcu::TextureFormat m_texFormat; const deUint32 m_flags; const int m_width; const int m_height; bool m_half_float_oes; private: TextureSpecCase (const TextureSpecCase& other); TextureSpecCase& operator= (const TextureSpecCase& other); void verifyTex2D (sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext); void verifyTexCube (sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext); void renderTex2D (tcu::Surface& dst, int width, int height); void renderTexCube (tcu::Surface& dst, int width, int height, tcu::CubeFace face); void readPixels (tcu::Surface& dst, int x, int y, int width, int height); // \todo [2012-03-27 pyry] Renderer should be extended to allow custom attributes, that would clean up this cubemap mess. Tex2DShader m_tex2DShader; TexCubeShader m_texCubeNegXShader; TexCubeShader m_texCubePosXShader; TexCubeShader m_texCubeNegYShader; TexCubeShader m_texCubePosYShader; TexCubeShader m_texCubeNegZShader; TexCubeShader m_texCubePosZShader; }; TextureSpecCase::TextureSpecCase (Context& context, const char* name, const char* desc, const TextureType type, const tcu::TextureFormat format, const deUint32 flags, int width, int height) : TestCase (context, name, desc) , m_texType (type) , m_texFormat (format) , m_flags (flags) , m_width (width) , m_height (height) , m_texCubeNegXShader (tcu::CUBEFACE_NEGATIVE_X) , m_texCubePosXShader (tcu::CUBEFACE_POSITIVE_X) , m_texCubeNegYShader (tcu::CUBEFACE_NEGATIVE_Y) , m_texCubePosYShader (tcu::CUBEFACE_POSITIVE_Y) , m_texCubeNegZShader (tcu::CUBEFACE_NEGATIVE_Z) , m_texCubePosZShader (tcu::CUBEFACE_POSITIVE_Z) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); m_half_float_oes = glu::hasExtension(gl, glu::ApiType::es(2, 0), "GL_OES_texture_half_float"); } TextureSpecCase::~TextureSpecCase (void) { } TextureSpecCase::IterateResult TextureSpecCase::iterate (void) { glu::RenderContext& renderCtx = TestCase::m_context.getRenderContext(); const tcu::RenderTarget& renderTarget = renderCtx.getRenderTarget(); tcu::TestLog& log = m_testCtx.getLog(); DE_ASSERT(m_width <= 256 && m_height <= 256); if (renderTarget.getWidth() < m_width || renderTarget.getHeight() < m_height) throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); // Context size, and viewport for GLES2 de::Random rnd (deStringHash(getName())); int width = deMin32(renderTarget.getWidth(), 256); int height = deMin32(renderTarget.getHeight(), 256); int x = rnd.getInt(0, renderTarget.getWidth() - width); int y = rnd.getInt(0, renderTarget.getHeight() - height); // Contexts. sglr::GLContext gles2Context (renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height)); sglr::ReferenceContextBuffers refBuffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, width, height); sglr::ReferenceContext refContext (sglr::ReferenceContextLimits(renderCtx), refBuffers.getColorbuffer(), refBuffers.getDepthbuffer(), refBuffers.getStencilbuffer()); // Clear color buffer. for (int ndx = 0; ndx < 2; ndx++) { setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles2Context); glClearColor(0.125f, 0.25f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); } // Construct texture using both GLES2 and reference contexts. for (int ndx = 0; ndx < 2; ndx++) { setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles2Context); createTexture(); TCU_CHECK(glGetError() == GL_NO_ERROR); } // Setup texture filtering state. for (int ndx = 0; ndx < 2; ndx++) { setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles2Context); deUint32 texTarget = m_texType == TEXTURETYPE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP; glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, (m_flags & MIPMAPS) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST); glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } // Initialize case result to pass. m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Disable logging. gles2Context.enableLogging(0); // Verify results. switch (m_texType) { case TEXTURETYPE_2D: verifyTex2D (gles2Context, refContext); break; case TEXTURETYPE_CUBE: verifyTexCube (gles2Context, refContext); break; default: DE_ASSERT(false); } return STOP; } void TextureSpecCase::verifyTex2D (sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext) { int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; DE_ASSERT(m_texType == TEXTURETYPE_2D); for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) { int levelW = de::max(1, m_width >> levelNdx); int levelH = de::max(1, m_height >> levelNdx); tcu::Surface reference; tcu::Surface result; if (levelW <= 2 || levelH <= 2) continue; // Don't bother checking. // Render with GLES2 setContext(&gles2Context); renderTex2D(result, levelW, levelH); // Render reference. setContext(&refContext); renderTex2D(reference, levelW, levelH); { tcu::UVec4 threshold = computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat); bool isOk = tcu::intThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR); if (!isOk) { m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); break; } } } } void TextureSpecCase::verifyTexCube (sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext) { int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; DE_ASSERT(m_texType == TEXTURETYPE_CUBE); for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) { int levelW = de::max(1, m_width >> levelNdx); int levelH = de::max(1, m_height >> levelNdx); bool isOk = true; for (int face = 0; face < tcu::CUBEFACE_LAST; face++) { tcu::Surface reference; tcu::Surface result; if (levelW <= 2 || levelH <= 2) continue; // Don't bother checking. // Render with GLES2 setContext(&gles2Context); renderTexCube(result, levelW, levelH, (tcu::CubeFace)face); // Render reference. setContext(&refContext); renderTexCube(reference, levelW, levelH, (tcu::CubeFace)face); const float threshold = 0.02f; isOk = tcu::fuzzyCompare(m_testCtx.getLog(), "Result", (string("Image comparison result: ") + de::toString((tcu::CubeFace)face)).c_str(), reference, result, threshold, levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR); if (!isOk) { m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); break; } } if (!isOk) break; } } void TextureSpecCase::renderTex2D (tcu::Surface& dst, int width, int height) { int targetW = getWidth(); int targetH = getHeight(); float w = (float)width / (float)targetW; float h = (float)height / (float)targetH; deUint32 shaderID = getCurrentContext()->createProgram(&m_tex2DShader); m_tex2DShader.setUniforms(*getCurrentContext(), shaderID); sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(-1.0f + w*2.0f, -1.0f + h*2.0f, 0.0f)); // Read pixels back. readPixels(dst, 0, 0, width, height); } void TextureSpecCase::renderTexCube (tcu::Surface& dst, int width, int height, tcu::CubeFace face) { int targetW = getWidth(); int targetH = getHeight(); float w = (float)width / (float)targetW; float h = (float)height / (float)targetH; TexCubeShader* shaders[] = { &m_texCubeNegXShader, &m_texCubePosXShader, &m_texCubeNegYShader, &m_texCubePosYShader, &m_texCubeNegZShader, &m_texCubePosZShader }; deUint32 shaderID = getCurrentContext()->createProgram(shaders[face]); shaders[face]->setUniforms(*getCurrentContext(), shaderID); sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(-1.0f + w*2.0f, -1.0f + h*2.0f, 0.0f)); // Read pixels back. readPixels(dst, 0, 0, width, height); } void TextureSpecCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height) { dst.setSize(width, height); glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr()); } // Basic TexImage2D() with 2D texture usage class BasicTexImage2DCase : public TextureSpecCase { public: BasicTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel levelData (fmt); de::Random rnd (deStringHash(getName())); if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); levelData.setSize(levelW, levelH); tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax); glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr()); } } deUint32 m_format; deUint32 m_dataType; }; // Basic TexImage2D() with cubemap usage class BasicTexImageCubeCase : public TextureSpecCase { public: BasicTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel levelData (fmt); de::Random rnd (deStringHash(getName())); DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2. if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); levelData.setSize(levelW, levelH); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) { Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax); glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr()); } } } deUint32 m_format; deUint32 m_dataType; }; // Randomized 2D texture specification using TexImage2D class RandomOrderTexImage2DCase : public TextureSpecCase { public: RandomOrderTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel levelData (fmt); de::Random rnd (deStringHash(getName())); if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); vector levels (numLevels); for (int i = 0; i < numLevels; i++) levels[i] = i; rnd.shuffle(levels.begin(), levels.end()); for (int ndx = 0; ndx < numLevels; ndx++) { int levelNdx = levels[ndx]; int levelW = de::max(1, m_width >> levelNdx); int levelH = de::max(1, m_height >> levelNdx); Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); levelData.setSize(levelW, levelH); tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax); glTexImage2D(GL_TEXTURE_2D, levelNdx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr()); } } deUint32 m_format; deUint32 m_dataType; }; // Randomized cubemap texture specification using TexImage2D class RandomOrderTexImageCubeCase : public TextureSpecCase { public: RandomOrderTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel levelData (fmt); de::Random rnd (deStringHash(getName())); DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2. if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Level-face pairs. vector > images (numLevels*6); for (int ndx = 0; ndx < numLevels; ndx++) for (int face = 0; face < tcu::CUBEFACE_LAST; face++) images[ndx*6 + face] = std::make_pair(ndx, (tcu::CubeFace)face); rnd.shuffle(images.begin(), images.end()); for (int ndx = 0; ndx < (int)images.size(); ndx++) { int levelNdx = images[ndx].first; tcu::CubeFace face = images[ndx].second; int levelW = de::max(1, m_width >> levelNdx); int levelH = de::max(1, m_height >> levelNdx); Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); levelData.setSize(levelW, levelH); tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax); glTexImage2D(s_cubeMapFaces[face], levelNdx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr()); } } deUint32 m_format; deUint32 m_dataType; }; static inline int getRowPitch (const tcu::TextureFormat& transferFmt, int rowLen, int alignment) { int basePitch = transferFmt.getPixelSize()*rowLen; return alignment*(basePitch/alignment + ((basePitch % alignment) ? 1 : 0)); } // TexImage2D() unpack alignment case. class TexImage2DAlignCase : public TextureSpecCase { public: TexImage2DAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height, int alignment) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) , m_alignment (alignment) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; vector data; if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); Vec4 colorA (1.0f, 0.0f, 0.0f, 1.0f); Vec4 colorB (0.0f, 1.0f, 0.0f, 1.0f); int rowPitch = getRowPitch(fmt, levelW, m_alignment); int cellSize = de::max(1, de::min(levelW >> 2, levelH >> 2)); data.resize(rowPitch*levelH); tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize, colorA, colorB); glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, &data[0]); } } deUint32 m_format; deUint32 m_dataType; int m_alignment; }; // TexImage2D() unpack alignment case. class TexImageCubeAlignCase : public TextureSpecCase { public: TexImageCubeAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height, int alignment) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) , m_alignment (alignment) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; vector data; DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2. if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); int rowPitch = getRowPitch(fmt, levelW, m_alignment); Vec4 colorA (1.0f, 0.0f, 0.0f, 1.0f); Vec4 colorB (0.0f, 1.0f, 0.0f, 1.0f); int cellSize = de::max(1, de::min(levelW >> 2, levelH >> 2)); data.resize(rowPitch*levelH); tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize, colorA, colorB); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, &data[0]); } } deUint32 m_format; deUint32 m_dataType; int m_alignment; }; // Basic TexSubImage2D() with 2D texture usage class BasicTexSubImage2DCase : public TextureSpecCase { public: BasicTexSubImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel data (fmt); de::Random rnd (deStringHash(getName())); if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // First specify full texture. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); data.setSize(levelW, levelH); tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax); glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr()); } // Re-specify parts of each level. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); int w = rnd.getInt(1, levelW); int h = rnd.getInt(1, levelH); int x = rnd.getInt(0, levelW-w); int y = rnd.getInt(0, levelH-h); Vec4 colorA = randomVector<4>(rnd); Vec4 colorB = randomVector<4>(rnd); int cellSize = rnd.getInt(2, 16); data.setSize(w, h); tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB); glTexSubImage2D(GL_TEXTURE_2D, ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr()); } } deUint32 m_format; deUint32 m_dataType; }; // Basic TexSubImage2D() with cubemap usage class BasicTexSubImageCubeCase : public TextureSpecCase { public: BasicTexSubImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel data (fmt); de::Random rnd (deStringHash(getName())); DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2. if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); data.setSize(levelW, levelH); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) { Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax); glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr()); } } // Re-specify parts of each face and level. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) { int w = rnd.getInt(1, levelW); int h = rnd.getInt(1, levelH); int x = rnd.getInt(0, levelW-w); int y = rnd.getInt(0, levelH-h); Vec4 colorA = randomVector<4>(rnd); Vec4 colorB = randomVector<4>(rnd); int cellSize = rnd.getInt(2, 16); data.setSize(w, h); tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB); glTexSubImage2D(s_cubeMapFaces[face], ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr()); } } } deUint32 m_format; deUint32 m_dataType; }; // TexSubImage2D() to texture initialized with empty data class TexSubImage2DEmptyTexCase : public TextureSpecCase { public: TexSubImage2DEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel data (fmt); de::Random rnd (deStringHash(getName())); if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // First allocate storage for each level. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, DE_NULL); } // Specify pixel data to all levels using glTexSubImage2D() for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); data.setSize(levelW, levelH); tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax); glTexSubImage2D(GL_TEXTURE_2D, ndx, 0, 0, levelW, levelH, m_format, m_dataType, data.getAccess().getDataPtr()); } } deUint32 m_format; deUint32 m_dataType; }; // TexSubImage2D() to empty cubemap texture class TexSubImageCubeEmptyTexCase : public TextureSpecCase { public: TexSubImageCubeEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel data (fmt); de::Random rnd (deStringHash(getName())); DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2. if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Specify storage for each level. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, DE_NULL); } // Specify data using glTexSubImage2D() for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); data.setSize(levelW, levelH); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) { Vec4 gMin = randomVector<4>(rnd); Vec4 gMax = randomVector<4>(rnd); tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax); glTexSubImage2D(s_cubeMapFaces[face], ndx, 0, 0, levelW, levelH, m_format, m_dataType, data.getAccess().getDataPtr()); } } } deUint32 m_format; deUint32 m_dataType; }; // TexSubImage2D() unpack alignment with 2D texture class TexSubImage2DAlignCase : public TextureSpecCase { public: TexSubImage2DAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height, int subX, int subY, int subW, int subH, int alignment) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), 0 /* Mipmaps are never used */, width, height) , m_format (format) , m_dataType (dataType) , m_subX (subX) , m_subY (subY) , m_subW (subW) , m_subH (subH) , m_alignment (alignment) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; deUint32 tex = 0; vector data; if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); // Specify base level. data.resize(fmt.getPixelSize()*m_width*m_height); tcu::fillWithComponentGradients(tcu::PixelBufferAccess(fmt, m_width, m_height, 1, &data[0]), Vec4(0.0f), Vec4(1.0f)); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, m_format, m_dataType, &data[0]); // Re-specify subrectangle. int rowPitch = getRowPitch(fmt, m_subW, m_alignment); data.resize(rowPitch*m_subH); tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4, Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f)); glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment); glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]); } deUint32 m_format; deUint32 m_dataType; int m_subX; int m_subY; int m_subW; int m_subH; int m_alignment; }; // TexSubImage2D() unpack alignment with cubemap texture class TexSubImageCubeAlignCase : public TextureSpecCase { public: TexSubImageCubeAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height, int subX, int subY, int subW, int subH, int alignment) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), 0 /* Mipmaps are never used */, width, height) , m_format (format) , m_dataType (dataType) , m_subX (subX) , m_subY (subY) , m_subW (subW) , m_subH (subH) , m_alignment (alignment) { } protected: void createTexture (void) { tcu::TextureFormat fmt = m_texFormat; deUint32 tex = 0; vector data; DE_ASSERT(m_width == m_height); if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); // Specify base level. data.resize(fmt.getPixelSize()*m_width*m_height); tcu::fillWithComponentGradients(tcu::PixelBufferAccess(fmt, m_width, m_height, 1, &data[0]), Vec4(0.0f), Vec4(1.0f)); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for (int face = 0; face < tcu::CUBEFACE_LAST; face++) glTexImage2D(s_cubeMapFaces[face], 0, m_format, m_width, m_height, 0, m_format, m_dataType, &data[0]); // Re-specify subrectangle. int rowPitch = getRowPitch(fmt, m_subW, m_alignment); data.resize(rowPitch*m_subH); tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4, Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f)); glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment); for (int face = 0; face < tcu::CUBEFACE_LAST; face++) glTexSubImage2D(s_cubeMapFaces[face], 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]); } deUint32 m_format; deUint32 m_dataType; int m_subX; int m_subY; int m_subW; int m_subH; int m_alignment; }; // Basic CopyTexImage2D() with 2D texture usage class BasicCopyTexImage2DCase : public TextureSpecCase { public: BasicCopyTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, mapGLUnsizedInternalFormat(internalFormat), flags, width, height) , m_internalFormat (internalFormat) { } protected: void createTexture (void) { const tcu::RenderTarget& renderTarget = TestCase::m_context.getRenderContext().getRenderTarget(); bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0; bool targetHasAlpha = renderTarget.getPixelFormat().alphaBits > 0; tcu::TextureFormat fmt = m_texFormat; bool texHasRGB = fmt.order != tcu::TextureFormat::A; bool texHasAlpha = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; de::Random rnd (deStringHash(getName())); GradientShader shader; deUint32 shaderID = getCurrentContext()->createProgram(&shader); if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha)) throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__); // Fill render target with gradient. sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f)); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); int x = rnd.getInt(0, getWidth() - levelW); int y = rnd.getInt(0, getHeight() - levelH); glCopyTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, x, y, levelW, levelH, 0); } } deUint32 m_internalFormat; }; // Basic CopyTexImage2D() with cubemap usage class BasicCopyTexImageCubeCase : public TextureSpecCase { public: BasicCopyTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, mapGLUnsizedInternalFormat(internalFormat), flags, width, height) , m_internalFormat (internalFormat) { } protected: void createTexture (void) { const tcu::RenderTarget& renderTarget = TestCase::m_context.getRenderContext().getRenderTarget(); bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0; bool targetHasAlpha = renderTarget.getPixelFormat().alphaBits > 0; tcu::TextureFormat fmt = m_texFormat; bool texHasRGB = fmt.order != tcu::TextureFormat::A; bool texHasAlpha = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A; int numLevels = (m_flags & MIPMAPS) ? deLog2Floor32(m_width)+1 : 1; deUint32 tex = 0; de::Random rnd (deStringHash(getName())); GradientShader shader; deUint32 shaderID = getCurrentContext()->createProgram(&shader); DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2. if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha)) throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__); // Fill render target with gradient. sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f)); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) { int x = rnd.getInt(0, getWidth() - levelW); int y = rnd.getInt(0, getHeight() - levelH); glCopyTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, x, y, levelW, levelH, 0); } } } deUint32 m_internalFormat; }; // Basic CopyTexSubImage2D() with 2D texture usage class BasicCopyTexSubImage2DCase : public TextureSpecCase { public: BasicCopyTexSubImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { const tcu::RenderTarget& renderTarget = TestCase::m_context.getRenderContext().getRenderTarget(); bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0; bool targetHasAlpha = renderTarget.getPixelFormat().alphaBits > 0; tcu::TextureFormat fmt = m_texFormat; bool texHasRGB = fmt.order != tcu::TextureFormat::A; bool texHasAlpha = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel data (fmt); de::Random rnd (deStringHash(getName())); GradientShader shader; deUint32 shaderID = getCurrentContext()->createProgram(&shader); if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha)) throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__); if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // First specify full texture. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); Vec4 colorA = randomVector<4>(rnd); Vec4 colorB = randomVector<4>(rnd); int cellSize = rnd.getInt(2, 16); data.setSize(levelW, levelH); tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB); glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr()); } // Fill render target with gradient. sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f)); // Re-specify parts of each level. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); int w = rnd.getInt(1, levelW); int h = rnd.getInt(1, levelH); int xo = rnd.getInt(0, levelW-w); int yo = rnd.getInt(0, levelH-h); int x = rnd.getInt(0, getWidth() - w); int y = rnd.getInt(0, getHeight() - h); glCopyTexSubImage2D(GL_TEXTURE_2D, ndx, xo, yo, x, y, w, h); } } deUint32 m_format; deUint32 m_dataType; }; // Basic CopyTexSubImage2D() with cubemap usage class BasicCopyTexSubImageCubeCase : public TextureSpecCase { public: BasicCopyTexSubImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height) : TextureSpecCase (context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height) , m_format (format) , m_dataType (dataType) { } protected: void createTexture (void) { const tcu::RenderTarget& renderTarget = TestCase::m_context.getRenderContext().getRenderTarget(); bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0; bool targetHasAlpha = renderTarget.getPixelFormat().alphaBits > 0; tcu::TextureFormat fmt = m_texFormat; bool texHasRGB = fmt.order != tcu::TextureFormat::A; bool texHasAlpha = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A; int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1; deUint32 tex = 0; tcu::TextureLevel data (fmt); de::Random rnd (deStringHash(getName())); GradientShader shader; deUint32 shaderID = getCurrentContext()->createProgram(&shader); DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2. if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha)) throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__); if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes) throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_CUBE_MAP, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); data.setSize(levelW, levelH); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) { Vec4 colorA = randomVector<4>(rnd); Vec4 colorB = randomVector<4>(rnd); int cellSize = rnd.getInt(2, 16); tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB); glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr()); } } // Fill render target with gradient. sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f)); // Re-specify parts of each face and level. for (int ndx = 0; ndx < numLevels; ndx++) { int levelW = de::max(1, m_width >> ndx); int levelH = de::max(1, m_height >> ndx); for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++) { int w = rnd.getInt(1, levelW); int h = rnd.getInt(1, levelH); int xo = rnd.getInt(0, levelW-w); int yo = rnd.getInt(0, levelH-h); int x = rnd.getInt(0, getWidth() - w); int y = rnd.getInt(0, getHeight() - h); glCopyTexSubImage2D(s_cubeMapFaces[face], ndx, xo, yo, x, y, w, h); } } } deUint32 m_format; deUint32 m_dataType; }; TextureSpecificationTests::TextureSpecificationTests (Context& context) : TestCaseGroup(context, "specification", "Texture Specification Tests") { } TextureSpecificationTests::~TextureSpecificationTests (void) { } void TextureSpecificationTests::init (void) { struct { const char* name; deUint32 format; deUint32 dataType; } texFormats[] = { { "a8", GL_ALPHA, GL_UNSIGNED_BYTE }, { "l8", GL_LUMINANCE, GL_UNSIGNED_BYTE }, { "la88", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE }, { "rgb565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, { "rgb888", GL_RGB, GL_UNSIGNED_BYTE }, { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, { "rgba5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE }, { "rgba16f", GL_RGBA, GL_HALF_FLOAT_OES }, { "rgb16f", GL_RGB, GL_HALF_FLOAT_OES }, { "la16f", GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES }, { "l16f", GL_LUMINANCE, GL_HALF_FLOAT_OES }, { "a16f", GL_ALPHA, GL_HALF_FLOAT_OES } }; // Basic TexImage2D usage. { tcu::TestCaseGroup* basicTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_teximage2d", "Basic glTexImage2D() usage"); addChild(basicTexImageGroup); for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++) { const char* fmtName = texFormats[formatNdx].name; deUint32 format = texFormats[formatNdx].format; deUint32 dataType = texFormats[formatNdx].dataType; const int tex2DWidth = 64; const int tex2DHeight = 128; const int texCubeSize = 64; basicTexImageGroup->addChild(new BasicTexImage2DCase (m_context, (string(fmtName) + "_2d").c_str(), "", format, dataType, MIPMAPS, tex2DWidth, tex2DHeight)); basicTexImageGroup->addChild(new BasicTexImageCubeCase (m_context, (string(fmtName) + "_cube").c_str(), "", format, dataType, MIPMAPS, texCubeSize, texCubeSize)); } } // Randomized TexImage2D order. { tcu::TestCaseGroup* randomTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "random_teximage2d", "Randomized glTexImage2D() usage"); addChild(randomTexImageGroup); de::Random rnd(9); // 2D cases. for (int ndx = 0; ndx < 10; ndx++) { int formatNdx = rnd.getInt(0, DE_LENGTH_OF_ARRAY(texFormats)-1); int width = 1 << rnd.getInt(2, 8); int height = 1 << rnd.getInt(2, 8); randomTexImageGroup->addChild(new RandomOrderTexImage2DCase(m_context, (string("2d_") + de::toString(ndx)).c_str(), "", texFormats[formatNdx].format, texFormats[formatNdx].dataType, MIPMAPS, width, height)); } // Cubemap cases. for (int ndx = 0; ndx < 10; ndx++) { int formatNdx = rnd.getInt(0, DE_LENGTH_OF_ARRAY(texFormats)-1); int size = 1 << rnd.getInt(2, 8); randomTexImageGroup->addChild(new RandomOrderTexImageCubeCase(m_context, (string("cube_") + de::toString(ndx)).c_str(), "", texFormats[formatNdx].format, texFormats[formatNdx].dataType, MIPMAPS, size, size)); } } // TexImage2D unpack alignment. { tcu::TestCaseGroup* alignGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_align", "glTexImage2D() unpack alignment tests"); addChild(alignGroup); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_l8_4_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, MIPMAPS, 4, 8, 8)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 1)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 2)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 4)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 8)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba4444_51_1", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 1)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba4444_51_2", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 2)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba4444_51_4", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 4)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba4444_51_8", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 8)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 1)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 2)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 4)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 8)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba8888_47_1", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 1)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba8888_47_2", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 2)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba8888_47_4", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 4)); alignGroup->addChild(new TexImage2DAlignCase (m_context, "2d_rgba8888_47_8", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 8)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_l8_4_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, MIPMAPS, 4, 4, 8)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 1)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 2)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 4)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 8)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba4444_51_1", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 1)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba4444_51_2", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 2)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba4444_51_4", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 4)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba4444_51_8", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 8)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 1)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 2)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 4)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 8)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba8888_47_1", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 1)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba8888_47_2", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 2)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba8888_47_4", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 4)); alignGroup->addChild(new TexImageCubeAlignCase (m_context, "cube_rgba8888_47_8", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 8)); } // Basic TexSubImage2D usage. { tcu::TestCaseGroup* basicTexSubImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_texsubimage2d", "Basic glTexSubImage2D() usage"); addChild(basicTexSubImageGroup); for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++) { const char* fmtName = texFormats[formatNdx].name; deUint32 format = texFormats[formatNdx].format; deUint32 dataType = texFormats[formatNdx].dataType; const int tex2DWidth = 64; const int tex2DHeight = 128; const int texCubeSize = 64; basicTexSubImageGroup->addChild(new BasicTexSubImage2DCase (m_context, (string(fmtName) + "_2d").c_str(), "", format, dataType, MIPMAPS, tex2DWidth, tex2DHeight)); basicTexSubImageGroup->addChild(new BasicTexSubImageCubeCase (m_context, (string(fmtName) + "_cube").c_str(), "", format, dataType, MIPMAPS, texCubeSize, texCubeSize)); } } // TexSubImage2D to empty texture. { tcu::TestCaseGroup* texSubImageEmptyTexGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_empty_tex", "glTexSubImage2D() to texture that has storage but no data"); addChild(texSubImageEmptyTexGroup); for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++) { const char* fmtName = texFormats[formatNdx].name; deUint32 format = texFormats[formatNdx].format; deUint32 dataType = texFormats[formatNdx].dataType; const int tex2DWidth = 64; const int tex2DHeight = 32; const int texCubeSize = 32; texSubImageEmptyTexGroup->addChild(new TexSubImage2DEmptyTexCase (m_context, (string(fmtName) + "_2d").c_str(), "", format, dataType, MIPMAPS, tex2DWidth, tex2DHeight)); texSubImageEmptyTexGroup->addChild(new TexSubImageCubeEmptyTexCase (m_context, (string(fmtName) + "_cube").c_str(), "", format, dataType, MIPMAPS, texCubeSize, texCubeSize)); } } // TexSubImage2D alignment cases. { tcu::TestCaseGroup* alignGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_align", "glTexSubImage2D() unpack alignment tests"); addChild(alignGroup); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_1_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 1)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_1_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 2)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_1_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 4)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_1_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 8)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 1)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 2)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 4)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 8)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba4444_51_1", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 1)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba4444_51_2", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 2)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba4444_51_4", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 4)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba4444_51_8", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 8)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 1)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 2)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 4)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 8)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba8888_47_1", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 1)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba8888_47_2", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 2)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba8888_47_4", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 4)); alignGroup->addChild(new TexSubImage2DAlignCase (m_context, "2d_rgba8888_47_8", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 8)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_1_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 1)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_1_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 2)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_1_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 4)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_1_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 13, 17, 1, 6, 8)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 1)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 2)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 4)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64, 64, 1, 9, 63, 30, 8)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba4444_51_1", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 1)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba4444_51_2", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 2)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba4444_51_4", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 4)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba4444_51_8", "", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 8)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 1)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 2)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 4)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE, 64, 64, 11, 8, 39, 43, 8)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba8888_47_1", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 1)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba8888_47_2", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 2)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba8888_47_4", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 4)); alignGroup->addChild(new TexSubImageCubeAlignCase (m_context, "cube_rgba8888_47_8", "", GL_RGBA, GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 8)); } // Basic glCopyTexImage2D() cases { tcu::TestCaseGroup* copyTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_copyteximage2d", "Basic glCopyTexImage2D() usage"); addChild(copyTexImageGroup); copyTexImageGroup->addChild(new BasicCopyTexImage2DCase (m_context, "2d_alpha", "", GL_ALPHA, MIPMAPS, 128, 64)); copyTexImageGroup->addChild(new BasicCopyTexImage2DCase (m_context, "2d_luminance", "", GL_LUMINANCE, MIPMAPS, 128, 64)); copyTexImageGroup->addChild(new BasicCopyTexImage2DCase (m_context, "2d_luminance_alpha", "", GL_LUMINANCE_ALPHA, MIPMAPS, 128, 64)); copyTexImageGroup->addChild(new BasicCopyTexImage2DCase (m_context, "2d_rgb", "", GL_RGB, MIPMAPS, 128, 64)); copyTexImageGroup->addChild(new BasicCopyTexImage2DCase (m_context, "2d_rgba", "", GL_RGBA, MIPMAPS, 128, 64)); copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase (m_context, "cube_alpha", "", GL_ALPHA, MIPMAPS, 64, 64)); copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase (m_context, "cube_luminance", "", GL_LUMINANCE, MIPMAPS, 64, 64)); copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase (m_context, "cube_luminance_alpha", "", GL_LUMINANCE_ALPHA, MIPMAPS, 64, 64)); copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase (m_context, "cube_rgb", "", GL_RGB, MIPMAPS, 64, 64)); copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase (m_context, "cube_rgba", "", GL_RGBA, MIPMAPS, 64, 64)); } // Basic glCopyTexSubImage2D() cases { tcu::TestCaseGroup* copyTexSubImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_copytexsubimage2d", "Basic glCopyTexSubImage2D() usage"); addChild(copyTexSubImageGroup); copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase (m_context, "2d_alpha", "", GL_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase (m_context, "2d_luminance", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase (m_context, "2d_luminance_alpha", "", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase (m_context, "2d_rgb", "", GL_RGB, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase (m_context, "2d_rgba", "", GL_RGBA, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase (m_context, "cube_alpha", "", GL_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase (m_context, "cube_luminance", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase (m_context, "cube_luminance_alpha", "", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase (m_context, "cube_rgb", "", GL_RGB, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64)); copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase (m_context, "cube_rgba", "", GL_RGBA, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64)); } } } // Functional } // gles2 } // deqp