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