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