/*-------------------------------------------------------------------------
* 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 <int Size>
static tcu::Vector<float, Size> randomVector (de::Random& rnd, const tcu::Vector<float, Size>& minVal = tcu::Vector<float, Size>(0.0f), const tcu::Vector<float, Size>& maxVal = tcu::Vector<float, Size>(1.0f))
{
tcu::Vector<float, Size> 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<float>(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<float>(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<float>(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<int> 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<pair<int, tcu::CubeFace> > 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<deUint8> 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<deUint8> 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<deUint8> 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<deUint8> 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