am 9c37338a: (-s ours) am 55d9f833: Remove two EGL tests with flaky results am: 11514...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fColorClearTest.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 Screen clearing test.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fColorClearTest.hpp"
25 #include "tcuRGBA.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuTestLog.hpp"
28 #include "gluRenderContext.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "tcuVector.hpp"
31 #include "tcuRenderTarget.hpp"
32 #include "deRandom.hpp"
33 #include "deInt32.h"
34
35 #include "glwFunctions.hpp"
36 #include "glwEnums.hpp"
37
38 #include <vector>
39
40 using tcu::RGBA;
41 using tcu::Surface;
42 using tcu::TestLog;
43
44 using namespace std;
45
46 namespace deqp
47 {
48 namespace gles3
49 {
50 namespace Functional
51 {
52
53 class ColorClearCase : public TestCase
54 {
55 public:
56         ColorClearCase(Context& context, const char* name, int numIters, int numClearsMin, int numClearsMax, bool testAlpha, bool testScissoring, bool testColorMasks, bool firstClearFull)
57                 : TestCase                      (context, name, name)
58                 , m_numIters            (numIters)
59                 , m_numClearsMin        (numClearsMin)
60                 , m_numClearsMax        (numClearsMax)
61                 , m_testAlpha           (testAlpha)
62                 , m_testScissoring      (testScissoring)
63                 , m_testColorMasks      (testColorMasks)
64                 , m_firstClearFull      (firstClearFull)
65         {
66                 m_curIter = 0;
67         }
68
69         virtual ~ColorClearCase (void)
70         {
71         }
72
73         virtual IterateResult iterate (void);
74
75 private:
76         const int               m_numIters;
77         const int               m_numClearsMin;
78         const int               m_numClearsMax;
79         const bool              m_testAlpha;
80         const bool              m_testScissoring;
81         const bool              m_testColorMasks;
82         const bool              m_firstClearFull;
83
84         int                             m_curIter;
85 };
86
87 class ClearInfo
88 {
89 public:
90         ClearInfo (const tcu::IVec4& rect, deUint8 colorMask, tcu::RGBA color)
91                 : m_rect(rect), m_colorMask(colorMask), m_color(color)
92         {
93         }
94
95         tcu::IVec4              m_rect;
96         deUint8                 m_colorMask;
97         tcu::RGBA               m_color;
98 };
99
100 TestCase::IterateResult ColorClearCase::iterate (void)
101 {
102         TestLog&                                        log                                             = m_testCtx.getLog();
103         const glw::Functions&           gl                                              = m_context.getRenderContext().getFunctions();
104         const tcu::RenderTarget&        renderTarget                    = m_context.getRenderTarget();
105         const tcu::PixelFormat&         pixelFormat                             = renderTarget.getPixelFormat();
106         const int                                       targetWidth                             = renderTarget.getWidth();
107         const int                                       targetHeight                    = renderTarget.getHeight();
108         const int                                       numPixels                               = targetWidth * targetHeight;
109
110         de::Random                                      rnd                                             (deInt32Hash(m_curIter));
111         vector<deUint8>                         pixelKnownChannelMask   (numPixels, 0);
112         Surface                                         refImage                                (targetWidth, targetHeight);
113         Surface                                         resImage                                (targetWidth, targetHeight);
114         Surface                                         diffImage                               (targetWidth, targetHeight);
115         int                                                     numClears                               = rnd.getUint32() % (m_numClearsMax + 1 - m_numClearsMin) + m_numClearsMin;
116         std::vector<ClearInfo>          clearOps;
117
118         if (m_testScissoring)
119                 gl.enable(GL_SCISSOR_TEST);
120
121         for (int clearNdx = 0; clearNdx < numClears; clearNdx++)
122         {
123                 // Rectangle.
124                 int clearX;
125                 int clearY;
126                 int clearWidth;
127                 int clearHeight;
128                 if (!m_testScissoring || (clearNdx == 0 && m_firstClearFull))
129                 {
130                         clearX          = 0;
131                         clearY          = 0;
132                         clearWidth      = targetWidth;
133                         clearHeight     = targetHeight;
134                 }
135                 else
136                 {
137                         clearX          = (rnd.getUint32() % (2*targetWidth)) - targetWidth;
138                         clearY          = (rnd.getUint32() % (2*targetHeight)) - targetHeight;
139                         clearWidth      = (rnd.getUint32() % targetWidth);
140                         clearHeight     = (rnd.getUint32() % targetHeight);
141                 }
142                 gl.scissor(clearX, clearY, clearWidth, clearHeight);
143
144                 // Color.
145                 int             r = (int)(rnd.getUint32() & 0xFF);
146                 int             g = (int)(rnd.getUint32() & 0xFF);
147                 int             b = (int)(rnd.getUint32() & 0xFF);
148                 int             a = m_testAlpha ? (int)(rnd.getUint32() & 0xFF) : 0xFF;
149                 RGBA    clearCol(r, g, b, a);
150                 gl.clearColor(float(r)/255.0f, float(g)/255.0f, float(b)/255.0f, float(a)/255.0f);
151
152                 // Mask.
153                 deUint8 clearMask;
154                 if (!m_testColorMasks || (clearNdx == 0 && m_firstClearFull))
155                         clearMask = 0xF;
156                 else
157                         clearMask = (rnd.getUint32() & 0xF);
158                 gl.colorMask((clearMask&0x1) != 0, (clearMask&0x2) != 0, (clearMask&0x4) != 0, (clearMask&0x8) != 0);
159
160                 // Clear & store op.
161                 gl.clear(GL_COLOR_BUFFER_BIT);
162                 clearOps.push_back(ClearInfo(tcu::IVec4(clearX, clearY, clearWidth, clearHeight), clearMask, clearCol));
163
164                 // Let watchdog know we're alive.
165                 m_testCtx.touchWatchdog();
166         }
167
168         // Compute reference image.
169         {
170                 for (int y = 0; y < targetHeight; y++)
171                 {
172                         std::vector<ClearInfo>  scanlineClearOps;
173
174                         // Find all rectangles affecting this scanline.
175                         for (int opNdx = 0; opNdx < (int)clearOps.size(); opNdx++)
176                         {
177                                 ClearInfo& op = clearOps[opNdx];
178                                 if (de::inBounds(y, op.m_rect.y(), op.m_rect.y()+op.m_rect.w()))
179                                         scanlineClearOps.push_back(op);
180                         }
181
182                         // Compute reference for scanline.
183                         int x = 0;
184                         while (x < targetWidth)
185                         {
186                                 tcu::RGBA       spanColor;
187                                 deUint8         spanKnownMask   = 0;
188                                 int                     spanLength              = (targetWidth - x);
189
190                                 for (int opNdx = (int)scanlineClearOps.size() - 1; opNdx >= 0; opNdx--)
191                                 {
192                                         const ClearInfo& op = scanlineClearOps[opNdx];
193
194                                         if (de::inBounds(x, op.m_rect.x(), op.m_rect.x()+op.m_rect.z()) &&
195                                                 de::inBounds(y, op.m_rect.y(), op.m_rect.y()+op.m_rect.w()))
196                                         {
197                                                 // Compute span length until end of given rectangle.
198                                                 spanLength = deMin32(spanLength, op.m_rect.x() + op.m_rect.z() - x);
199
200                                                 tcu::RGBA       clearCol        = op.m_color;
201                                                 deUint8         clearMask       = op.m_colorMask;
202                                                 if ((clearMask & 0x1) && !(spanKnownMask & 0x1)) spanColor.setRed(clearCol.getRed());
203                                                 if ((clearMask & 0x2) && !(spanKnownMask & 0x2)) spanColor.setGreen(clearCol.getGreen());
204                                                 if ((clearMask & 0x4) && !(spanKnownMask & 0x4)) spanColor.setBlue(clearCol.getBlue());
205                                                 if ((clearMask & 0x8) && !(spanKnownMask & 0x8)) spanColor.setAlpha(clearCol.getAlpha());
206                                                 spanKnownMask |= clearMask;
207
208                                                 // Break if have all colors.
209                                                 if (spanKnownMask == 0xF)
210                                                         break;
211                                         }
212                                         else if (op.m_rect.x() > x)
213                                                 spanLength = deMin32(spanLength, op.m_rect.x() - x);
214                                 }
215
216                                 // Set reference alpha channel to 0xFF, if no alpha in target.
217                                 if (pixelFormat.alphaBits == 0)
218                                         spanColor.setAlpha(0xFF);
219
220                                 // Fill the span.
221                                 for (int ndx = 0; ndx < spanLength; ndx++)
222                                 {
223                                         refImage.setPixel(x + ndx, y, spanColor);
224                                         pixelKnownChannelMask[y*targetWidth + x + ndx] |= spanKnownMask;
225                                 }
226
227                                 x += spanLength;
228                         }
229                 }
230         }
231
232         glu::readPixels(m_context.getRenderContext(), 0, 0, resImage.getAccess());
233         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
234
235         // Compute difference image.
236         RGBA colorThreshold = pixelFormat.getColorThreshold();
237         RGBA matchColor(0, 255, 0, 255);
238         RGBA diffColor(255, 0, 0, 255);
239         RGBA maxDiff(0, 0, 0, 0);
240         bool isImageOk = true;
241
242         if (gl.isEnabled(GL_DITHER))
243         {
244                 colorThreshold.setRed(colorThreshold.getRed() + 1);
245                 colorThreshold.setGreen(colorThreshold.getGreen() + 1);
246                 colorThreshold.setBlue(colorThreshold.getBlue() + 1);
247                 colorThreshold.setAlpha(colorThreshold.getAlpha() + 1);
248         }
249
250         for (int y = 0; y < targetHeight; y++)
251         for (int x = 0; x < targetWidth; x++)
252         {
253                 int                     offset          = (y*targetWidth + x);
254                 RGBA            refRGBA         = refImage.getPixel(x, y);
255                 RGBA            resRGBA         = resImage.getPixel(x, y);
256                 deUint8         colMask         = pixelKnownChannelMask[offset];
257                 RGBA            diff            = computeAbsDiffMasked(refRGBA, resRGBA, colMask);
258                 bool            isPixelOk       = diff.isBelowThreshold(colorThreshold);
259
260                 diffImage.setPixel(x, y, isPixelOk ? matchColor : diffColor);
261
262                 isImageOk       = isImageOk && isPixelOk;
263                 maxDiff         = max(maxDiff, diff);
264         }
265
266         if (isImageOk)
267         {
268                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
269         }
270         else
271         {
272                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
273
274                 m_testCtx.getLog() << tcu::TestLog::Message << "Image comparison failed, max diff = " << maxDiff << ", threshold = " << colorThreshold << tcu::TestLog::EndMessage;
275
276                 log << TestLog::ImageSet("Result", "Resulting framebuffer")
277                         << TestLog::Image("Result",             "Resulting framebuffer",        resImage)
278                         << TestLog::Image("Reference",  "Reference image",                      refImage)
279                         << TestLog::Image("DiffMask",   "Failing pixels",                       diffImage)
280                         << TestLog::EndImageSet;
281                 return TestCase::STOP;
282         }
283
284         bool isFinal = (++m_curIter == m_numIters);
285
286         // On final frame, dump images.
287         if (isFinal)
288         {
289                 log << TestLog::ImageSet("Result", "Resulting framebuffer")
290                         << TestLog::Image("Result",             "Resulting framebuffer",        resImage)
291                         << TestLog::EndImageSet;
292         }
293
294         return isFinal ? TestCase::STOP : TestCase::CONTINUE;
295 }
296
297 ColorClearTest::ColorClearTest (Context& context) : TestCaseGroup(context, "color_clear", "Color Clear Tests")
298 {
299 }
300
301 ColorClearTest::~ColorClearTest (void)
302 {
303 }
304
305 void ColorClearTest::init (void)
306 {
307         //                                                                              name                                    iters,  #..#,           alpha?, scissor,masks,  1stfull?
308         addChild(new ColorClearCase(m_context, "single_rgb",                    30,             1,3,            false,  false,  false,  true    ));
309         addChild(new ColorClearCase(m_context, "single_rgba",                   30,             1,3,            true,   false,  false,  true    ));
310         addChild(new ColorClearCase(m_context, "multiple_rgb",                  15,             4,20,           false,  false,  false,  true    ));
311         addChild(new ColorClearCase(m_context, "multiple_rgba",                 15,             4,20,           true,   false,  false,  true    ));
312         addChild(new ColorClearCase(m_context, "long_rgb",                              2,              100,500,        false,  false,  false,  true    ));
313         addChild(new ColorClearCase(m_context, "long_rgba",                             2,              100,500,        true,   false,  false,  true    ));
314         addChild(new ColorClearCase(m_context, "subclears_rgb",                 15,             4,30,           false,  false,  false,  false   ));
315         addChild(new ColorClearCase(m_context, "subclears_rgba",                15,             4,30,           true,   false,  false,  false   ));
316         addChild(new ColorClearCase(m_context, "short_scissored_rgb",   30,             2,4,            false,  true,   false,  true    ));
317         addChild(new ColorClearCase(m_context, "scissored_rgb",                 15,             4,30,           false,  true,   false,  true    ));
318         addChild(new ColorClearCase(m_context, "scissored_rgba",                15,             4,30,           true,   true,   false,  true    ));
319         addChild(new ColorClearCase(m_context, "masked_rgb",                    15,             4,30,           false,  true,   false,  true    ));
320         addChild(new ColorClearCase(m_context, "masked_rgba",                   15,             4,30,           true,   true,   false,  true    ));
321         addChild(new ColorClearCase(m_context, "masked_scissored_rgb",  15,             4,30,           false,  true,   true,   true    ));
322         addChild(new ColorClearCase(m_context, "masked_scissored_rgba", 15,             4,30,           true,   true,   true,   true    ));
323         addChild(new ColorClearCase(m_context, "complex_rgb",                   15,             5,50,           false,  true,   true,   false   ));
324         addChild(new ColorClearCase(m_context, "complex_rgba",                  15,             5,50,           true,   true,   true,   false   ));
325         addChild(new ColorClearCase(m_context, "long_masked_rgb",               2,              100,500,        false,  true,   true,   true    ));
326         addChild(new ColorClearCase(m_context, "long_masked_rgba",              2,              100,500,        true,   true,   true,   true    ));
327 }
328
329 } // Functional
330 } // gles3
331 } // deqp