346 lines
12 KiB
C++
346 lines
12 KiB
C++
/*-------------------------------------------------------------------------
|
|
* 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, deUint32 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, deUint32 swzR, deUint32 swzG, deUint32 swzB, deUint32 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, deUint32 internalFormat, deUint32 format, deUint32 dataType, deUint32 swizzleR, deUint32 swizzleG, deUint32 swizzleB, deUint32 swizzleA);
|
|
~Texture2DSwizzleCase (void);
|
|
|
|
void init (void);
|
|
void deinit (void);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
Texture2DSwizzleCase (const Texture2DSwizzleCase& other);
|
|
Texture2DSwizzleCase& operator= (const Texture2DSwizzleCase& other);
|
|
|
|
deUint32 m_internalFormat;
|
|
deUint32 m_format;
|
|
deUint32 m_dataType;
|
|
deUint32 m_swizzleR;
|
|
deUint32 m_swizzleG;
|
|
deUint32 m_swizzleB;
|
|
deUint32 m_swizzleA;
|
|
|
|
glu::Texture2D* m_texture;
|
|
TextureRenderer m_renderer;
|
|
};
|
|
|
|
Texture2DSwizzleCase::Texture2DSwizzleCase (Context& context, const char* name, const char* description, deUint32 internalFormat, deUint32 format, deUint32 dataType, deUint32 swizzleR, deUint32 swizzleG, deUint32 swizzleB, deUint32 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;
|
|
deUint32 internalFormat;
|
|
deUint32 format;
|
|
deUint32 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;
|
|
deUint32 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;
|
|
deUint32 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;
|
|
deUint32 swzR;
|
|
deUint32 swzG;
|
|
deUint32 swzB;
|
|
deUint32 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 deUint32 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;
|
|
deUint32 swz = swizzles[swzNdx].swizzle;
|
|
deUint32 swzR = (chanNdx == 0) ? swz : defaultSwizzles[0];
|
|
deUint32 swzG = (chanNdx == 1) ? swz : defaultSwizzles[1];
|
|
deUint32 swzB = (chanNdx == 2) ? swz : defaultSwizzles[2];
|
|
deUint32 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;
|
|
deUint32 swzR = swizzleCases[caseNdx].swzR;
|
|
deUint32 swzG = swizzleCases[caseNdx].swzG;
|
|
deUint32 swzB = swizzleCases[caseNdx].swzB;
|
|
deUint32 swzA = swizzleCases[caseNdx].swzA;
|
|
deUint32 intFormat = formats[fmtNdx].internalFormat;
|
|
deUint32 format = formats[fmtNdx].format;
|
|
deUint32 dataType = formats[fmtNdx].dataType;
|
|
|
|
multiChannelGroup->addChild(new Texture2DSwizzleCase(m_context, name.c_str(), "Multi-channel swizzle", intFormat, format, dataType, swzR, swzG, swzB, swzA));
|
|
}
|
|
}
|
|
}
|
|
|
|
} // Functional
|
|
} // gles3
|
|
} // deqp
|