1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Mipmapping tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fTextureMipmapTests.hpp"
25
26 #include "glsTextureTestUtil.hpp"
27 #include "gluTexture.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuMatrix.hpp"
32 #include "tcuMatrixUtil.hpp"
33 #include "tcuTexLookupVerifier.hpp"
34 #include "tcuVectorUtil.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37 #include "deString.h"
38 #include "glwFunctions.hpp"
39 #include "glwEnums.hpp"
40
41 using std::string;
42 using std::vector;
43 using namespace deqp::gls;
44
45 namespace deqp
46 {
47 namespace gles3
48 {
49 namespace Functional
50 {
51
52 using std::string;
53 using std::vector;
54 using tcu::IVec4;
55 using tcu::TestLog;
56 using tcu::Vec2;
57 using tcu::Vec3;
58 using tcu::Vec4;
59 using namespace gls::TextureTestUtil;
60 using namespace glu::TextureTestUtil;
61
getMinLodForCell(int cellNdx)62 static float getMinLodForCell(int cellNdx)
63 {
64 static const float s_values[] = {1.0f, 3.5f, 2.0f, -2.0f, 0.0f, 3.0f, 10.0f, 4.8f,
65 5.8f, 5.7f, -1.9f, 4.0f, 6.5f, 7.1f, -1e10, 1000.f};
66 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
67 }
68
getMaxLodForCell(int cellNdx)69 static float getMaxLodForCell(int cellNdx)
70 {
71 static const float s_values[] = {0.0f, 0.2f, 0.7f, 0.4f, 1.3f, 0.0f, 0.5f, 1.2f, -2.0f,
72 1.0f, 0.1f, 0.3f, 2.7f, 1.2f, 10.0f, -1000.f, 1e10f};
73 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
74 }
75
76 enum CoordType
77 {
78 COORDTYPE_BASIC, //!< texCoord = translateScale(position).
79 COORDTYPE_BASIC_BIAS, //!< Like basic, but with bias values.
80 COORDTYPE_AFFINE, //!< texCoord = translateScaleRotateShear(position).
81 COORDTYPE_PROJECTED, //!< Projected coordinates, w != 1
82
83 COORDTYPE_LAST
84 };
85
86 // Texture2DMipmapCase
87
88 class Texture2DMipmapCase : public tcu::TestCase
89 {
90 public:
91 Texture2DMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const glu::ContextInfo &renderCtxInfo,
92 const char *name, const char *desc, CoordType coordType, uint32_t minFilter, uint32_t wrapS,
93 uint32_t wrapT, uint32_t format, uint32_t dataType, int width, int height);
94 ~Texture2DMipmapCase(void);
95
96 void init(void);
97 void deinit(void);
98 IterateResult iterate(void);
99
100 private:
101 Texture2DMipmapCase(const Texture2DMipmapCase &other);
102 Texture2DMipmapCase &operator=(const Texture2DMipmapCase &other);
103
104 glu::RenderContext &m_renderCtx;
105 const glu::ContextInfo &m_renderCtxInfo;
106
107 CoordType m_coordType;
108 uint32_t m_minFilter;
109 uint32_t m_wrapS;
110 uint32_t m_wrapT;
111 uint32_t m_format;
112 uint32_t m_dataType;
113 int m_width;
114 int m_height;
115
116 glu::Texture2D *m_texture;
117 TextureRenderer m_renderer;
118 };
119
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)120 Texture2DMipmapCase::Texture2DMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
121 const glu::ContextInfo &renderCtxInfo, const char *name, const char *desc,
122 CoordType coordType, uint32_t minFilter, uint32_t wrapS, uint32_t wrapT,
123 uint32_t format, uint32_t dataType, int width, int height)
124 : TestCase(testCtx, name, desc)
125 , m_renderCtx(renderCtx)
126 , m_renderCtxInfo(renderCtxInfo)
127 , m_coordType(coordType)
128 , m_minFilter(minFilter)
129 , m_wrapS(wrapS)
130 , m_wrapT(wrapT)
131 , m_format(format)
132 , m_dataType(dataType)
133 , m_width(width)
134 , m_height(height)
135 , m_texture(DE_NULL)
136 , m_renderer(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
137 {
138 }
139
~Texture2DMipmapCase(void)140 Texture2DMipmapCase::~Texture2DMipmapCase(void)
141 {
142 deinit();
143 }
144
init(void)145 void Texture2DMipmapCase::init(void)
146 {
147 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
148 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
149
150 m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
151
152 int numLevels = deLog2Floor32(de::max(m_width, m_height)) + 1;
153
154 // Fill texture with colored grid.
155 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
156 {
157 uint32_t step = 0xff / (numLevels - 1);
158 uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
159 uint32_t dec = 0xff - inc;
160 uint32_t rgb = (inc << 16) | (dec << 8) | 0xff;
161 uint32_t color = 0xff000000 | rgb;
162
163 m_texture->getRefTexture().allocLevel(levelNdx);
164 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec());
165 }
166 }
167
deinit(void)168 void Texture2DMipmapCase::deinit(void)
169 {
170 delete m_texture;
171 m_texture = DE_NULL;
172
173 m_renderer.clear();
174 }
175
getBasicTexCoord2D(std::vector<float> & dst,int cellNdx)176 static void getBasicTexCoord2D(std::vector<float> &dst, int cellNdx)
177 {
178 static const struct
179 {
180 Vec2 bottomLeft;
181 Vec2 topRight;
182 } s_basicCoords[] = {
183 {Vec2(-0.1f, 0.1f), Vec2(0.8f, 1.0f)}, {Vec2(-0.3f, -0.6f), Vec2(0.7f, 0.4f)},
184 {Vec2(-0.3f, 0.6f), Vec2(0.7f, -0.9f)}, {Vec2(-0.8f, 0.6f), Vec2(0.7f, -0.9f)},
185
186 {Vec2(-0.5f, -0.5f), Vec2(1.5f, 1.5f)}, {Vec2(1.0f, -1.0f), Vec2(-1.3f, 1.0f)},
187 {Vec2(1.2f, -1.0f), Vec2(-1.3f, 1.6f)}, {Vec2(2.2f, -1.1f), Vec2(-1.3f, 0.8f)},
188
189 {Vec2(-1.5f, 1.6f), Vec2(1.7f, -1.4f)}, {Vec2(2.0f, 1.6f), Vec2(2.3f, -1.4f)},
190 {Vec2(1.3f, -2.6f), Vec2(-2.7f, 2.9f)}, {Vec2(-0.8f, -6.6f), Vec2(6.0f, -0.9f)},
191
192 {Vec2(-8.0f, 9.0f), Vec2(8.3f, -7.0f)}, {Vec2(-16.0f, 10.0f), Vec2(18.3f, 24.0f)},
193 {Vec2(30.2f, 55.0f), Vec2(-24.3f, -1.6f)}, {Vec2(-33.2f, 64.1f), Vec2(32.1f, -64.1f)},
194 };
195
196 DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
197
198 const Vec2 &bottomLeft = s_basicCoords[cellNdx].bottomLeft;
199 const Vec2 &topRight = s_basicCoords[cellNdx].topRight;
200
201 computeQuadTexCoord2D(dst, bottomLeft, topRight);
202 }
203
getAffineTexCoord2D(std::vector<float> & dst,int cellNdx)204 static void getAffineTexCoord2D(std::vector<float> &dst, int cellNdx)
205 {
206 // Use basic coords as base.
207 getBasicTexCoord2D(dst, cellNdx);
208
209 // Rotate based on cell index.
210 float angle = 2.0f * DE_PI * ((float)cellNdx / 16.0f);
211 tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle);
212
213 // Second and third row are sheared.
214 float shearX = de::inRange(cellNdx, 4, 11) ? (float)(15 - cellNdx) / 16.0f : 0.0f;
215 tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
216
217 tcu::Mat2 transform = rotMatrix * shearMatrix;
218 Vec2 p0 = transform * Vec2(dst[0], dst[1]);
219 Vec2 p1 = transform * Vec2(dst[2], dst[3]);
220 Vec2 p2 = transform * Vec2(dst[4], dst[5]);
221 Vec2 p3 = transform * Vec2(dst[6], dst[7]);
222
223 dst[0] = p0.x();
224 dst[1] = p0.y();
225 dst[2] = p1.x();
226 dst[3] = p1.y();
227 dst[4] = p2.x();
228 dst[5] = p2.y();
229 dst[6] = p3.x();
230 dst[7] = p3.y();
231 }
232
iterate(void)233 Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate(void)
234 {
235 const glw::Functions &gl = m_renderCtx.getFunctions();
236
237 const tcu::Texture2D &refTexture = m_texture->getRefTexture();
238
239 const uint32_t magFilter = GL_NEAREST;
240 const int texWidth = refTexture.getWidth();
241 const int texHeight = refTexture.getHeight();
242 const int defViewportWidth = texWidth * 4;
243 const int defViewportHeight = texHeight * 4;
244
245 const RandomViewport viewport(m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight,
246 deStringHash(getName()));
247 ReferenceParams sampleParams(TEXTURETYPE_2D);
248 vector<float> texCoord;
249
250 const bool isProjected = m_coordType == COORDTYPE_PROJECTED;
251 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS;
252
253 tcu::Surface renderedFrame(viewport.width, viewport.height);
254
255 // Viewport is divided into 4x4 grid.
256 int gridWidth = 4;
257 int gridHeight = 4;
258 int cellWidth = viewport.width / gridWidth;
259 int cellHeight = viewport.height / gridHeight;
260
261 // Bail out if rendertarget is too small.
262 if (viewport.width < defViewportWidth / 2 || viewport.height < defViewportHeight / 2)
263 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
264
265 // Sampling parameters.
266 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
267 sampleParams.samplerType = glu::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat());
268 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
269 sampleParams.lodMode = LODMODE_EXACT; // Use ideal lod.
270
271 // Upload texture data.
272 m_texture->upload();
273
274 // Bind gradient texture and setup sampler parameters.
275 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
276 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
277 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
278 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
279 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
280
281 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
282
283 // Bias values.
284 static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
285
286 // Projection values.
287 static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 2.0f),
288 Vec4(0.8f, 1.0f, 1.7f, 0.6f), Vec4(1.2f, 1.0f, 1.7f, 1.5f)};
289
290 // Render cells.
291 for (int gridY = 0; gridY < gridHeight; gridY++)
292 {
293 for (int gridX = 0; gridX < gridWidth; gridX++)
294 {
295 const int curX = cellWidth * gridX;
296 const int curY = cellHeight * gridY;
297 const int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
298 const int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
299 const int cellNdx = gridY * gridWidth + gridX;
300
301 // Compute texcoord.
302 switch (m_coordType)
303 {
304 case COORDTYPE_BASIC_BIAS: // Fall-through.
305 case COORDTYPE_PROJECTED:
306 case COORDTYPE_BASIC:
307 getBasicTexCoord2D(texCoord, cellNdx);
308 break;
309 case COORDTYPE_AFFINE:
310 getAffineTexCoord2D(texCoord, cellNdx);
311 break;
312 default:
313 DE_ASSERT(false);
314 }
315
316 if (isProjected)
317 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
318
319 if (useLodBias)
320 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
321
322 // Render with GL.
323 gl.viewport(viewport.x + curX, viewport.y + curY, curW, curH);
324 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
325 }
326 }
327
328 // Read result.
329 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
330
331 // Compare and log.
332 {
333 const tcu::PixelFormat &pixelFormat = m_renderCtx.getRenderTarget().getPixelFormat();
334 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
335 tcu::Surface referenceFrame(viewport.width, viewport.height);
336 tcu::Surface errorMask(viewport.width, viewport.height);
337 tcu::LookupPrecision lookupPrec;
338 tcu::LodPrecision lodPrec;
339 int numFailedPixels = 0;
340
341 lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
342 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
343 lookupPrec.colorThreshold =
344 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
345 lookupPrec.colorMask = getCompareMask(pixelFormat);
346 lodPrec.derivateBits = 10;
347 lodPrec.lodBits = isProjected ? 6 : 8;
348
349 for (int gridY = 0; gridY < gridHeight; gridY++)
350 {
351 for (int gridX = 0; gridX < gridWidth; gridX++)
352 {
353 const int curX = cellWidth * gridX;
354 const int curY = cellHeight * gridY;
355 const int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
356 const int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
357 const int cellNdx = gridY * gridWidth + gridX;
358
359 // Compute texcoord.
360 switch (m_coordType)
361 {
362 case COORDTYPE_BASIC_BIAS: // Fall-through.
363 case COORDTYPE_PROJECTED:
364 case COORDTYPE_BASIC:
365 getBasicTexCoord2D(texCoord, cellNdx);
366 break;
367 case COORDTYPE_AFFINE:
368 getAffineTexCoord2D(texCoord, cellNdx);
369 break;
370 default:
371 DE_ASSERT(false);
372 }
373
374 if (isProjected)
375 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
376
377 if (useLodBias)
378 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
379
380 // Render ideal result
381 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
382 &texCoord[0], sampleParams);
383
384 // Compare this cell
385 numFailedPixels += computeTextureLookupDiff(
386 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
387 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
388 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getRefTexture(),
389 &texCoord[0], sampleParams, lookupPrec, lodPrec, m_testCtx.getWatchDog());
390 }
391 }
392
393 if (numFailedPixels > 0)
394 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels
395 << " invalid pixels!" << TestLog::EndMessage;
396
397 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
398 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
399
400 if (numFailedPixels > 0)
401 {
402 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
403 << TestLog::Image("ErrorMask", "Error mask", errorMask);
404 }
405
406 m_testCtx.getLog() << TestLog::EndImageSet;
407
408 {
409 const bool isOk = numFailedPixels == 0;
410 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
411 isOk ? "Pass" : "Image verification failed");
412 }
413 }
414
415 return STOP;
416 }
417
418 // TextureCubeMipmapCase
419
420 class TextureCubeMipmapCase : public tcu::TestCase
421 {
422 public:
423 TextureCubeMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
424 const glu::ContextInfo &renderCtxInfo, const char *name, const char *desc,
425 CoordType coordType, uint32_t minFilter, uint32_t wrapS, uint32_t wrapT, uint32_t format,
426 uint32_t dataType, int size);
427 ~TextureCubeMipmapCase(void);
428
429 void init(void);
430 void deinit(void);
431 IterateResult iterate(void);
432
433 private:
434 TextureCubeMipmapCase(const TextureCubeMipmapCase &other);
435 TextureCubeMipmapCase &operator=(const TextureCubeMipmapCase &other);
436
437 glu::RenderContext &m_renderCtx;
438 const glu::ContextInfo &m_renderCtxInfo;
439
440 CoordType m_coordType;
441 uint32_t m_minFilter;
442 uint32_t m_wrapS;
443 uint32_t m_wrapT;
444 uint32_t m_format;
445 uint32_t m_dataType;
446 int m_size;
447
448 glu::TextureCube *m_texture;
449 TextureRenderer m_renderer;
450 };
451
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)452 TextureCubeMipmapCase::TextureCubeMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
453 const glu::ContextInfo &renderCtxInfo, const char *name, const char *desc,
454 CoordType coordType, uint32_t minFilter, uint32_t wrapS, uint32_t wrapT,
455 uint32_t format, uint32_t dataType, int size)
456 : TestCase(testCtx, name, desc)
457 , m_renderCtx(renderCtx)
458 , m_renderCtxInfo(renderCtxInfo)
459 , m_coordType(coordType)
460 , m_minFilter(minFilter)
461 , m_wrapS(wrapS)
462 , m_wrapT(wrapT)
463 , m_format(format)
464 , m_dataType(dataType)
465 , m_size(size)
466 , m_texture(DE_NULL)
467 , m_renderer(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
468 {
469 }
470
~TextureCubeMipmapCase(void)471 TextureCubeMipmapCase::~TextureCubeMipmapCase(void)
472 {
473 deinit();
474 }
475
init(void)476 void TextureCubeMipmapCase::init(void)
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 glu::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 // Upload texture data.
588 m_texture->upload();
589
590 // Bind gradient texture and setup sampler parameters.
591 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
592 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS);
593 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT);
594 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
595 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
596
597 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
598
599 // Compute grid.
600 vector<IVec4> gridLayout;
601 computeGridLayout(gridLayout, viewport.width, viewport.height);
602
603 // Bias values.
604 static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
605
606 // Projection values \note Less agressive than in 2D case due to smaller quads.
607 static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 1.1f),
608 Vec4(0.8f, 1.0f, 1.2f, 0.8f), Vec4(1.2f, 1.0f, 1.3f, 0.9f)};
609
610 // Render with GL
611 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
612 {
613 const int curX = gridLayout[cellNdx].x();
614 const int curY = gridLayout[cellNdx].y();
615 const int curW = gridLayout[cellNdx].z();
616 const int curH = gridLayout[cellNdx].w();
617 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
618 RenderParams params(TEXTURETYPE_CUBE);
619
620 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
621 computeQuadTexCoordCube(texCoord, cubeFace);
622
623 if (isProjected)
624 {
625 params.flags |= ReferenceParams::PROJECTED;
626 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
627 }
628
629 if (useLodBias)
630 {
631 params.flags |= ReferenceParams::USE_BIAS;
632 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
633 }
634
635 // Render with GL.
636 gl.viewport(viewport.x + curX, viewport.y + curY, curW, curH);
637 m_renderer.renderQuad(0, &texCoord[0], params);
638 }
639 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
640
641 // Read result.
642 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
643 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
644
645 // Render reference and compare
646 {
647 tcu::Surface referenceFrame(viewport.width, viewport.height);
648 tcu::Surface errorMask(viewport.width, viewport.height);
649 int numFailedPixels = 0;
650 ReferenceParams params(TEXTURETYPE_CUBE);
651 tcu::LookupPrecision lookupPrec;
652 tcu::LodPrecision lodPrec;
653
654 // Params for rendering reference
655 params.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
656 params.sampler.seamlessCubeMap = true;
657 params.lodMode = LODMODE_EXACT;
658
659 // Comparison parameters
660 lookupPrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
661 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(
662 max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat()) - 2, IVec4(0)));
663 lookupPrec.coordBits = isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
664 lookupPrec.uvwBits = tcu::IVec3(5, 5, 0);
665 lodPrec.derivateBits = 10;
666 lodPrec.lodBits = isProjected ? 3 : 6;
667
668 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
669 {
670 const int curX = gridLayout[cellNdx].x();
671 const int curY = gridLayout[cellNdx].y();
672 const int curW = gridLayout[cellNdx].z();
673 const int curH = gridLayout[cellNdx].w();
674 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
675
676 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
677 computeQuadTexCoordCube(texCoord, cubeFace);
678
679 if (isProjected)
680 {
681 params.flags |= ReferenceParams::PROJECTED;
682 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
683 }
684
685 if (useLodBias)
686 {
687 params.flags |= ReferenceParams::USE_BIAS;
688 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
689 }
690
691 // Render ideal reference.
692 {
693 tcu::SurfaceAccess idealDst(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY,
694 curW, curH);
695 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
696 }
697
698 // Compare this cell
699 numFailedPixels += computeTextureLookupDiff(
700 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
701 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
702 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getRefTexture(),
703 &texCoord[0], params, lookupPrec, lodPrec, m_testCtx.getWatchDog());
704 }
705
706 if (numFailedPixels > 0)
707 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels
708 << " invalid pixels!" << TestLog::EndMessage;
709
710 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
711 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
712
713 if (numFailedPixels > 0)
714 {
715 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
716 << TestLog::Image("ErrorMask", "Error mask", errorMask);
717 }
718
719 m_testCtx.getLog() << TestLog::EndImageSet;
720
721 {
722 const bool isOk = numFailedPixels == 0;
723 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
724 isOk ? "Pass" : "Image verification failed");
725 }
726 }
727
728 return STOP;
729 }
730
731 // Texture2DGenMipmapCase
732
733 class Texture2DGenMipmapCase : public tcu::TestCase
734 {
735 public:
736 Texture2DGenMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const char *name, const char *desc,
737 uint32_t format, uint32_t dataType, uint32_t hint, int width, int height);
738 ~Texture2DGenMipmapCase(void);
739
740 void init(void);
741 void deinit(void);
742 IterateResult iterate(void);
743
744 private:
745 Texture2DGenMipmapCase(const Texture2DGenMipmapCase &other);
746 Texture2DGenMipmapCase &operator=(const Texture2DGenMipmapCase &other);
747
748 glu::RenderContext &m_renderCtx;
749
750 uint32_t m_format;
751 uint32_t m_dataType;
752 uint32_t m_hint;
753 int m_width;
754 int m_height;
755
756 glu::Texture2D *m_texture;
757 TextureRenderer m_renderer;
758 };
759
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)760 Texture2DGenMipmapCase::Texture2DGenMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
761 const char *name, const char *desc, uint32_t format, uint32_t dataType,
762 uint32_t hint, int width, int height)
763 : TestCase(testCtx, name, desc)
764 , m_renderCtx(renderCtx)
765 , m_format(format)
766 , m_dataType(dataType)
767 , m_hint(hint)
768 , m_width(width)
769 , m_height(height)
770 , m_texture(DE_NULL)
771 , m_renderer(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
772 {
773 }
774
~Texture2DGenMipmapCase(void)775 Texture2DGenMipmapCase::~Texture2DGenMipmapCase(void)
776 {
777 deinit();
778 }
779
init(void)780 void Texture2DGenMipmapCase::init(void)
781 {
782 DE_ASSERT(!m_texture);
783 m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
784 }
785
deinit(void)786 void Texture2DGenMipmapCase::deinit(void)
787 {
788 delete m_texture;
789 m_texture = DE_NULL;
790
791 m_renderer.clear();
792 }
793
iterate(void)794 Texture2DGenMipmapCase::IterateResult Texture2DGenMipmapCase::iterate(void)
795 {
796 const glw::Functions &gl = m_renderCtx.getFunctions();
797
798 const uint32_t minFilter = GL_NEAREST_MIPMAP_NEAREST;
799 const uint32_t magFilter = GL_NEAREST;
800 const uint32_t wrapS = GL_CLAMP_TO_EDGE;
801 const uint32_t wrapT = GL_CLAMP_TO_EDGE;
802
803 const int numLevels = deLog2Floor32(de::max(m_width, m_height)) + 1;
804
805 tcu::Texture2D resultTexture(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
806 m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight());
807
808 vector<float> texCoord;
809
810 // Initialize texture level 0 with colored grid.
811 m_texture->getRefTexture().allocLevel(0);
812 tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 8, tcu::Vec4(1.0f, 0.5f, 0.0f, 0.5f),
813 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
814
815 // Upload data and setup params.
816 m_texture->upload();
817
818 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
819 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
820 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
821 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
822 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
823 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
824
825 // Generate mipmap.
826 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
827 gl.generateMipmap(GL_TEXTURE_2D);
828 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
829
830 // Use (0, 0) -> (1, 1) texture coordinates.
831 computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));
832
833 // Fetch resulting texture by rendering.
834 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
835 {
836 const int levelWidth = de::max(1, m_width >> levelNdx);
837 const int levelHeight = de::max(1, m_height >> levelNdx);
838 const RandomViewport viewport(m_renderCtx.getRenderTarget(), levelWidth, levelHeight,
839 deStringHash(getName()) + levelNdx);
840
841 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
842 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);
843
844 resultTexture.allocLevel(levelNdx);
845 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevel(levelNdx));
846 }
847
848 // Compare results
849 {
850 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat()) - 2, IVec4(0));
851 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
852 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0));
853 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask);
854 GenMipmapPrecision comparePrec;
855
856 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
857 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits);
858 comparePrec.filterBits = tcu::IVec3(4, 4, 0);
859
860 const qpTestResult compareResult =
861 compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
862
863 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" :
864 compareResult == QP_TEST_RESULT_QUALITY_WARNING ?
865 "Low-quality method used" :
866 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" :
867 "");
868 }
869
870 return STOP;
871 }
872
873 // TextureCubeGenMipmapCase
874
875 class TextureCubeGenMipmapCase : public tcu::TestCase
876 {
877 public:
878 TextureCubeGenMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const char *name,
879 const char *desc, uint32_t format, uint32_t dataType, uint32_t hint, int size);
880 ~TextureCubeGenMipmapCase(void);
881
882 void init(void);
883 void deinit(void);
884 IterateResult iterate(void);
885
886 private:
887 TextureCubeGenMipmapCase(const TextureCubeGenMipmapCase &other);
888 TextureCubeGenMipmapCase &operator=(const TextureCubeGenMipmapCase &other);
889
890 glu::RenderContext &m_renderCtx;
891
892 uint32_t m_format;
893 uint32_t m_dataType;
894 uint32_t m_hint;
895 int m_size;
896
897 glu::TextureCube *m_texture;
898 TextureRenderer m_renderer;
899 };
900
TextureCubeGenMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t hint,int size)901 TextureCubeGenMipmapCase::TextureCubeGenMipmapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
902 const char *name, const char *desc, uint32_t format,
903 uint32_t dataType, uint32_t hint, int size)
904 : TestCase(testCtx, name, desc)
905 , m_renderCtx(renderCtx)
906 , m_format(format)
907 , m_dataType(dataType)
908 , m_hint(hint)
909 , m_size(size)
910 , m_texture(DE_NULL)
911 , m_renderer(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
912 {
913 }
914
~TextureCubeGenMipmapCase(void)915 TextureCubeGenMipmapCase::~TextureCubeGenMipmapCase(void)
916 {
917 deinit();
918 }
919
init(void)920 void TextureCubeGenMipmapCase::init(void)
921 {
922 if (m_renderCtx.getRenderTarget().getWidth() < 3 * m_size || m_renderCtx.getRenderTarget().getHeight() < 2 * m_size)
923 throw tcu::NotSupportedError("Render target size must be at least (" + de::toString(3 * m_size) + ", " +
924 de::toString(2 * m_size) + ")");
925
926 DE_ASSERT(!m_texture);
927 m_texture = new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_size);
928 }
929
deinit(void)930 void TextureCubeGenMipmapCase::deinit(void)
931 {
932 delete m_texture;
933 m_texture = DE_NULL;
934
935 m_renderer.clear();
936 }
937
iterate(void)938 TextureCubeGenMipmapCase::IterateResult TextureCubeGenMipmapCase::iterate(void)
939 {
940 const glw::Functions &gl = m_renderCtx.getFunctions();
941
942 const uint32_t minFilter = GL_NEAREST_MIPMAP_NEAREST;
943 const uint32_t magFilter = GL_NEAREST;
944 const uint32_t wrapS = GL_CLAMP_TO_EDGE;
945 const uint32_t wrapT = GL_CLAMP_TO_EDGE;
946
947 tcu::TextureCube resultTexture(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
948 m_size);
949
950 const int numLevels = deLog2Floor32(m_size) + 1;
951 vector<float> texCoord;
952
953 // Initialize texture level 0 with colored grid.
954 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
955 {
956 Vec4 ca, cb; // Grid colors.
957
958 switch (face)
959 {
960 case 0:
961 ca = Vec4(1.0f, 0.3f, 0.0f, 0.7f);
962 cb = Vec4(0.0f, 0.0f, 1.0f, 1.0f);
963 break;
964 case 1:
965 ca = Vec4(0.0f, 1.0f, 0.5f, 0.5f);
966 cb = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
967 break;
968 case 2:
969 ca = Vec4(0.7f, 0.0f, 1.0f, 0.3f);
970 cb = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
971 break;
972 case 3:
973 ca = Vec4(0.0f, 0.3f, 1.0f, 1.0f);
974 cb = Vec4(1.0f, 0.0f, 0.0f, 0.7f);
975 break;
976 case 4:
977 ca = Vec4(1.0f, 0.0f, 0.5f, 1.0f);
978 cb = Vec4(0.0f, 1.0f, 0.0f, 0.5f);
979 break;
980 case 5:
981 ca = Vec4(0.7f, 1.0f, 0.0f, 1.0f);
982 cb = Vec4(0.0f, 0.0f, 1.0f, 0.3f);
983 break;
984 }
985
986 m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
987 fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), 8, ca, cb);
988 }
989
990 // Upload data and setup params.
991 m_texture->upload();
992
993 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
994 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS);
995 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT);
996 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter);
997 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
998 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
999
1000 // Generate mipmap.
1001 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
1002 gl.generateMipmap(GL_TEXTURE_CUBE_MAP);
1003 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
1004
1005 // Render all levels.
1006 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1007 {
1008 const int levelWidth = de::max(1, m_size >> levelNdx);
1009 const int levelHeight = de::max(1, m_size >> levelNdx);
1010
1011 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1012 {
1013 const RandomViewport viewport(m_renderCtx.getRenderTarget(), levelWidth * 3, levelHeight * 2,
1014 deStringHash(getName()) ^ deInt32Hash(levelNdx + faceNdx));
1015 const tcu::CubeFace face = tcu::CubeFace(faceNdx);
1016
1017 computeQuadTexCoordCube(texCoord, face);
1018
1019 gl.viewport(viewport.x, viewport.y, levelWidth, levelHeight);
1020 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);
1021
1022 resultTexture.allocLevel(face, levelNdx);
1023 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevelFace(levelNdx, face));
1024 }
1025 }
1026
1027 // Compare results
1028 {
1029 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat()) - 2, IVec4(0));
1030 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
1031 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0));
1032 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask);
1033 GenMipmapPrecision comparePrec;
1034
1035 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
1036 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits);
1037 comparePrec.filterBits = tcu::IVec3(4, 4, 0);
1038
1039 const qpTestResult compareResult =
1040 compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
1041
1042 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" :
1043 compareResult == QP_TEST_RESULT_QUALITY_WARNING ?
1044 "Low-quality method used" :
1045 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" :
1046 "");
1047 }
1048
1049 return STOP;
1050 }
1051
1052 // Texture3DMipmapCase
1053
1054 class Texture3DMipmapCase : public TestCase
1055 {
1056 public:
1057 Texture3DMipmapCase(Context &context, const char *name, const char *desc, CoordType coordType, uint32_t minFilter,
1058 uint32_t wrapS, uint32_t wrapT, uint32_t wrapR, uint32_t format, int width, int height,
1059 int depth);
1060 ~Texture3DMipmapCase(void);
1061
1062 void init(void);
1063 void deinit(void);
1064 IterateResult iterate(void);
1065
1066 private:
1067 Texture3DMipmapCase(const Texture3DMipmapCase &other);
1068 Texture3DMipmapCase &operator=(const Texture3DMipmapCase &other);
1069
1070 CoordType m_coordType;
1071 uint32_t m_minFilter;
1072 uint32_t m_wrapS;
1073 uint32_t m_wrapT;
1074 uint32_t m_wrapR;
1075 uint32_t m_internalFormat;
1076 int m_width;
1077 int m_height;
1078 int m_depth;
1079
1080 glu::Texture3D *m_texture;
1081 TextureTestUtil::TextureRenderer m_renderer;
1082 };
1083
Texture3DMipmapCase(Context & context,const char * name,const char * desc,CoordType coordType,uint32_t minFilter,uint32_t wrapS,uint32_t wrapT,uint32_t wrapR,uint32_t format,int width,int height,int depth)1084 Texture3DMipmapCase::Texture3DMipmapCase(Context &context, const char *name, const char *desc, CoordType coordType,
1085 uint32_t minFilter, uint32_t wrapS, uint32_t wrapT, uint32_t wrapR,
1086 uint32_t format, int width, int height, int depth)
1087 : TestCase(context, name, desc)
1088 , m_coordType(coordType)
1089 , m_minFilter(minFilter)
1090 , m_wrapS(wrapS)
1091 , m_wrapT(wrapT)
1092 , m_wrapR(wrapR)
1093 , m_internalFormat(format)
1094 , m_width(width)
1095 , m_height(height)
1096 , m_depth(depth)
1097 , m_texture(DE_NULL)
1098 , m_renderer(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES,
1099 glu::PRECISION_HIGHP)
1100 {
1101 }
1102
~Texture3DMipmapCase(void)1103 Texture3DMipmapCase::~Texture3DMipmapCase(void)
1104 {
1105 Texture3DMipmapCase::deinit();
1106 }
1107
init(void)1108 void Texture3DMipmapCase::init(void)
1109 {
1110 const tcu::TextureFormat &texFmt = glu::mapGLInternalFormat(m_internalFormat);
1111 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
1112 const tcu::Vec4 &cScale = fmtInfo.lookupScale;
1113 const tcu::Vec4 &cBias = fmtInfo.lookupBias;
1114 int numLevels = deLog2Floor32(de::max(de::max(m_width, m_height), m_depth)) + 1;
1115
1116 if (m_coordType == COORDTYPE_PROJECTED && m_context.getRenderTarget().getNumSamples() > 0)
1117 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
1118
1119 m_texture = new glu::Texture3D(m_context.getRenderContext(), m_internalFormat, m_width, m_height, m_depth);
1120
1121 // Fill texture with colored grid.
1122 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1123 {
1124 uint32_t step = 0xff / (numLevels - 1);
1125 uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
1126 uint32_t dec = 0xff - inc;
1127 uint32_t rgb = (0xff << 16) | (dec << 8) | inc;
1128 uint32_t color = 0xff000000 | rgb;
1129
1130 m_texture->getRefTexture().allocLevel(levelNdx);
1131 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec() * cScale + cBias);
1132 }
1133
1134 m_texture->upload();
1135 }
1136
deinit(void)1137 void Texture3DMipmapCase::deinit(void)
1138 {
1139 delete m_texture;
1140 m_texture = DE_NULL;
1141
1142 m_renderer.clear();
1143 }
1144
getBasicTexCoord3D(std::vector<float> & dst,int cellNdx)1145 static void getBasicTexCoord3D(std::vector<float> &dst, int cellNdx)
1146 {
1147 static const struct
1148 {
1149 float sScale;
1150 float sBias;
1151 float tScale;
1152 float tBias;
1153 float rScale;
1154 float rBias;
1155 } s_params[] = {// sScale sBias tScale tBias rScale rBias
1156 {0.9f, -0.1f, 0.7f, 0.3f, 0.8f, 0.9f}, {1.2f, -0.1f, 1.1f, 0.3f, 1.0f, 0.9f},
1157 {1.5f, 0.7f, 0.9f, -0.3f, 1.1f, 0.1f}, {1.2f, 0.7f, -2.3f, -0.3f, 1.1f, 0.2f},
1158 {1.1f, 0.8f, -1.3f, -0.3f, 2.9f, 0.9f}, {3.4f, 0.8f, 4.0f, 0.0f, -3.3f, -1.0f},
1159 {-3.4f, -0.1f, -4.0f, 0.0f, -5.1f, 1.0f}, {-4.0f, -0.1f, 3.4f, 0.1f, 5.7f, 0.0f},
1160 {-5.6f, 0.0f, 0.5f, 1.2f, 3.9f, 4.0f}, {5.0f, -2.0f, 3.1f, 1.2f, 5.1f, 0.2f},
1161 {2.5f, -2.0f, 6.3f, 3.0f, 5.1f, 0.2f}, {-8.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f},
1162 {3.8f, 0.0f, 9.7f, 1.0f, 7.0f, 0.7f}, {13.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f},
1163 {16.0f, 8.0f, 12.7f, 1.0f, 17.1f, 0.7f}, {15.3f, 0.0f, 20.1f, 3.0f, 33.0f, 3.2f}};
1164
1165 float sScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].sScale;
1166 float sBias = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].sBias;
1167 float tScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].tScale;
1168 float tBias = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].tBias;
1169 float rScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].rScale;
1170 float rBias = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].rBias;
1171
1172 dst.resize(3 * 4);
1173
1174 dst[0] = sBias;
1175 dst[1] = tBias;
1176 dst[2] = rBias;
1177 dst[3] = sBias;
1178 dst[4] = tBias + tScale;
1179 dst[5] = rBias + rScale * 0.5f;
1180 dst[6] = sBias + sScale;
1181 dst[7] = tBias;
1182 dst[8] = rBias + rScale * 0.5f;
1183 dst[9] = sBias + sScale;
1184 dst[10] = tBias + tScale;
1185 dst[11] = rBias + rScale;
1186 }
1187
getAffineTexCoord3D(std::vector<float> & dst,int cellNdx)1188 static void getAffineTexCoord3D(std::vector<float> &dst, int cellNdx)
1189 {
1190 // Use basic coords as base.
1191 getBasicTexCoord3D(dst, cellNdx);
1192
1193 // Rotate based on cell index.
1194 float angleX = 0.0f + 2.0f * DE_PI * ((float)cellNdx / 16.0f);
1195 float angleY = 1.0f + 2.0f * DE_PI * ((float)cellNdx / 32.0f);
1196 tcu::Mat3 rotMatrix = tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY);
1197
1198 Vec3 p0 = rotMatrix * Vec3(dst[0], dst[1], dst[2]);
1199 Vec3 p1 = rotMatrix * Vec3(dst[3], dst[4], dst[5]);
1200 Vec3 p2 = rotMatrix * Vec3(dst[6], dst[7], dst[8]);
1201 Vec3 p3 = rotMatrix * Vec3(dst[9], dst[10], dst[11]);
1202
1203 dst[0] = p0.x();
1204 dst[1] = p0.y();
1205 dst[2] = p0.z();
1206 dst[3] = p1.x();
1207 dst[4] = p1.y();
1208 dst[5] = p1.z();
1209 dst[6] = p2.x();
1210 dst[7] = p2.y();
1211 dst[8] = p2.z();
1212 dst[9] = p3.x();
1213 dst[10] = p3.y();
1214 dst[11] = p3.z();
1215 }
1216
iterate(void)1217 Texture3DMipmapCase::IterateResult Texture3DMipmapCase::iterate(void)
1218 {
1219 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1220
1221 const tcu::Texture3D &refTexture = m_texture->getRefTexture();
1222 const tcu::TextureFormat &texFmt = refTexture.getFormat();
1223 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
1224 const int texWidth = refTexture.getWidth();
1225 const int texHeight = refTexture.getHeight();
1226 const uint32_t magFilter = GL_NEAREST;
1227
1228 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
1229 const RandomViewport viewport(renderTarget, texWidth * 4, texHeight * 4, deStringHash(getName()));
1230
1231 const bool isProjected = m_coordType == COORDTYPE_PROJECTED;
1232 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS;
1233
1234 // Viewport is divided into 4x4 grid.
1235 const int gridWidth = 4;
1236 const int gridHeight = 4;
1237 const int cellWidth = viewport.width / gridWidth;
1238 const int cellHeight = viewport.height / gridHeight;
1239
1240 ReferenceParams sampleParams(TEXTURETYPE_3D);
1241
1242 tcu::Surface renderedFrame(viewport.width, viewport.height);
1243 vector<float> texCoord;
1244
1245 // Sampling parameters.
1246 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_wrapR, m_minFilter, magFilter);
1247 sampleParams.samplerType = getSamplerType(texFmt);
1248 sampleParams.colorBias = fmtInfo.lookupBias;
1249 sampleParams.colorScale = fmtInfo.lookupScale;
1250 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
1251
1252 // Bind texture and setup sampler parameters.
1253 gl.bindTexture(GL_TEXTURE_3D, m_texture->getGLTexture());
1254 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, m_wrapS);
1255 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, m_wrapT);
1256 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, m_wrapR);
1257 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_minFilter);
1258 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, magFilter);
1259
1260 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
1261
1262 // Bias values.
1263 static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
1264
1265 // Projection values.
1266 static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 2.0f),
1267 Vec4(0.8f, 1.0f, 1.7f, 0.6f), Vec4(1.2f, 1.0f, 1.7f, 1.5f)};
1268
1269 // Render cells.
1270 for (int gridY = 0; gridY < gridHeight; gridY++)
1271 {
1272 for (int gridX = 0; gridX < gridWidth; gridX++)
1273 {
1274 const int curX = cellWidth * gridX;
1275 const int curY = cellHeight * gridY;
1276 const int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
1277 const int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
1278 const int cellNdx = gridY * gridWidth + gridX;
1279
1280 // Compute texcoord.
1281 switch (m_coordType)
1282 {
1283 case COORDTYPE_BASIC_BIAS: // Fall-through.
1284 case COORDTYPE_PROJECTED:
1285 case COORDTYPE_BASIC:
1286 getBasicTexCoord3D(texCoord, cellNdx);
1287 break;
1288 case COORDTYPE_AFFINE:
1289 getAffineTexCoord3D(texCoord, cellNdx);
1290 break;
1291 default:
1292 DE_ASSERT(false);
1293 }
1294
1295 // Set projection.
1296 if (isProjected)
1297 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
1298
1299 // Set LOD bias.
1300 if (useLodBias)
1301 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
1302
1303 // Render with GL.
1304 gl.viewport(viewport.x + curX, viewport.y + curY, curW, curH);
1305 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
1306 }
1307 }
1308
1309 // Read result.
1310 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
1311
1312 // Compare and log
1313 {
1314 const tcu::PixelFormat &pixelFormat = m_context.getRenderTarget().getPixelFormat();
1315 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
1316 tcu::Surface referenceFrame(viewport.width, viewport.height);
1317 tcu::Surface errorMask(viewport.width, viewport.height);
1318 tcu::LookupPrecision lookupPrec;
1319 tcu::LodPrecision lodPrec;
1320 int numFailedPixels = 0;
1321
1322 lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
1323 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
1324 lookupPrec.colorThreshold =
1325 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1326 lookupPrec.colorMask = getCompareMask(pixelFormat);
1327 lodPrec.derivateBits = 10;
1328 lodPrec.lodBits = isProjected ? 6 : 8;
1329
1330 for (int gridY = 0; gridY < gridHeight; gridY++)
1331 {
1332 for (int gridX = 0; gridX < gridWidth; gridX++)
1333 {
1334 const int curX = cellWidth * gridX;
1335 const int curY = cellHeight * gridY;
1336 const int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
1337 const int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
1338 const int cellNdx = gridY * gridWidth + gridX;
1339
1340 switch (m_coordType)
1341 {
1342 case COORDTYPE_BASIC_BIAS: // Fall-through.
1343 case COORDTYPE_PROJECTED:
1344 case COORDTYPE_BASIC:
1345 getBasicTexCoord3D(texCoord, cellNdx);
1346 break;
1347 case COORDTYPE_AFFINE:
1348 getAffineTexCoord3D(texCoord, cellNdx);
1349 break;
1350 default:
1351 DE_ASSERT(false);
1352 }
1353
1354 if (isProjected)
1355 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
1356
1357 if (useLodBias)
1358 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
1359
1360 // Render ideal result
1361 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
1362 &texCoord[0], sampleParams);
1363
1364 // Compare this cell
1365 numFailedPixels += computeTextureLookupDiff(
1366 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1367 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1368 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getRefTexture(),
1369 &texCoord[0], sampleParams, lookupPrec, lodPrec, m_testCtx.getWatchDog());
1370 }
1371 }
1372
1373 if (numFailedPixels > 0)
1374 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels
1375 << " invalid pixels!" << TestLog::EndMessage;
1376
1377 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
1378 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1379
1380 if (numFailedPixels > 0)
1381 {
1382 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1383 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1384 }
1385
1386 m_testCtx.getLog() << TestLog::EndImageSet;
1387
1388 {
1389 const bool isOk = numFailedPixels == 0;
1390 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1391 isOk ? "Pass" : "Image verification failed");
1392 }
1393 }
1394
1395 return STOP;
1396 }
1397
1398 // Texture2DLodControlCase + test cases
1399
1400 class Texture2DLodControlCase : public TestCase
1401 {
1402 public:
1403 Texture2DLodControlCase(Context &context, const char *name, const char *desc, uint32_t minFilter);
1404 ~Texture2DLodControlCase(void);
1405
1406 void init(void);
1407 void deinit(void);
1408 IterateResult iterate(void);
1409
1410 protected:
1411 virtual void setTextureParams(int cellNdx) = DE_NULL;
1412 virtual void getReferenceParams(ReferenceParams ¶ms, int cellNdx) = DE_NULL;
1413
1414 const int m_texWidth;
1415 const int m_texHeight;
1416
1417 private:
1418 Texture2DLodControlCase(const Texture2DLodControlCase &other);
1419 Texture2DLodControlCase &operator=(const Texture2DLodControlCase &other);
1420
1421 uint32_t m_minFilter;
1422
1423 glu::Texture2D *m_texture;
1424 TextureTestUtil::TextureRenderer m_renderer;
1425 };
1426
Texture2DLodControlCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1427 Texture2DLodControlCase::Texture2DLodControlCase(Context &context, const char *name, const char *desc,
1428 uint32_t minFilter)
1429 : TestCase(context, name, desc)
1430 , m_texWidth(64)
1431 , m_texHeight(64)
1432 , m_minFilter(minFilter)
1433 , m_texture(DE_NULL)
1434 , m_renderer(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES,
1435 glu::PRECISION_HIGHP)
1436 {
1437 }
1438
~Texture2DLodControlCase(void)1439 Texture2DLodControlCase::~Texture2DLodControlCase(void)
1440 {
1441 Texture2DLodControlCase::deinit();
1442 }
1443
init(void)1444 void Texture2DLodControlCase::init(void)
1445 {
1446 const uint32_t format = GL_RGBA8;
1447 int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1448
1449 m_texture = new glu::Texture2D(m_context.getRenderContext(), format, m_texWidth, m_texHeight);
1450
1451 // Fill texture with colored grid.
1452 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1453 {
1454 uint32_t step = 0xff / (numLevels - 1);
1455 uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
1456 uint32_t dec = 0xff - inc;
1457 uint32_t rgb = (inc << 16) | (dec << 8) | 0xff;
1458 uint32_t color = 0xff000000 | rgb;
1459
1460 m_texture->getRefTexture().allocLevel(levelNdx);
1461 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec());
1462 }
1463 }
1464
deinit(void)1465 void Texture2DLodControlCase::deinit(void)
1466 {
1467 delete m_texture;
1468 m_texture = DE_NULL;
1469
1470 m_renderer.clear();
1471 }
1472
iterate(void)1473 Texture2DLodControlCase::IterateResult Texture2DLodControlCase::iterate(void)
1474 {
1475 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1476
1477 const uint32_t wrapS = GL_REPEAT;
1478 const uint32_t wrapT = GL_REPEAT;
1479 const uint32_t magFilter = GL_NEAREST;
1480
1481 const tcu::Texture2D &refTexture = m_texture->getRefTexture();
1482 const int texWidth = refTexture.getWidth();
1483 const int texHeight = refTexture.getHeight();
1484
1485 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
1486 const RandomViewport viewport(renderTarget, texWidth * 4, texHeight * 4, deStringHash(getName()));
1487
1488 ReferenceParams sampleParams(TEXTURETYPE_2D, glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter));
1489 vector<float> texCoord;
1490 tcu::Surface renderedFrame(viewport.width, viewport.height);
1491
1492 // Viewport is divided into 4x4 grid.
1493 const int gridWidth = 4;
1494 const int gridHeight = 4;
1495 const int cellWidth = viewport.width / gridWidth;
1496 const int cellHeight = viewport.height / gridHeight;
1497
1498 // Upload texture data.
1499 m_texture->upload();
1500
1501 // Bind gradient texture and setup sampler parameters.
1502 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
1503 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
1504 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
1505 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
1506 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
1507
1508 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
1509
1510 // Render cells.
1511 for (int gridY = 0; gridY < gridHeight; gridY++)
1512 {
1513 for (int gridX = 0; gridX < gridWidth; gridX++)
1514 {
1515 int curX = cellWidth * gridX;
1516 int curY = cellHeight * gridY;
1517 int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
1518 int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
1519 int cellNdx = gridY * gridWidth + gridX;
1520
1521 // Compute texcoord.
1522 getBasicTexCoord2D(texCoord, cellNdx);
1523
1524 // Render with GL.
1525 setTextureParams(cellNdx);
1526 gl.viewport(viewport.x + curX, viewport.y + curY, curW, curH);
1527 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
1528 }
1529 }
1530
1531 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
1532 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
1533
1534 // Compare and log.
1535 {
1536 const tcu::PixelFormat &pixelFormat = m_context.getRenderTarget().getPixelFormat();
1537 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
1538 tcu::Surface referenceFrame(viewport.width, viewport.height);
1539 tcu::Surface errorMask(viewport.width, viewport.height);
1540 tcu::LookupPrecision lookupPrec;
1541 tcu::LodPrecision lodPrec;
1542 int numFailedPixels = 0;
1543
1544 lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
1545 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
1546 lookupPrec.colorThreshold =
1547 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1548 lookupPrec.colorMask = getCompareMask(pixelFormat);
1549 lodPrec.derivateBits = 10;
1550 lodPrec.lodBits = 8;
1551
1552 for (int gridY = 0; gridY < gridHeight; gridY++)
1553 {
1554 for (int gridX = 0; gridX < gridWidth; gridX++)
1555 {
1556 const int curX = cellWidth * gridX;
1557 const int curY = cellHeight * gridY;
1558 const int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
1559 const int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
1560 const int cellNdx = gridY * gridWidth + gridX;
1561
1562 getBasicTexCoord2D(texCoord, cellNdx);
1563 getReferenceParams(sampleParams, cellNdx);
1564
1565 // Render ideal result
1566 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
1567 &texCoord[0], sampleParams);
1568
1569 // Compare this cell
1570 numFailedPixels += computeTextureLookupDiff(
1571 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1572 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1573 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getRefTexture(),
1574 &texCoord[0], sampleParams, lookupPrec, lodPrec, m_testCtx.getWatchDog());
1575 }
1576 }
1577
1578 if (numFailedPixels > 0)
1579 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels
1580 << " invalid pixels!" << TestLog::EndMessage;
1581
1582 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
1583 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1584
1585 if (numFailedPixels > 0)
1586 {
1587 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1588 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1589 }
1590
1591 m_testCtx.getLog() << TestLog::EndImageSet;
1592
1593 {
1594 const bool isOk = numFailedPixels == 0;
1595 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1596 isOk ? "Pass" : "Image verification failed");
1597 }
1598 }
1599
1600 return STOP;
1601 }
1602
1603 class Texture2DMinLodCase : public Texture2DLodControlCase
1604 {
1605 public:
Texture2DMinLodCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1606 Texture2DMinLodCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
1607 : Texture2DLodControlCase(context, name, desc, minFilter)
1608 {
1609 }
1610
1611 protected:
setTextureParams(int cellNdx)1612 void setTextureParams(int cellNdx)
1613 {
1614 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1615 gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
1616 }
1617
getReferenceParams(ReferenceParams & params,int cellNdx)1618 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1619 {
1620 params.minLod = getMinLodForCell(cellNdx);
1621 }
1622 };
1623
1624 class Texture2DMaxLodCase : public Texture2DLodControlCase
1625 {
1626 public:
Texture2DMaxLodCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1627 Texture2DMaxLodCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
1628 : Texture2DLodControlCase(context, name, desc, minFilter)
1629 {
1630 }
1631
1632 protected:
setTextureParams(int cellNdx)1633 void setTextureParams(int cellNdx)
1634 {
1635 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1636 gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
1637 }
1638
getReferenceParams(ReferenceParams & params,int cellNdx)1639 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1640 {
1641 params.maxLod = getMaxLodForCell(cellNdx);
1642 }
1643 };
1644
1645 class Texture2DBaseLevelCase : public Texture2DLodControlCase
1646 {
1647 public:
Texture2DBaseLevelCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1648 Texture2DBaseLevelCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
1649 : Texture2DLodControlCase(context, name, desc, minFilter)
1650 {
1651 }
1652
1653 protected:
getBaseLevel(int cellNdx) const1654 int getBaseLevel(int cellNdx) const
1655 {
1656 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1657 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0xac2f274a) % numLevels;
1658
1659 return baseLevel;
1660 }
1661
setTextureParams(int cellNdx)1662 void setTextureParams(int cellNdx)
1663 {
1664 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1665 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
1666 }
1667
getReferenceParams(ReferenceParams & params,int cellNdx)1668 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1669 {
1670 params.baseLevel = getBaseLevel(cellNdx);
1671 }
1672 };
1673
1674 class Texture2DMaxLevelCase : public Texture2DLodControlCase
1675 {
1676 public:
Texture2DMaxLevelCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1677 Texture2DMaxLevelCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
1678 : Texture2DLodControlCase(context, name, desc, minFilter)
1679 {
1680 }
1681
1682 protected:
getMaxLevel(int cellNdx) const1683 int getMaxLevel(int cellNdx) const
1684 {
1685 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1686 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x82cfa4e) % numLevels;
1687
1688 return maxLevel;
1689 }
1690
setTextureParams(int cellNdx)1691 void setTextureParams(int cellNdx)
1692 {
1693 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1694 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
1695 }
1696
getReferenceParams(ReferenceParams & params,int cellNdx)1697 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1698 {
1699 params.maxLevel = getMaxLevel(cellNdx);
1700 }
1701 };
1702
1703 // TextureCubeLodControlCase + test cases
1704
1705 class TextureCubeLodControlCase : public TestCase
1706 {
1707 public:
1708 TextureCubeLodControlCase(Context &context, const char *name, const char *desc, uint32_t minFilter);
1709 ~TextureCubeLodControlCase(void);
1710
1711 void init(void);
1712 void deinit(void);
1713 IterateResult iterate(void);
1714
1715 protected:
1716 virtual void setTextureParams(int cellNdx) = DE_NULL;
1717 virtual void getReferenceParams(ReferenceParams ¶ms, int cellNdx) = DE_NULL;
1718
1719 const int m_texSize;
1720
1721 private:
1722 TextureCubeLodControlCase(const TextureCubeLodControlCase &other);
1723 TextureCubeLodControlCase &operator=(const TextureCubeLodControlCase &other);
1724
1725 uint32_t m_minFilter;
1726
1727 glu::TextureCube *m_texture;
1728 TextureTestUtil::TextureRenderer m_renderer;
1729 };
1730
TextureCubeLodControlCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1731 TextureCubeLodControlCase::TextureCubeLodControlCase(Context &context, const char *name, const char *desc,
1732 uint32_t minFilter)
1733 : TestCase(context, name, desc)
1734 , m_texSize(64)
1735 , m_minFilter(minFilter)
1736 , m_texture(DE_NULL)
1737 , m_renderer(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES,
1738 glu::PRECISION_HIGHP)
1739 {
1740 }
1741
~TextureCubeLodControlCase(void)1742 TextureCubeLodControlCase::~TextureCubeLodControlCase(void)
1743 {
1744 deinit();
1745 }
1746
init(void)1747 void TextureCubeLodControlCase::init(void)
1748 {
1749 const uint32_t format = GL_RGBA8;
1750 const int numLevels = deLog2Floor32(m_texSize) + 1;
1751
1752 m_texture = new glu::TextureCube(m_context.getRenderContext(), format, m_texSize);
1753
1754 // Fill texture with colored grid.
1755 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1756 {
1757 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1758 {
1759 uint32_t step = 0xff / (numLevels - 1);
1760 uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
1761 uint32_t dec = 0xff - inc;
1762 uint32_t rgb = 0;
1763
1764 switch (faceNdx)
1765 {
1766 case 0:
1767 rgb = (inc << 16) | (dec << 8) | 255;
1768 break;
1769 case 1:
1770 rgb = (255 << 16) | (inc << 8) | dec;
1771 break;
1772 case 2:
1773 rgb = (dec << 16) | (255 << 8) | inc;
1774 break;
1775 case 3:
1776 rgb = (dec << 16) | (inc << 8) | 255;
1777 break;
1778 case 4:
1779 rgb = (255 << 16) | (dec << 8) | inc;
1780 break;
1781 case 5:
1782 rgb = (inc << 16) | (255 << 8) | dec;
1783 break;
1784 }
1785
1786 uint32_t color = 0xff000000 | rgb;
1787
1788 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx);
1789 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx),
1790 tcu::RGBA(color).toVec());
1791 }
1792 }
1793 }
1794
deinit(void)1795 void TextureCubeLodControlCase::deinit(void)
1796 {
1797 delete m_texture;
1798 m_texture = DE_NULL;
1799
1800 m_renderer.clear();
1801 }
1802
iterate(void)1803 TextureCubeLodControlCase::IterateResult TextureCubeLodControlCase::iterate(void)
1804 {
1805 const uint32_t wrapS = GL_CLAMP_TO_EDGE;
1806 const uint32_t wrapT = GL_CLAMP_TO_EDGE;
1807 const uint32_t magFilter = GL_NEAREST;
1808
1809 const int texWidth = m_texture->getRefTexture().getSize();
1810 const int texHeight = m_texture->getRefTexture().getSize();
1811
1812 const int defViewportWidth = texWidth * 2;
1813 const int defViewportHeight = texHeight * 2;
1814
1815 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1816 const RandomViewport viewport(m_context.getRenderTarget(), defViewportWidth, defViewportHeight,
1817 deStringHash(getName()));
1818
1819 vector<float> texCoord;
1820
1821 tcu::Surface renderedFrame(viewport.width, viewport.height);
1822
1823 // Upload texture data.
1824 m_texture->upload();
1825
1826 // Bind gradient texture and setup sampler parameters.
1827 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
1828 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS);
1829 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT);
1830 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
1831 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
1832
1833 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
1834
1835 // Compute grid.
1836 vector<tcu::IVec4> gridLayout;
1837 computeGridLayout(gridLayout, viewport.width, viewport.height);
1838
1839 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1840 {
1841 const int curX = gridLayout[cellNdx].x();
1842 const int curY = gridLayout[cellNdx].y();
1843 const int curW = gridLayout[cellNdx].z();
1844 const int curH = gridLayout[cellNdx].w();
1845 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1846 RenderParams params(TEXTURETYPE_CUBE);
1847
1848 computeQuadTexCoordCube(texCoord, cubeFace);
1849
1850 setTextureParams(cellNdx);
1851
1852 // Render with GL.
1853 gl.viewport(viewport.x + curX, viewport.y + curY, curW, curH);
1854 m_renderer.renderQuad(0, &texCoord[0], params);
1855 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1856 }
1857
1858 // Read result.
1859 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
1860 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
1861
1862 // Render reference and compare
1863 {
1864 tcu::Surface referenceFrame(viewport.width, viewport.height);
1865 tcu::Surface errorMask(viewport.width, viewport.height);
1866 int numFailedPixels = 0;
1867 ReferenceParams params(TEXTURETYPE_CUBE);
1868 tcu::LookupPrecision lookupPrec;
1869 tcu::LodPrecision lodPrec;
1870
1871 // Params for rendering reference
1872 params.sampler = glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter);
1873 params.sampler.seamlessCubeMap = true;
1874 params.lodMode = LODMODE_EXACT;
1875
1876 // Comparison parameters
1877 lookupPrec.colorMask = getCompareMask(m_context.getRenderTarget().getPixelFormat());
1878 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(
1879 max(getBitsVec(m_context.getRenderTarget().getPixelFormat()) - 2, IVec4(0)));
1880 lookupPrec.coordBits = tcu::IVec3(10);
1881 lookupPrec.uvwBits = tcu::IVec3(5, 5, 0);
1882 lodPrec.derivateBits = 10;
1883 lodPrec.lodBits = 6;
1884
1885 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1886 {
1887 const int curX = gridLayout[cellNdx].x();
1888 const int curY = gridLayout[cellNdx].y();
1889 const int curW = gridLayout[cellNdx].z();
1890 const int curH = gridLayout[cellNdx].w();
1891 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1892
1893 computeQuadTexCoordCube(texCoord, cubeFace);
1894 getReferenceParams(params, cellNdx);
1895
1896 // Render ideal reference.
1897 {
1898 tcu::SurfaceAccess idealDst(referenceFrame, m_context.getRenderTarget().getPixelFormat(), curX, curY,
1899 curW, curH);
1900 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
1901 }
1902
1903 // Compare this cell
1904 numFailedPixels += computeTextureLookupDiff(
1905 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1906 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1907 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getRefTexture(),
1908 &texCoord[0], params, lookupPrec, lodPrec, m_testCtx.getWatchDog());
1909 }
1910
1911 if (numFailedPixels > 0)
1912 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels
1913 << " invalid pixels!" << TestLog::EndMessage;
1914
1915 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
1916 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1917
1918 if (numFailedPixels > 0)
1919 {
1920 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1921 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1922 }
1923
1924 m_testCtx.getLog() << TestLog::EndImageSet;
1925
1926 {
1927 const bool isOk = numFailedPixels == 0;
1928 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1929 isOk ? "Pass" : "Image verification failed");
1930 }
1931 }
1932
1933 return STOP;
1934 }
1935
1936 class TextureCubeMinLodCase : public TextureCubeLodControlCase
1937 {
1938 public:
TextureCubeMinLodCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1939 TextureCubeMinLodCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
1940 : TextureCubeLodControlCase(context, name, desc, minFilter)
1941 {
1942 }
1943
1944 protected:
setTextureParams(int cellNdx)1945 void setTextureParams(int cellNdx)
1946 {
1947 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1948 gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
1949 }
1950
getReferenceParams(ReferenceParams & params,int cellNdx)1951 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1952 {
1953 params.minLod = getMinLodForCell(cellNdx);
1954 }
1955 };
1956
1957 class TextureCubeMaxLodCase : public TextureCubeLodControlCase
1958 {
1959 public:
TextureCubeMaxLodCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1960 TextureCubeMaxLodCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
1961 : TextureCubeLodControlCase(context, name, desc, minFilter)
1962 {
1963 }
1964
1965 protected:
setTextureParams(int cellNdx)1966 void setTextureParams(int cellNdx)
1967 {
1968 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1969 gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
1970 }
1971
getReferenceParams(ReferenceParams & params,int cellNdx)1972 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1973 {
1974 params.maxLod = getMaxLodForCell(cellNdx);
1975 }
1976 };
1977
1978 class TextureCubeBaseLevelCase : public TextureCubeLodControlCase
1979 {
1980 public:
TextureCubeBaseLevelCase(Context & context,const char * name,const char * desc,uint32_t minFilter)1981 TextureCubeBaseLevelCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
1982 : TextureCubeLodControlCase(context, name, desc, minFilter)
1983 {
1984 }
1985
1986 protected:
getBaseLevel(int cellNdx) const1987 int getBaseLevel(int cellNdx) const
1988 {
1989 const int numLevels = deLog2Floor32(m_texSize) + 1;
1990 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x23fae13) % numLevels;
1991
1992 return baseLevel;
1993 }
1994
setTextureParams(int cellNdx)1995 void setTextureParams(int cellNdx)
1996 {
1997 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1998 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
1999 }
2000
getReferenceParams(ReferenceParams & params,int cellNdx)2001 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2002 {
2003 params.baseLevel = getBaseLevel(cellNdx);
2004 }
2005 };
2006
2007 class TextureCubeMaxLevelCase : public TextureCubeLodControlCase
2008 {
2009 public:
TextureCubeMaxLevelCase(Context & context,const char * name,const char * desc,uint32_t minFilter)2010 TextureCubeMaxLevelCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
2011 : TextureCubeLodControlCase(context, name, desc, minFilter)
2012 {
2013 }
2014
2015 protected:
getMaxLevel(int cellNdx) const2016 int getMaxLevel(int cellNdx) const
2017 {
2018 const int numLevels = deLog2Floor32(m_texSize) + 1;
2019 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x974e21) % numLevels;
2020
2021 return maxLevel;
2022 }
2023
setTextureParams(int cellNdx)2024 void setTextureParams(int cellNdx)
2025 {
2026 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2027 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
2028 }
2029
getReferenceParams(ReferenceParams & params,int cellNdx)2030 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2031 {
2032 params.maxLevel = getMaxLevel(cellNdx);
2033 }
2034 };
2035
2036 // Texture3DLodControlCase + test cases
2037
2038 class Texture3DLodControlCase : public TestCase
2039 {
2040 public:
2041 Texture3DLodControlCase(Context &context, const char *name, const char *desc, uint32_t minFilter);
2042 ~Texture3DLodControlCase(void);
2043
2044 void init(void);
2045 void deinit(void);
2046 IterateResult iterate(void);
2047
2048 protected:
2049 virtual void setTextureParams(int cellNdx) = DE_NULL;
2050 virtual void getReferenceParams(ReferenceParams ¶ms, int cellNdx) = DE_NULL;
2051
2052 const int m_texWidth;
2053 const int m_texHeight;
2054 const int m_texDepth;
2055
2056 private:
2057 Texture3DLodControlCase(const Texture3DLodControlCase &other);
2058 Texture3DLodControlCase &operator=(const Texture3DLodControlCase &other);
2059
2060 uint32_t m_minFilter;
2061
2062 glu::Texture3D *m_texture;
2063 TextureTestUtil::TextureRenderer m_renderer;
2064 };
2065
Texture3DLodControlCase(Context & context,const char * name,const char * desc,uint32_t minFilter)2066 Texture3DLodControlCase::Texture3DLodControlCase(Context &context, const char *name, const char *desc,
2067 uint32_t minFilter)
2068 : TestCase(context, name, desc)
2069 , m_texWidth(32)
2070 , m_texHeight(32)
2071 , m_texDepth(32)
2072 , m_minFilter(minFilter)
2073 , m_texture(DE_NULL)
2074 , m_renderer(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES,
2075 glu::PRECISION_HIGHP)
2076 {
2077 }
2078
~Texture3DLodControlCase(void)2079 Texture3DLodControlCase::~Texture3DLodControlCase(void)
2080 {
2081 Texture3DLodControlCase::deinit();
2082 }
2083
init(void)2084 void Texture3DLodControlCase::init(void)
2085 {
2086 const uint32_t format = GL_RGBA8;
2087 const tcu::TextureFormat &texFmt = glu::mapGLInternalFormat(format);
2088 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
2089 const tcu::Vec4 &cScale = fmtInfo.lookupScale;
2090 const tcu::Vec4 &cBias = fmtInfo.lookupBias;
2091 int numLevels = deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth)) + 1;
2092
2093 m_texture = new glu::Texture3D(m_context.getRenderContext(), format, m_texWidth, m_texHeight, m_texDepth);
2094
2095 // Fill texture with colored grid.
2096 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
2097 {
2098 uint32_t step = 0xff / (numLevels - 1);
2099 uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
2100 uint32_t dec = 0xff - inc;
2101 uint32_t rgb = (inc << 16) | (dec << 8) | 0xff;
2102 uint32_t color = 0xff000000 | rgb;
2103
2104 m_texture->getRefTexture().allocLevel(levelNdx);
2105 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec() * cScale + cBias);
2106 }
2107
2108 m_texture->upload();
2109 }
2110
deinit(void)2111 void Texture3DLodControlCase::deinit(void)
2112 {
2113 delete m_texture;
2114 m_texture = DE_NULL;
2115
2116 m_renderer.clear();
2117 }
2118
iterate(void)2119 Texture3DLodControlCase::IterateResult Texture3DLodControlCase::iterate(void)
2120 {
2121 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2122
2123 const uint32_t wrapS = GL_CLAMP_TO_EDGE;
2124 const uint32_t wrapT = GL_CLAMP_TO_EDGE;
2125 const uint32_t wrapR = GL_CLAMP_TO_EDGE;
2126 const uint32_t magFilter = GL_NEAREST;
2127 const tcu::Texture3D &refTexture = m_texture->getRefTexture();
2128 const tcu::TextureFormat &texFmt = refTexture.getFormat();
2129 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
2130 const int texWidth = refTexture.getWidth();
2131 const int texHeight = refTexture.getHeight();
2132
2133 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
2134 const RandomViewport viewport(renderTarget, texWidth * 4, texHeight * 4, deStringHash(getName()));
2135
2136 // Viewport is divided into 4x4 grid.
2137 const int gridWidth = 4;
2138 const int gridHeight = 4;
2139 const int cellWidth = viewport.width / gridWidth;
2140 const int cellHeight = viewport.height / gridHeight;
2141
2142 tcu::Surface renderedFrame(viewport.width, viewport.height);
2143 vector<float> texCoord;
2144 ReferenceParams sampleParams(TEXTURETYPE_3D);
2145
2146 // Sampling parameters.
2147 sampleParams.sampler = glu::mapGLSampler(wrapS, wrapT, wrapR, m_minFilter, magFilter);
2148 sampleParams.samplerType = getSamplerType(texFmt);
2149 sampleParams.colorBias = fmtInfo.lookupBias;
2150 sampleParams.colorScale = fmtInfo.lookupScale;
2151
2152 // Bind texture and setup sampler parameters.
2153 gl.bindTexture(GL_TEXTURE_3D, m_texture->getGLTexture());
2154 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrapS);
2155 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrapT);
2156 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrapR);
2157 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_minFilter);
2158 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, magFilter);
2159
2160 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
2161
2162 // Render cells.
2163 for (int gridY = 0; gridY < gridHeight; gridY++)
2164 {
2165 for (int gridX = 0; gridX < gridWidth; gridX++)
2166 {
2167 int curX = cellWidth * gridX;
2168 int curY = cellHeight * gridY;
2169 int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
2170 int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
2171 int cellNdx = gridY * gridWidth + gridX;
2172
2173 // Compute texcoord.
2174 getBasicTexCoord3D(texCoord, cellNdx);
2175
2176 setTextureParams(cellNdx);
2177
2178 // Render with GL.
2179 gl.viewport(viewport.x + curX, viewport.y + curY, curW, curH);
2180 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
2181 }
2182 }
2183
2184 // Read result.
2185 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
2186
2187 // Compare and log
2188 {
2189 const tcu::PixelFormat &pixelFormat = m_context.getRenderTarget().getPixelFormat();
2190 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
2191 tcu::Surface referenceFrame(viewport.width, viewport.height);
2192 tcu::Surface errorMask(viewport.width, viewport.height);
2193 tcu::LookupPrecision lookupPrec;
2194 tcu::LodPrecision lodPrec;
2195 int numFailedPixels = 0;
2196
2197 lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
2198 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
2199 lookupPrec.colorThreshold =
2200 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
2201 lookupPrec.colorMask = getCompareMask(pixelFormat);
2202 lodPrec.derivateBits = 10;
2203 lodPrec.lodBits = 8;
2204
2205 for (int gridY = 0; gridY < gridHeight; gridY++)
2206 {
2207 for (int gridX = 0; gridX < gridWidth; gridX++)
2208 {
2209 const int curX = cellWidth * gridX;
2210 const int curY = cellHeight * gridY;
2211 const int curW = gridX + 1 == gridWidth ? (viewport.width - curX) : cellWidth;
2212 const int curH = gridY + 1 == gridHeight ? (viewport.height - curY) : cellHeight;
2213 const int cellNdx = gridY * gridWidth + gridX;
2214
2215 getBasicTexCoord3D(texCoord, cellNdx);
2216 getReferenceParams(sampleParams, cellNdx);
2217
2218 // Render ideal result
2219 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
2220 &texCoord[0], sampleParams);
2221
2222 // Compare this cell
2223 numFailedPixels += computeTextureLookupDiff(
2224 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
2225 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
2226 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getRefTexture(),
2227 &texCoord[0], sampleParams, lookupPrec, lodPrec, m_testCtx.getWatchDog());
2228 }
2229 }
2230
2231 if (numFailedPixels > 0)
2232 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels
2233 << " invalid pixels!" << TestLog::EndMessage;
2234
2235 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
2236 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
2237
2238 if (numFailedPixels > 0)
2239 {
2240 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
2241 << TestLog::Image("ErrorMask", "Error mask", errorMask);
2242 }
2243
2244 m_testCtx.getLog() << TestLog::EndImageSet;
2245
2246 {
2247 const bool isOk = numFailedPixels == 0;
2248 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
2249 isOk ? "Pass" : "Image verification failed");
2250 }
2251 }
2252
2253 return STOP;
2254 }
2255
2256 class Texture3DMinLodCase : public Texture3DLodControlCase
2257 {
2258 public:
Texture3DMinLodCase(Context & context,const char * name,const char * desc,uint32_t minFilter)2259 Texture3DMinLodCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
2260 : Texture3DLodControlCase(context, name, desc, minFilter)
2261 {
2262 }
2263
2264 protected:
setTextureParams(int cellNdx)2265 void setTextureParams(int cellNdx)
2266 {
2267 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2268 gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
2269 }
2270
getReferenceParams(ReferenceParams & params,int cellNdx)2271 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2272 {
2273 params.minLod = getMinLodForCell(cellNdx);
2274 }
2275 };
2276
2277 class Texture3DMaxLodCase : public Texture3DLodControlCase
2278 {
2279 public:
Texture3DMaxLodCase(Context & context,const char * name,const char * desc,uint32_t minFilter)2280 Texture3DMaxLodCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
2281 : Texture3DLodControlCase(context, name, desc, minFilter)
2282 {
2283 }
2284
2285 protected:
setTextureParams(int cellNdx)2286 void setTextureParams(int cellNdx)
2287 {
2288 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2289 gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
2290 }
2291
getReferenceParams(ReferenceParams & params,int cellNdx)2292 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2293 {
2294 params.maxLod = getMaxLodForCell(cellNdx);
2295 }
2296 };
2297
2298 class Texture3DBaseLevelCase : public Texture3DLodControlCase
2299 {
2300 public:
Texture3DBaseLevelCase(Context & context,const char * name,const char * desc,uint32_t minFilter)2301 Texture3DBaseLevelCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
2302 : Texture3DLodControlCase(context, name, desc, minFilter)
2303 {
2304 }
2305
2306 protected:
getBaseLevel(int cellNdx) const2307 int getBaseLevel(int cellNdx) const
2308 {
2309 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
2310 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x7347e9) % numLevels;
2311
2312 return baseLevel;
2313 }
2314
setTextureParams(int cellNdx)2315 void setTextureParams(int cellNdx)
2316 {
2317 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2318 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
2319 }
2320
getReferenceParams(ReferenceParams & params,int cellNdx)2321 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2322 {
2323 params.baseLevel = getBaseLevel(cellNdx);
2324 }
2325 };
2326
2327 class Texture3DMaxLevelCase : public Texture3DLodControlCase
2328 {
2329 public:
Texture3DMaxLevelCase(Context & context,const char * name,const char * desc,uint32_t minFilter)2330 Texture3DMaxLevelCase(Context &context, const char *name, const char *desc, uint32_t minFilter)
2331 : Texture3DLodControlCase(context, name, desc, minFilter)
2332 {
2333 }
2334
2335 protected:
getMaxLevel(int cellNdx) const2336 int getMaxLevel(int cellNdx) const
2337 {
2338 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
2339 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x9111e7) % numLevels;
2340
2341 return maxLevel;
2342 }
2343
setTextureParams(int cellNdx)2344 void setTextureParams(int cellNdx)
2345 {
2346 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2347 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
2348 }
2349
getReferenceParams(ReferenceParams & params,int cellNdx)2350 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2351 {
2352 params.maxLevel = getMaxLevel(cellNdx);
2353 }
2354 };
2355
TextureMipmapTests(Context & context)2356 TextureMipmapTests::TextureMipmapTests(Context &context) : TestCaseGroup(context, "mipmap", "Mipmapping tests")
2357 {
2358 }
2359
~TextureMipmapTests(void)2360 TextureMipmapTests::~TextureMipmapTests(void)
2361 {
2362 }
2363
init(void)2364 void TextureMipmapTests::init(void)
2365 {
2366 tcu::TestCaseGroup *group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Mipmapping");
2367 tcu::TestCaseGroup *groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Mipmapping");
2368 tcu::TestCaseGroup *group3D = new tcu::TestCaseGroup(m_testCtx, "3d", "3D Texture Mipmapping");
2369 addChild(group2D);
2370 addChild(groupCube);
2371 addChild(group3D);
2372
2373 static const struct
2374 {
2375 const char *name;
2376 uint32_t mode;
2377 } wrapModes[] = {{"clamp", GL_CLAMP_TO_EDGE}, {"repeat", GL_REPEAT}, {"mirror", GL_MIRRORED_REPEAT}};
2378
2379 static const struct
2380 {
2381 const char *name;
2382 uint32_t mode;
2383 } minFilterModes[] = {{"nearest_nearest", GL_NEAREST_MIPMAP_NEAREST},
2384 {"linear_nearest", GL_LINEAR_MIPMAP_NEAREST},
2385 {"nearest_linear", GL_NEAREST_MIPMAP_LINEAR},
2386 {"linear_linear", GL_LINEAR_MIPMAP_LINEAR}};
2387
2388 static const struct
2389 {
2390 CoordType type;
2391 const char *name;
2392 const char *desc;
2393 } coordTypes[] = {{COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates"},
2394 {COORDTYPE_AFFINE, "affine", "Mipmapping with affine coordinate transform"},
2395 {COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection"}};
2396
2397 static const struct
2398 {
2399 const char *name;
2400 uint32_t format;
2401 uint32_t dataType;
2402 } formats[] = {{"a8", GL_ALPHA, GL_UNSIGNED_BYTE},
2403 {"l8", GL_LUMINANCE, GL_UNSIGNED_BYTE},
2404 {"la88", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
2405 {"rgb565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
2406 {"rgb888", GL_RGB, GL_UNSIGNED_BYTE},
2407 {"rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
2408 {"rgba5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
2409 {"rgba8888", GL_RGBA, GL_UNSIGNED_BYTE}};
2410
2411 static const struct
2412 {
2413 const char *name;
2414 uint32_t hint;
2415 } genHints[] = {{"fastest", GL_FASTEST}, {"nicest", GL_NICEST}};
2416
2417 static const struct
2418 {
2419 const char *name;
2420 int width;
2421 int height;
2422 } tex2DSizes[] = {{DE_NULL, 64, 64}, // Default.
2423 {"npot", 63, 57},
2424 {"non_square", 32, 64}};
2425
2426 static const struct
2427 {
2428 const char *name;
2429 int width;
2430 int height;
2431 int depth;
2432 } tex3DSizes[] = {{DE_NULL, 32, 32, 32}, // Default.
2433 {"npot", 33, 29, 27}};
2434
2435 const int cubeMapSize = 64;
2436
2437 static const struct
2438 {
2439 CoordType type;
2440 const char *name;
2441 const char *desc;
2442 } cubeCoordTypes[] = {{COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates"},
2443 {COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection"},
2444 {COORDTYPE_BASIC_BIAS, "bias", "User-supplied bias value"}};
2445
2446 // 2D cases.
2447 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
2448 {
2449 tcu::TestCaseGroup *coordTypeGroup =
2450 new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
2451 group2D->addChild(coordTypeGroup);
2452
2453 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2454 {
2455 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
2456 {
2457 // Add non_square variants to basic cases only.
2458 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
2459
2460 for (int size = 0; size < sizeEnd; size++)
2461 {
2462 std::ostringstream name;
2463 name << minFilterModes[minFilter].name << "_" << wrapModes[wrapMode].name;
2464
2465 if (tex2DSizes[size].name)
2466 name << "_" << tex2DSizes[size].name;
2467
2468 coordTypeGroup->addChild(new Texture2DMipmapCase(
2469 m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.str().c_str(), "",
2470 coordTypes[coordType].type, minFilterModes[minFilter].mode, wrapModes[wrapMode].mode,
2471 wrapModes[wrapMode].mode, GL_RGBA, GL_UNSIGNED_BYTE, tex2DSizes[size].width,
2472 tex2DSizes[size].height));
2473 }
2474 }
2475 }
2476 }
2477
2478 // 2D bias variants.
2479 {
2480 tcu::TestCaseGroup *biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
2481 group2D->addChild(biasGroup);
2482
2483 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2484 biasGroup->addChild(new Texture2DMipmapCase(
2485 m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), minFilterModes[minFilter].name, "",
2486 COORDTYPE_BASIC_BIAS, minFilterModes[minFilter].mode, GL_REPEAT, GL_REPEAT, GL_RGBA, GL_UNSIGNED_BYTE,
2487 tex2DSizes[0].width, tex2DSizes[0].height));
2488 }
2489
2490 // 2D mipmap generation variants.
2491 {
2492 tcu::TestCaseGroup *genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
2493 group2D->addChild(genMipmapGroup);
2494
2495 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
2496 {
2497 for (int size = 0; size < DE_LENGTH_OF_ARRAY(tex2DSizes); size++)
2498 {
2499 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
2500 {
2501 std::ostringstream name;
2502 name << formats[format].name;
2503
2504 if (tex2DSizes[size].name)
2505 name << "_" << tex2DSizes[size].name;
2506
2507 name << "_" << genHints[hint].name;
2508
2509 genMipmapGroup->addChild(new Texture2DGenMipmapCase(
2510 m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format,
2511 formats[format].dataType, genHints[hint].hint, tex2DSizes[size].width,
2512 tex2DSizes[size].height));
2513 }
2514 }
2515 }
2516 }
2517
2518 // 2D LOD controls.
2519 {
2520 // MIN_LOD
2521 tcu::TestCaseGroup *minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
2522 group2D->addChild(minLodGroup);
2523
2524 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2525 minLodGroup->addChild(
2526 new Texture2DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2527
2528 // MAX_LOD
2529 tcu::TestCaseGroup *maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
2530 group2D->addChild(maxLodGroup);
2531
2532 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2533 maxLodGroup->addChild(
2534 new Texture2DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2535
2536 // BASE_LEVEL
2537 tcu::TestCaseGroup *baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
2538 group2D->addChild(baseLevelGroup);
2539
2540 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2541 baseLevelGroup->addChild(new Texture2DBaseLevelCase(m_context, minFilterModes[minFilter].name, "",
2542 minFilterModes[minFilter].mode));
2543
2544 // MAX_LEVEL
2545 tcu::TestCaseGroup *maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
2546 group2D->addChild(maxLevelGroup);
2547
2548 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2549 maxLevelGroup->addChild(new Texture2DMaxLevelCase(m_context, minFilterModes[minFilter].name, "",
2550 minFilterModes[minFilter].mode));
2551 }
2552
2553 // Cubemap cases.
2554 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
2555 {
2556 tcu::TestCaseGroup *coordTypeGroup =
2557 new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc);
2558 groupCube->addChild(coordTypeGroup);
2559
2560 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2561 {
2562 coordTypeGroup->addChild(new TextureCubeMipmapCase(
2563 m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), minFilterModes[minFilter].name, "",
2564 cubeCoordTypes[coordType].type, minFilterModes[minFilter].mode, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
2565 GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize));
2566 }
2567 }
2568
2569 // Cubemap mipmap generation variants.
2570 {
2571 tcu::TestCaseGroup *genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
2572 groupCube->addChild(genMipmapGroup);
2573
2574 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
2575 {
2576 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
2577 {
2578 std::ostringstream name;
2579 name << formats[format].name << "_" << genHints[hint].name;
2580
2581 genMipmapGroup->addChild(new TextureCubeGenMipmapCase(
2582 m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format,
2583 formats[format].dataType, genHints[hint].hint, cubeMapSize));
2584 }
2585 }
2586 }
2587
2588 // Cubemap LOD controls.
2589 {
2590 // MIN_LOD
2591 tcu::TestCaseGroup *minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
2592 groupCube->addChild(minLodGroup);
2593
2594 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2595 minLodGroup->addChild(new TextureCubeMinLodCase(m_context, minFilterModes[minFilter].name, "",
2596 minFilterModes[minFilter].mode));
2597
2598 // MAX_LOD
2599 tcu::TestCaseGroup *maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
2600 groupCube->addChild(maxLodGroup);
2601
2602 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2603 maxLodGroup->addChild(new TextureCubeMaxLodCase(m_context, minFilterModes[minFilter].name, "",
2604 minFilterModes[minFilter].mode));
2605
2606 // BASE_LEVEL
2607 tcu::TestCaseGroup *baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
2608 groupCube->addChild(baseLevelGroup);
2609
2610 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2611 baseLevelGroup->addChild(new TextureCubeBaseLevelCase(m_context, minFilterModes[minFilter].name, "",
2612 minFilterModes[minFilter].mode));
2613
2614 // MAX_LEVEL
2615 tcu::TestCaseGroup *maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
2616 groupCube->addChild(maxLevelGroup);
2617
2618 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2619 maxLevelGroup->addChild(new TextureCubeMaxLevelCase(m_context, minFilterModes[minFilter].name, "",
2620 minFilterModes[minFilter].mode));
2621 }
2622
2623 // 3D cases.
2624 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
2625 {
2626 tcu::TestCaseGroup *coordTypeGroup =
2627 new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
2628 group3D->addChild(coordTypeGroup);
2629
2630 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2631 {
2632 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
2633 {
2634 // Add other size variants to basic cases only.
2635 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;
2636
2637 for (int size = 0; size < sizeEnd; size++)
2638 {
2639 std::ostringstream name;
2640 name << minFilterModes[minFilter].name << "_" << wrapModes[wrapMode].name;
2641
2642 if (tex3DSizes[size].name)
2643 name << "_" << tex3DSizes[size].name;
2644
2645 coordTypeGroup->addChild(new Texture3DMipmapCase(
2646 m_context, name.str().c_str(), "", coordTypes[coordType].type, minFilterModes[minFilter].mode,
2647 wrapModes[wrapMode].mode, wrapModes[wrapMode].mode, wrapModes[wrapMode].mode, GL_RGBA8,
2648 tex3DSizes[size].width, tex3DSizes[size].height, tex3DSizes[size].depth));
2649 }
2650 }
2651 }
2652 }
2653
2654 // 3D bias variants.
2655 {
2656 tcu::TestCaseGroup *biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
2657 group3D->addChild(biasGroup);
2658
2659 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2660 biasGroup->addChild(new Texture3DMipmapCase(m_context, minFilterModes[minFilter].name, "",
2661 COORDTYPE_BASIC_BIAS, minFilterModes[minFilter].mode, GL_REPEAT,
2662 GL_REPEAT, GL_REPEAT, GL_RGBA8, tex3DSizes[0].width,
2663 tex3DSizes[0].height, tex3DSizes[0].depth));
2664 }
2665
2666 // 3D LOD controls.
2667 {
2668 // MIN_LOD
2669 tcu::TestCaseGroup *minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
2670 group3D->addChild(minLodGroup);
2671
2672 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2673 minLodGroup->addChild(
2674 new Texture3DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2675
2676 // MAX_LOD
2677 tcu::TestCaseGroup *maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
2678 group3D->addChild(maxLodGroup);
2679
2680 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2681 maxLodGroup->addChild(
2682 new Texture3DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2683
2684 // BASE_LEVEL
2685 tcu::TestCaseGroup *baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
2686 group3D->addChild(baseLevelGroup);
2687
2688 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2689 baseLevelGroup->addChild(new Texture3DBaseLevelCase(m_context, minFilterModes[minFilter].name, "",
2690 minFilterModes[minFilter].mode));
2691
2692 // MAX_LEVEL
2693 tcu::TestCaseGroup *maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
2694 group3D->addChild(maxLevelGroup);
2695
2696 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2697 maxLevelGroup->addChild(new Texture3DMaxLevelCase(m_context, minFilterModes[minFilter].name, "",
2698 minFilterModes[minFilter].mode));
2699 }
2700 }
2701
2702 } // namespace Functional
2703 } // namespace gles3
2704 } // namespace deqp
2705