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