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