blob: 28e71c77eb35f52cbdd0535e2561f95e26a7f5dd [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.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 FBO colorbuffer tests.
*//*--------------------------------------------------------------------*/
#include "es3fFboColorbufferTests.hpp"
#include "es3fFboTestCase.hpp"
#include "es3fFboTestUtil.hpp"
#include "gluTextureUtil.hpp"
#include "gluContextInfo.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRGBA.hpp"
#include "tcuTestLog.hpp"
#include "tcuTextureUtil.hpp"
#include "sglrContextUtil.hpp"
#include "deRandom.hpp"
#include "deString.h"
#include "glwEnums.hpp"
namespace deqp
{
namespace gles3
{
namespace Functional
{
using std::string;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec3;
using tcu::IVec4;
using tcu::UVec4;
using tcu::TestLog;
using namespace FboTestUtil;
const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
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::Vec4 generateRandomColor (de::Random& random)
{
tcu::Vec4 retVal;
for (int i = 0; i < 3; ++i)
retVal[i] = random.getFloat();
retVal[3] = 1.0f;
return retVal;
}
class FboColorbufferCase : public FboTestCase
{
public:
FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format)
: FboTestCase (context, name, desc)
, m_format (format)
{
}
bool compare (const tcu::Surface& reference, const tcu::Surface& result)
{
const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
}
protected:
const deUint32 m_format;
};
class FboColorClearCase : public FboColorbufferCase
{
public:
FboColorClearCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height)
: FboColorbufferCase (context, name, desc, format)
, m_width (width)
, m_height (height)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(fboFormat.type);
tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
de::Random rnd (17);
const int numClears = 16;
deUint32 fbo = 0;
deUint32 rbo = 0;
glGenFramebuffers(1, &fbo);
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height);
checkError();
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
glViewport(0, 0, m_width, m_height);
// Initialize to transparent black.
switch (fmtClass)
{
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
break;
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
glClearBufferuiv(GL_COLOR, 0, UVec4(0).getPtr());
break;
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
glClearBufferiv(GL_COLOR, 0, IVec4(0).getPtr());
break;
default:
DE_ASSERT(DE_FALSE);
}
// Do random scissored clears.
glEnable(GL_SCISSOR_TEST);
for (int ndx = 0; ndx < numClears; ndx++)
{
int x = rnd.getInt(0, m_width - 1);
int y = rnd.getInt(0, m_height - 1);
int w = rnd.getInt(1, m_width - x);
int h = rnd.getInt(1, m_height - y);
Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
glScissor(x, y, w, h);
switch (fmtClass)
{
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
glClearBufferfv(GL_COLOR, 0, color.getPtr());
break;
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
glClearBufferuiv(GL_COLOR, 0, color.cast<deUint32>().getPtr());
break;
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
glClearBufferiv(GL_COLOR, 0, color.cast<int>().getPtr());
break;
default:
DE_ASSERT(DE_FALSE);
}
}
// Read results from renderbuffer.
readPixels(dst, 0, 0, m_width, m_height, fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
checkError();
}
private:
const int m_width;
const int m_height;
};
class FboColorMultiTex2DCase : public FboColorbufferCase
{
public:
FboColorMultiTex2DCase (Context& context, const char* name, const char* description, deUint32 tex0Fmt, const IVec2& tex0Size, deUint32 tex1Fmt, const IVec2& tex1Size)
: FboColorbufferCase (context, name, description, tex0Fmt)
, m_tex0Fmt (tex0Fmt)
, m_tex1Fmt (tex1Fmt)
, m_tex0Size (tex0Size)
, m_tex1Size (tex1Size)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_tex0Fmt);
checkFormatSupport(m_tex1Fmt);
}
void render (tcu::Surface& dst)
{
tcu::TextureFormat texFmt0 = glu::mapGLInternalFormat(m_tex0Fmt);
tcu::TextureFormat texFmt1 = glu::mapGLInternalFormat(m_tex1Fmt);
tcu::TextureFormatInfo fmtInfo0 = tcu::getTextureFormatInfo(texFmt0);
tcu::TextureFormatInfo fmtInfo1 = tcu::getTextureFormatInfo(texFmt1);
Texture2DShader texToFbo0Shader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt0), fmtInfo0.valueMax-fmtInfo0.valueMin, fmtInfo0.valueMin);
Texture2DShader texToFbo1Shader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt1), fmtInfo1.valueMax-fmtInfo1.valueMin, fmtInfo1.valueMin);
Texture2DShader multiTexShader (DataTypes() << glu::getSampler2DType(texFmt0) << glu::getSampler2DType(texFmt1), glu::TYPE_FLOAT_VEC4);
deUint32 texToFbo0ShaderID = getCurrentContext()->createProgram(&texToFbo0Shader);
deUint32 texToFbo1ShaderID = getCurrentContext()->createProgram(&texToFbo1Shader);
deUint32 multiTexShaderID = getCurrentContext()->createProgram(&multiTexShader);
// Setup shaders
multiTexShader.setTexScaleBias(0, fmtInfo0.lookupScale * 0.5f, fmtInfo0.lookupBias * 0.5f);
multiTexShader.setTexScaleBias(1, fmtInfo1.lookupScale * 0.5f, fmtInfo1.lookupBias * 0.5f);
texToFbo0Shader.setUniforms(*getCurrentContext(), texToFbo0ShaderID);
texToFbo1Shader.setUniforms(*getCurrentContext(), texToFbo1ShaderID);
multiTexShader.setUniforms (*getCurrentContext(), multiTexShaderID);
// Framebuffers.
deUint32 fbo0, fbo1;
deUint32 tex0, tex1;
for (int ndx = 0; ndx < 2; ndx++)
{
glu::TransferFormat transferFmt = glu::getTransferFormat(ndx ? texFmt1 : texFmt0);
deUint32 format = ndx ? m_tex1Fmt : m_tex0Fmt;
bool isFilterable = glu::isGLInternalColorFormatFilterable(format);
const IVec2& size = ndx ? m_tex1Size : m_tex0Size;
deUint32& fbo = ndx ? fbo1 : fbo0;
deUint32& tex = ndx ? tex1 : tex0;
glGenFramebuffers(1, &fbo);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
}
// Render textures to both framebuffers.
for (int ndx = 0; ndx < 2; ndx++)
{
const deUint32 format = GL_RGBA;
const deUint32 dataType = GL_UNSIGNED_BYTE;
const int texW = 128;
const int texH = 128;
deUint32 tmpTex = 0;
deUint32 fbo = ndx ? fbo1 : fbo0;
const IVec2& viewport = ndx ? m_tex1Size : m_tex0Size;
tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
if (ndx == 0)
tcu::fillWithComponentGradients(data.getAccess(), Vec4(0.0f), Vec4(1.0f));
else
tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
glGenTextures(1, &tmpTex);
glBindTexture(GL_TEXTURE_2D, tmpTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, viewport.x(), viewport.y());
sglr::drawQuad(*getCurrentContext(), ndx ? texToFbo1ShaderID : texToFbo0ShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
}
// Render to framebuffer.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, getWidth(), getHeight());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tex1);
sglr::drawQuad(*getCurrentContext(), multiTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
readPixels(dst, 0, 0, getWidth(), getHeight());
}
private:
deUint32 m_tex0Fmt;
deUint32 m_tex1Fmt;
IVec2 m_tex0Size;
IVec2 m_tex1Size;
};
class FboColorTexCubeCase : public FboColorbufferCase
{
public:
FboColorTexCubeCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec2& texSize)
: FboColorbufferCase (context, name, description, texFmt)
, m_texSize (texSize)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
static const deUint32 cubeGLFaces[] =
{
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};
static const tcu::CubeFace cubeTexFaces[] =
{
tcu::CUBEFACE_POSITIVE_X,
tcu::CUBEFACE_POSITIVE_Y,
tcu::CUBEFACE_POSITIVE_Z,
tcu::CUBEFACE_NEGATIVE_X,
tcu::CUBEFACE_NEGATIVE_Y,
tcu::CUBEFACE_NEGATIVE_Z
};
de::Random rnd (deStringHash(getName()) ^ 0x9eef603d);
tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format);
tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
TextureCubeShader cubeTexShader (glu::getSamplerCubeType(texFmt), glu::TYPE_FLOAT_VEC4);
deUint32 texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
deUint32 cubeTexShaderID = getCurrentContext()->createProgram(&cubeTexShader);
// Setup shaders
texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
cubeTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
// Framebuffers.
std::vector<deUint32> fbos;
deUint32 tex;
{
glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
bool isFilterable = glu::isGLInternalColorFormatFilterable(m_format);
const IVec2& size = m_texSize;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
// Generate an image and FBO for each cube face
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
glTexImage2D(cubeGLFaces[ndx], 0, m_format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
checkError();
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
{
deUint32 layerFbo;
glGenFramebuffers(1, &layerFbo);
glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeGLFaces[ndx], tex, 0);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
fbos.push_back(layerFbo);
}
}
// Render test images to random cube faces
std::vector<int> order;
for (size_t n = 0; n < fbos.size(); n++)
order.push_back((int)n);
rnd.shuffle(order.begin(), order.end());
DE_ASSERT(order.size() >= 4);
for (int ndx = 0; ndx < 4; ndx++)
{
const int face = order[ndx];
const deUint32 format = GL_RGBA;
const deUint32 dataType = GL_UNSIGNED_BYTE;
const int texW = 128;
const int texH = 128;
deUint32 tmpTex = 0;
const deUint32 fbo = fbos[face];
const IVec2& viewport = m_texSize;
tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
glGenTextures(1, &tmpTex);
glBindTexture(GL_TEXTURE_2D, tmpTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, viewport.x(), viewport.y());
sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
checkError();
// Render to framebuffer
{
const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, getWidth(), getHeight());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
cubeTexShader.setFace(cubeTexFaces[face]);
cubeTexShader.setUniforms(*getCurrentContext(), cubeTexShaderID);
sglr::drawQuad(*getCurrentContext(), cubeTexShaderID, p0, p1);
checkError();
}
}
readPixels(dst, 0, 0, getWidth(), getHeight());
}
private:
IVec2 m_texSize;
};
class FboColorTex2DArrayCase : public FboColorbufferCase
{
public:
FboColorTex2DArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
: FboColorbufferCase (context, name, description, texFmt)
, m_texSize (texSize)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
de::Random rnd (deStringHash(getName()) ^ 0xed607a89);
tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format);
tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
Texture2DArrayShader arrayTexShader (glu::getSampler2DArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
deUint32 texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
deUint32 arrayTexShaderID = getCurrentContext()->createProgram(&arrayTexShader);
// Setup textures
texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
// Framebuffers.
std::vector<deUint32> fbos;
deUint32 tex;
{
glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
bool isFilterable = glu::isGLInternalColorFormatFilterable(m_format);
const IVec3& size = m_texSize;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
// Generate an FBO for each layer
for (int ndx = 0; ndx < m_texSize.z(); ndx++)
{
deUint32 layerFbo;
glGenFramebuffers(1, &layerFbo);
glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
fbos.push_back(layerFbo);
}
}
// Render test images to random texture layers
std::vector<int> order;
for (size_t n = 0; n < fbos.size(); n++)
order.push_back((int)n);
rnd.shuffle(order.begin(), order.end());
for (size_t ndx = 0; ndx < order.size(); ndx++)
{
const int layer = order[ndx];
const deUint32 format = GL_RGBA;
const deUint32 dataType = GL_UNSIGNED_BYTE;
const int texW = 128;
const int texH = 128;
deUint32 tmpTex = 0;
const deUint32 fbo = fbos[layer];
const IVec3& viewport = m_texSize;
tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
glGenTextures(1, &tmpTex);
glBindTexture(GL_TEXTURE_2D, tmpTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, viewport.x(), viewport.y());
sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
checkError();
// Render to framebuffer
{
const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, getWidth(), getHeight());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
arrayTexShader.setLayer(layer);
arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
checkError();
}
}
readPixels(dst, 0, 0, getWidth(), getHeight());
}
private:
IVec3 m_texSize;
};
class FboColorTex3DCase : public FboColorbufferCase
{
public:
FboColorTex3DCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
: FboColorbufferCase (context, name, description, texFmt)
, m_texSize (texSize)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
de::Random rnd (deStringHash(getName()) ^ 0x74d947b2);
tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format);
tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
Texture3DShader tdTexShader (glu::getSampler3DType(texFmt), glu::TYPE_FLOAT_VEC4);
deUint32 texToFboShaderID= getCurrentContext()->createProgram(&texToFboShader);
deUint32 tdTexShaderID = getCurrentContext()->createProgram(&tdTexShader);
// Setup shaders
texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
tdTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
// Framebuffers.
std::vector<deUint32> fbos;
deUint32 tex;
{
glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
const IVec3& size = m_texSize;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_3D, tex);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage3D(GL_TEXTURE_3D, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
// Generate an FBO for each layer
for (int ndx = 0; ndx < m_texSize.z(); ndx++)
{
deUint32 layerFbo;
glGenFramebuffers(1, &layerFbo);
glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
fbos.push_back(layerFbo);
}
}
// Render test images to random texture layers
std::vector<int> order;
for (size_t n = 0; n < fbos.size(); n++)
order.push_back((int)n);
rnd.shuffle(order.begin(), order.end());
for (size_t ndx = 0; ndx < order.size(); ndx++)
{
const int layer = order[ndx];
const deUint32 format = GL_RGBA;
const deUint32 dataType = GL_UNSIGNED_BYTE;
const int texW = 128;
const int texH = 128;
deUint32 tmpTex = 0;
const deUint32 fbo = fbos[layer];
const IVec3& viewport = m_texSize;
tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
glGenTextures(1, &tmpTex);
glBindTexture(GL_TEXTURE_2D, tmpTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, viewport.x(), viewport.y());
sglr::drawQuad(*getCurrentContext() , texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
checkError();
// Render to framebuffer
{
const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, getWidth(), getHeight());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, tex);
tdTexShader.setDepth(float(layer) / float(m_texSize.z()-1));
tdTexShader.setUniforms(*getCurrentContext(), tdTexShaderID);
sglr::drawQuad(*getCurrentContext(), tdTexShaderID, p0, p1);
checkError();
}
}
readPixels(dst, 0, 0, getWidth(), getHeight());
}
private:
IVec3 m_texSize;
};
class FboBlendCase : public FboColorbufferCase
{
public:
FboBlendCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, deUint32 funcRGB, deUint32 funcAlpha, deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
: FboColorbufferCase (context, name, desc, format)
, m_size (size)
, m_funcRGB (funcRGB)
, m_funcAlpha (funcAlpha)
, m_srcRGB (srcRGB)
, m_dstRGB (dstRGB)
, m_srcAlpha (srcAlpha)
, m_dstAlpha (dstAlpha)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
// \note Assumes floating-point or fixed-point format.
tcu::TextureFormat fboFmt = glu::mapGLInternalFormat(m_format);
Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
GradientShader gradShader (glu::TYPE_FLOAT_VEC4);
deUint32 texShaderID = getCurrentContext()->createProgram(&texShader);
deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader);
deUint32 fbo = 0;
deUint32 rbo = 0;
// Setup shaders
texShader.setUniforms (*getCurrentContext(), texShaderID);
gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
glGenFramebuffers(1, &fbo);
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y());
checkError();
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
glViewport(0, 0, m_size.x(), m_size.y());
// Fill framebuffer with grid pattern.
{
const deUint32 format = GL_RGBA;
const deUint32 dataType = GL_UNSIGNED_BYTE;
const int texW = 128;
const int texH = 128;
deUint32 gridTex = 0;
tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
glGenTextures(1, &gridTex);
glBindTexture(GL_TEXTURE_2D, gridTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
}
// Setup blend.
glEnable(GL_BLEND);
glBlendEquationSeparate(m_funcRGB, m_funcAlpha);
glBlendFuncSeparate(m_srcRGB, m_dstRGB, m_srcAlpha, m_dstAlpha);
// Render gradient with blend.
sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
readPixels(dst, 0, 0, m_size.x(), m_size.y(), fboFmt, Vec4(1.0f), Vec4(0.0f));
}
private:
IVec2 m_size;
deUint32 m_funcRGB;
deUint32 m_funcAlpha;
deUint32 m_srcRGB;
deUint32 m_dstRGB;
deUint32 m_srcAlpha;
deUint32 m_dstAlpha;
};
class FboRepeatedClearSampleTex2DCase : public FboColorbufferCase
{
public:
FboRepeatedClearSampleTex2DCase (Context& context, const char* name, const char* desc, deUint32 format)
: FboColorbufferCase(context, name, desc, format)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
const int numRowsCols = 4;
const int cellSize = 16;
const int fboSizes[] = { cellSize, cellSize*numRowsCols };
Texture2DShader fboBlitShader (DataTypes() << glu::getSampler2DType(fboFormat), getFragmentOutputType(fboFormat), Vec4(1.0f), Vec4(0.0f));
const deUint32 fboBlitShaderID = getCurrentContext()->createProgram(&fboBlitShader);
de::Random rnd (18169662);
deUint32 fbos[] = { 0, 0 };
deUint32 textures[] = { 0, 0 };
glGenFramebuffers(2, &fbos[0]);
glGenTextures(2, &textures[0]);
for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
{
glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
checkError();
glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
}
// larger fbo bound -- clear to transparent black
clearColorBuffer(fboFormat, Vec4(0.0f));
fboBlitShader.setUniforms(*getCurrentContext(), fboBlitShaderID);
glBindTexture(GL_TEXTURE_2D, textures[0]);
for (int cellY = 0; cellY < numRowsCols; cellY++)
for (int cellX = 0; cellX < numRowsCols; cellX++)
{
const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
clearColorBuffer(fboFormat, color);
glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
glViewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
sglr::drawQuad(*getCurrentContext(), fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
}
readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
checkError();
}
};
class FboRepeatedClearBlitTex2DCase : public FboColorbufferCase
{
public:
FboRepeatedClearBlitTex2DCase (Context& context, const char* name, const char* desc, deUint32 format)
: FboColorbufferCase(context, name, desc, format)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
const int numRowsCols = 4;
const int cellSize = 16;
const int fboSizes[] = { cellSize, cellSize*numRowsCols };
de::Random rnd (18169662);
deUint32 fbos[] = { 0, 0 };
deUint32 textures[] = { 0, 0 };
glGenFramebuffers(2, &fbos[0]);
glGenTextures(2, &textures[0]);
for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
{
glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
checkError();
glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
}
// larger fbo bound -- clear to transparent black
clearColorBuffer(fboFormat, Vec4(0.0f));
for (int cellY = 0; cellY < numRowsCols; cellY++)
for (int cellX = 0; cellX < numRowsCols; cellX++)
{
const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
clearColorBuffer(fboFormat, color);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
checkError();
}
};
class FboRepeatedClearBlitRboCase : public FboColorbufferCase
{
public:
FboRepeatedClearBlitRboCase (Context& context, const char* name, const char* desc, deUint32 format)
: FboColorbufferCase(context, name, desc, format)
{
}
protected:
void preCheck (void)
{
checkFormatSupport(m_format);
}
void render (tcu::Surface& dst)
{
const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format);
const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
const int numRowsCols = 4;
const int cellSize = 16;
const int fboSizes[] = { cellSize, cellSize*numRowsCols };
de::Random rnd (18169662);
deUint32 fbos[] = { 0, 0 };
deUint32 rbos[] = { 0, 0 };
glGenFramebuffers(2, &fbos[0]);
glGenRenderbuffers(2, &rbos[0]);
for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
{
glBindRenderbuffer(GL_RENDERBUFFER, rbos[fboNdx]);
glRenderbufferStorage(GL_RENDERBUFFER, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
checkError();
glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbos[fboNdx]);
checkError();
checkFramebufferStatus(GL_FRAMEBUFFER);
}
// larger fbo bound -- clear to transparent black
clearColorBuffer(fboFormat, Vec4(0.0f));
for (int cellY = 0; cellY < numRowsCols; cellY++)
for (int cellX = 0; cellX < numRowsCols; cellX++)
{
const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
clearColorBuffer(fboFormat, color);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
checkError();
}
};
FboColorTests::FboColorTests (Context& context)
: TestCaseGroup(context, "color", "Colorbuffer tests")
{
}
FboColorTests::~FboColorTests (void)
{
}
void FboColorTests::init (void)
{
static const deUint32 colorFormats[] =
{
// RGBA formats
GL_RGBA32I,
GL_RGBA32UI,
GL_RGBA16I,
GL_RGBA16UI,
GL_RGBA8,
GL_RGBA8I,
GL_RGBA8UI,
GL_SRGB8_ALPHA8,
GL_RGB10_A2,
GL_RGB10_A2UI,
GL_RGBA4,
GL_RGB5_A1,
// RGB formats
GL_RGB8,
GL_RGB565,
// RG formats
GL_RG32I,
GL_RG32UI,
GL_RG16I,
GL_RG16UI,
GL_RG8,
GL_RG8I,
GL_RG8UI,
// R formats
GL_R32I,
GL_R32UI,
GL_R16I,
GL_R16UI,
GL_R8,
GL_R8I,
GL_R8UI,
// GL_EXT_color_buffer_float
GL_RGBA32F,
GL_RGBA16F,
GL_R11F_G11F_B10F,
GL_RG32F,
GL_RG16F,
GL_R32F,
GL_R16F,
// GL_EXT_color_buffer_half_float
GL_RGB16F
};
// .clear
{
tcu::TestCaseGroup* clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Color clears");
addChild(clearGroup);
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
clearGroup->addChild(new FboColorClearCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], 129, 117));
}
// .tex2d
{
tcu::TestCaseGroup* tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "Texture 2D tests");
addChild(tex2DGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
tex2DGroup->addChild(new FboColorMultiTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
colorFormats[fmtNdx], IVec2(129, 117),
colorFormats[fmtNdx], IVec2(99, 128)));
}
// .texcube
{
tcu::TestCaseGroup* texCubeGroup = new tcu::TestCaseGroup(m_testCtx, "texcube", "Texture cube map tests");
addChild(texCubeGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
texCubeGroup->addChild(new FboColorTexCubeCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
colorFormats[fmtNdx], IVec2(128, 128)));
}
// .tex2darray
{
tcu::TestCaseGroup* tex2DArrayGroup = new tcu::TestCaseGroup(m_testCtx, "tex2darray", "Texture 2D array tests");
addChild(tex2DArrayGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
tex2DArrayGroup->addChild(new FboColorTex2DArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
colorFormats[fmtNdx], IVec3(128, 128, 5)));
}
// .tex3d
{
tcu::TestCaseGroup* tex3DGroup = new tcu::TestCaseGroup(m_testCtx, "tex3d", "Texture 3D tests");
addChild(tex3DGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
tex3DGroup->addChild(new FboColorTex3DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
colorFormats[fmtNdx], IVec3(128, 128, 5)));
}
// .blend
{
tcu::TestCaseGroup* blendGroup = new tcu::TestCaseGroup(m_testCtx, "blend", "Blending tests");
addChild(blendGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
{
deUint32 format = colorFormats[fmtNdx];
tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format);
tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(texFmt.type);
string fmtName = getFormatName(format);
if (texFmt.type == tcu::TextureFormat::FLOAT ||
fmtClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ||
fmtClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
continue; // Blending is not supported.
blendGroup->addChild(new FboBlendCase(m_context, (fmtName + "_src_over").c_str(), "", format, IVec2(127, 111), GL_FUNC_ADD, GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
}
}
// .repeated_clear
{
tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated clears and blits");
addChild(repeatedClearGroup);
// .sample.tex2d
{
tcu::TestCaseGroup* const sampleGroup = new tcu::TestCaseGroup(m_testCtx, "sample", "Read by sampling");
repeatedClearGroup->addChild(sampleGroup);
tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
sampleGroup->addChild(tex2DGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
tex2DGroup->addChild(new FboRepeatedClearSampleTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]),
"", colorFormats[fmtNdx]));
}
// .blit
{
tcu::TestCaseGroup* const blitGroup = new tcu::TestCaseGroup(m_testCtx, "blit", "Blitted");
repeatedClearGroup->addChild(blitGroup);
// .tex2d
{
tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
blitGroup->addChild(tex2DGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
tex2DGroup->addChild(new FboRepeatedClearBlitTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]),
"", colorFormats[fmtNdx]));
}
// .rbo
{
tcu::TestCaseGroup* const rboGroup = new tcu::TestCaseGroup(m_testCtx, "rbo", "Renderbuffer");
blitGroup->addChild(rboGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
rboGroup->addChild(new FboRepeatedClearBlitRboCase(m_context, getFormatName(colorFormats[fmtNdx]),
"", colorFormats[fmtNdx]));
}
}
}
}
} // Functional
} // gles3
} // deqp