Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Texture swizzle tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fTextureSwizzleTests.hpp"
     25 #include "glsTextureTestUtil.hpp"
     26 #include "gluPixelTransfer.hpp"
     27 #include "gluTexture.hpp"
     28 #include "gluRenderContext.hpp"
     29 #include "tcuTextureUtil.hpp"
     30 #include "tcuRenderTarget.hpp"
     31 #include "deString.h"
     32 #include "glwEnums.hpp"
     33 #include "glwFunctions.hpp"
     34 
     35 namespace deqp
     36 {
     37 namespace gles3
     38 {
     39 namespace Functional
     40 {
     41 
     42 using std::string;
     43 using std::vector;
     44 using tcu::TestLog;
     45 using namespace deqp::gls;
     46 using namespace deqp::gls::TextureTestUtil;
     47 
     48 static int swizzle (const tcu::RGBA& c, deUint32 swz)
     49 {
     50 	switch (swz)
     51 	{
     52 		case GL_RED:	return c.getRed();
     53 		case GL_GREEN:	return c.getGreen();
     54 		case GL_BLUE:	return c.getBlue();
     55 		case GL_ALPHA:	return c.getAlpha();
     56 		case GL_ZERO:	return 0;
     57 		case GL_ONE:	return (1<<8)-1;
     58 		default:
     59 			DE_ASSERT(false);
     60 			return 0;
     61 	}
     62 }
     63 
     64 static void swizzle (tcu::Surface& surface, deUint32 swzR, deUint32 swzG, deUint32 swzB, deUint32 swzA)
     65 {
     66 	for (int y = 0; y < surface.getHeight(); y++)
     67 	{
     68 		for (int x = 0; x < surface.getWidth(); x++)
     69 		{
     70 			tcu::RGBA p = surface.getPixel(x, y);
     71 			surface.setPixel(x, y, tcu::RGBA(swizzle(p, swzR), swizzle(p, swzG), swizzle(p, swzB), swizzle(p, swzA)));
     72 		}
     73 	}
     74 }
     75 
     76 class Texture2DSwizzleCase : public TestCase
     77 {
     78 public:
     79 							Texture2DSwizzleCase	(Context& context, const char* name, const char* description, deUint32 internalFormat, deUint32 format, deUint32 dataType, deUint32 swizzleR, deUint32 swizzleG, deUint32 swizzleB, deUint32 swizzleA);
     80 							~Texture2DSwizzleCase	(void);
     81 
     82 	void					init					(void);
     83 	void					deinit					(void);
     84 	IterateResult			iterate					(void);
     85 
     86 private:
     87 							Texture2DSwizzleCase	(const Texture2DSwizzleCase& other);
     88 	Texture2DSwizzleCase&	operator=				(const Texture2DSwizzleCase& other);
     89 
     90 	deUint32				m_internalFormat;
     91 	deUint32				m_format;
     92 	deUint32				m_dataType;
     93 	deUint32				m_swizzleR;
     94 	deUint32				m_swizzleG;
     95 	deUint32				m_swizzleB;
     96 	deUint32				m_swizzleA;
     97 
     98 	glu::Texture2D*			m_texture;
     99 	TextureRenderer			m_renderer;
    100 };
    101 
    102 Texture2DSwizzleCase::Texture2DSwizzleCase (Context& context, const char* name, const char* description, deUint32 internalFormat, deUint32 format, deUint32 dataType, deUint32 swizzleR, deUint32 swizzleG, deUint32 swizzleB, deUint32 swizzleA)
    103 	: TestCase			(context, name, description)
    104 	, m_internalFormat	(internalFormat)
    105 	, m_format			(format)
    106 	, m_dataType		(dataType)
    107 	, m_swizzleR		(swizzleR)
    108 	, m_swizzleG		(swizzleG)
    109 	, m_swizzleB		(swizzleB)
    110 	, m_swizzleA		(swizzleA)
    111 	, m_texture			(DE_NULL)
    112 	, m_renderer		(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
    113 {
    114 }
    115 
    116 Texture2DSwizzleCase::~Texture2DSwizzleCase (void)
    117 {
    118 	deinit();
    119 }
    120 
    121 void Texture2DSwizzleCase::init (void)
    122 {
    123 	int	width	= de::min(128, m_context.getRenderContext().getRenderTarget().getWidth());
    124 	int	height	= de::min(128, m_context.getRenderContext().getRenderTarget().getHeight());
    125 
    126 	m_texture = (m_internalFormat == m_format) ? new glu::Texture2D(m_context.getRenderContext(), m_format, m_dataType, width, height)
    127 											   : new glu::Texture2D(m_context.getRenderContext(), m_internalFormat, width, height);
    128 
    129 	tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
    130 
    131 	// Fill level 0.
    132 	m_texture->getRefTexture().allocLevel(0);
    133 	tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);
    134 }
    135 
    136 void Texture2DSwizzleCase::deinit (void)
    137 {
    138 	delete m_texture;
    139 	m_texture = DE_NULL;
    140 
    141 	m_renderer.clear();
    142 }
    143 
    144 Texture2DSwizzleCase::IterateResult Texture2DSwizzleCase::iterate (void)
    145 {
    146 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
    147 	TestLog&				log					= m_testCtx.getLog();
    148 	RandomViewport			viewport			(m_context.getRenderContext().getRenderTarget(), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight(), deStringHash(getName()));
    149 	tcu::Surface			renderedFrame		(viewport.width, viewport.height);
    150 	tcu::Surface			referenceFrame		(viewport.width, viewport.height);
    151 	tcu::RGBA				threshold			= m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
    152 	vector<float>			texCoord;
    153 	ReferenceParams			renderParams		(TEXTURETYPE_2D);
    154 	tcu::TextureFormatInfo	spec				= tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
    155 
    156 	renderParams.samplerType	= getSamplerType(m_texture->getRefTexture().getFormat());
    157 	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);
    158 	renderParams.colorScale		= spec.lookupScale;
    159 	renderParams.colorBias		= spec.lookupBias;
    160 
    161 	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
    162 
    163 	// Setup base viewport.
    164 	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
    165 
    166 	// Upload texture data to GL.
    167 	m_texture->upload();
    168 
    169 	// Bind to unit 0.
    170 	gl.activeTexture(GL_TEXTURE0);
    171 	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
    172 
    173 	// Setup nearest neighbor filtering and clamp-to-edge.
    174 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    175 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    176 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
    177 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
    178 
    179 	// Setup texture swizzle.
    180 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R,	m_swizzleR);
    181 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G,	m_swizzleG);
    182 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B,	m_swizzleB);
    183 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A,	m_swizzleA);
    184 
    185 	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
    186 
    187 	// Draw.
    188 	m_renderer.renderQuad(0, &texCoord[0], renderParams);
    189 	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
    190 
    191 	// Compute reference
    192 	{
    193 		const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
    194 
    195 		// Do initial rendering to RGBA8 in order to keep alpha
    196 		sampleTexture(SurfaceAccess(referenceFrame, tcu::PixelFormat(8,8,8,8)), m_texture->getRefTexture(), &texCoord[0], renderParams);
    197 
    198 		// Swizzle channels
    199 		swizzle(referenceFrame, m_swizzleR, m_swizzleG, m_swizzleB, m_swizzleA);
    200 
    201 		// Convert to destination format
    202 		if (pixelFormat != tcu::PixelFormat(8,8,8,8))
    203 		{
    204 			for (int y = 0; y < referenceFrame.getHeight(); y++)
    205 			{
    206 				for (int x = 0; x < referenceFrame.getWidth(); x++)
    207 				{
    208 					tcu::RGBA p = referenceFrame.getPixel(x, y);
    209 					referenceFrame.setPixel(x, y, pixelFormat.convertColor(p));
    210 				}
    211 			}
    212 		}
    213 	}
    214 
    215 	// Compare and log.
    216 	bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
    217 
    218 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
    219 							isOk ? "Pass"				: "Image comparison failed");
    220 
    221 	return STOP;
    222 }
    223 
    224 TextureSwizzleTests::TextureSwizzleTests (Context& context)
    225 	: TestCaseGroup(context, "swizzle", "Texture Swizzle Tests")
    226 {
    227 }
    228 
    229 TextureSwizzleTests::~TextureSwizzleTests (void)
    230 {
    231 }
    232 
    233 void TextureSwizzleTests::init (void)
    234 {
    235 	static const struct
    236 	{
    237 		const char*		name;
    238 		deUint32		internalFormat;
    239 		deUint32		format;
    240 		deUint32		dataType;
    241 	} formats[] =
    242 	{
    243 		{ "alpha",				GL_ALPHA,				GL_ALPHA,			GL_UNSIGNED_BYTE },
    244 		{ "luminance",			GL_LUMINANCE,			GL_LUMINANCE,		GL_UNSIGNED_BYTE },
    245 		{ "luminance_alpha",	GL_LUMINANCE_ALPHA,		GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
    246 		{ "red",				GL_R8,					GL_RED,				GL_UNSIGNED_BYTE },
    247 		{ "rg",					GL_RG8,					GL_RG,				GL_UNSIGNED_BYTE },
    248 		{ "rgb",				GL_RGB8,				GL_RGB,				GL_UNSIGNED_BYTE },
    249 		{ "rgba",				GL_RGBA8,				GL_RGBA,			GL_UNSIGNED_BYTE }
    250 	};
    251 
    252 	static const struct
    253 	{
    254 		const char*		name;
    255 		deUint32		channel;
    256 	} channels[] =
    257 	{
    258 		{ "r",	GL_TEXTURE_SWIZZLE_R },
    259 		{ "g",	GL_TEXTURE_SWIZZLE_G },
    260 		{ "b",	GL_TEXTURE_SWIZZLE_B },
    261 		{ "a",	GL_TEXTURE_SWIZZLE_A }
    262 	};
    263 
    264 	static const struct
    265 	{
    266 		const char*		name;
    267 		deUint32		swizzle;
    268 	} swizzles[] =
    269 	{
    270 		{ "red",		GL_RED		},
    271 		{ "green",		GL_GREEN	},
    272 		{ "blue",		GL_BLUE		},
    273 		{ "alpha",		GL_ALPHA	},
    274 		{ "zero",		GL_ZERO		},
    275 		{ "one",		GL_ONE		}
    276 	};
    277 
    278 	static const struct
    279 	{
    280 		const char*		name;
    281 		deUint32		swzR;
    282 		deUint32		swzG;
    283 		deUint32		swzB;
    284 		deUint32		swzA;
    285 	} swizzleCases[] =
    286 	{
    287 		{ "all_red",			GL_RED,		GL_RED,		GL_RED,		GL_RED		},
    288 		{ "all_green",			GL_GREEN,	GL_GREEN,	GL_GREEN,	GL_GREEN	},
    289 		{ "all_blue",			GL_BLUE,	GL_BLUE,	GL_BLUE,	GL_BLUE		},
    290 		{ "all_alpha",			GL_ALPHA,	GL_ALPHA,	GL_ALPHA,	GL_ALPHA	},
    291 		{ "all_zero",			GL_ZERO,	GL_ZERO,	GL_ZERO,	GL_ZERO		},
    292 		{ "all_one",			GL_ONE,		GL_ONE,		GL_ONE,		GL_ONE		},
    293 		{ "bgra",				GL_BLUE,	GL_GREEN,	GL_RED,		GL_ALPHA	},
    294 		{ "abgr",				GL_ALPHA,	GL_BLUE,	GL_GREEN,	GL_RED		},
    295 		{ "one_one_red_green",	GL_ONE,		GL_ONE,		GL_RED,		GL_GREEN	}
    296 	};
    297 
    298 	static const deUint32 defaultSwizzles[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
    299 
    300 	// All swizzles applied to each channel.
    301 	tcu::TestCaseGroup* singleChannelGroup = new tcu::TestCaseGroup(m_testCtx, "single_channel", "Single-channel swizzle");
    302 	addChild(singleChannelGroup);
    303 	for (int chanNdx = 0; chanNdx < DE_LENGTH_OF_ARRAY(channels); chanNdx++)
    304 	{
    305 		for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++)
    306 		{
    307 			if (swizzles[swzNdx].swizzle == defaultSwizzles[chanNdx])
    308 				continue; // No need to test default case.
    309 
    310 			string		name	= string(channels[chanNdx].name) + "_" + swizzles[swzNdx].name;
    311 			deUint32	swz		= swizzles[swzNdx].swizzle;
    312 			deUint32	swzR	= (chanNdx == 0) ? swz : defaultSwizzles[0];
    313 			deUint32	swzG	= (chanNdx == 1) ? swz : defaultSwizzles[1];
    314 			deUint32	swzB	= (chanNdx == 2) ? swz : defaultSwizzles[2];
    315 			deUint32	swzA	= (chanNdx == 3) ? swz : defaultSwizzles[3];
    316 
    317 			singleChannelGroup->addChild(new Texture2DSwizzleCase(m_context, name.c_str(), "Single-channel swizzle", GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, swzR, swzG, swzB, swzA));
    318 		}
    319 	}
    320 
    321 	// Swizzles for all formats.
    322 	tcu::TestCaseGroup* multiChannelGroup = new tcu::TestCaseGroup(m_testCtx, "multi_channel", "Multi-channel swizzle");
    323 	addChild(multiChannelGroup);
    324 	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); fmtNdx++)
    325 	{
    326 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(swizzleCases); caseNdx++)
    327 		{
    328 			string		name		= string(formats[fmtNdx].name) + "_" + swizzleCases[caseNdx].name;
    329 			deUint32	swzR		= swizzleCases[caseNdx].swzR;
    330 			deUint32	swzG		= swizzleCases[caseNdx].swzG;
    331 			deUint32	swzB		= swizzleCases[caseNdx].swzB;
    332 			deUint32	swzA		= swizzleCases[caseNdx].swzA;
    333 			deUint32	intFormat	= formats[fmtNdx].internalFormat;
    334 			deUint32	format		= formats[fmtNdx].format;
    335 			deUint32	dataType	= formats[fmtNdx].dataType;
    336 
    337 			multiChannelGroup->addChild(new Texture2DSwizzleCase(m_context, name.c_str(), "Multi-channel swizzle", intFormat, format, dataType, swzR, swzG, swzB, swzA));
    338 		}
    339 	}
    340 }
    341 
    342 } // Functional
    343 } // gles3
    344 } // deqp
    345