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
35namespace deqp
36{
37namespace gles3
38{
39namespace Functional
40{
41
42using std::string;
43using std::vector;
44using tcu::TestLog;
45using namespace deqp::gls;
46using namespace deqp::gls::TextureTestUtil;
47
48static 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
64static 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
76class Texture2DSwizzleCase : public TestCase
77{
78public:
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
86private:
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
102Texture2DSwizzleCase::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
116Texture2DSwizzleCase::~Texture2DSwizzleCase (void)
117{
118	deinit();
119}
120
121void 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
136void Texture2DSwizzleCase::deinit (void)
137{
138	delete m_texture;
139	m_texture = DE_NULL;
140
141	m_renderer.clear();
142}
143
144Texture2DSwizzleCase::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
224TextureSwizzleTests::TextureSwizzleTests (Context& context)
225	: TestCaseGroup(context, "swizzle", "Texture Swizzle Tests")
226{
227}
228
229TextureSwizzleTests::~TextureSwizzleTests (void)
230{
231}
232
233void 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