blob: 0ae330e83b61f4aa81b3137cda5418ceced9e02f [file] [log] [blame] [edit]
/*-------------------------------------------------------------------------
* 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 Texture swizzle tests.
*//*--------------------------------------------------------------------*/
#include "es3fTextureSwizzleTests.hpp"
#include "glsTextureTestUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTexture.hpp"
#include "gluRenderContext.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuRenderTarget.hpp"
#include "deString.h"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
namespace deqp
{
namespace gles3
{
namespace Functional
{
using std::string;
using std::vector;
using tcu::TestLog;
using namespace deqp::gls;
using namespace deqp::gls::TextureTestUtil;
using namespace glu::TextureTestUtil;
static int swizzle(const tcu::RGBA &c, uint32_t swz)
{
switch (swz)
{
case GL_RED:
return c.getRed();
case GL_GREEN:
return c.getGreen();
case GL_BLUE:
return c.getBlue();
case GL_ALPHA:
return c.getAlpha();
case GL_ZERO:
return 0;
case GL_ONE:
return (1 << 8) - 1;
default:
DE_ASSERT(false);
return 0;
}
}
static void swizzle(tcu::Surface &surface, uint32_t swzR, uint32_t swzG, uint32_t swzB, uint32_t swzA)
{
for (int y = 0; y < surface.getHeight(); y++)
{
for (int x = 0; x < surface.getWidth(); x++)
{
tcu::RGBA p = surface.getPixel(x, y);
surface.setPixel(x, y, tcu::RGBA(swizzle(p, swzR), swizzle(p, swzG), swizzle(p, swzB), swizzle(p, swzA)));
}
}
}
class Texture2DSwizzleCase : public TestCase
{
public:
Texture2DSwizzleCase(Context &context, const char *name, const char *description, uint32_t internalFormat,
uint32_t format, uint32_t dataType, uint32_t swizzleR, uint32_t swizzleG, uint32_t swizzleB,
uint32_t swizzleA);
~Texture2DSwizzleCase(void);
void init(void);
void deinit(void);
IterateResult iterate(void);
private:
Texture2DSwizzleCase(const Texture2DSwizzleCase &other);
Texture2DSwizzleCase &operator=(const Texture2DSwizzleCase &other);
uint32_t m_internalFormat;
uint32_t m_format;
uint32_t m_dataType;
uint32_t m_swizzleR;
uint32_t m_swizzleG;
uint32_t m_swizzleB;
uint32_t m_swizzleA;
glu::Texture2D *m_texture;
TextureRenderer m_renderer;
};
Texture2DSwizzleCase::Texture2DSwizzleCase(Context &context, const char *name, const char *description,
uint32_t internalFormat, uint32_t format, uint32_t dataType,
uint32_t swizzleR, uint32_t swizzleG, uint32_t swizzleB, uint32_t swizzleA)
: TestCase(context, name, description)
, m_internalFormat(internalFormat)
, m_format(format)
, m_dataType(dataType)
, m_swizzleR(swizzleR)
, m_swizzleG(swizzleG)
, m_swizzleB(swizzleB)
, m_swizzleA(swizzleA)
, m_texture(DE_NULL)
, m_renderer(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES,
glu::PRECISION_HIGHP)
{
}
Texture2DSwizzleCase::~Texture2DSwizzleCase(void)
{
deinit();
}
void Texture2DSwizzleCase::init(void)
{
int width = de::min(128, m_context.getRenderContext().getRenderTarget().getWidth());
int height = de::min(128, m_context.getRenderContext().getRenderTarget().getHeight());
m_texture = (m_internalFormat == m_format) ?
new glu::Texture2D(m_context.getRenderContext(), m_format, m_dataType, width, height) :
new glu::Texture2D(m_context.getRenderContext(), m_internalFormat, width, height);
tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
// Fill level 0.
m_texture->getRefTexture().allocLevel(0);
tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);
}
void Texture2DSwizzleCase::deinit(void)
{
delete m_texture;
m_texture = DE_NULL;
m_renderer.clear();
}
Texture2DSwizzleCase::IterateResult Texture2DSwizzleCase::iterate(void)
{
const glw::Functions &gl = m_context.getRenderContext().getFunctions();
TestLog &log = m_testCtx.getLog();
RandomViewport viewport(m_context.getRenderContext().getRenderTarget(), m_texture->getRefTexture().getWidth(),
m_texture->getRefTexture().getHeight(), deStringHash(getName()));
tcu::Surface renderedFrame(viewport.width, viewport.height);
tcu::Surface referenceFrame(viewport.width, viewport.height);
tcu::RGBA threshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1, 1, 1, 1);
vector<float> texCoord;
ReferenceParams renderParams(TEXTURETYPE_2D);
tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
renderParams.samplerType = getSamplerType(m_texture->getRefTexture().getFormat());
renderParams.sampler = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
renderParams.colorScale = spec.lookupScale;
renderParams.colorBias = spec.lookupBias;
computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
// Setup base viewport.
gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
// Upload texture data to GL.
m_texture->upload();
// Bind to unit 0.
gl.activeTexture(GL_TEXTURE0);
gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
// Setup nearest neighbor filtering and clamp-to-edge.
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Setup texture swizzle.
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, m_swizzleR);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, m_swizzleG);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, m_swizzleB);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, m_swizzleA);
GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
// Draw.
m_renderer.renderQuad(0, &texCoord[0], renderParams);
glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
// Compute reference
{
const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
// Do initial rendering to RGBA8 in order to keep alpha
sampleTexture(tcu::SurfaceAccess(referenceFrame, tcu::PixelFormat(8, 8, 8, 8)), m_texture->getRefTexture(),
&texCoord[0], renderParams);
// Swizzle channels
swizzle(referenceFrame, m_swizzleR, m_swizzleG, m_swizzleB, m_swizzleA);
// Convert to destination format
if (pixelFormat != tcu::PixelFormat(8, 8, 8, 8))
{
for (int y = 0; y < referenceFrame.getHeight(); y++)
{
for (int x = 0; x < referenceFrame.getWidth(); x++)
{
tcu::RGBA p = referenceFrame.getPixel(x, y);
referenceFrame.setPixel(x, y, pixelFormat.convertColor(p));
}
}
}
}
// Compare and log.
bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
isOk ? "Pass" : "Image comparison failed");
return STOP;
}
TextureSwizzleTests::TextureSwizzleTests(Context &context) : TestCaseGroup(context, "swizzle", "Texture Swizzle Tests")
{
}
TextureSwizzleTests::~TextureSwizzleTests(void)
{
}
void TextureSwizzleTests::init(void)
{
static const struct
{
const char *name;
uint32_t internalFormat;
uint32_t format;
uint32_t dataType;
} formats[] = {{"alpha", GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE},
{"luminance", GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE},
{"luminance_alpha", GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
{"red", GL_R8, GL_RED, GL_UNSIGNED_BYTE},
{"rg", GL_RG8, GL_RG, GL_UNSIGNED_BYTE},
{"rgb", GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
{"rgba", GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}};
static const struct
{
const char *name;
uint32_t channel;
} channels[] = {{"r", GL_TEXTURE_SWIZZLE_R},
{"g", GL_TEXTURE_SWIZZLE_G},
{"b", GL_TEXTURE_SWIZZLE_B},
{"a", GL_TEXTURE_SWIZZLE_A}};
static const struct
{
const char *name;
uint32_t swizzle;
} swizzles[] = {{"red", GL_RED}, {"green", GL_GREEN}, {"blue", GL_BLUE},
{"alpha", GL_ALPHA}, {"zero", GL_ZERO}, {"one", GL_ONE}};
static const struct
{
const char *name;
uint32_t swzR;
uint32_t swzG;
uint32_t swzB;
uint32_t swzA;
} swizzleCases[] = {{"all_red", GL_RED, GL_RED, GL_RED, GL_RED},
{"all_green", GL_GREEN, GL_GREEN, GL_GREEN, GL_GREEN},
{"all_blue", GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE},
{"all_alpha", GL_ALPHA, GL_ALPHA, GL_ALPHA, GL_ALPHA},
{"all_zero", GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO},
{"all_one", GL_ONE, GL_ONE, GL_ONE, GL_ONE},
{"bgra", GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA},
{"abgr", GL_ALPHA, GL_BLUE, GL_GREEN, GL_RED},
{"one_one_red_green", GL_ONE, GL_ONE, GL_RED, GL_GREEN}};
static const uint32_t defaultSwizzles[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
// All swizzles applied to each channel.
tcu::TestCaseGroup *singleChannelGroup =
new tcu::TestCaseGroup(m_testCtx, "single_channel", "Single-channel swizzle");
addChild(singleChannelGroup);
for (int chanNdx = 0; chanNdx < DE_LENGTH_OF_ARRAY(channels); chanNdx++)
{
for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++)
{
if (swizzles[swzNdx].swizzle == defaultSwizzles[chanNdx])
continue; // No need to test default case.
string name = string(channels[chanNdx].name) + "_" + swizzles[swzNdx].name;
uint32_t swz = swizzles[swzNdx].swizzle;
uint32_t swzR = (chanNdx == 0) ? swz : defaultSwizzles[0];
uint32_t swzG = (chanNdx == 1) ? swz : defaultSwizzles[1];
uint32_t swzB = (chanNdx == 2) ? swz : defaultSwizzles[2];
uint32_t swzA = (chanNdx == 3) ? swz : defaultSwizzles[3];
singleChannelGroup->addChild(new Texture2DSwizzleCase(m_context, name.c_str(), "Single-channel swizzle",
GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, swzR, swzG, swzB,
swzA));
}
}
// Swizzles for all formats.
tcu::TestCaseGroup *multiChannelGroup = new tcu::TestCaseGroup(m_testCtx, "multi_channel", "Multi-channel swizzle");
addChild(multiChannelGroup);
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); fmtNdx++)
{
for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(swizzleCases); caseNdx++)
{
string name = string(formats[fmtNdx].name) + "_" + swizzleCases[caseNdx].name;
uint32_t swzR = swizzleCases[caseNdx].swzR;
uint32_t swzG = swizzleCases[caseNdx].swzG;
uint32_t swzB = swizzleCases[caseNdx].swzB;
uint32_t swzA = swizzleCases[caseNdx].swzA;
uint32_t intFormat = formats[fmtNdx].internalFormat;
uint32_t format = formats[fmtNdx].format;
uint32_t dataType = formats[fmtNdx].dataType;
multiChannelGroup->addChild(new Texture2DSwizzleCase(m_context, name.c_str(), "Multi-channel swizzle",
intFormat, format, dataType, swzR, swzG, swzB, swzA));
}
}
}
} // namespace Functional
} // namespace gles3
} // namespace deqp