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 size tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fTextureSizeTests.hpp"
25 #include "glsTextureTestUtil.hpp"
26 #include "gluTexture.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuTextureUtil.hpp"
32
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35
36 namespace deqp
37 {
38 namespace gles3
39 {
40 namespace Functional
41 {
42
43 using tcu::TestLog;
44 using std::vector;
45 using std::string;
46 using tcu::Sampler;
47 using namespace glu;
48 using namespace gls::TextureTestUtil;
49
50 class Texture2DSizeCase : public tcu::TestCase
51 {
52 public:
53 Texture2DSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps);
54 ~Texture2DSizeCase (void);
55
56 void init (void);
57 void deinit (void);
58 IterateResult iterate (void);
59
60 private:
61 Texture2DSizeCase (const Texture2DSizeCase& other);
62 Texture2DSizeCase& operator= (const Texture2DSizeCase& other);
63
64 glu::RenderContext& m_renderCtx;
65
66 deUint32 m_format;
67 deUint32 m_dataType;
68 int m_width;
69 int m_height;
70 bool m_useMipmaps;
71
72 glu::Texture2D* m_texture;
73 TextureRenderer m_renderer;
74 };
75
Texture2DSizeCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * description,deUint32 format,deUint32 dataType,int width,int height,bool mipmaps)76 Texture2DSizeCase::Texture2DSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps)
77 : TestCase (testCtx, name, description)
78 , m_renderCtx (renderCtx)
79 , m_format (format)
80 , m_dataType (dataType)
81 , m_width (width)
82 , m_height (height)
83 , m_useMipmaps (mipmaps)
84 , m_texture (DE_NULL)
85 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_MEDIUMP)
86 {
87 }
88
~Texture2DSizeCase(void)89 Texture2DSizeCase::~Texture2DSizeCase (void)
90 {
91 Texture2DSizeCase::deinit();
92 }
93
init(void)94 void Texture2DSizeCase::init (void)
95 {
96 DE_ASSERT(!m_texture);
97 m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
98
99 int numLevels = m_useMipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
100
101 // Fill levels.
102 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
103 {
104 m_texture->getRefTexture().allocLevel(levelNdx);
105 tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(levelNdx), tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
106 }
107 }
108
deinit(void)109 void Texture2DSizeCase::deinit (void)
110 {
111 delete m_texture;
112 m_texture = DE_NULL;
113
114 m_renderer.clear();
115 }
116
iterate(void)117 Texture2DSizeCase::IterateResult Texture2DSizeCase::iterate (void)
118 {
119 const glw::Functions& gl = m_renderCtx.getFunctions();
120 TestLog& log = m_testCtx.getLog();
121 RandomViewport viewport (m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName()));
122 tcu::Surface renderedFrame (viewport.width, viewport.height);
123 tcu::Surface referenceFrame (viewport.width, viewport.height);
124 tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
125 deUint32 wrapS = GL_CLAMP_TO_EDGE;
126 deUint32 wrapT = GL_CLAMP_TO_EDGE;
127 deUint32 minFilter = m_useMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
128 deUint32 magFilter = GL_NEAREST;
129 vector<float> texCoord;
130
131 computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
132
133 // Setup base viewport.
134 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
135
136 // Upload texture data to GL.
137 m_texture->upload();
138
139 // Bind to unit 0.
140 gl.activeTexture(GL_TEXTURE0);
141 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
142
143 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
144 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
145 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
146 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
147 GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
148
149 // Draw.
150 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);
151 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
152
153 // Compute reference.
154 sampleTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], ReferenceParams(TEXTURETYPE_2D, mapGLSampler(wrapS, wrapT, minFilter, magFilter)));
155
156 // Compare and log.
157 bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
158
159 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
160 isOk ? "Pass" : "Image comparison failed");
161
162 return STOP;
163 }
164
165 class TextureCubeSizeCase : public tcu::TestCase
166 {
167 public:
168 TextureCubeSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps);
169 ~TextureCubeSizeCase (void);
170
171 void init (void);
172 void deinit (void);
173 IterateResult iterate (void);
174
175 private:
176 TextureCubeSizeCase (const TextureCubeSizeCase& other);
177 TextureCubeSizeCase& operator= (const TextureCubeSizeCase& other);
178
179 bool testFace (tcu::CubeFace face);
180
181 glu::RenderContext& m_renderCtx;
182
183 deUint32 m_format;
184 deUint32 m_dataType;
185 int m_width;
186 int m_height;
187 bool m_useMipmaps;
188
189 glu::TextureCube* m_texture;
190 TextureRenderer m_renderer;
191
192 int m_curFace;
193 bool m_isOk;
194 };
195
TextureCubeSizeCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * description,deUint32 format,deUint32 dataType,int width,int height,bool mipmaps)196 TextureCubeSizeCase::TextureCubeSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps)
197 : TestCase (testCtx, name, description)
198 , m_renderCtx (renderCtx)
199 , m_format (format)
200 , m_dataType (dataType)
201 , m_width (width)
202 , m_height (height)
203 , m_useMipmaps (mipmaps)
204 , m_texture (DE_NULL)
205 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_MEDIUMP)
206 , m_curFace (0)
207 , m_isOk (false)
208 {
209 }
210
~TextureCubeSizeCase(void)211 TextureCubeSizeCase::~TextureCubeSizeCase (void)
212 {
213 TextureCubeSizeCase::deinit();
214 }
215
init(void)216 void TextureCubeSizeCase::init (void)
217 {
218 DE_ASSERT(!m_texture);
219 DE_ASSERT(m_width == m_height);
220 m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_width);
221
222 static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
223 {
224 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
225 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
226 { tcu::Vec4(-1.0f, 0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
227 { tcu::Vec4(-1.0f, -1.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
228 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
229 { tcu::Vec4( 0.0f, 0.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z
230 };
231
232 int numLevels = m_useMipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
233
234 // Fill levels.
235 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
236 {
237 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
238 {
239 m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
240 fillWithComponentGradients(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0], gradients[face][1]);
241 }
242 }
243
244 // Upload texture data to GL.
245 m_texture->upload();
246
247 // Initialize iteration state.
248 m_curFace = 0;
249 m_isOk = true;
250 }
251
deinit(void)252 void TextureCubeSizeCase::deinit (void)
253 {
254 delete m_texture;
255 m_texture = DE_NULL;
256
257 m_renderer.clear();
258 }
259
testFace(tcu::CubeFace face)260 bool TextureCubeSizeCase::testFace (tcu::CubeFace face)
261 {
262 const glw::Functions& gl = m_renderCtx.getFunctions();
263 TestLog& log = m_testCtx.getLog();
264 RandomViewport viewport (m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName())+(deUint32)face);
265 tcu::Surface renderedFrame (viewport.width, viewport.height);
266 tcu::Surface referenceFrame (viewport.width, viewport.height);
267 tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
268 deUint32 wrapS = GL_CLAMP_TO_EDGE;
269 deUint32 wrapT = GL_CLAMP_TO_EDGE;
270 deUint32 minFilter = m_useMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
271 deUint32 magFilter = GL_NEAREST;
272 vector<float> texCoord;
273
274 computeQuadTexCoordCube(texCoord, face);
275
276 // \todo [2011-10-28 pyry] Image set name / section?
277 log << TestLog::Message << face << TestLog::EndMessage;
278
279 // Setup base viewport.
280 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
281
282 // Bind to unit 0.
283 gl.activeTexture(GL_TEXTURE0);
284 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
285
286 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS);
287 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT);
288 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter);
289 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
290 GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
291
292 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);
293 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
294
295 // Compute reference.
296 Sampler sampler = mapGLSampler(wrapS, wrapT, minFilter, magFilter);
297 sampler.seamlessCubeMap = true;
298 sampleTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], ReferenceParams(TEXTURETYPE_CUBE, sampler));
299
300 // Compare and log.
301 return compareImages(log, referenceFrame, renderedFrame, threshold);
302 }
303
iterate(void)304 TextureCubeSizeCase::IterateResult TextureCubeSizeCase::iterate (void)
305 {
306 // Execute test for all faces.
307 if (!testFace((tcu::CubeFace)m_curFace))
308 m_isOk = false;
309
310 m_curFace += 1;
311
312 if (m_curFace == tcu::CUBEFACE_LAST)
313 {
314 m_testCtx.setTestResult(m_isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
315 m_isOk ? "Pass" : "Image comparison failed");
316 return STOP;
317 }
318 else
319 return CONTINUE;
320 }
321
TextureSizeTests(Context & context)322 TextureSizeTests::TextureSizeTests (Context& context)
323 : TestCaseGroup(context, "size", "Texture Size Tests")
324 {
325 }
326
~TextureSizeTests(void)327 TextureSizeTests::~TextureSizeTests (void)
328 {
329 }
330
init(void)331 void TextureSizeTests::init (void)
332 {
333 struct
334 {
335 int width;
336 int height;
337 } sizes2D[] =
338 {
339 { 64, 64 }, // Spec-mandated minimum.
340 { 65, 63 },
341 { 512, 512 },
342 { 1024, 1024 },
343 { 2048, 2048 }
344 };
345
346 struct
347 {
348 int width;
349 int height;
350 } sizesCube[] =
351 {
352 { 15, 15 },
353 { 16, 16 }, // Spec-mandated minimum
354 { 64, 64 },
355 { 128, 128 },
356 { 256, 256 },
357 { 512, 512 }
358 };
359
360 struct
361 {
362 const char* name;
363 deUint32 format;
364 deUint32 dataType;
365 } formats[] =
366 {
367 { "l8", GL_LUMINANCE, GL_UNSIGNED_BYTE },
368 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
369 { "rgb888", GL_RGB, GL_UNSIGNED_BYTE },
370 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE }
371 };
372
373 // 2D cases.
374 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Size Tests");
375 addChild(group2D);
376 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
377 {
378 int width = sizes2D[sizeNdx].width;
379 int height = sizes2D[sizeNdx].height;
380 bool isPOT = deIsPowerOfTwo32(width) && deIsPowerOfTwo32(height);
381
382 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
383 {
384 for (int mipmap = 0; mipmap < (isPOT ? 2 : 1); mipmap++)
385 {
386 std::ostringstream name;
387 name << width << "x" << height << "_" << formats[formatNdx].name << (mipmap ? "_mipmap" : "");
388
389 group2D->addChild(new Texture2DSizeCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
390 formats[formatNdx].format, formats[formatNdx].dataType,
391 width, height, mipmap != 0));
392 }
393 }
394 }
395
396 // Cubemap cases.
397 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cubemap Texture Size Tests");
398 addChild(groupCube);
399 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
400 {
401 int width = sizesCube[sizeNdx].width;
402 int height = sizesCube[sizeNdx].height;
403 bool isPOT = deIsPowerOfTwo32(width) && deIsPowerOfTwo32(height);
404
405 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
406 {
407 for (int mipmap = 0; mipmap < (isPOT ? 2 : 1); mipmap++)
408 {
409 std::ostringstream name;
410 name << width << "x" << height << "_" << formats[formatNdx].name << (mipmap ? "_mipmap" : "");
411
412 groupCube->addChild(new TextureCubeSizeCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
413 formats[formatNdx].format, formats[formatNdx].dataType,
414 width, height, mipmap != 0));
415 }
416 }
417 }
418 }
419
420 } // Functional
421 } // gles3
422 } // deqp
423