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