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 
swizzle(const tcu::RGBA & c,deUint32 swz)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 
swizzle(tcu::Surface & surface,deUint32 swzR,deUint32 swzG,deUint32 swzB,deUint32 swzA)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 
Texture2DSwizzleCase(Context & context,const char * name,const char * description,deUint32 internalFormat,deUint32 format,deUint32 dataType,deUint32 swizzleR,deUint32 swizzleG,deUint32 swizzleB,deUint32 swizzleA)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 
~Texture2DSwizzleCase(void)116 Texture2DSwizzleCase::~Texture2DSwizzleCase (void)
117 {
118 	deinit();
119 }
120 
init(void)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 
deinit(void)136 void Texture2DSwizzleCase::deinit (void)
137 {
138 	delete m_texture;
139 	m_texture = DE_NULL;
140 
141 	m_renderer.clear();
142 }
143 
iterate(void)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 
TextureSwizzleTests(Context & context)224 TextureSwizzleTests::TextureSwizzleTests (Context& context)
225 	: TestCaseGroup(context, "swizzle", "Texture Swizzle Tests")
226 {
227 }
228 
~TextureSwizzleTests(void)229 TextureSwizzleTests::~TextureSwizzleTests (void)
230 {
231 }
232 
init(void)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