Fix PIPELINE_STAGE_TOP_OF_PIPE_BIT usage in api tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fMultisampleTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 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 Multisample tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fMultisampleTests.hpp"
25 #include "tcuRenderTarget.hpp"
26 #include "tcuVector.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuImageCompare.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluRenderContext.hpp"
32 #include "gluCallLogWrapper.hpp"
33 #include "gluObjectWrapper.hpp"
34 #include "gluShaderProgram.hpp"
35 #include "glwFunctions.hpp"
36 #include "glwEnums.hpp"
37 #include "deRandom.hpp"
38 #include "deStringUtil.hpp"
39 #include "deString.h"
40 #include "deMath.h"
41
42 using namespace glw;
43
44 using tcu::TestLog;
45 using tcu::Vec2;
46 using tcu::Vec3;
47 using tcu::Vec4;
48
49 namespace deqp
50 {
51 namespace gles31
52 {
53 namespace Functional
54 {
55 namespace
56 {
57
58 using std::map;
59 using std::string;
60
61 static std::string sampleMaskToString (const std::vector<deUint32>& bitfield, int numBits)
62 {
63         std::string result(numBits, '0');
64
65         // move from back to front and set chars to 1
66         for (int wordNdx = 0; wordNdx < (int)bitfield.size(); ++wordNdx)
67         {
68                 for (int bit = 0; bit < 32; ++bit)
69                 {
70                         const int targetCharNdx = numBits - (wordNdx*32+bit) - 1;
71
72                         // beginning of the string reached
73                         if (targetCharNdx < 0)
74                                 return result;
75
76                         if ((bitfield[wordNdx] >> bit) & 0x01)
77                                 result[targetCharNdx] = '1';
78                 }
79         }
80
81         return result;
82 }
83
84 /*--------------------------------------------------------------------*//*!
85  * \brief Returns the number of words needed to represent mask of given length
86  *//*--------------------------------------------------------------------*/
87 static int getEffectiveSampleMaskWordCount (int highestBitNdx)
88 {
89         const int wordSize      = 32;
90         const int maskLen       = highestBitNdx + 1;
91
92         return ((maskLen - 1) / wordSize) + 1; // round_up(mask_len /  wordSize)
93 }
94
95 /*--------------------------------------------------------------------*//*!
96  * \brief Creates sample mask with all less significant bits than nthBit set
97  *//*--------------------------------------------------------------------*/
98 static std::vector<deUint32> genAllSetToNthBitSampleMask (int nthBit)
99 {
100         const int                               wordSize        = 32;
101         const int                               numWords        = getEffectiveSampleMaskWordCount(nthBit - 1);
102         const deUint32                  topWordBits     = (deUint32)(nthBit - (numWords - 1) * wordSize);
103         std::vector<deUint32>   mask            (numWords);
104
105         for (int ndx = 0; ndx < numWords - 1; ++ndx)
106                 mask[ndx] = 0xFFFFFFFF;
107
108         mask[numWords - 1] = deBitMask32(0, (int)topWordBits);
109         return mask;
110 }
111
112 class SamplePosQueryCase : public TestCase
113 {
114 public:
115                                         SamplePosQueryCase (Context& context, const char* name, const char* desc);
116 private:
117         void                    init                            (void);
118         IterateResult   iterate                         (void);
119 };
120
121 SamplePosQueryCase::SamplePosQueryCase (Context& context, const char* name, const char* desc)
122         : TestCase(context, name, desc)
123 {
124 }
125
126 void SamplePosQueryCase::init (void)
127 {
128         if (m_context.getRenderTarget().getNumSamples() == 0)
129                 throw tcu::NotSupportedError("No multisample buffers");
130 }
131
132 SamplePosQueryCase::IterateResult SamplePosQueryCase::iterate (void)
133 {
134         glu::CallLogWrapper gl          (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
135         bool                            error   = false;
136
137         gl.enableLogging(true);
138
139         for (int ndx = 0; ndx < m_context.getRenderTarget().getNumSamples(); ++ndx)
140         {
141                 tcu::Vec2 samplePos = tcu::Vec2(-1, -1);
142
143                 gl.glGetMultisamplefv(GL_SAMPLE_POSITION, ndx, samplePos.getPtr());
144                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getMultisamplefv");
145
146                 // check value range
147                 if (samplePos.x() < 0.0f || samplePos.x() > 1.0f ||
148                         samplePos.y() < 0.0f || samplePos.y() > 1.0f)
149                 {
150                         m_testCtx.getLog() << tcu::TestLog::Message << "Sample " << ndx << " is not in valid range [0,1], got " << samplePos << tcu::TestLog::EndMessage;
151                         error = true;
152                 }
153         }
154
155         if (!error)
156                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
157         else
158                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid sample pos");
159
160         return STOP;
161 }
162
163 /*--------------------------------------------------------------------*//*!
164  * \brief Abstract base class handling common stuff for default fbo multisample cases.
165  *//*--------------------------------------------------------------------*/
166 class DefaultFBOMultisampleCase : public TestCase
167 {
168 public:
169                                                                 DefaultFBOMultisampleCase       (Context& context, const char* name, const char* desc, int desiredViewportSize);
170         virtual                                         ~DefaultFBOMultisampleCase      (void);
171
172         virtual void                            init                                            (void);
173         virtual void                            deinit                                          (void);
174
175 protected:
176         void                                            renderTriangle                          (const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const;
177         void                                            renderTriangle                          (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const;
178         void                                            renderTriangle                          (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& color) const;
179         void                                            renderQuad                                      (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& c0, const Vec4& c1, const Vec4& c2, const Vec4& c3) const;
180         void                                            renderQuad                                      (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& color) const;
181
182         void                                            randomizeViewport                       (void);
183         void                                            readImage                                       (tcu::Surface& dst) const;
184
185         int                                                     m_numSamples;
186
187         int                                                     m_viewportSize;
188
189 private:
190                                                                 DefaultFBOMultisampleCase       (const DefaultFBOMultisampleCase& other);
191         DefaultFBOMultisampleCase&      operator=                                       (const DefaultFBOMultisampleCase& other);
192
193         const int                                       m_desiredViewportSize;
194
195         glu::ShaderProgram*                     m_program;
196         int                                                     m_attrPositionLoc;
197         int                                                     m_attrColorLoc;
198
199         int                                                     m_viewportX;
200         int                                                     m_viewportY;
201         de::Random                                      m_rnd;
202
203         bool                                            m_initCalled;
204 };
205
206 DefaultFBOMultisampleCase::DefaultFBOMultisampleCase (Context& context, const char* name, const char* desc, int desiredViewportSize)
207         : TestCase                              (context, name, desc)
208         , m_numSamples                  (0)
209         , m_viewportSize                (0)
210         , m_desiredViewportSize (desiredViewportSize)
211         , m_program                             (DE_NULL)
212         , m_attrPositionLoc             (-1)
213         , m_attrColorLoc                (-1)
214         , m_viewportX                   (0)
215         , m_viewportY                   (0)
216         , m_rnd                                 (deStringHash(name))
217         , m_initCalled                  (false)
218 {
219 }
220
221 DefaultFBOMultisampleCase::~DefaultFBOMultisampleCase (void)
222 {
223         DefaultFBOMultisampleCase::deinit();
224 }
225
226 void DefaultFBOMultisampleCase::init (void)
227 {
228         const bool                                      supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
229         map<string, string>                     args;
230         args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
231
232         static const char* vertShaderSource =
233                 "${GLSL_VERSION_DECL}\n"
234                 "in highp vec4 a_position;\n"
235                 "in mediump vec4 a_color;\n"
236                 "out mediump vec4 v_color;\n"
237                 "void main()\n"
238                 "{\n"
239                 "       gl_Position = a_position;\n"
240                 "       v_color = a_color;\n"
241                 "}\n";
242
243         static const char* fragShaderSource =
244                 "${GLSL_VERSION_DECL}\n"
245                 "in mediump vec4 v_color;\n"
246                 "layout(location = 0) out mediump vec4 o_color;\n"
247                 "void main()\n"
248                 "{\n"
249                 "       o_color = v_color;\n"
250                 "}\n";
251
252         TestLog&                                log     = m_testCtx.getLog();
253         const glw::Functions&   gl      = m_context.getRenderContext().getFunctions();
254
255         if (m_context.getRenderTarget().getNumSamples() <= 1)
256                 throw tcu::NotSupportedError("No multisample buffers");
257
258         m_initCalled = true;
259
260         // Query and log number of samples per pixel.
261
262         gl.getIntegerv(GL_SAMPLES, &m_numSamples);
263         GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_SAMPLES)");
264         log << TestLog::Message << "GL_SAMPLES = " << m_numSamples << TestLog::EndMessage;
265
266         // Prepare program.
267
268         DE_ASSERT(!m_program);
269
270         m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
271                 << glu::VertexSource(tcu::StringTemplate(vertShaderSource).specialize(args))
272                 << glu::FragmentSource(tcu::StringTemplate(fragShaderSource).specialize(args)));
273         if (!m_program->isOk())
274                 throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);
275
276         m_attrPositionLoc       = gl.getAttribLocation(m_program->getProgram(), "a_position");
277         m_attrColorLoc          = gl.getAttribLocation(m_program->getProgram(), "a_color");
278         GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation");
279
280         if (m_attrPositionLoc < 0 || m_attrColorLoc < 0)
281         {
282                 delete m_program;
283                 throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
284         }
285
286         // Get suitable viewport size.
287
288         m_viewportSize = de::min<int>(m_desiredViewportSize, de::min(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight()));
289         randomizeViewport();
290 }
291
292 void DefaultFBOMultisampleCase::deinit (void)
293 {
294         // Do not try to call GL functions during case list creation
295         if (!m_initCalled)
296                 return;
297
298         delete m_program;
299         m_program = DE_NULL;
300 }
301
302 void DefaultFBOMultisampleCase::renderTriangle (const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const
303 {
304         const float vertexPositions[] =
305         {
306                 p0.x(), p0.y(), p0.z(), 1.0f,
307                 p1.x(), p1.y(), p1.z(), 1.0f,
308                 p2.x(), p2.y(), p2.z(), 1.0f
309         };
310         const float vertexColors[] =
311         {
312                 c0.x(), c0.y(), c0.z(), c0.w(),
313                 c1.x(), c1.y(), c1.z(), c1.w(),
314                 c2.x(), c2.y(), c2.z(), c2.w(),
315         };
316
317         const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
318         glu::Buffer                             vtxBuf  (m_context.getRenderContext());
319         glu::Buffer                             colBuf  (m_context.getRenderContext());
320         glu::VertexArray                vao             (m_context.getRenderContext());
321
322         gl.bindVertexArray(*vao);
323         GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
324
325         gl.bindBuffer(GL_ARRAY_BUFFER, *vtxBuf);
326         gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), &vertexPositions[0], GL_STATIC_DRAW);
327         GLU_EXPECT_NO_ERROR(gl.getError(), "vtx buf");
328
329         gl.enableVertexAttribArray(m_attrPositionLoc);
330         gl.vertexAttribPointer(m_attrPositionLoc, 4, GL_FLOAT, false, 0, DE_NULL);
331         GLU_EXPECT_NO_ERROR(gl.getError(), "vtx vertexAttribPointer");
332
333         gl.bindBuffer(GL_ARRAY_BUFFER, *colBuf);
334         gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexColors), &vertexColors[0], GL_STATIC_DRAW);
335         GLU_EXPECT_NO_ERROR(gl.getError(), "col buf");
336
337         gl.enableVertexAttribArray(m_attrColorLoc);
338         gl.vertexAttribPointer(m_attrColorLoc, 4, GL_FLOAT, false, 0, DE_NULL);
339         GLU_EXPECT_NO_ERROR(gl.getError(), "col vertexAttribPointer");
340
341         gl.useProgram(m_program->getProgram());
342         gl.drawArrays(GL_TRIANGLES, 0, 3);
343         GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
344 }
345
346 void DefaultFBOMultisampleCase::renderTriangle (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const
347 {
348         renderTriangle(Vec3(p0.x(), p0.y(), 0.0f),
349                                    Vec3(p1.x(), p1.y(), 0.0f),
350                                    Vec3(p2.x(), p2.y(), 0.0f),
351                                    c0, c1, c2);
352 }
353
354 void DefaultFBOMultisampleCase::renderTriangle (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& color) const
355 {
356         renderTriangle(p0, p1, p2, color, color, color);
357 }
358
359 void DefaultFBOMultisampleCase::renderQuad (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& c0, const Vec4& c1, const Vec4& c2, const Vec4& c3) const
360 {
361         renderTriangle(p0, p1, p2, c0, c1, c2);
362         renderTriangle(p2, p1, p3, c2, c1, c3);
363 }
364
365 void DefaultFBOMultisampleCase::renderQuad (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& color) const
366 {
367         renderQuad(p0, p1, p2, p3, color, color, color, color);
368 }
369
370 void DefaultFBOMultisampleCase::randomizeViewport (void)
371 {
372         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
373
374         m_viewportX = m_rnd.getInt(0, m_context.getRenderTarget().getWidth()  - m_viewportSize);
375         m_viewportY = m_rnd.getInt(0, m_context.getRenderTarget().getHeight() - m_viewportSize);
376
377         gl.viewport(m_viewportX, m_viewportY, m_viewportSize, m_viewportSize);
378         GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
379 }
380
381 void DefaultFBOMultisampleCase::readImage (tcu::Surface& dst) const
382 {
383         glu::readPixels(m_context.getRenderContext(), m_viewportX, m_viewportY, dst.getAccess());
384 }
385
386 /*--------------------------------------------------------------------*//*!
387  * \brief Tests coverage mask inversion validity.
388  *
389  * Tests that the coverage masks obtained by masks set with glSampleMaski(mask)
390  * and glSampleMaski(~mask) are indeed each others' inverses.
391  *
392  * This is done by drawing a pattern, with varying coverage values,
393  * overlapped by a pattern that has inverted masks and is otherwise
394  * identical. The resulting image is compared to one obtained by drawing
395  * the same pattern but with all-ones coverage masks.
396  *//*--------------------------------------------------------------------*/
397 class MaskInvertCase : public DefaultFBOMultisampleCase
398 {
399 public:
400                                         MaskInvertCase                          (Context& context, const char* name, const char* description);
401                                         ~MaskInvertCase                         (void) {}
402
403         void                    init                                            (void);
404         IterateResult   iterate                                         (void);
405
406 private:
407         void                    drawPattern                                     (bool invert) const;
408 };
409
410 MaskInvertCase::MaskInvertCase (Context& context, const char* name, const char* description)
411         : DefaultFBOMultisampleCase     (context, name, description, 256)
412 {
413 }
414
415 void MaskInvertCase::init (void)
416 {
417         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
418
419         // check the test is even possible
420
421         GLint maxSampleMaskWords = 0;
422         gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
423         if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
424                 throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
425
426         // normal init
427         DefaultFBOMultisampleCase::init();
428 }
429
430 MaskInvertCase::IterateResult MaskInvertCase::iterate (void)
431 {
432         const glw::Functions&   gl = m_context.getRenderContext().getFunctions();
433         TestLog&                                log                                                             = m_testCtx.getLog();
434         tcu::Surface                    renderedImgNoSampleCoverage             (m_viewportSize, m_viewportSize);
435         tcu::Surface                    renderedImgSampleCoverage               (m_viewportSize, m_viewportSize);
436
437         randomizeViewport();
438
439         gl.enable(GL_BLEND);
440         gl.blendEquation(GL_FUNC_ADD);
441         gl.blendFunc(GL_ONE, GL_ONE);
442         GLU_EXPECT_NO_ERROR(gl.getError(), "set blend");
443         log << TestLog::Message << "Additive blending enabled in order to detect (erroneously) overlapping samples" << TestLog::EndMessage;
444
445         log << TestLog::Message << "Clearing color to all-zeros" << TestLog::EndMessage;
446         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
447         gl.clear(GL_COLOR_BUFFER_BIT);
448         GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
449
450         log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK disabled" << TestLog::EndMessage;
451         drawPattern(false);
452         readImage(renderedImgNoSampleCoverage);
453
454         log << TestLog::Image("RenderedImageNoSampleMask", "Rendered image with GL_SAMPLE_MASK disabled", renderedImgNoSampleCoverage, QP_IMAGE_COMPRESSION_MODE_PNG);
455
456         log << TestLog::Message << "Clearing color to all-zeros" << TestLog::EndMessage;
457         gl.clear(GL_COLOR_BUFFER_BIT);
458         GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
459
460         gl.enable(GL_SAMPLE_MASK);
461         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK)");
462
463         log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK enabled, using non-inverted sample masks" << TestLog::EndMessage;
464         drawPattern(false);
465         log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK enabled, using inverted sample masks" << TestLog::EndMessage;
466         drawPattern(true);
467
468         readImage(renderedImgSampleCoverage);
469
470         log << TestLog::Image("RenderedImageSampleMask", "Rendered image with GL_SAMPLE_MASK enabled", renderedImgSampleCoverage, QP_IMAGE_COMPRESSION_MODE_PNG);
471
472         bool passed = tcu::pixelThresholdCompare(log,
473                                                                                          "CoverageVsNoCoverage",
474                                                                                          "Comparison of same pattern with GL_SAMPLE_MASK disabled and enabled",
475                                                                                          renderedImgNoSampleCoverage,
476                                                                                          renderedImgSampleCoverage,
477                                                                                          tcu::RGBA(0),
478                                                                                          tcu::COMPARE_LOG_ON_ERROR);
479
480         if (passed)
481                 log << TestLog::Message << "Success: The two images rendered are identical" << TestLog::EndMessage;
482
483         m_context.getTestContext().setTestResult(passed ? QP_TEST_RESULT_PASS   : QP_TEST_RESULT_FAIL,
484                                                                                          passed ? "Passed"                              : "Failed");
485
486         return STOP;
487 }
488
489 void MaskInvertCase::drawPattern (bool invert) const
490 {
491         const int                               numTriangles    = 25;
492         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
493
494         for (int triNdx = 0; triNdx < numTriangles; triNdx++)
495         {
496                 const float     angle0  = 2.0f*DE_PI * (float)triNdx                    / (float)numTriangles;
497                 const float     angle1  = 2.0f*DE_PI * ((float)triNdx + 0.5f)   / (float)numTriangles;
498                 const Vec4      color   = Vec4(0.4f + (float)triNdx/(float)numTriangles*0.6f,
499                                            0.5f + (float)triNdx/(float)numTriangles*0.3f,
500                                            0.6f - (float)triNdx/(float)numTriangles*0.5f,
501                                            0.7f - (float)triNdx/(float)numTriangles*0.7f);
502
503
504                 const int                       wordCount               = getEffectiveSampleMaskWordCount(m_numSamples - 1);
505                 const GLbitfield        finalWordBits   = m_numSamples - 32 * ((m_numSamples-1) / 32);
506                 const GLbitfield        finalWordMask   = (GLbitfield)deBitMask32(0, (int)finalWordBits);
507
508                 for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
509                 {
510                         const GLbitfield        rawMask         = (GLbitfield)deUint32Hash(wordNdx * 32 + triNdx);
511                         const GLbitfield        mask            = (invert) ? (~rawMask) : (rawMask);
512                         const bool                      isFinalWord     = (wordNdx + 1) == wordCount;
513                         const GLbitfield        maskMask        = (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask prevents setting coverage bits higher than sample count
514
515                         gl.sampleMaski(wordNdx, mask & maskMask);
516                 }
517                 GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
518
519                 renderTriangle(Vec2(0.0f, 0.0f),
520                                            Vec2(deFloatCos(angle0)*0.95f, deFloatSin(angle0)*0.95f),
521                                            Vec2(deFloatCos(angle1)*0.95f, deFloatSin(angle1)*0.95f),
522                                            color);
523         }
524 }
525
526 /*--------------------------------------------------------------------*//*!
527  * \brief Tests coverage mask generation proportionality property.
528  *
529  * Tests that the number of coverage bits in a coverage mask set with
530  * glSampleMaski is, on average, proportional to the number of set bits.
531  * Draws multiple frames, each time increasing the number of mask bits set
532  * and checks that the average color is changing appropriately.
533  *//*--------------------------------------------------------------------*/
534 class MaskProportionalityCase : public DefaultFBOMultisampleCase
535 {
536 public:
537                                         MaskProportionalityCase                         (Context& context, const char* name, const char* description);
538                                         ~MaskProportionalityCase                        (void) {}
539
540         void                    init                                                            (void);
541
542         IterateResult   iterate                                                         (void);
543
544 private:
545         int                             m_numIterations;
546         int                             m_currentIteration;
547
548         deInt32                 m_previousIterationColorSum;
549 };
550
551 MaskProportionalityCase::MaskProportionalityCase (Context& context, const char* name, const char* description)
552         : DefaultFBOMultisampleCase             (context, name, description, 32)
553         , m_numIterations                               (-1)
554         , m_currentIteration                    (0)
555         , m_previousIterationColorSum   (-1)
556 {
557 }
558
559 void MaskProportionalityCase::init (void)
560 {
561         const glw::Functions&   gl      = m_context.getRenderContext().getFunctions();
562         TestLog&                                log     = m_testCtx.getLog();
563
564         // check the test is even possible
565         GLint maxSampleMaskWords = 0;
566         gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
567         if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
568                 throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
569
570         DefaultFBOMultisampleCase::init();
571
572         // set state
573         gl.enable(GL_SAMPLE_MASK);
574         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK)");
575         log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
576
577         m_numIterations = m_numSamples + 1;
578
579         randomizeViewport(); // \note Using the same viewport for every iteration since coverage mask may depend on window-relative pixel coordinate.
580 }
581
582 MaskProportionalityCase::IterateResult MaskProportionalityCase::iterate (void)
583 {
584         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
585         TestLog&                                log                             = m_testCtx.getLog();
586         tcu::Surface                    renderedImg             (m_viewportSize, m_viewportSize);
587         deInt32                                 numPixels               = (deInt32)renderedImg.getWidth()*(deInt32)renderedImg.getHeight();
588
589         DE_ASSERT(m_numIterations >= 0);
590
591         log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
592         gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
593         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
594         gl.clear(GL_COLOR_BUFFER_BIT);
595         GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
596
597         // Draw quad.
598
599         {
600                 const Vec2                                      pt0                                             (-1.0f, -1.0f);
601                 const Vec2                                      pt1                                             ( 1.0f, -1.0f);
602                 const Vec2                                      pt2                                             (-1.0f,  1.0f);
603                 const Vec2                                      pt3                                             ( 1.0f,  1.0f);
604                 Vec4                                            quadColor                               (1.0f, 0.0f, 0.0f, 1.0f);
605                 const std::vector<deUint32>     sampleMask                              = genAllSetToNthBitSampleMask(m_currentIteration);
606
607                 DE_ASSERT(m_currentIteration <= m_numSamples + 1);
608
609                 log << TestLog::Message << "Drawing a red quad using sample mask 0b" << sampleMaskToString(sampleMask, m_numSamples) << TestLog::EndMessage;
610
611                 for (int wordNdx = 0; wordNdx < getEffectiveSampleMaskWordCount(m_numSamples - 1); ++wordNdx)
612                 {
613                         const GLbitfield mask = (wordNdx < (int)sampleMask.size()) ? ((GLbitfield)(sampleMask[wordNdx])) : (0);
614
615                         gl.sampleMaski(wordNdx, mask);
616                         GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
617                 }
618
619                 renderQuad(pt0, pt1, pt2, pt3, quadColor);
620         }
621
622         // Read ang log image.
623
624         readImage(renderedImg);
625
626         log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);
627
628         // Compute average red component in rendered image.
629
630         deInt32 sumRed = 0;
631
632         for (int y = 0; y < renderedImg.getHeight(); y++)
633         for (int x = 0; x < renderedImg.getWidth(); x++)
634                 sumRed += renderedImg.getPixel(x, y).getRed();
635
636         log << TestLog::Message << "Average red color component: " << de::floatToString((float)sumRed / 255.0f / (float)numPixels, 2) << TestLog::EndMessage;
637
638         // Check if average color has decreased from previous frame's color.
639
640         if (sumRed < m_previousIterationColorSum)
641         {
642                 log << TestLog::Message << "Failure: Current average red color component is lower than previous" << TestLog::EndMessage;
643                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
644                 return STOP;
645         }
646
647         // Check if coverage mask is not all-zeros if alpha or coverage value is 0 (or 1, if inverted).
648
649         if (m_currentIteration == 0 && sumRed != 0)
650         {
651                 log << TestLog::Message << "Failure: Image should be completely black" << TestLog::EndMessage;
652                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
653                 return STOP;
654         }
655
656         if (m_currentIteration == m_numIterations-1 && sumRed != 0xff*numPixels)
657         {
658                 log << TestLog::Message << "Failure: Image should be completely red" << TestLog::EndMessage;
659
660                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
661                 return STOP;
662         }
663
664         m_previousIterationColorSum = sumRed;
665
666         m_currentIteration++;
667
668         if (m_currentIteration >= m_numIterations)
669         {
670                 log << TestLog::Message << "Success: Number of coverage mask bits set appears to be, on average, proportional to the number of set sample mask bits" << TestLog::EndMessage;
671                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
672                 return STOP;
673         }
674         else
675                 return CONTINUE;
676 }
677
678 /*--------------------------------------------------------------------*//*!
679  * \brief Tests coverage mask generation constancy property.
680  *
681  * Tests that the coverage mask created by GL_SAMPLE_MASK is constant at
682  * given pixel coordinates. Draws two quads, with the second one fully
683  * overlapping the first one such that at any given pixel, both quads have
684  * the same coverage mask value. This way, if the constancy property is
685  * fulfilled, only the second quad should be visible.
686  *//*--------------------------------------------------------------------*/
687 class MaskConstancyCase : public DefaultFBOMultisampleCase
688 {
689 public:
690         enum CaseBits
691         {
692                 CASEBIT_ALPHA_TO_COVERAGE                       = 1,    //!< Use alpha-to-coverage.
693                 CASEBIT_SAMPLE_COVERAGE                         = 2,    //!< Use sample coverage.
694                 CASEBIT_SAMPLE_COVERAGE_INVERTED        = 4,    //!< Inverted sample coverage.
695                 CASEBIT_SAMPLE_MASK                                     = 8,    //!< Use sample mask.
696         };
697
698                                         MaskConstancyCase                       (Context& context, const char* name, const char* description, deUint32 typeBits);
699                                         ~MaskConstancyCase                      (void) {}
700
701         void                    init                                            (void);
702         IterateResult   iterate                                         (void);
703
704 private:
705         const bool              m_isAlphaToCoverageCase;
706         const bool              m_isSampleCoverageCase;
707         const bool              m_isInvertedSampleCoverageCase;
708         const bool              m_isSampleMaskCase;
709 };
710
711 MaskConstancyCase::MaskConstancyCase (Context& context, const char* name, const char* description, deUint32 typeBits)
712         : DefaultFBOMultisampleCase                     (context, name, description, 256)
713         , m_isAlphaToCoverageCase                       (0 != (typeBits & CASEBIT_ALPHA_TO_COVERAGE))
714         , m_isSampleCoverageCase                        (0 != (typeBits & CASEBIT_SAMPLE_COVERAGE))
715         , m_isInvertedSampleCoverageCase        (0 != (typeBits & CASEBIT_SAMPLE_COVERAGE_INVERTED))
716         , m_isSampleMaskCase                            (0 != (typeBits & CASEBIT_SAMPLE_MASK))
717 {
718         // CASEBIT_SAMPLE_COVERAGE_INVERT => CASEBIT_SAMPLE_COVERAGE
719         DE_ASSERT((typeBits & CASEBIT_SAMPLE_COVERAGE) || ~(typeBits & CASEBIT_SAMPLE_COVERAGE_INVERTED));
720         DE_ASSERT(m_isSampleMaskCase); // no point testing non-sample-mask cases, they are checked already in gles3
721 }
722
723 void MaskConstancyCase::init (void)
724 {
725         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
726
727         // check the test is even possible
728         if (m_isSampleMaskCase)
729         {
730                 GLint maxSampleMaskWords = 0;
731                 gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
732                 if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
733                         throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
734         }
735
736         // normal init
737         DefaultFBOMultisampleCase::init();
738 }
739
740 MaskConstancyCase::IterateResult MaskConstancyCase::iterate (void)
741 {
742         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
743         TestLog&                                log                             = m_testCtx.getLog();
744         tcu::Surface                    renderedImg             (m_viewportSize, m_viewportSize);
745
746         randomizeViewport();
747
748         log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
749         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
750         gl.clear(GL_COLOR_BUFFER_BIT);
751         GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
752
753         if (m_isAlphaToCoverageCase)
754         {
755                 gl.enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
756                 gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
757                 GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_ALPHA_TO_COVERAGE");
758
759                 log << TestLog::Message << "GL_SAMPLE_ALPHA_TO_COVERAGE is enabled" << TestLog::EndMessage;
760                 log << TestLog::Message << "Color mask is TRUE, TRUE, TRUE, FALSE" << TestLog::EndMessage;
761         }
762
763         if (m_isSampleCoverageCase)
764         {
765                 gl.enable(GL_SAMPLE_COVERAGE);
766                 GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_COVERAGE");
767
768                 log << TestLog::Message << "GL_SAMPLE_COVERAGE is enabled" << TestLog::EndMessage;
769         }
770
771         if (m_isSampleMaskCase)
772         {
773                 gl.enable(GL_SAMPLE_MASK);
774                 GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_MASK");
775
776                 log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
777         }
778
779         log << TestLog::Message
780                 << "Drawing several green quads, each fully overlapped by a red quad with the same "
781                 << (m_isAlphaToCoverageCase ? "alpha" : "")
782                 << (m_isAlphaToCoverageCase && (m_isSampleCoverageCase || m_isSampleMaskCase) ? " and " : "")
783                 << (m_isInvertedSampleCoverageCase ? "inverted " : "")
784                 << (m_isSampleCoverageCase ? "sample coverage" : "")
785                 << (m_isSampleCoverageCase && m_isSampleMaskCase ? " and " : "")
786                 << (m_isSampleMaskCase ? "sample mask" : "")
787                 << " values"
788                 << TestLog::EndMessage;
789
790         const int numQuadRowsCols = m_numSamples*4;
791
792         for (int row = 0; row < numQuadRowsCols; row++)
793         {
794                 for (int col = 0; col < numQuadRowsCols; col++)
795                 {
796                         float           x0                      = (float)(col+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
797                         float           x1                      = (float)(col+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
798                         float           y0                      = (float)(row+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
799                         float           y1                      = (float)(row+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
800                         const Vec4      baseGreen       (0.0f, 1.0f, 0.0f, 0.0f);
801                         const Vec4      baseRed         (1.0f, 0.0f, 0.0f, 0.0f);
802                         Vec4            alpha0          (0.0f, 0.0f, 0.0f, m_isAlphaToCoverageCase ? (float)col / (float)(numQuadRowsCols-1) : 1.0f);
803                         Vec4            alpha1          (0.0f, 0.0f, 0.0f, m_isAlphaToCoverageCase ? (float)row / (float)(numQuadRowsCols-1) : 1.0f);
804
805                         if (m_isSampleCoverageCase)
806                         {
807                                 float value = (float)(row*numQuadRowsCols + col) / (float)(numQuadRowsCols*numQuadRowsCols-1);
808                                 gl.sampleCoverage(m_isInvertedSampleCoverageCase ? 1.0f - value : value, m_isInvertedSampleCoverageCase ? GL_TRUE : GL_FALSE);
809                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleCoverage");
810                         }
811
812                         if (m_isSampleMaskCase)
813                         {
814                                 const int                       wordCount               = getEffectiveSampleMaskWordCount(m_numSamples - 1);
815                                 const GLbitfield        finalWordBits   = m_numSamples - 32 * ((m_numSamples-1) / 32);
816                                 const GLbitfield        finalWordMask   = (GLbitfield)deBitMask32(0, (int)finalWordBits);
817
818                                 for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
819                                 {
820                                         const GLbitfield        mask            = (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
821                                         const bool                      isFinalWord     = (wordNdx + 1) == wordCount;
822                                         const GLbitfield        maskMask        = (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask prevents setting coverage bits higher than sample count
823
824                                         gl.sampleMaski(wordNdx, mask & maskMask);
825                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
826                                 }
827                         }
828
829                         renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseGreen + alpha0,  baseGreen + alpha1,     baseGreen + alpha0,     baseGreen + alpha1);
830                         renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseRed + alpha0,    baseRed + alpha1,       baseRed + alpha0,       baseRed + alpha1);
831                 }
832         }
833
834         readImage(renderedImg);
835
836         log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);
837
838         for (int y = 0; y < renderedImg.getHeight(); y++)
839         for (int x = 0; x < renderedImg.getWidth(); x++)
840         {
841                 if (renderedImg.getPixel(x, y).getGreen() > 0)
842                 {
843                         log << TestLog::Message << "Failure: Non-zero green color component detected - should have been completely overwritten by red quad" << TestLog::EndMessage;
844                         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
845                         return STOP;
846                 }
847         }
848
849         log << TestLog::Message
850                 << "Success: Coverage mask appears to be constant at a given pixel coordinate with a given "
851                 << (m_isAlphaToCoverageCase ? "alpha" : "")
852                 << (m_isAlphaToCoverageCase && m_isSampleCoverageCase ? " and " : "")
853                 << (m_isSampleCoverageCase ? "coverage value" : "")
854                 << TestLog::EndMessage;
855
856         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
857
858         return STOP;
859 }
860
861 /*--------------------------------------------------------------------*//*!
862  * \brief Tests that unused bits of a sample mask have no effect
863  *
864  * Tests that the bits in the sample mask with positions higher than
865  * the number of samples do not have effect. In multisample fragment
866  * operations the sample mask is ANDed with the fragment coverage value.
867  * The coverage value cannot have the corresponding bits set.
868  *
869  * This is done by drawing a quads with varying sample masks and then
870  * redrawing the quads with identical masks but with the mask's high bits
871  * having different values. Only the latter quad pattern should be visible.
872  *//*--------------------------------------------------------------------*/
873 class SampleMaskHighBitsCase : public DefaultFBOMultisampleCase
874 {
875 public:
876                                         SampleMaskHighBitsCase          (Context& context, const char* name, const char* description);
877                                         ~SampleMaskHighBitsCase         (void) {}
878
879         void                    init                                            (void);
880         IterateResult   iterate                                         (void);
881 };
882
883 SampleMaskHighBitsCase::SampleMaskHighBitsCase (Context& context, const char* name, const char* description)
884         : DefaultFBOMultisampleCase(context, name, description, 256)
885 {
886 }
887
888 void SampleMaskHighBitsCase::init (void)
889 {
890         const glw::Functions&   gl                                      = m_context.getRenderContext().getFunctions();
891         GLint                                    maxSampleMaskWords     = 0;
892
893         // check the test is even possible
894         gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
895         if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
896                 throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
897
898         // normal init
899         DefaultFBOMultisampleCase::init();
900 }
901
902 SampleMaskHighBitsCase::IterateResult SampleMaskHighBitsCase::iterate (void)
903 {
904         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
905         TestLog&                                log                             = m_testCtx.getLog();
906         tcu::Surface                    renderedImg             (m_viewportSize, m_viewportSize);
907         de::Random                              rnd                             (12345);
908
909         if (m_numSamples % 32 == 0)
910         {
911                 log << TestLog::Message << "Sample count is multiple of word size. No unused high bits in sample mask.\nSkipping." << TestLog::EndMessage;
912                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Skipped");
913                 return STOP;
914         }
915
916         randomizeViewport();
917
918         log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
919         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
920         gl.clear(GL_COLOR_BUFFER_BIT);
921         GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
922
923         gl.enable(GL_SAMPLE_MASK);
924         GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_MASK");
925         log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
926         log << TestLog::Message << "Drawing several green quads, each fully overlapped by a red quad with the same effective sample mask values" << TestLog::EndMessage;
927
928         const int numQuadRowsCols = m_numSamples*4;
929
930         for (int row = 0; row < numQuadRowsCols; row++)
931         {
932                 for (int col = 0; col < numQuadRowsCols; col++)
933                 {
934                         float                           x0                              = (float)(col+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
935                         float                           x1                              = (float)(col+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
936                         float                           y0                              = (float)(row+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
937                         float                           y1                              = (float)(row+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
938                         const Vec4                      baseGreen               (0.0f, 1.0f, 0.0f, 1.0f);
939                         const Vec4                      baseRed                 (1.0f, 0.0f, 0.0f, 1.0f);
940
941                         const int                       wordCount               = getEffectiveSampleMaskWordCount(m_numSamples - 1);
942                         const GLbitfield        finalWordBits   = m_numSamples - 32 * ((m_numSamples-1) / 32);
943                         const GLbitfield        finalWordMask   = (GLbitfield)deBitMask32(0, (int)finalWordBits);
944
945                         for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
946                         {
947                                 const GLbitfield        mask            = (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
948                                 const bool                      isFinalWord     = (wordNdx + 1) == wordCount;
949                                 const GLbitfield        maskMask        = (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask is 1 on bits in lower positions than sample count
950                                 const GLbitfield        highBits        = rnd.getUint32();
951
952                                 gl.sampleMaski(wordNdx, (mask & maskMask) | (highBits & ~maskMask));
953                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
954                         }
955                         renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseGreen, baseGreen, baseGreen, baseGreen);
956
957                         for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
958                         {
959                                 const GLbitfield        mask            = (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
960                                 const bool                      isFinalWord     = (wordNdx + 1) == wordCount;
961                                 const GLbitfield        maskMask        = (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask is 1 on bits in lower positions than sample count
962                                 const GLbitfield        highBits        = rnd.getUint32();
963
964                                 gl.sampleMaski(wordNdx, (mask & maskMask) | (highBits & ~maskMask));
965                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
966                         }
967                         renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseRed, baseRed, baseRed, baseRed);
968                 }
969         }
970
971         readImage(renderedImg);
972
973         log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);
974
975         for (int y = 0; y < renderedImg.getHeight(); y++)
976         for (int x = 0; x < renderedImg.getWidth(); x++)
977         {
978                 if (renderedImg.getPixel(x, y).getGreen() > 0)
979                 {
980                         log << TestLog::Message << "Failure: Non-zero green color component detected - should have been completely overwritten by red quad. Mask unused bits have effect." << TestLog::EndMessage;
981                         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Unused mask bits modified mask");
982                         return STOP;
983                 }
984         }
985
986         log << TestLog::Message << "Success: Coverage mask high bits appear to have no effect." << TestLog::EndMessage;
987         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
988
989         return STOP;
990 }
991
992 } // anonymous
993
994 MultisampleTests::MultisampleTests (Context& context)
995         : TestCaseGroup(context, "multisample", "Multisample tests")
996 {
997 }
998
999 MultisampleTests::~MultisampleTests (void)
1000 {
1001 }
1002
1003 void MultisampleTests::init (void)
1004 {
1005         tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "default_framebuffer", "Test with default framebuffer");
1006
1007         addChild(group);
1008
1009         // .default_framebuffer
1010         {
1011                 // sample positions
1012                 group->addChild(new SamplePosQueryCase                  (m_context, "sample_position", "test SAMPLE_POSITION"));
1013
1014                 // sample mask
1015                 group->addChild(new MaskInvertCase                              (m_context, "sample_mask_sum_of_inverses",      "Test that mask and its negation's sum equal the fully set mask"));
1016                 group->addChild(new MaskProportionalityCase             (m_context, "proportionality_sample_mask",      "Test the proportionality property of GL_SAMPLE_MASK"));
1017
1018                 group->addChild(new MaskConstancyCase                   (m_context, "constancy_sample_mask",
1019                                                                                                                                         "Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_MASK",
1020                                                                                                                                         MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1021                 group->addChild(new MaskConstancyCase                   (m_context, "constancy_alpha_to_coverage_sample_mask",
1022                                                                                                                                         "Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_ALPHA_TO_COVERAGE and GL_SAMPLE_MASK",
1023                                                                                                                                         MaskConstancyCase::CASEBIT_ALPHA_TO_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1024                 group->addChild(new MaskConstancyCase                   (m_context, "constancy_sample_coverage_sample_mask",
1025                                                                                                                                         "Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_COVERAGE and GL_SAMPLE_MASK",
1026                                                                                                                                         MaskConstancyCase::CASEBIT_SAMPLE_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1027                 group->addChild(new MaskConstancyCase                   (m_context, "constancy_alpha_to_coverage_sample_coverage_sample_mask",
1028                                                                                                                                         "Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE and GL_SAMPLE_MASK",
1029                                                                                                                                         MaskConstancyCase::CASEBIT_ALPHA_TO_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1030                 group->addChild(new SampleMaskHighBitsCase              (m_context, "sample_mask_non_effective_bits",
1031                                                                                                                                         "Test that values of unused bits of a sample mask (bit index > sample count) have no effect"));
1032         }
1033 }
1034
1035 } // Functional
1036 } // gles31
1037 } // deqp