Merge Vulkan CTS 1.0.2.2 into goog/oc-dev
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fASTCDecompressionCases.cpp
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 ASTC decompression tests
22  *
23  * \todo Parts of the block-generation code are same as in decompression
24  *               code in tcuCompressedTexture.cpp ; could put them to some shared
25  *               ASTC utility file.
26  *
27  * \todo Tests for void extents with nontrivial extent coordinates.
28  *
29  * \todo Better checking of the error color. Currently legitimate error
30  *               pixels are just ignored in image comparison; however, spec says
31  *               that error color is either magenta or all-NaNs. Can NaNs cause
32  *               troubles, or can we assume that NaNs are well-supported in shader
33  *               if the implementation chooses NaNs as error color?
34  *//*--------------------------------------------------------------------*/
35
36 #include "es3fASTCDecompressionCases.hpp"
37 #include "gluTexture.hpp"
38 #include "gluPixelTransfer.hpp"
39 #include "gluStrUtil.hpp"
40 #include "gluTextureUtil.hpp"
41 #include "glsTextureTestUtil.hpp"
42 #include "tcuCompressedTexture.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuSurface.hpp"
46 #include "tcuVectorUtil.hpp"
47 #include "tcuImageCompare.hpp"
48 #include "deStringUtil.hpp"
49 #include "deRandom.hpp"
50 #include "deFloat16.h"
51 #include "deString.h"
52 #include "deMemory.h"
53
54 #include "glwFunctions.hpp"
55 #include "glwEnums.hpp"
56
57 #include <vector>
58 #include <string>
59 #include <algorithm>
60
61 using tcu::TestLog;
62 using tcu::CompressedTexture;
63 using tcu::CompressedTexFormat;
64 using tcu::IVec2;
65 using tcu::IVec3;
66 using tcu::IVec4;
67 using tcu::Vec2;
68 using tcu::Vec4;
69 using tcu::Sampler;
70 using tcu::Surface;
71 using tcu::astc::BlockTestType;
72 using std::vector;
73 using std::string;
74
75 namespace deqp
76 {
77
78 using gls::TextureTestUtil::TextureRenderer;
79 using gls::TextureTestUtil::RandomViewport;
80 using namespace glu::TextureTestUtil;
81
82 namespace gles3
83 {
84 namespace Functional
85 {
86
87 namespace ASTCDecompressionCaseInternal
88 {
89
90 // Get a string describing the data of an ASTC block. Currently contains just hex and bin dumps of the block.
91 static string astcBlockDataStr (const deUint8* data)
92 {
93         string result;
94         result += "  Hexadecimal (big endian: upper left hex digit is block bits 127 to 124):";
95
96         {
97                 static const char* const hexDigits = "0123456789ABCDEF";
98
99                 for (int i = tcu::astc::BLOCK_SIZE_BYTES-1; i >= 0; i--)
100                 {
101                         if ((i+1) % 2 == 0)
102                                 result += "\n    ";
103                         else
104                                 result += "  ";
105
106                         result += hexDigits[(data[i] & 0xf0) >> 4];
107                         result += " ";
108                         result += hexDigits[(data[i] & 0x0f) >> 0];
109                 }
110         }
111
112         result += "\n\n  Binary (big endian: upper left bit is block bit 127):";
113
114         for (int i = tcu::astc::BLOCK_SIZE_BYTES-1; i >= 0; i--)
115         {
116                 if ((i+1) % 2 == 0)
117                         result += "\n    ";
118                 else
119                         result += "  ";
120
121                 for (int j = 8-1; j >= 0; j--)
122                 {
123                         if (j == 3)
124                                 result += " ";
125
126                         result += (data[i] >> j) & 1 ? "1" : "0";
127                 }
128         }
129
130         result += "\n";
131
132         return result;
133 }
134
135 // Compare reference and result block images, reporting also the position of the first non-matching block.
136 static bool compareBlockImages (const Surface&          reference,
137                                                                 const Surface&          result,
138                                                                 const tcu::RGBA&        thresholdRGBA,
139                                                                 const IVec2&            blockSize,
140                                                                 int                                     numNonDummyBlocks,
141                                                                 IVec2&                          firstFailedBlockCoordDst,
142                                                                 Surface&                        errorMaskDst,
143                                                                 IVec4&                          maxDiffDst)
144 {
145         TCU_CHECK_INTERNAL(reference.getWidth() == result.getWidth() && reference.getHeight() == result.getHeight());
146
147         const int               width           = result.getWidth();
148         const int               height          = result.getHeight();
149         const IVec4             threshold       = thresholdRGBA.toIVec();
150         const int               numXBlocks      = width / blockSize.x();
151
152         DE_ASSERT(width % blockSize.x() == 0 && height % blockSize.y() == 0);
153
154         errorMaskDst.setSize(width, height);
155
156         firstFailedBlockCoordDst        = IVec2(-1, -1);
157         maxDiffDst                                      = IVec4(0);
158
159         for (int y = 0; y < height; y++)
160         for (int x = 0; x < width; x++)
161         {
162                 const IVec2 blockCoord = IVec2(x, y) / blockSize;
163
164                 if (blockCoord.y()*numXBlocks + blockCoord.x() < numNonDummyBlocks)
165                 {
166                         const IVec4 refPix = reference.getPixel(x, y).toIVec();
167
168                         if (refPix == IVec4(255, 0, 255, 255))
169                         {
170                                 // ASTC error color - allow anything in result.
171                                 errorMaskDst.setPixel(x, y, tcu::RGBA(255, 0, 255, 255));
172                                 continue;
173                         }
174
175                         const IVec4             resPix          = result.getPixel(x, y).toIVec();
176                         const IVec4             diff            = tcu::abs(refPix - resPix);
177                         const bool              isOk            = tcu::boolAll(tcu::lessThanEqual(diff, threshold));
178
179                         maxDiffDst = tcu::max(maxDiffDst, diff);
180
181                         errorMaskDst.setPixel(x, y, isOk ? tcu::RGBA::green() : tcu::RGBA::red());
182
183                         if (!isOk && firstFailedBlockCoordDst.x() == -1)
184                                 firstFailedBlockCoordDst = blockCoord;
185                 }
186         }
187
188         return boolAll(lessThanEqual(maxDiffDst, threshold));
189 }
190
191 enum ASTCSupportLevel
192 {
193         // \note Ordered from smallest subset to full, for convenient comparison.
194         ASTCSUPPORTLEVEL_NONE = 0,
195         ASTCSUPPORTLEVEL_LDR,
196         ASTCSUPPORTLEVEL_HDR,
197         ASTCSUPPORTLEVEL_FULL
198 };
199
200 static inline ASTCSupportLevel getASTCSupportLevel (const glu::ContextInfo& contextInfo, const glu::RenderContext& renderCtx)
201 {
202         const bool isES32 = glu::contextSupports(renderCtx.getType(), glu::ApiType::es(3, 2));
203
204         const vector<string>& extensions = contextInfo.getExtensions();
205
206         ASTCSupportLevel maxLevel = ASTCSUPPORTLEVEL_NONE;
207
208         for (int extNdx = 0; extNdx < (int)extensions.size(); extNdx++)
209         {
210                 const string& ext = extensions[extNdx];
211                 if (isES32)
212                 {
213                         maxLevel =      de::max(maxLevel, ext == "GL_KHR_texture_compression_astc_hdr"  ? ASTCSUPPORTLEVEL_HDR
214                                                                                 : ext == "GL_OES_texture_compression_astc"              ? ASTCSUPPORTLEVEL_FULL
215                                                                                 : ASTCSUPPORTLEVEL_LDR);
216                 }
217                 else
218                 {
219                         maxLevel =      de::max(maxLevel, ext == "GL_KHR_texture_compression_astc_ldr"  ? ASTCSUPPORTLEVEL_LDR
220                                                                                 : ext == "GL_KHR_texture_compression_astc_hdr"  ? ASTCSUPPORTLEVEL_HDR
221                                                                                 : ext == "GL_OES_texture_compression_astc"              ? ASTCSUPPORTLEVEL_FULL
222                                                                                 : ASTCSUPPORTLEVEL_NONE);
223                 }
224         }
225
226         return maxLevel;
227 }
228
229 // Class handling the common rendering stuff of ASTC cases.
230 class ASTCRenderer2D
231 {
232 public:
233                                                                 ASTCRenderer2D          (Context&                               context,
234                                                                                                          CompressedTexFormat    format,
235                                                                                                          deUint32                               randomSeed);
236
237                                                                 ~ASTCRenderer2D         (void);
238
239         void                                            initialize                      (int minRenderWidth, int minRenderHeight, const Vec4& colorScale, const Vec4& colorBias);
240         void                                            clear                           (void);
241
242         void                                            render                          (Surface&                                       referenceDst,
243                                                                                                          Surface&                                       resultDst,
244                                                                                                          const glu::Texture2D&          texture,
245                                                                                                          const tcu::TextureFormat&      uncompressedFormat);
246
247         CompressedTexFormat                     getFormat                       (void) const { return m_format; }
248         IVec2                                           getBlockSize            (void) const { return m_blockSize; }
249         ASTCSupportLevel                        getASTCSupport          (void) const { DE_ASSERT(m_initialized); return m_astcSupport;  }
250
251 private:
252         Context&                                        m_context;
253         TextureRenderer                         m_renderer;
254
255         const CompressedTexFormat       m_format;
256         const IVec2                                     m_blockSize;
257         ASTCSupportLevel                        m_astcSupport;
258         Vec4                                            m_colorScale;
259         Vec4                                            m_colorBias;
260
261         de::Random                                      m_rnd;
262
263         bool                                            m_initialized;
264 };
265
266 } // ASTCDecompressionCaseInternal
267
268 using namespace ASTCDecompressionCaseInternal;
269
270 ASTCRenderer2D::ASTCRenderer2D (Context&                        context,
271                                                                 CompressedTexFormat     format,
272                                                                 deUint32                        randomSeed)
273         : m_context                     (context)
274         , m_renderer            (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
275         , m_format                      (format)
276         , m_blockSize           (tcu::getBlockPixelSize(format).xy())
277         , m_astcSupport         (ASTCSUPPORTLEVEL_NONE)
278         , m_colorScale          (-1.0f)
279         , m_colorBias           (-1.0f)
280         , m_rnd                         (randomSeed)
281         , m_initialized         (false)
282 {
283         DE_ASSERT(tcu::getBlockPixelSize(format).z() == 1);
284 }
285
286 ASTCRenderer2D::~ASTCRenderer2D (void)
287 {
288         clear();
289 }
290
291 void ASTCRenderer2D::initialize (int minRenderWidth, int minRenderHeight, const Vec4& colorScale, const Vec4& colorBias)
292 {
293         DE_ASSERT(!m_initialized);
294
295         const tcu::RenderTarget&        renderTarget    = m_context.getRenderTarget();
296         TestLog&                                        log                             = m_context.getTestContext().getLog();
297
298         m_astcSupport   = getASTCSupportLevel(m_context.getContextInfo(), m_context.getRenderContext());
299         m_colorScale    = colorScale;
300         m_colorBias             = colorBias;
301
302         switch (m_astcSupport)
303         {
304                 case ASTCSUPPORTLEVEL_NONE:             log << TestLog::Message << "No ASTC support detected" << TestLog::EndMessage;           throw tcu::NotSupportedError("ASTC not supported");
305                 case ASTCSUPPORTLEVEL_LDR:              log << TestLog::Message << "LDR ASTC support detected" << TestLog::EndMessage;          break;
306                 case ASTCSUPPORTLEVEL_HDR:              log << TestLog::Message << "HDR ASTC support detected" << TestLog::EndMessage;          break;
307                 case ASTCSUPPORTLEVEL_FULL:             log << TestLog::Message << "Full ASTC support detected" << TestLog::EndMessage;         break;
308                 default:
309                         DE_ASSERT(false);
310         }
311
312         if (renderTarget.getWidth() < minRenderWidth || renderTarget.getHeight() < minRenderHeight)
313                 throw tcu::NotSupportedError("Render target must be at least " + de::toString(minRenderWidth) + "x" + de::toString(minRenderHeight));
314
315         log << TestLog::Message << "Using color scale and bias: result = raw * " << colorScale << " + " << colorBias << TestLog::EndMessage;
316
317         m_initialized = true;
318 }
319
320 void ASTCRenderer2D::clear (void)
321 {
322         m_renderer.clear();
323 }
324
325 void ASTCRenderer2D::render (Surface& referenceDst, Surface& resultDst, const glu::Texture2D& texture, const tcu::TextureFormat& uncompressedFormat)
326 {
327         DE_ASSERT(m_initialized);
328
329         const glw::Functions&                   gl                                              = m_context.getRenderContext().getFunctions();
330         const glu::RenderContext&               renderCtx                               = m_context.getRenderContext();
331         const int                                               textureWidth                    = texture.getRefTexture().getWidth();
332         const int                                               textureHeight                   = texture.getRefTexture().getHeight();
333         const RandomViewport                    viewport                                (renderCtx.getRenderTarget(), textureWidth, textureHeight, m_rnd.getUint32());
334         ReferenceParams                                 renderParams                    (TEXTURETYPE_2D);
335         vector<float>                                   texCoord;
336         computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));
337
338         renderParams.samplerType        = getSamplerType(uncompressedFormat);
339         renderParams.sampler            = Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
340         renderParams.colorScale         = m_colorScale;
341         renderParams.colorBias          = m_colorBias;
342
343         // Setup base viewport.
344         gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
345
346         // Bind to unit 0.
347         gl.activeTexture(GL_TEXTURE0);
348         gl.bindTexture(GL_TEXTURE_2D, texture.getGLTexture());
349
350         // Setup nearest neighbor filtering and clamp-to-edge.
351         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,              GL_CLAMP_TO_EDGE);
352         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,              GL_CLAMP_TO_EDGE);
353         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,  GL_NEAREST);
354         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,  GL_NEAREST);
355
356         GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
357
358         // Issue GL draws.
359         m_renderer.renderQuad(0, &texCoord[0], renderParams);
360         gl.flush();
361
362         // Compute reference.
363         sampleTexture(tcu::SurfaceAccess(referenceDst, renderCtx.getRenderTarget().getPixelFormat()), texture.getRefTexture(), &texCoord[0], renderParams);
364
365         // Read GL-rendered image.
366         glu::readPixels(renderCtx, viewport.x, viewport.y, resultDst.getAccess());
367 }
368
369 ASTCBlockCase2D::ASTCBlockCase2D (Context&                              context,
370                                                                   const char*                   name,
371                                                                   const char*                   description,
372                                                                   BlockTestType                 testType,
373                                                                   CompressedTexFormat   format)
374         : TestCase                              (context, name, description)
375         , m_testType                    (testType)
376         , m_format                              (format)
377         , m_numBlocksTested             (0)
378         , m_currentIteration    (0)
379         , m_renderer                    (new ASTCRenderer2D(context, format, deStringHash(getName())))
380 {
381         DE_ASSERT(!(tcu::isAstcSRGBFormat(m_format) && tcu::astc::isBlockTestTypeHDROnly(m_testType))); // \note There is no HDR sRGB mode, so these would be redundant.
382 }
383
384 ASTCBlockCase2D::~ASTCBlockCase2D (void)
385 {
386         ASTCBlockCase2D::deinit();
387 }
388
389 void ASTCBlockCase2D::init (void)
390 {
391         m_renderer->initialize(64, 64, tcu::astc::getBlockTestTypeColorScale(m_testType), tcu::astc::getBlockTestTypeColorBias(m_testType));
392
393         generateBlockCaseTestData(m_blockData, m_format, m_testType);
394         DE_ASSERT(!m_blockData.empty());
395         DE_ASSERT(m_blockData.size() % tcu::astc::BLOCK_SIZE_BYTES == 0);
396
397         m_testCtx.getLog() << TestLog::Message << "Total " << m_blockData.size() / tcu::astc::BLOCK_SIZE_BYTES << " blocks to test" << TestLog::EndMessage
398                                            << TestLog::Message << "Note: Legitimate ASTC error pixels will be ignored when comparing to reference" << TestLog::EndMessage;
399 }
400
401 void ASTCBlockCase2D::deinit (void)
402 {
403         m_renderer->clear();
404         m_blockData.clear();
405 }
406
407 ASTCBlockCase2D::IterateResult ASTCBlockCase2D::iterate (void)
408 {
409         TestLog&                                                log                                             = m_testCtx.getLog();
410
411         if (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR && tcu::astc::isBlockTestTypeHDROnly(m_testType))
412         {
413                 log << TestLog::Message << "Passing the case immediately, since only LDR support was detected and test only contains HDR blocks" << TestLog::EndMessage;
414                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
415                 return STOP;
416         }
417
418         const IVec2                                             blockSize                               = m_renderer->getBlockSize();
419         const int                                               totalNumBlocks                  = (int)m_blockData.size() / tcu::astc::BLOCK_SIZE_BYTES;
420         const int                                               numXBlocksPerImage              = de::min(m_context.getRenderTarget().getWidth(),  512) / blockSize.x();
421         const int                                               numYBlocksPerImage              = de::min(m_context.getRenderTarget().getHeight(), 512) / blockSize.y();
422         const int                                               numBlocksPerImage               = numXBlocksPerImage * numYBlocksPerImage;
423         const int                                               imageWidth                              = numXBlocksPerImage * blockSize.x();
424         const int                                               imageHeight                             = numYBlocksPerImage * blockSize.y();
425         const int                                               numBlocksRemaining              = totalNumBlocks - m_numBlocksTested;
426         const int                                               curNumNonDummyBlocks    = de::min(numBlocksPerImage, numBlocksRemaining);
427         const int                                               curNumDummyBlocks               = numBlocksPerImage - curNumNonDummyBlocks;
428         const glu::RenderContext&               renderCtx                               = m_context.getRenderContext();
429         const tcu::RGBA                                 threshold                               = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + (tcu::isAstcSRGBFormat(m_format) ? tcu::RGBA(2,2,2,2) : tcu::RGBA(1,1,1,1));
430         tcu::CompressedTexture                  compressed                              (m_format, imageWidth, imageHeight);
431
432         if (m_currentIteration == 0)
433         {
434                 log << TestLog::Message << "Using texture of size "
435                                                                 << imageWidth << "x" << imageHeight
436                                                                 << ", with " << numXBlocksPerImage << " block columns and " << numYBlocksPerImage << " block rows "
437                                                                 << ", with block size " << blockSize.x() << "x" << blockSize.y()
438                         << TestLog::EndMessage;
439         }
440
441         DE_ASSERT(compressed.getDataSize() == numBlocksPerImage*tcu::astc::BLOCK_SIZE_BYTES);
442         deMemcpy(compressed.getData(), &m_blockData[m_numBlocksTested*tcu::astc::BLOCK_SIZE_BYTES], curNumNonDummyBlocks*tcu::astc::BLOCK_SIZE_BYTES);
443         if (curNumDummyBlocks > 1)
444                 tcu::astc::generateDummyVoidExtentBlocks((deUint8*)compressed.getData() + curNumNonDummyBlocks*tcu::astc::BLOCK_SIZE_BYTES, curNumDummyBlocks);
445
446         // Create texture and render.
447
448         const tcu::TexDecompressionParams::AstcMode     decompressionMode       = (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format))
449                                                                                                                                         ? tcu::TexDecompressionParams::ASTCMODE_LDR
450                                                                                                                                         : tcu::TexDecompressionParams::ASTCMODE_HDR;
451         glu::Texture2D                                                          texture                         (renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(decompressionMode));
452         Surface                                                                         renderedFrame           (imageWidth, imageHeight);
453         Surface                                                                         referenceFrame          (imageWidth, imageHeight);
454
455         m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
456
457         // Compare and log.
458         // \note Since a case can draw quite many images, only log the first iteration and failures.
459
460         {
461                 Surface         errorMask;
462                 IVec2           firstFailedBlockCoord;
463                 IVec4           maxDiff;
464                 const bool      compareOk = compareBlockImages(referenceFrame, renderedFrame, threshold, blockSize, curNumNonDummyBlocks, firstFailedBlockCoord, errorMask, maxDiff);
465
466                 if (m_currentIteration == 0 || !compareOk)
467                 {
468                         const char* const               imageSetName    = "ComparisonResult";
469                         const char* const               imageSetDesc    = "Comparison Result";
470
471                         {
472                                 tcu::ScopedLogSection section(log, "Iteration " + de::toString(m_currentIteration),
473                                                                                                         "Blocks " + de::toString(m_numBlocksTested) + " to " + de::toString(m_numBlocksTested + curNumNonDummyBlocks - 1));
474
475                                 if (curNumDummyBlocks > 0)
476                                         log << TestLog::Message << "Note: Only the first " << curNumNonDummyBlocks << " blocks in the image are relevant; rest " << curNumDummyBlocks << " are dummies and not checked" << TestLog::EndMessage;
477
478                                 if (!compareOk)
479                                 {
480                                         log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage
481                                                 << TestLog::ImageSet(imageSetName, imageSetDesc)
482                                                 << TestLog::Image("Result",             "Result",               renderedFrame)
483                                                 << TestLog::Image("Reference",  "Reference",    referenceFrame)
484                                                 << TestLog::Image("ErrorMask",  "Error mask",   errorMask)
485                                                 << TestLog::EndImageSet;
486
487                                         const int blockNdx = m_numBlocksTested + firstFailedBlockCoord.y()*numXBlocksPerImage + firstFailedBlockCoord.x();
488                                         DE_ASSERT(blockNdx < totalNumBlocks);
489
490                                         log << TestLog::Message << "First failed block at column " << firstFailedBlockCoord.x() << " and row " << firstFailedBlockCoord.y() << TestLog::EndMessage
491                                                 << TestLog::Message << "Data of first failed block:\n" << astcBlockDataStr(&m_blockData[blockNdx*tcu::astc::BLOCK_SIZE_BYTES]) << TestLog::EndMessage;
492
493                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
494                                         return STOP;
495                                 }
496                                 else
497                                 {
498                                         log << TestLog::ImageSet(imageSetName, imageSetDesc)
499                                                 << TestLog::Image("Result", "Result", renderedFrame)
500                                                 << TestLog::EndImageSet;
501                                 }
502                         }
503
504                         if (m_numBlocksTested + curNumNonDummyBlocks < totalNumBlocks)
505                                 log << TestLog::Message << "Note: not logging further images unless reference comparison fails" << TestLog::EndMessage;
506                 }
507         }
508
509         m_currentIteration++;
510         m_numBlocksTested += curNumNonDummyBlocks;
511
512         if (m_numBlocksTested >= totalNumBlocks)
513         {
514                 DE_ASSERT(m_numBlocksTested == totalNumBlocks);
515                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
516                 return STOP;
517         }
518
519         return CONTINUE;
520 }
521
522
523
524 ASTCBlockSizeRemainderCase2D::ASTCBlockSizeRemainderCase2D (Context&                    context,
525                                                                                                                         const char*                     name,
526                                                                                                                         const char*                     description,
527                                                                                                                         CompressedTexFormat     format)
528         : TestCase                              (context, name, description)
529         , m_format                              (format)
530         , m_currentIteration    (0)
531         , m_renderer                    (new ASTCRenderer2D(context, format, deStringHash(getName())))
532 {
533 }
534
535 ASTCBlockSizeRemainderCase2D::~ASTCBlockSizeRemainderCase2D (void)
536 {
537         ASTCBlockSizeRemainderCase2D::deinit();
538 }
539
540 void ASTCBlockSizeRemainderCase2D::init (void)
541 {
542         const IVec2 blockSize = m_renderer->getBlockSize();
543         m_renderer->initialize(MAX_NUM_BLOCKS_X*blockSize.x(), MAX_NUM_BLOCKS_Y*blockSize.y(), Vec4(1.0f), Vec4(0.0f));
544 }
545
546 void ASTCBlockSizeRemainderCase2D::deinit (void)
547 {
548         m_renderer->clear();
549 }
550
551 ASTCBlockSizeRemainderCase2D::IterateResult ASTCBlockSizeRemainderCase2D::iterate (void)
552 {
553         TestLog&                                                log                                             = m_testCtx.getLog();
554         const IVec2                                             blockSize                               = m_renderer->getBlockSize();
555         const int                                               curRemainderX                   = m_currentIteration % blockSize.x();
556         const int                                               curRemainderY                   = m_currentIteration / blockSize.x();
557         const int                                               imageWidth                              = (MAX_NUM_BLOCKS_X-1)*blockSize.x() + curRemainderX;
558         const int                                               imageHeight                             = (MAX_NUM_BLOCKS_Y-1)*blockSize.y() + curRemainderY;
559         const int                                               numBlocksX                              = deDivRoundUp32(imageWidth, blockSize.x());
560         const int                                               numBlocksY                              = deDivRoundUp32(imageHeight, blockSize.y());
561         const int                                               totalNumBlocks                  = numBlocksX * numBlocksY;
562         const glu::RenderContext&               renderCtx                               = m_context.getRenderContext();
563         const tcu::RGBA                                 threshold                               = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + (tcu::isAstcSRGBFormat(m_format) ? tcu::RGBA(2,2,2,2) : tcu::RGBA(1,1,1,1));
564         tcu::CompressedTexture                  compressed                              (m_format, imageWidth, imageHeight);
565
566         DE_ASSERT(compressed.getDataSize() == totalNumBlocks*tcu::astc::BLOCK_SIZE_BYTES);
567         tcu::astc::generateDummyNormalBlocks((deUint8*)compressed.getData(), totalNumBlocks, blockSize.x(), blockSize.y());
568
569         // Create texture and render.
570
571         const tcu::TexDecompressionParams::AstcMode     decompressionMode       = (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format))
572                                                                                                                                         ? tcu::TexDecompressionParams::ASTCMODE_LDR
573                                                                                                                                         : tcu::TexDecompressionParams::ASTCMODE_HDR;
574         Surface                                                                         renderedFrame           (imageWidth, imageHeight);
575         Surface                                                                         referenceFrame          (imageWidth, imageHeight);
576         glu::Texture2D                                                          texture                         (renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(decompressionMode));
577
578         m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
579
580         {
581                 // Compare and log.
582
583                 tcu::ScopedLogSection section(log, "Iteration " + de::toString(m_currentIteration),
584                                                                                    "Remainder " + de::toString(curRemainderX) + "x" + de::toString(curRemainderY));
585
586                 log << TestLog::Message << "Using texture of size "
587                                                                 << imageWidth << "x" << imageHeight
588                                                                 << " and block size "
589                                                                 << blockSize.x() << "x" << blockSize.y()
590                                                                 << "; the x and y remainders are "
591                                                                 << curRemainderX << " and " << curRemainderY << " respectively"
592                         << TestLog::EndMessage;
593
594                 const bool compareOk = tcu::pixelThresholdCompare(m_testCtx.getLog(), "ComparisonResult", "Comparison Result", referenceFrame, renderedFrame, threshold,
595                                                                                                                   m_currentIteration == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
596
597                 if (!compareOk)
598                 {
599                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
600                         return STOP;
601                 }
602         }
603
604         if (m_currentIteration == 0 && m_currentIteration+1 < blockSize.x()*blockSize.y())
605                 log << TestLog::Message << "Note: not logging further images unless reference comparison fails" << TestLog::EndMessage;
606
607         m_currentIteration++;
608
609         if (m_currentIteration >= blockSize.x()*blockSize.y())
610         {
611                 DE_ASSERT(m_currentIteration == blockSize.x()*blockSize.y());
612                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
613                 return STOP;
614         }
615         return CONTINUE;
616 }
617
618 } // Functional
619 } // gles3
620 } // deqp