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