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