1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 Mipmapping tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fTextureMipmapTests.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 #include "tcuVector.hpp"
33 #include "tcuMatrix.hpp"
34 #include "tcuMatrixUtil.hpp"
35 #include "tcuTexLookupVerifier.hpp"
36 #include "tcuVectorUtil.hpp"
37 #include "deStringUtil.hpp"
38 #include "deRandom.hpp"
39 #include "glwFunctions.hpp"
40 #include "glwEnums.hpp"
41
42 namespace deqp
43 {
44 namespace gles2
45 {
46 namespace Functional
47 {
48
49 using tcu::TestLog;
50 using std::vector;
51 using std::string;
52 using tcu::Sampler;
53 using tcu::Vec2;
54 using tcu::Mat2;
55 using tcu::Vec4;
56 using tcu::IVec2;
57 using tcu::IVec4;
58 using namespace glu;
59 using namespace gls::TextureTestUtil;
60
61 enum CoordType
62 {
63 COORDTYPE_BASIC, //!< texCoord = translateScale(position).
64 COORDTYPE_BASIC_BIAS, //!< Like basic, but with bias values.
65 COORDTYPE_AFFINE, //!< texCoord = translateScaleRotateShear(position).
66 COORDTYPE_PROJECTED, //!< Projected coordinates, w != 1
67
68 COORDTYPE_LAST
69 };
70
71 // Texture2DMipmapCase
72
73 class Texture2DMipmapCase : public tcu::TestCase
74 {
75 public:
76
77 Texture2DMipmapCase (tcu::TestContext& testCtx,
78 glu::RenderContext& renderCtx,
79 const glu::ContextInfo& renderCtxInfo,
80 const char* name,
81 const char* desc,
82 CoordType coordType,
83 deUint32 minFilter,
84 deUint32 wrapS,
85 deUint32 wrapT,
86 deUint32 format,
87 deUint32 dataType,
88 int width,
89 int height);
90 ~Texture2DMipmapCase (void);
91
92 void init (void);
93 void deinit (void);
94 IterateResult iterate (void);
95
96 private:
97 Texture2DMipmapCase (const Texture2DMipmapCase& other);
98 Texture2DMipmapCase& operator= (const Texture2DMipmapCase& other);
99
100 glu::RenderContext& m_renderCtx;
101 const glu::ContextInfo& m_renderCtxInfo;
102
103 CoordType m_coordType;
104 deUint32 m_minFilter;
105 deUint32 m_wrapS;
106 deUint32 m_wrapT;
107 deUint32 m_format;
108 deUint32 m_dataType;
109 int m_width;
110 int m_height;
111
112 glu::Texture2D* m_texture;
113 TextureRenderer m_renderer;
114 };
115
Texture2DMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const glu::ContextInfo & renderCtxInfo,const char * name,const char * desc,CoordType coordType,deUint32 minFilter,deUint32 wrapS,deUint32 wrapT,deUint32 format,deUint32 dataType,int width,int height)116 Texture2DMipmapCase::Texture2DMipmapCase (tcu::TestContext& testCtx,
117 glu::RenderContext& renderCtx,
118 const glu::ContextInfo& renderCtxInfo,
119 const char* name,
120 const char* desc,
121 CoordType coordType,
122 deUint32 minFilter,
123 deUint32 wrapS,
124 deUint32 wrapT,
125 deUint32 format,
126 deUint32 dataType,
127 int width,
128 int height)
129 : TestCase (testCtx, name, desc)
130 , m_renderCtx (renderCtx)
131 , m_renderCtxInfo (renderCtxInfo)
132 , m_coordType (coordType)
133 , m_minFilter (minFilter)
134 , m_wrapS (wrapS)
135 , m_wrapT (wrapT)
136 , m_format (format)
137 , m_dataType (dataType)
138 , m_width (width)
139 , m_height (height)
140 , m_texture (DE_NULL)
141 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES,
142 renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available.
143 : glu::PRECISION_MEDIUMP)
144 {
145 }
146
~Texture2DMipmapCase(void)147 Texture2DMipmapCase::~Texture2DMipmapCase (void)
148 {
149 deinit();
150 }
151
init(void)152 void Texture2DMipmapCase::init (void)
153 {
154 if (!m_renderCtxInfo.isFragmentHighPrecisionSupported())
155 m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage;
156
157 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
158 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
159
160 m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
161
162 int numLevels = deLog2Floor32(de::max(m_width, m_height))+1;
163
164 // Fill texture with colored grid.
165 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
166 {
167 deUint32 step = 0xff / (numLevels-1);
168 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
169 deUint32 dec = 0xff - inc;
170 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff;
171 deUint32 color = 0xff000000 | rgb;
172
173 m_texture->getRefTexture().allocLevel(levelNdx);
174 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), toVec4(tcu::RGBA(color)));
175 }
176 }
177
deinit(void)178 void Texture2DMipmapCase::deinit (void)
179 {
180 delete m_texture;
181 m_texture = DE_NULL;
182
183 m_renderer.clear();
184 }
185
getBasicTexCoord2D(std::vector<float> & dst,int cellNdx)186 static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx)
187 {
188 static const struct
189 {
190 Vec2 bottomLeft;
191 Vec2 topRight;
192 } s_basicCoords[] =
193 {
194 { Vec2(-0.1f, 0.1f), Vec2( 0.8f, 1.0f) },
195 { Vec2(-0.3f, -0.6f), Vec2( 0.7f, 0.4f) },
196 { Vec2(-0.3f, 0.6f), Vec2( 0.7f, -0.9f) },
197 { Vec2(-0.8f, 0.6f), Vec2( 0.7f, -0.9f) },
198
199 { Vec2(-0.5f, -0.5f), Vec2( 1.5f, 1.5f) },
200 { Vec2( 1.0f, -1.0f), Vec2(-1.3f, 1.0f) },
201 { Vec2( 1.2f, -1.0f), Vec2(-1.3f, 1.6f) },
202 { Vec2( 2.2f, -1.1f), Vec2(-1.3f, 0.8f) },
203
204 { Vec2(-1.5f, 1.6f), Vec2( 1.7f, -1.4f) },
205 { Vec2( 2.0f, 1.6f), Vec2( 2.3f, -1.4f) },
206 { Vec2( 1.3f, -2.6f), Vec2(-2.7f, 2.9f) },
207 { Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) },
208
209 { Vec2( -8.0f, 9.0f), Vec2( 8.3f, -7.0f) },
210 { Vec2(-16.0f, 10.0f), Vec2( 18.3f, 24.0f) },
211 { Vec2( 30.2f, 55.0f), Vec2(-24.3f, -1.6f) },
212 { Vec2(-33.2f, 64.1f), Vec2( 32.1f, -64.1f) },
213 };
214
215 DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
216
217 const Vec2& bottomLeft = s_basicCoords[cellNdx].bottomLeft;
218 const Vec2& topRight = s_basicCoords[cellNdx].topRight;
219
220 computeQuadTexCoord2D(dst, bottomLeft, topRight);
221 }
222
getAffineTexCoord2D(std::vector<float> & dst,int cellNdx)223 static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx)
224 {
225 // Use basic coords as base.
226 getBasicTexCoord2D(dst, cellNdx);
227
228 // Rotate based on cell index.
229 float angle = 2.0f*DE_PI * ((float)cellNdx / 16.0f);
230 tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle);
231
232 // Second and third row are sheared.
233 float shearX = de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f;
234 tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
235
236 tcu::Mat2 transform = rotMatrix * shearMatrix;
237 Vec2 p0 = transform * Vec2(dst[0], dst[1]);
238 Vec2 p1 = transform * Vec2(dst[2], dst[3]);
239 Vec2 p2 = transform * Vec2(dst[4], dst[5]);
240 Vec2 p3 = transform * Vec2(dst[6], dst[7]);
241
242 dst[0] = p0.x(); dst[1] = p0.y();
243 dst[2] = p1.x(); dst[3] = p1.y();
244 dst[4] = p2.x(); dst[5] = p2.y();
245 dst[6] = p3.x(); dst[7] = p3.y();
246 }
247
iterate(void)248 Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void)
249 {
250 const glw::Functions& gl = m_renderCtx.getFunctions();
251
252 const tcu::Texture2D& refTexture = m_texture->getRefTexture();
253
254 const deUint32 magFilter = GL_NEAREST;
255 const int texWidth = refTexture.getWidth();
256 const int texHeight = refTexture.getHeight();
257 const int defViewportWidth = texWidth*4;
258 const int defViewportHeight = texHeight*4;
259
260 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
261 ReferenceParams sampleParams (TEXTURETYPE_2D);
262 vector<float> texCoord;
263
264 const bool isProjected = m_coordType == COORDTYPE_PROJECTED;
265 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS;
266
267 tcu::Surface renderedFrame (viewport.width, viewport.height);
268
269 // Viewport is divided into 4x4 grid.
270 int gridWidth = 4;
271 int gridHeight = 4;
272 int cellWidth = viewport.width / gridWidth;
273 int cellHeight = viewport.height / gridHeight;
274
275 // Bail out if rendertarget is too small.
276 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
277 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
278
279 // Sampling parameters.
280 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
281 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat());
282 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
283 sampleParams.lodMode = LODMODE_EXACT; // Use ideal lod.
284
285 // Upload texture data.
286 m_texture->upload();
287
288 // Bind gradient texture and setup sampler parameters.
289 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture());
290 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
291 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
292 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
293 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
294
295 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
296
297 // Bias values.
298 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
299
300 // Projection values.
301 static const Vec4 s_projections[] =
302 {
303 Vec4(1.2f, 1.0f, 0.7f, 1.0f),
304 Vec4(1.3f, 0.8f, 0.6f, 2.0f),
305 Vec4(0.8f, 1.0f, 1.7f, 0.6f),
306 Vec4(1.2f, 1.0f, 1.7f, 1.5f)
307 };
308
309 // Render cells.
310 for (int gridY = 0; gridY < gridHeight; gridY++)
311 {
312 for (int gridX = 0; gridX < gridWidth; gridX++)
313 {
314 const int curX = cellWidth*gridX;
315 const int curY = cellHeight*gridY;
316 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
317 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
318 const int cellNdx = gridY*gridWidth + gridX;
319
320 // Compute texcoord.
321 switch (m_coordType)
322 {
323 case COORDTYPE_BASIC_BIAS: // Fall-through.
324 case COORDTYPE_PROJECTED:
325 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break;
326 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break;
327 default: DE_ASSERT(DE_FALSE);
328 }
329
330 if (isProjected)
331 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
332
333 if (useLodBias)
334 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
335
336 // Render with GL.
337 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
338 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
339 }
340 }
341
342 // Read result.
343 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
344
345 // Compare and log.
346 {
347 const tcu::PixelFormat& pixelFormat = m_renderCtx.getRenderTarget().getPixelFormat();
348 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
349 tcu::Surface referenceFrame (viewport.width, viewport.height);
350 tcu::Surface errorMask (viewport.width, viewport.height);
351 tcu::LookupPrecision lookupPrec;
352 tcu::LodPrecision lodPrec;
353 int numFailedPixels = 0;
354
355 lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
356 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
357 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
358 lookupPrec.colorMask = getCompareMask(pixelFormat);
359 lodPrec.derivateBits = 10;
360 lodPrec.lodBits = isProjected ? 6 : 8;
361
362 for (int gridY = 0; gridY < gridHeight; gridY++)
363 {
364 for (int gridX = 0; gridX < gridWidth; gridX++)
365 {
366 const int curX = cellWidth*gridX;
367 const int curY = cellHeight*gridY;
368 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
369 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
370 const int cellNdx = gridY*gridWidth + gridX;
371
372 // Compute texcoord.
373 switch (m_coordType)
374 {
375 case COORDTYPE_BASIC_BIAS: // Fall-through.
376 case COORDTYPE_PROJECTED:
377 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break;
378 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break;
379 default: DE_ASSERT(DE_FALSE);
380 }
381
382 if (isProjected)
383 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
384
385 if (useLodBias)
386 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
387
388 // Render ideal result
389 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
390 refTexture, &texCoord[0], sampleParams);
391
392 // Compare this cell
393 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
394 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
395 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
396 m_texture->getRefTexture(), &texCoord[0], sampleParams,
397 lookupPrec, lodPrec, m_testCtx.getWatchDog());
398 }
399 }
400
401 if (numFailedPixels > 0)
402 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
403
404 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
405 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
406
407 if (numFailedPixels > 0)
408 {
409 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
410 << TestLog::Image("ErrorMask", "Error mask", errorMask);
411 }
412
413 m_testCtx.getLog() << TestLog::EndImageSet;
414
415 {
416 const bool isOk = numFailedPixels == 0;
417 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
418 isOk ? "Pass" : "Image verification failed");
419 }
420 }
421
422 return STOP;
423 }
424
425 // TextureCubeMipmapCase
426
427 class TextureCubeMipmapCase : public tcu::TestCase
428 {
429 public:
430
431 TextureCubeMipmapCase (tcu::TestContext& testCtx,
432 glu::RenderContext& renderCtx,
433 const glu::ContextInfo& renderCtxInfo,
434 const char* name,
435 const char* desc,
436 CoordType coordType,
437 deUint32 minFilter,
438 deUint32 wrapS,
439 deUint32 wrapT,
440 deUint32 format,
441 deUint32 dataType,
442 int size);
443 ~TextureCubeMipmapCase (void);
444
445 void init (void);
446 void deinit (void);
447 IterateResult iterate (void);
448
449 private:
450 TextureCubeMipmapCase (const TextureCubeMipmapCase& other);
451 TextureCubeMipmapCase& operator= (const TextureCubeMipmapCase& other);
452
453 glu::RenderContext& m_renderCtx;
454 const glu::ContextInfo& m_renderCtxInfo;
455
456 CoordType m_coordType;
457 deUint32 m_minFilter;
458 deUint32 m_wrapS;
459 deUint32 m_wrapT;
460 deUint32 m_format;
461 deUint32 m_dataType;
462 int m_size;
463
464 glu::TextureCube* m_texture;
465 TextureRenderer m_renderer;
466 };
467
TextureCubeMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const glu::ContextInfo & renderCtxInfo,const char * name,const char * desc,CoordType coordType,deUint32 minFilter,deUint32 wrapS,deUint32 wrapT,deUint32 format,deUint32 dataType,int size)468 TextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext& testCtx,
469 glu::RenderContext& renderCtx,
470 const glu::ContextInfo& renderCtxInfo,
471 const char* name,
472 const char* desc,
473 CoordType coordType,
474 deUint32 minFilter,
475 deUint32 wrapS,
476 deUint32 wrapT,
477 deUint32 format,
478 deUint32 dataType,
479 int size)
480 : TestCase (testCtx, name, desc)
481 , m_renderCtx (renderCtx)
482 , m_renderCtxInfo (renderCtxInfo)
483 , m_coordType (coordType)
484 , m_minFilter (minFilter)
485 , m_wrapS (wrapS)
486 , m_wrapT (wrapT)
487 , m_format (format)
488 , m_dataType (dataType)
489 , m_size (size)
490 , m_texture (DE_NULL)
491 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES,
492 renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available.
493 : glu::PRECISION_MEDIUMP)
494 {
495 }
496
~TextureCubeMipmapCase(void)497 TextureCubeMipmapCase::~TextureCubeMipmapCase (void)
498 {
499 deinit();
500 }
501
init(void)502 void TextureCubeMipmapCase::init (void)
503 {
504 if (!m_renderCtxInfo.isFragmentHighPrecisionSupported())
505 m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage;
506
507 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
508 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
509
510 m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size);
511
512 int numLevels = deLog2Floor32(m_size)+1;
513
514 // Fill texture with colored grid.
515 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
516 {
517 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
518 {
519 deUint32 step = 0xff / (numLevels-1);
520 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
521 deUint32 dec = 0xff - inc;
522 deUint32 rgb = 0;
523
524 switch (faceNdx)
525 {
526 case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
527 case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
528 case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
529 case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
530 case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
531 case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
532 }
533
534 deUint32 color = 0xff000000 | rgb;
535
536 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx);
537 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), toVec4(tcu::RGBA(color)));
538 }
539 }
540 }
541
deinit(void)542 void TextureCubeMipmapCase::deinit (void)
543 {
544 delete m_texture;
545 m_texture = DE_NULL;
546
547 m_renderer.clear();
548 }
549
randomPartition(vector<IVec4> & dst,de::Random & rnd,int x,int y,int width,int height)550 static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height)
551 {
552 const int minWidth = 8;
553 const int minHeight = 8;
554
555 bool partition = rnd.getFloat() > 0.4f;
556 bool partitionX = partition && width > minWidth && rnd.getBool();
557 bool partitionY = partition && height > minHeight && !partitionX;
558
559 if (partitionX)
560 {
561 int split = width/2 + rnd.getInt(-width/4, +width/4);
562 randomPartition(dst, rnd, x, y, split, height);
563 randomPartition(dst, rnd, x+split, y, width-split, height);
564 }
565 else if (partitionY)
566 {
567 int split = height/2 + rnd.getInt(-height/4, +height/4);
568 randomPartition(dst, rnd, x, y, width, split);
569 randomPartition(dst, rnd, x, y+split, width, height-split);
570 }
571 else
572 dst.push_back(IVec4(x, y, width, height));
573 }
574
computeGridLayout(vector<IVec4> & dst,int width,int height)575 static void computeGridLayout (vector<IVec4>& dst, int width, int height)
576 {
577 de::Random rnd(7);
578 randomPartition(dst, rnd, 0, 0, width, height);
579 }
580
iterate(void)581 TextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void)
582 {
583 const deUint32 magFilter = GL_NEAREST;
584 const int texWidth = m_texture->getRefTexture().getSize();
585 const int texHeight = m_texture->getRefTexture().getSize();
586 const int defViewportWidth = texWidth*2;
587 const int defViewportHeight = texHeight*2;
588
589 const glw::Functions& gl = m_renderCtx.getFunctions();
590 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
591
592 const bool isProjected = m_coordType == COORDTYPE_PROJECTED;
593 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS;
594
595 vector<float> texCoord;
596 tcu::Surface renderedFrame (viewport.width, viewport.height);
597
598 // Bail out if rendertarget is too small.
599 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
600 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
601
602 // Upload texture data.
603 m_texture->upload();
604
605 // Bind gradient texture and setup sampler parameters.
606 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
607 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS);
608 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT);
609 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
610 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
611
612 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
613
614 // Compute grid.
615 vector<IVec4> gridLayout;
616 computeGridLayout(gridLayout, viewport.width, viewport.height);
617
618 // Bias values.
619 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
620
621 // Projection values \note Less agressive than in 2D case due to smaller quads.
622 static const Vec4 s_projections[] =
623 {
624 Vec4(1.2f, 1.0f, 0.7f, 1.0f),
625 Vec4(1.3f, 0.8f, 0.6f, 1.1f),
626 Vec4(0.8f, 1.0f, 1.2f, 0.8f),
627 Vec4(1.2f, 1.0f, 1.3f, 0.9f)
628 };
629
630 // Render with GL
631 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
632 {
633 const int curX = gridLayout[cellNdx].x();
634 const int curY = gridLayout[cellNdx].y();
635 const int curW = gridLayout[cellNdx].z();
636 const int curH = gridLayout[cellNdx].w();
637 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
638 RenderParams params (TEXTURETYPE_CUBE);
639
640 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
641 computeQuadTexCoordCube(texCoord, cubeFace);
642
643 if (isProjected)
644 {
645 params.flags |= ReferenceParams::PROJECTED;
646 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
647 }
648
649 if (useLodBias)
650 {
651 params.flags |= ReferenceParams::USE_BIAS;
652 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
653 }
654
655 // Render with GL.
656 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
657 m_renderer.renderQuad(0, &texCoord[0], params);
658 }
659 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
660
661 // Read result.
662 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
663 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
664
665 // Render reference and compare
666 {
667 tcu::Surface referenceFrame (viewport.width, viewport.height);
668 tcu::Surface errorMask (viewport.width, viewport.height);
669 int numFailedPixels = 0;
670 ReferenceParams params (TEXTURETYPE_CUBE);
671 tcu::LookupPrecision lookupPrec;
672 tcu::LodPrecision lodPrec;
673
674 // Params for rendering reference
675 params.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
676 params.sampler.seamlessCubeMap = false;
677 params.lodMode = LODMODE_EXACT;
678
679 // Comparison parameters
680 lookupPrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
681 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)));
682 lookupPrec.coordBits = isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
683 lookupPrec.uvwBits = tcu::IVec3(5,5,0);
684 lodPrec.derivateBits = 10;
685 lodPrec.lodBits = isProjected ? 4 : 6;
686
687 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
688 {
689 const int curX = gridLayout[cellNdx].x();
690 const int curY = gridLayout[cellNdx].y();
691 const int curW = gridLayout[cellNdx].z();
692 const int curH = gridLayout[cellNdx].w();
693 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
694
695 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
696 computeQuadTexCoordCube(texCoord, cubeFace);
697
698 if (isProjected)
699 {
700 params.flags |= ReferenceParams::PROJECTED;
701 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
702 }
703
704 if (useLodBias)
705 {
706 params.flags |= ReferenceParams::USE_BIAS;
707 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
708 }
709
710 // Render ideal reference.
711 {
712 SurfaceAccess idealDst(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
713 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
714 }
715
716 // Compare this cell
717 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
718 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
719 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
720 m_texture->getRefTexture(), &texCoord[0], params,
721 lookupPrec, lodPrec, m_testCtx.getWatchDog());
722 }
723
724 if (numFailedPixels > 0)
725 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
726
727 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
728 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
729
730 if (numFailedPixels > 0)
731 {
732 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
733 << TestLog::Image("ErrorMask", "Error mask", errorMask);
734 }
735
736 m_testCtx.getLog() << TestLog::EndImageSet;
737
738 {
739 const bool isOk = numFailedPixels == 0;
740 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
741 isOk ? "Pass" : "Image verification failed");
742 }
743 }
744
745 return STOP;
746 }
747
748 // Texture2DGenMipmapCase
749
750 class Texture2DGenMipmapCase : public tcu::TestCase
751 {
752 public:
753
754 Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height);
755 ~Texture2DGenMipmapCase (void);
756
757 void init (void);
758 void deinit (void);
759 IterateResult iterate (void);
760
761 private:
762 Texture2DGenMipmapCase (const Texture2DGenMipmapCase& other);
763 Texture2DGenMipmapCase& operator= (const Texture2DGenMipmapCase& other);
764
765 glu::RenderContext& m_renderCtx;
766
767 deUint32 m_format;
768 deUint32 m_dataType;
769 deUint32 m_hint;
770 int m_width;
771 int m_height;
772
773 glu::Texture2D* m_texture;
774 TextureRenderer m_renderer;
775 };
776
Texture2DGenMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,deUint32 format,deUint32 dataType,deUint32 hint,int width,int height)777 Texture2DGenMipmapCase::Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height)
778 : TestCase (testCtx, name, desc)
779 , m_renderCtx (renderCtx)
780 , m_format (format)
781 , m_dataType (dataType)
782 , m_hint (hint)
783 , m_width (width)
784 , m_height (height)
785 , m_texture (DE_NULL)
786 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
787 {
788 }
789
~Texture2DGenMipmapCase(void)790 Texture2DGenMipmapCase::~Texture2DGenMipmapCase (void)
791 {
792 deinit();
793 }
794
init(void)795 void Texture2DGenMipmapCase::init (void)
796 {
797 DE_ASSERT(!m_texture);
798 m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
799 }
800
deinit(void)801 void Texture2DGenMipmapCase::deinit (void)
802 {
803 delete m_texture;
804 m_texture = DE_NULL;
805
806 m_renderer.clear();
807 }
808
iterate(void)809 Texture2DGenMipmapCase::IterateResult Texture2DGenMipmapCase::iterate (void)
810 {
811 const glw::Functions& gl = m_renderCtx.getFunctions();
812
813 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST;
814 const deUint32 magFilter = GL_NEAREST;
815 const deUint32 wrapS = GL_CLAMP_TO_EDGE;
816 const deUint32 wrapT = GL_CLAMP_TO_EDGE;
817
818 const int numLevels = deLog2Floor32(de::max(m_width, m_height))+1;
819
820 tcu::Texture2D resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight());
821
822 vector<float> texCoord;
823
824 // Initialize texture level 0 with colored grid.
825 m_texture->getRefTexture().allocLevel(0);
826 tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 8, tcu::Vec4(1.0f, 0.5f, 0.0f, 0.5f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
827
828 // Upload data and setup params.
829 m_texture->upload();
830
831 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture());
832 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
833 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
834 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
835 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
836 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
837
838 // Generate mipmap.
839 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
840 gl.generateMipmap(GL_TEXTURE_2D);
841 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
842
843 // Use (0, 0) -> (1, 1) texture coordinates.
844 computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));
845
846 // Fetch resulting texture by rendering.
847 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
848 {
849 const int levelWidth = de::max(1, m_width >> levelNdx);
850 const int levelHeight = de::max(1, m_height >> levelNdx);
851 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth, levelHeight, deStringHash(getName()) + levelNdx);
852
853 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
854 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);
855
856 resultTexture.allocLevel(levelNdx);
857 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevel(levelNdx));
858 }
859
860 // Compare results
861 {
862
863 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
864 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
865 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0));
866 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask);
867 GenMipmapPrecision comparePrec;
868
869 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
870 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits);
871 comparePrec.filterBits = tcu::IVec3(4, 4, 0);
872
873 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
874
875 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" :
876 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" :
877 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : "");
878 }
879
880 return STOP;
881 }
882
883 // TextureCubeGenMipmapCase
884
885 class TextureCubeGenMipmapCase : public tcu::TestCase
886 {
887 public:
888
889 TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size);
890 ~TextureCubeGenMipmapCase (void);
891
892 void init (void);
893 void deinit (void);
894 IterateResult iterate (void);
895
896 private:
897 TextureCubeGenMipmapCase (const TextureCubeGenMipmapCase& other);
898 TextureCubeGenMipmapCase& operator= (const TextureCubeGenMipmapCase& other);
899
900 glu::RenderContext& m_renderCtx;
901
902 deUint32 m_format;
903 deUint32 m_dataType;
904 deUint32 m_hint;
905 int m_size;
906
907 glu::TextureCube* m_texture;
908 TextureRenderer m_renderer;
909 };
910
TextureCubeGenMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,deUint32 format,deUint32 dataType,deUint32 hint,int size)911 TextureCubeGenMipmapCase::TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size)
912 : TestCase (testCtx, name, desc)
913 , m_renderCtx (renderCtx)
914 , m_format (format)
915 , m_dataType (dataType)
916 , m_hint (hint)
917 , m_size (size)
918 , m_texture (DE_NULL)
919 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
920 {
921 }
922
~TextureCubeGenMipmapCase(void)923 TextureCubeGenMipmapCase::~TextureCubeGenMipmapCase (void)
924 {
925 deinit();
926 }
927
init(void)928 void TextureCubeGenMipmapCase::init (void)
929 {
930 if (m_renderCtx.getRenderTarget().getWidth() < 3*m_size || m_renderCtx.getRenderTarget().getHeight() < 2*m_size)
931 throw tcu::NotSupportedError("Render target size must be at least (" + de::toString(3*m_size) + ", " + de::toString(2*m_size) + ")");
932
933 DE_ASSERT(!m_texture);
934 m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size);
935 }
936
deinit(void)937 void TextureCubeGenMipmapCase::deinit (void)
938 {
939 delete m_texture;
940 m_texture = DE_NULL;
941
942 m_renderer.clear();
943 }
944
iterate(void)945 TextureCubeGenMipmapCase::IterateResult TextureCubeGenMipmapCase::iterate (void)
946 {
947 const glw::Functions& gl = m_renderCtx.getFunctions();
948
949 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST;
950 const deUint32 magFilter = GL_NEAREST;
951 const deUint32 wrapS = GL_CLAMP_TO_EDGE;
952 const deUint32 wrapT = GL_CLAMP_TO_EDGE;
953
954 tcu::TextureCube resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_size);
955
956 const int numLevels = deLog2Floor32(m_size)+1;
957 vector<float> texCoord;
958
959 // Initialize texture level 0 with colored grid.
960 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
961 {
962 Vec4 ca, cb; // Grid colors.
963
964 switch (face)
965 {
966 case 0: ca = Vec4(1.0f, 0.3f, 0.0f, 0.7f); cb = Vec4(0.0f, 0.0f, 1.0f, 1.0f); break;
967 case 1: ca = Vec4(0.0f, 1.0f, 0.5f, 0.5f); cb = Vec4(1.0f, 0.0f, 0.0f, 1.0f); break;
968 case 2: ca = Vec4(0.7f, 0.0f, 1.0f, 0.3f); cb = Vec4(0.0f, 1.0f, 0.0f, 1.0f); break;
969 case 3: ca = Vec4(0.0f, 0.3f, 1.0f, 1.0f); cb = Vec4(1.0f, 0.0f, 0.0f, 0.7f); break;
970 case 4: ca = Vec4(1.0f, 0.0f, 0.5f, 1.0f); cb = Vec4(0.0f, 1.0f, 0.0f, 0.5f); break;
971 case 5: ca = Vec4(0.7f, 1.0f, 0.0f, 1.0f); cb = Vec4(0.0f, 0.0f, 1.0f, 0.3f); break;
972 }
973
974 m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
975 fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), 8, ca, cb);
976 }
977
978 // Upload data and setup params.
979 m_texture->upload();
980
981 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
982 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS);
983 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT);
984 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter);
985 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
986 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
987
988 // Generate mipmap.
989 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
990 gl.generateMipmap(GL_TEXTURE_CUBE_MAP);
991 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
992
993 // Render all levels.
994 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
995 {
996 const int levelWidth = de::max(1, m_size >> levelNdx);
997 const int levelHeight = de::max(1, m_size >> levelNdx);
998
999 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1000 {
1001 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth*3, levelHeight*2, deStringHash(getName()) ^ deInt32Hash(levelNdx + faceNdx));
1002 const tcu::CubeFace face = tcu::CubeFace(faceNdx);
1003
1004 computeQuadTexCoordCube(texCoord, face);
1005
1006 gl.viewport(viewport.x, viewport.y, levelWidth, levelHeight);
1007 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);
1008
1009 resultTexture.allocLevel(face, levelNdx);
1010 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevelFace(levelNdx, face));
1011 }
1012 }
1013
1014 // Compare results
1015 {
1016 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
1017 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
1018 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0));
1019 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask);
1020 GenMipmapPrecision comparePrec;
1021
1022 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
1023 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits);
1024 comparePrec.filterBits = tcu::IVec3(4, 4, 0);
1025
1026 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
1027
1028 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" :
1029 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" :
1030 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : "");
1031 }
1032
1033 return STOP;
1034 }
1035
TextureMipmapTests(Context & context)1036 TextureMipmapTests::TextureMipmapTests (Context& context)
1037 : TestCaseGroup(context, "mipmap", "Mipmapping tests")
1038 {
1039 }
1040
~TextureMipmapTests(void)1041 TextureMipmapTests::~TextureMipmapTests (void)
1042 {
1043 }
1044
init(void)1045 void TextureMipmapTests::init (void)
1046 {
1047 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Mipmapping");
1048 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Filtering");
1049 addChild(group2D);
1050 addChild(groupCube);
1051
1052 static const struct
1053 {
1054 const char* name;
1055 deUint32 mode;
1056 } wrapModes[] =
1057 {
1058 { "clamp", GL_CLAMP_TO_EDGE },
1059 { "repeat", GL_REPEAT },
1060 { "mirror", GL_MIRRORED_REPEAT }
1061 };
1062
1063 static const struct
1064 {
1065 const char* name;
1066 deUint32 mode;
1067 } minFilterModes[] =
1068 {
1069 { "nearest_nearest", GL_NEAREST_MIPMAP_NEAREST },
1070 { "linear_nearest", GL_LINEAR_MIPMAP_NEAREST },
1071 { "nearest_linear", GL_NEAREST_MIPMAP_LINEAR },
1072 { "linear_linear", GL_LINEAR_MIPMAP_LINEAR }
1073 };
1074
1075 static const struct
1076 {
1077 CoordType type;
1078 const char* name;
1079 const char* desc;
1080 } coordTypes[] =
1081 {
1082 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" },
1083 { COORDTYPE_AFFINE, "affine", "Mipmapping with affine coordinate transform" },
1084 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" }
1085 };
1086
1087 static const struct
1088 {
1089 const char* name;
1090 deUint32 format;
1091 deUint32 dataType;
1092 } formats[] =
1093 {
1094 { "a8", GL_ALPHA, GL_UNSIGNED_BYTE },
1095 { "l8", GL_LUMINANCE, GL_UNSIGNED_BYTE },
1096 { "la88", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
1097 { "rgb565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
1098 { "rgb888", GL_RGB, GL_UNSIGNED_BYTE },
1099 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
1100 { "rgba5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
1101 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE }
1102 };
1103
1104 static const struct
1105 {
1106 const char* name;
1107 deUint32 hint;
1108 } genHints[] =
1109 {
1110 { "fastest", GL_FASTEST },
1111 { "nicest", GL_NICEST }
1112 };
1113
1114 static const struct
1115 {
1116 const char* name;
1117 int width;
1118 int height;
1119 } tex2DSizes[] =
1120 {
1121 { DE_NULL, 64, 64 }, // Default.
1122 { "non_square", 32, 64 }
1123 };
1124
1125 // 2D cases.
1126 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
1127 {
1128 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
1129 group2D->addChild(coordTypeGroup);
1130
1131 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1132 {
1133 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
1134 {
1135 // Add non_square variants to basic cases only.
1136 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
1137
1138 for (int size = 0; size < sizeEnd; size++)
1139 {
1140 std::ostringstream name;
1141 name << minFilterModes[minFilter].name
1142 << "_" << wrapModes[wrapMode].name;
1143
1144 if (tex2DSizes[size].name)
1145 name << "_" << tex2DSizes[size].name;
1146
1147 coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
1148 name.str().c_str(), "",
1149 coordTypes[coordType].type,
1150 minFilterModes[minFilter].mode,
1151 wrapModes[wrapMode].mode,
1152 wrapModes[wrapMode].mode,
1153 GL_RGBA, GL_UNSIGNED_BYTE,
1154 tex2DSizes[size].width, tex2DSizes[size].height));
1155 }
1156 }
1157 }
1158 }
1159
1160 // 2D bias variants.
1161 {
1162 tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
1163 group2D->addChild(biasGroup);
1164
1165 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1166 biasGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
1167 minFilterModes[minFilter].name, "",
1168 COORDTYPE_BASIC_BIAS,
1169 minFilterModes[minFilter].mode,
1170 GL_REPEAT, GL_REPEAT,
1171 GL_RGBA, GL_UNSIGNED_BYTE,
1172 tex2DSizes[0].width, tex2DSizes[0].height));
1173 }
1174
1175 // 2D mipmap generation variants.
1176 {
1177 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
1178 group2D->addChild(genMipmapGroup);
1179
1180 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
1181 {
1182 for (int size = 0; size < DE_LENGTH_OF_ARRAY(tex2DSizes); size++)
1183 {
1184 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
1185 {
1186 std::ostringstream name;
1187 name << formats[format].name;
1188
1189 if (tex2DSizes[size].name)
1190 name << "_" << tex2DSizes[size].name;
1191
1192 name << "_" << genHints[hint].name;
1193
1194 genMipmapGroup->addChild(new Texture2DGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
1195 formats[format].format, formats[format].dataType, genHints[hint].hint,
1196 tex2DSizes[size].width, tex2DSizes[size].height));
1197 }
1198 }
1199 }
1200 }
1201
1202 const int cubeMapSize = 64;
1203
1204 static const struct
1205 {
1206 CoordType type;
1207 const char* name;
1208 const char* desc;
1209 } cubeCoordTypes[] =
1210 {
1211 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" },
1212 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" },
1213 { COORDTYPE_BASIC_BIAS, "bias", "User-supplied bias value" }
1214 };
1215
1216 // Cubemap cases.
1217 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
1218 {
1219 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc);
1220 groupCube->addChild(coordTypeGroup);
1221
1222 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1223 {
1224 coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
1225 minFilterModes[minFilter].name, "",
1226 cubeCoordTypes[coordType].type,
1227 minFilterModes[minFilter].mode,
1228 GL_CLAMP_TO_EDGE,
1229 GL_CLAMP_TO_EDGE,
1230 GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize));
1231 }
1232 }
1233
1234 // Cubemap mipmap generation variants.
1235 {
1236 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
1237 groupCube->addChild(genMipmapGroup);
1238
1239 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
1240 {
1241 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
1242 {
1243 std::ostringstream name;
1244 name << formats[format].name
1245 << "_" << genHints[hint].name;
1246
1247 genMipmapGroup->addChild(new TextureCubeGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format, formats[format].dataType, genHints[hint].hint, cubeMapSize));
1248 }
1249 }
1250 }
1251 }
1252
1253 } // Functional
1254 } // gles2
1255 } // deqp
1256