• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // TextureMultisampleTest: Tests of multisampled texture
8 
9 #include "test_utils/ANGLETest.h"
10 
11 #include "test_utils/gl_raii.h"
12 #include "util/shader_utils.h"
13 
14 using namespace angle;
15 
16 namespace
17 {
18 // Sample positions of d3d standard pattern. Some of the sample positions might not the same as
19 // opengl.
20 using SamplePositionsArray                                            = std::array<float, 32>;
21 static constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
22     {{{0.5f, 0.5f}},
23      {{0.75f, 0.75f, 0.25f, 0.25f}},
24      {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
25      {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
26        0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
27      {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f,  0.75f,   0.4375f,
28        0.1875f, 0.375f,  0.625f,  0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
29        0.375f,  0.875f,  0.5f,    0.0625f, 0.25f,   0.125f,  0.125f,  0.75f,
30        0.0f,    0.5f,    0.9375f, 0.25f,   0.875f,  0.9375f, 0.0625f, 0.0f}}}};
31 
32 class TextureMultisampleTest : public ANGLETest<>
33 {
34   protected:
TextureMultisampleTest()35     TextureMultisampleTest()
36     {
37         setWindowWidth(64);
38         setWindowHeight(64);
39         setConfigRedBits(8);
40         setConfigGreenBits(8);
41         setConfigBlueBits(8);
42         setConfigAlphaBits(8);
43     }
44 
testSetUp()45     void testSetUp() override
46     {
47         glGenFramebuffers(1, &mFramebuffer);
48         glGenTextures(1, &mTexture);
49 
50         ASSERT_GL_NO_ERROR();
51     }
52 
testTearDown()53     void testTearDown() override
54     {
55         glDeleteFramebuffers(1, &mFramebuffer);
56         mFramebuffer = 0;
57         glDeleteTextures(1, &mTexture);
58         mTexture = 0;
59     }
60 
61     void texStorageMultisample(GLenum target,
62                                GLint samples,
63                                GLenum format,
64                                GLsizei width,
65                                GLsizei height,
66                                GLboolean fixedsamplelocations);
67 
68     void getTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params);
69     void getTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
70 
71     void getMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
72     void sampleMaski(GLuint maskNumber, GLbitfield mask);
73 
74     GLuint mFramebuffer = 0;
75     GLuint mTexture     = 0;
76 
77     // Returns a sample count that can be used with the given texture target for all the given
78     // formats. Assumes that if format A supports a number of samples N and another format B
79     // supports a number of samples M > N then format B also supports number of samples N.
getSamplesToUse(GLenum texTarget,const std::vector<GLenum> & formats)80     GLint getSamplesToUse(GLenum texTarget, const std::vector<GLenum> &formats)
81     {
82         GLint maxSamples = 65536;
83         for (GLenum format : formats)
84         {
85             GLint maxSamplesFormat = 0;
86             glGetInternalformativ(texTarget, format, GL_SAMPLES, 1, &maxSamplesFormat);
87             maxSamples = std::min(maxSamples, maxSamplesFormat);
88         }
89         return maxSamples;
90     }
91 
lessThanES31MultisampleExtNotSupported()92     bool lessThanES31MultisampleExtNotSupported()
93     {
94         return getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
95                !EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample");
96     }
97 
multisampleTextureFragmentShader()98     const char *multisampleTextureFragmentShader()
99     {
100         return R"(#version 300 es
101 #extension GL_ANGLE_texture_multisample : require
102 precision highp float;
103 precision highp int;
104 
105 uniform highp sampler2DMS tex;
106 uniform int sampleNum;
107 
108 in vec4 v_position;
109 out vec4 my_FragColor;
110 
111 void main() {
112     ivec2 texSize = textureSize(tex);
113     ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
114     my_FragColor = texelFetch(tex, sampleCoords, sampleNum);
115 }
116 )";
117     }
118 
blitArrayTextureLayerFragmentShader()119     const char *blitArrayTextureLayerFragmentShader()
120     {
121         return R"(#version 310 es
122 #extension GL_OES_texture_storage_multisample_2d_array : require
123 precision highp float;
124 precision highp int;
125 
126 uniform highp sampler2DMSArray tex;
127 uniform int layer;
128 uniform int sampleNum;
129 
130 in vec4 v_position;
131 out vec4 my_FragColor;
132 
133 void main() {
134     ivec3 texSize = textureSize(tex);
135     ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
136     my_FragColor = texelFetch(tex, ivec3(sampleCoords, layer), sampleNum);
137 }
138 )";
139     }
140 
blitIntArrayTextureLayerFragmentShader()141     const char *blitIntArrayTextureLayerFragmentShader()
142     {
143         return R"(#version 310 es
144 #extension GL_OES_texture_storage_multisample_2d_array : require
145 precision highp float;
146 precision highp int;
147 
148 uniform highp isampler2DMSArray tex;
149 uniform int layer;
150 uniform int sampleNum;
151 
152 in vec4 v_position;
153 out vec4 my_FragColor;
154 
155 void main() {
156     ivec3 texSize = textureSize(tex);
157     ivec2 sampleCoords = ivec2((v_position.xy * 0.5 + 0.5) * vec2(texSize.xy - 1));
158     my_FragColor = vec4(texelFetch(tex, ivec3(sampleCoords, layer), sampleNum));
159 }
160 )";
161     }
162 };
163 
164 class NegativeTextureMultisampleTest : public TextureMultisampleTest
165 {
166   protected:
NegativeTextureMultisampleTest()167     NegativeTextureMultisampleTest() : TextureMultisampleTest() {}
168 };
169 
170 class TextureMultisampleArrayWebGLTest : public TextureMultisampleTest
171 {
172   protected:
TextureMultisampleArrayWebGLTest()173     TextureMultisampleArrayWebGLTest() : TextureMultisampleTest()
174     {
175         // These tests run in WebGL mode so we can test with both extension off and on.
176         setWebGLCompatibilityEnabled(true);
177     }
178 
179     // Requests the ANGLE_texture_multisample_array extension and returns true if the operation
180     // succeeds.
requestArrayExtension()181     bool requestArrayExtension()
182     {
183         if (IsGLExtensionRequestable("GL_OES_texture_storage_multisample_2d_array"))
184         {
185             glRequestExtensionANGLE("GL_OES_texture_storage_multisample_2d_array");
186         }
187 
188         if (!IsGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"))
189         {
190             return false;
191         }
192         return true;
193     }
194 };
195 
texStorageMultisample(GLenum target,GLint samples,GLenum internalformat,GLsizei width,GLsizei height,GLboolean fixedsamplelocations)196 void TextureMultisampleTest::texStorageMultisample(GLenum target,
197                                                    GLint samples,
198                                                    GLenum internalformat,
199                                                    GLsizei width,
200                                                    GLsizei height,
201                                                    GLboolean fixedsamplelocations)
202 {
203     if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
204         EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
205     {
206         glTexStorage2DMultisampleANGLE(target, samples, internalformat, width, height,
207                                        fixedsamplelocations);
208     }
209     else
210     {
211         glTexStorage2DMultisample(target, samples, internalformat, width, height,
212                                   fixedsamplelocations);
213     }
214 }
215 
getTexLevelParameterfv(GLenum target,GLint level,GLenum pname,GLfloat * params)216 void TextureMultisampleTest::getTexLevelParameterfv(GLenum target,
217                                                     GLint level,
218                                                     GLenum pname,
219                                                     GLfloat *params)
220 {
221     if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
222         EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
223     {
224         glGetTexLevelParameterfvANGLE(target, level, pname, params);
225     }
226     else
227     {
228         glGetTexLevelParameterfv(target, level, pname, params);
229     }
230 }
231 
getTexLevelParameteriv(GLenum target,GLint level,GLenum pname,GLint * params)232 void TextureMultisampleTest::getTexLevelParameteriv(GLenum target,
233                                                     GLint level,
234                                                     GLenum pname,
235                                                     GLint *params)
236 {
237     if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
238         EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
239     {
240         glGetTexLevelParameterivANGLE(target, level, pname, params);
241     }
242     else
243     {
244         glGetTexLevelParameteriv(target, level, pname, params);
245     }
246 }
247 
getMultisamplefv(GLenum pname,GLuint index,GLfloat * val)248 void TextureMultisampleTest::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
249 {
250     if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
251         EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
252     {
253         glGetMultisamplefvANGLE(pname, index, val);
254     }
255     else
256     {
257         glGetMultisamplefv(pname, index, val);
258     }
259 }
260 
sampleMaski(GLuint maskNumber,GLbitfield mask)261 void TextureMultisampleTest::sampleMaski(GLuint maskNumber, GLbitfield mask)
262 {
263     if (getClientMajorVersion() <= 3 && getClientMinorVersion() < 1 &&
264         EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"))
265     {
266         glSampleMaskiANGLE(maskNumber, mask);
267     }
268     else
269     {
270         glSampleMaski(maskNumber, mask);
271     }
272 }
273 
274 // Tests that if es version < 3.1, GL_TEXTURE_2D_MULTISAMPLE is not supported in
275 // GetInternalformativ. Checks that the number of samples returned is valid in case of ES >= 3.1.
TEST_P(TextureMultisampleTest,MultisampleTargetGetInternalFormativBase)276 TEST_P(TextureMultisampleTest, MultisampleTargetGetInternalFormativBase)
277 {
278     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
279 
280     // This query returns supported sample counts in descending order. If only one sample count is
281     // queried, it should be the maximum one.
282     GLint maxSamplesR8 = 0;
283     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamplesR8);
284 
285     // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
286     GLint maxColorTextureSamples;
287     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
288     GLint maxSamples;
289     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
290     GLint maxSamplesR8Required = std::min(maxColorTextureSamples, maxSamples);
291 
292     EXPECT_GE(maxSamplesR8, maxSamplesR8Required);
293     ASSERT_GL_NO_ERROR();
294 }
295 
296 // Tests that if es version < 3.1 and multisample extension is unsupported,
297 // GL_TEXTURE_2D_MULTISAMPLE_ANGLE is not supported in FramebufferTexture2D.
TEST_P(TextureMultisampleTest,MultisampleTargetFramebufferTexture2D)298 TEST_P(TextureMultisampleTest, MultisampleTargetFramebufferTexture2D)
299 {
300     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
301     GLint samples = 1;
302     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
303     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA8, 64, 64, GL_FALSE);
304 
305     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
306     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
307                            mTexture, 0);
308 
309     ASSERT_GL_NO_ERROR();
310 }
311 
312 // Tests basic functionality of glTexStorage2DMultisample.
TEST_P(TextureMultisampleTest,ValidateTextureStorageMultisampleParameters)313 TEST_P(TextureMultisampleTest, ValidateTextureStorageMultisampleParameters)
314 {
315     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
316 
317     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
318     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
319     ASSERT_GL_NO_ERROR();
320 
321     GLint params = 0;
322     glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, &params);
323     EXPECT_EQ(1, params);
324 
325     texStorageMultisample(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, GL_FALSE);
326     ASSERT_GL_ERROR(GL_INVALID_ENUM);
327 
328     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 0, 0, GL_FALSE);
329     ASSERT_GL_ERROR(GL_INVALID_VALUE);
330 
331     GLint maxSize = 0;
332     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
333     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, maxSize + 1, 1, GL_FALSE);
334     ASSERT_GL_ERROR(GL_INVALID_VALUE);
335 
336     GLint maxSamples = 0;
337     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
338     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples + 1, GL_RGBA8, 1, 1, GL_FALSE);
339     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
340 
341     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_RGBA8, 1, 1, GL_FALSE);
342     ASSERT_GL_ERROR(GL_INVALID_VALUE);
343 
344     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA, 0, 0, GL_FALSE);
345     ASSERT_GL_ERROR(GL_INVALID_VALUE);
346 
347     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
348     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_FALSE);
349     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
350 }
351 
352 // Tests the value of MAX_INTEGER_SAMPLES is no less than 1.
353 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxIntegerSamples)354 TEST_P(TextureMultisampleTest, MaxIntegerSamples)
355 {
356     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
357 
358     // Fixed in recent mesa.  http://crbug.com/1071142
359     ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && (IsIntel() || IsAMD()));
360 
361     GLint maxIntegerSamples;
362     glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &maxIntegerSamples);
363     EXPECT_GE(maxIntegerSamples, 1);
364     EXPECT_NE(std::numeric_limits<GLint>::max(), maxIntegerSamples);
365 }
366 
367 // Tests the value of MAX_COLOR_TEXTURE_SAMPLES is no less than 1.
368 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxColorTextureSamples)369 TEST_P(TextureMultisampleTest, MaxColorTextureSamples)
370 {
371     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
372     GLint maxColorTextureSamples;
373     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
374     EXPECT_GE(maxColorTextureSamples, 1);
375     EXPECT_NE(std::numeric_limits<GLint>::max(), maxColorTextureSamples);
376 }
377 
378 // Tests the value of MAX_DEPTH_TEXTURE_SAMPLES is no less than 1.
379 // [OpenGL ES 3.1 SPEC Table 20.40]
TEST_P(TextureMultisampleTest,MaxDepthTextureSamples)380 TEST_P(TextureMultisampleTest, MaxDepthTextureSamples)
381 {
382     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
383     GLint maxDepthTextureSamples;
384     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
385     EXPECT_GE(maxDepthTextureSamples, 1);
386     EXPECT_NE(std::numeric_limits<GLint>::max(), maxDepthTextureSamples);
387 }
388 
389 // Tests the maximum value of MAX_INTEGER_SAMPLES is supported
TEST_P(TextureMultisampleTest,MaxIntegerSamplesValid)390 TEST_P(TextureMultisampleTest, MaxIntegerSamplesValid)
391 {
392     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
393 
394     // Fixed in recent mesa.  http://crbug.com/1071142
395     ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && (IsIntel() || IsAMD()));
396 
397     GLint maxIntegerSamples;
398     glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &maxIntegerSamples);
399 
400     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
401 
402     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxIntegerSamples, GL_RGBA8I, 1, 1, GL_FALSE);
403     ASSERT_GL_NO_ERROR();
404 }
405 
406 // Tests the maximum value of MAX_COLOR_TEXTURE_SAMPLES is supported
TEST_P(TextureMultisampleTest,MaxColorTextureSamplesValid)407 TEST_P(TextureMultisampleTest, MaxColorTextureSamplesValid)
408 {
409     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
410     GLint maxColorTextureSamples;
411     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
412 
413     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
414     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxColorTextureSamples, GL_RGBA8, 1, 1,
415                           GL_FALSE);
416     ASSERT_GL_NO_ERROR();
417 }
418 
419 // Tests the maximum value of MAX_DEPTH_TEXTURE_SAMPLES is supported
TEST_P(TextureMultisampleTest,MaxDepthTextureSamplesValid)420 TEST_P(TextureMultisampleTest, MaxDepthTextureSamplesValid)
421 {
422     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
423     GLint maxDepthTextureSamples;
424     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
425 
426     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
427     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxDepthTextureSamples, GL_DEPTH_COMPONENT16,
428                           1, 1, GL_FALSE);
429     ASSERT_GL_NO_ERROR();
430 }
431 
432 // Tests that getTexLevelParameter is supported by ES 3.1 or ES 3.0 and ANGLE_texture_multisample
TEST_P(TextureMultisampleTest,GetTexLevelParameter)433 TEST_P(TextureMultisampleTest, GetTexLevelParameter)
434 {
435     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
436 
437     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
438     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 1, 1, GL_TRUE);
439     ASSERT_GL_NO_ERROR();
440 
441     GLfloat levelSamples = 0;
442     getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
443     EXPECT_EQ(levelSamples, 4);
444 
445     GLint fixedSampleLocation = false;
446     getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
447                            &fixedSampleLocation);
448     EXPECT_EQ(fixedSampleLocation, 1);
449 
450     ASSERT_GL_NO_ERROR();
451 }
452 
453 // The value of sample position should be equal to standard pattern on D3D.
TEST_P(TextureMultisampleTest,CheckSamplePositions)454 TEST_P(TextureMultisampleTest, CheckSamplePositions)
455 {
456     ANGLE_SKIP_TEST_IF(!IsD3D11());
457 
458     GLsizei maxSamples = 0;
459     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
460 
461     GLfloat samplePosition[2];
462 
463     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
464 
465     for (int sampleCount = 1; sampleCount <= maxSamples; sampleCount++)
466     {
467         GLTexture texture;
468         size_t indexKey = static_cast<size_t>(ceil(log2(sampleCount)));
469         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
470         texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, 1, 1, GL_TRUE);
471         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
472                                texture, 0);
473         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
474         ASSERT_GL_NO_ERROR();
475 
476         for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
477         {
478             getMultisamplefv(GL_SAMPLE_POSITION, sampleIndex, samplePosition);
479             EXPECT_EQ(samplePosition[0], kSamplePositions[indexKey][2 * sampleIndex]);
480             EXPECT_EQ(samplePosition[1], kSamplePositions[indexKey][2 * sampleIndex + 1]);
481         }
482     }
483 
484     ASSERT_GL_NO_ERROR();
485 }
486 
487 // Test textureSize and texelFetch when using ANGLE_texture_multisample extension
TEST_P(TextureMultisampleTest,SimpleTexelFetch)488 TEST_P(TextureMultisampleTest, SimpleTexelFetch)
489 {
490     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
491 
492     ANGLE_GL_PROGRAM(texelFetchProgram, essl3_shaders::vs::Passthrough(),
493                      multisampleTextureFragmentShader());
494 
495     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
496     ASSERT_GE(texLocation, 0);
497     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
498     ASSERT_GE(sampleNumLocation, 0);
499 
500     const GLsizei kWidth  = 4;
501     const GLsizei kHeight = 4;
502 
503     std::vector<GLenum> testFormats = {GL_RGBA8};
504     GLint samplesToUse              = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, testFormats);
505 
506     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, mTexture);
507     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE_ANGLE, samplesToUse, GL_RGBA8, kWidth, kHeight,
508                           GL_TRUE);
509     ASSERT_GL_NO_ERROR();
510 
511     // Clear texture zero to green.
512     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
513     GLColor clearColor = GLColor::green;
514 
515     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE_ANGLE,
516                            mTexture, 0);
517     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
518     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
519     glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
520                  clearColor.A / 255.0f);
521     glClear(GL_COLOR_BUFFER_BIT);
522     ASSERT_GL_NO_ERROR();
523 
524     glBindFramebuffer(GL_FRAMEBUFFER, 0);
525     glUseProgram(texelFetchProgram);
526     glViewport(0, 0, kWidth, kHeight);
527 
528     for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
529     {
530         glUniform1i(sampleNumLocation, sampleNum);
531         drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
532         ASSERT_GL_NO_ERROR();
533         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColor);
534     }
535 }
536 
TEST_P(TextureMultisampleTest,SampleMaski)537 TEST_P(TextureMultisampleTest, SampleMaski)
538 {
539     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
540 
541     GLint maxSampleMaskWords = 0;
542     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
543     sampleMaski(maxSampleMaskWords - 1, 0x1);
544     ASSERT_GL_NO_ERROR();
545 
546     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
547     sampleMaski(maxSampleMaskWords, 0x1);
548     ASSERT_GL_ERROR(GL_INVALID_VALUE);
549 }
550 
TEST_P(TextureMultisampleTest,ResolveToDefaultFramebuffer)551 TEST_P(TextureMultisampleTest, ResolveToDefaultFramebuffer)
552 {
553     ANGLE_SKIP_TEST_IF(lessThanES31MultisampleExtNotSupported());
554 
555     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
556     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, getWindowWidth(),
557                           getWindowHeight(), GL_TRUE);
558     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
559     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
560 
561     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
562     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
563                            mTexture, 0);
564     ASSERT_GL_NO_ERROR();
565 
566     // Clear the framebuffer
567     glClearColor(0.25, 0.5, 0.75, 0.25);
568     glClear(GL_COLOR_BUFFER_BIT);
569 
570     // Resolve into default framebuffer
571     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
572     glClearColor(1, 0, 0, 1);
573     glClear(GL_COLOR_BUFFER_BIT);
574     glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
575                       getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
576     ASSERT_GL_NO_ERROR();
577 
578     const GLColor kResult = GLColor(63, 127, 191, 63);
579     const int w           = getWindowWidth() - 1;
580     const int h           = getWindowHeight() - 1;
581     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
582     EXPECT_PIXEL_COLOR_NEAR(0, 0, kResult, 1);
583     EXPECT_PIXEL_COLOR_NEAR(w, 0, kResult, 1);
584     EXPECT_PIXEL_COLOR_NEAR(0, h, kResult, 1);
585     EXPECT_PIXEL_COLOR_NEAR(w, h, kResult, 1);
586     EXPECT_PIXEL_COLOR_NEAR(w / 2, h / 2, kResult, 1);
587 }
588 
589 // Negative tests of multisample texture. When context less than ES 3.1 and ANGLE_texture_multsample
590 // not enabled, the feature isn't supported.
TEST_P(NegativeTextureMultisampleTest,Negtive)591 TEST_P(NegativeTextureMultisampleTest, Negtive)
592 {
593     ANGLE_SKIP_TEST_IF(EnsureGLExtensionEnabled("GL_ANGLE_texture_multisample"));
594 
595     GLint maxSamples = 0;
596     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R8, GL_SAMPLES, 1, &maxSamples);
597     ASSERT_GL_ERROR(GL_INVALID_ENUM);
598 
599     GLint maxColorTextureSamples;
600     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
601     ASSERT_GL_ERROR(GL_INVALID_ENUM);
602 
603     GLint maxDepthTextureSamples;
604     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
605     ASSERT_GL_ERROR(GL_INVALID_ENUM);
606 
607     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
608     ASSERT_GL_ERROR(GL_INVALID_ENUM);
609 
610     texStorageMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 64, 64, GL_FALSE);
611     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
612 
613     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
614                            mTexture, 0);
615     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
616 
617     GLint params = 0;
618     glGetTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_IMMUTABLE_FORMAT, &params);
619     ASSERT_GL_ERROR(GL_INVALID_ENUM);
620 
621     GLfloat levelSamples = 0;
622     getTexLevelParameterfv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &levelSamples);
623     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
624 
625     GLint fixedSampleLocation = false;
626     getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS,
627                            &fixedSampleLocation);
628     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
629 
630     GLint maxSampleMaskWords = 0;
631     glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
632     ASSERT_GL_ERROR(GL_INVALID_ENUM);
633     sampleMaski(maxSampleMaskWords - 1, 0x1);
634     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
635 }
636 
637 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is not supported in GetInternalformativ when the
638 // extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativWithoutExtension)639 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativWithoutExtension)
640 {
641     GLint maxSamples = 0;
642     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
643                           &maxSamples);
644     ASSERT_GL_ERROR(GL_INVALID_ENUM);
645 }
646 
647 // Attempt to bind a texture to multisample array binding point when extension is not supported.
TEST_P(TextureMultisampleArrayWebGLTest,BindMultisampleArrayTextureWithoutExtension)648 TEST_P(TextureMultisampleArrayWebGLTest, BindMultisampleArrayTextureWithoutExtension)
649 {
650     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
651     ASSERT_GL_ERROR(GL_INVALID_ENUM);
652 }
653 
654 // Try to compile shaders using GL_OES_texture_storage_multisample_2d_array when the extension is
655 // not enabled.
TEST_P(TextureMultisampleArrayWebGLTest,ShaderWithoutExtension)656 TEST_P(TextureMultisampleArrayWebGLTest, ShaderWithoutExtension)
657 {
658     constexpr char kFSRequiresExtension[] = R"(#version 310 es
659 #extension GL_OES_texture_storage_multisample_2d_array : require
660 out highp vec4 my_FragColor;
661 
662 void main() {
663         my_FragColor = vec4(0.0);
664 })";
665 
666     GLuint program = CompileProgram(essl31_shaders::vs::Simple(), kFSRequiresExtension);
667     EXPECT_EQ(0u, program);
668 
669     constexpr char kFSEnableAndUseExtension[] = R"(#version 310 es
670 #extension GL_OES_texture_storage_multisample_2d_array : enable
671 
672 uniform highp sampler2DMSArray tex;
673 out highp ivec4 outSize;
674 
675 void main() {
676         outSize = ivec4(textureSize(tex), 0);
677 })";
678 
679     program = CompileProgram(essl31_shaders::vs::Simple(), kFSEnableAndUseExtension);
680     EXPECT_EQ(0u, program);
681 }
682 
683 // Tests that GL_TEXTURE_2D_MULTISAMPLE_ARRAY is supported in GetInternalformativ.
TEST_P(TextureMultisampleArrayWebGLTest,MultisampleArrayTargetGetInternalFormativ)684 TEST_P(TextureMultisampleArrayWebGLTest, MultisampleArrayTargetGetInternalFormativ)
685 {
686     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
687 
688     // This query returns supported sample counts in descending order. If only one sample count is
689     // queried, it should be the maximum one.
690     GLint maxSamplesRGBA8 = 0;
691     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
692                           &maxSamplesRGBA8);
693     GLint maxSamplesDepth = 0;
694     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_DEPTH_COMPONENT24, GL_SAMPLES, 1,
695                           &maxSamplesDepth);
696     ASSERT_GL_NO_ERROR();
697 
698     // GLES 3.1 section 19.3.1 specifies the required minimum of how many samples are supported.
699     GLint maxColorTextureSamples;
700     glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
701     GLint maxDepthTextureSamples;
702     glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
703     GLint maxSamples;
704     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
705 
706     GLint maxSamplesRGBA8Required = std::min(maxColorTextureSamples, maxSamples);
707     EXPECT_GE(maxSamplesRGBA8, maxSamplesRGBA8Required);
708 
709     GLint maxSamplesDepthRequired = std::min(maxDepthTextureSamples, maxSamples);
710     EXPECT_GE(maxSamplesDepth, maxSamplesDepthRequired);
711 }
712 
713 // Tests that TexImage3D call cannot be used for GL_TEXTURE_2D_MULTISAMPLE_ARRAY.
TEST_P(TextureMultisampleArrayWebGLTest,MultiSampleArrayTexImage)714 TEST_P(TextureMultisampleArrayWebGLTest, MultiSampleArrayTexImage)
715 {
716     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
717 
718     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
719     ASSERT_GL_NO_ERROR();
720 
721     glTexImage3D(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA,
722                  GL_UNSIGNED_BYTE, nullptr);
723     EXPECT_GL_ERROR(GL_INVALID_ENUM);
724 }
725 
726 // Tests passing invalid parameters to TexStorage3DMultisample.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexStorage3DMultisample)727 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexStorage3DMultisample)
728 {
729     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
730 
731     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
732     ASSERT_GL_NO_ERROR();
733 
734     // Invalid target
735     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, 1, GL_TRUE);
736     EXPECT_GL_ERROR(GL_INVALID_ENUM);
737 
738     // Samples 0
739     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_RGBA8, 1, 1, 1,
740                                  GL_TRUE);
741     EXPECT_GL_ERROR(GL_INVALID_VALUE);
742 
743     // Unsized internalformat
744     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA, 1, 1, 1, GL_TRUE);
745     EXPECT_GL_ERROR(GL_INVALID_ENUM);
746 
747     // Width 0
748     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 0, 1, 1,
749                                  GL_TRUE);
750     EXPECT_GL_ERROR(GL_INVALID_VALUE);
751 
752     // Height 0
753     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 0, 1,
754                                  GL_TRUE);
755     EXPECT_GL_ERROR(GL_INVALID_VALUE);
756 
757     // Depth 0
758     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, 1, 1, 0,
759                                  GL_TRUE);
760     EXPECT_GL_ERROR(GL_INVALID_VALUE);
761 }
762 
763 // Tests passing invalid parameters to TexParameteri.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidTexParameteri)764 TEST_P(TextureMultisampleArrayWebGLTest, InvalidTexParameteri)
765 {
766     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
767 
768     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
769     ASSERT_GL_NO_ERROR();
770 
771     // None of the sampler parameters can be set on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES.
772     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
773     EXPECT_GL_ERROR(GL_INVALID_ENUM);
774     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
775     EXPECT_GL_ERROR(GL_INVALID_ENUM);
776 
777     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
778     EXPECT_GL_ERROR(GL_INVALID_ENUM);
779     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
780     EXPECT_GL_ERROR(GL_INVALID_ENUM);
781     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
782     EXPECT_GL_ERROR(GL_INVALID_ENUM);
783 
784     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MIN_LOD, 0);
785     EXPECT_GL_ERROR(GL_INVALID_ENUM);
786     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_MAX_LOD, 0);
787     EXPECT_GL_ERROR(GL_INVALID_ENUM);
788 
789     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_MODE, GL_NONE);
790     EXPECT_GL_ERROR(GL_INVALID_ENUM);
791     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
792     EXPECT_GL_ERROR(GL_INVALID_ENUM);
793 
794     // Only valid base level on GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES is 0.
795     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, 1);
796     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
797 }
798 
799 // Test a valid TexStorage3DMultisample call and check that the queried texture level parameters
800 // match. Does not do any drawing.
TEST_P(TextureMultisampleArrayWebGLTest,TexStorage3DMultisample)801 TEST_P(TextureMultisampleArrayWebGLTest, TexStorage3DMultisample)
802 {
803     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
804 
805     GLint maxSamplesRGBA8 = 0;
806     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
807                           &maxSamplesRGBA8);
808 
809     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
810     ASSERT_GL_NO_ERROR();
811 
812     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 8,
813                                  4, 2, GL_TRUE);
814     ASSERT_GL_NO_ERROR();
815 
816     GLint width = 0, height = 0, depth = 0, samples = 0;
817     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_WIDTH, &width);
818     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_HEIGHT, &height);
819     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_DEPTH, &depth);
820     glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0, GL_TEXTURE_SAMPLES, &samples);
821     ASSERT_GL_NO_ERROR();
822 
823     EXPECT_EQ(8, width);
824     EXPECT_EQ(4, height);
825     EXPECT_EQ(2, depth);
826     EXPECT_EQ(maxSamplesRGBA8, samples);
827 }
828 
829 // Test for invalid FramebufferTextureLayer calls with GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES
830 // textures.
TEST_P(TextureMultisampleArrayWebGLTest,InvalidFramebufferTextureLayer)831 TEST_P(TextureMultisampleArrayWebGLTest, InvalidFramebufferTextureLayer)
832 {
833     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
834 
835     GLint maxSamplesRGBA8 = 0;
836     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, 1,
837                           &maxSamplesRGBA8);
838 
839     GLint maxArrayTextureLayers;
840     glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers);
841 
842     // Test framebuffer status with just a color texture attached.
843     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
844     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, maxSamplesRGBA8, GL_RGBA8, 4,
845                                  4, 2, GL_TRUE);
846     ASSERT_GL_NO_ERROR();
847 
848     // Test with mip level 1 and -1 (only level 0 is valid for multisample textures).
849     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
850     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 1, 0);
851     EXPECT_GL_ERROR(GL_INVALID_VALUE);
852     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, -1, 0);
853     EXPECT_GL_ERROR(GL_INVALID_VALUE);
854 
855     // Test with layer -1 and layer == MAX_ARRAY_TEXTURE_LAYERS
856     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
857     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, -1);
858     EXPECT_GL_ERROR(GL_INVALID_VALUE);
859     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0,
860                               maxArrayTextureLayers);
861     EXPECT_GL_ERROR(GL_INVALID_VALUE);
862 }
863 
864 // Attach layers of TEXTURE_2D_MULTISAMPLE_ARRAY textures to a framebuffer and check for
865 // completeness.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferCompleteness)866 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferCompleteness)
867 {
868     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
869 
870     std::vector<GLenum> testFormats = {{GL_RGBA8, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8}};
871     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
872 
873     // Test framebuffer status with just a color texture attached.
874     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
875     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8, 4, 4,
876                                  2, GL_TRUE);
877     ASSERT_GL_NO_ERROR();
878 
879     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
880     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
881     ASSERT_GL_NO_ERROR();
882 
883     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
884     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
885 
886     // Test framebuffer status with both color and depth textures attached.
887     GLTexture depthTexture;
888     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthTexture);
889     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
890                                  GL_DEPTH_COMPONENT24, 4, 4, 2, GL_TRUE);
891     ASSERT_GL_NO_ERROR();
892 
893     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0);
894     ASSERT_GL_NO_ERROR();
895 
896     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
897     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
898 
899     // Test with color and depth/stencil textures attached.
900     GLTexture depthStencilTexture;
901     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, depthStencilTexture);
902     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse,
903                                  GL_DEPTH24_STENCIL8, 4, 4, 2, GL_TRUE);
904     ASSERT_GL_NO_ERROR();
905 
906     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilTexture, 0,
907                               0);
908     ASSERT_GL_NO_ERROR();
909 
910     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
911     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
912 }
913 
914 // Attach a layer of TEXTURE_2D_MULTISAMPLE_ARRAY texture to a framebuffer, clear it, and resolve by
915 // blitting.
TEST_P(TextureMultisampleArrayWebGLTest,FramebufferColorClearAndBlit)916 TEST_P(TextureMultisampleArrayWebGLTest, FramebufferColorClearAndBlit)
917 {
918     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
919 
920     const GLsizei kWidth  = 4;
921     const GLsizei kHeight = 4;
922 
923     std::vector<GLenum> testFormats = {GL_RGBA8};
924     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
925 
926     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
927     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
928                                  kWidth, kHeight, 2, GL_TRUE);
929 
930     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
931     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, 0);
932 
933     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
934     ASSERT_GL_NO_ERROR();
935     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
936 
937     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
938     glClear(GL_COLOR_BUFFER_BIT);
939 
940     GLFramebuffer resolveFramebuffer;
941     GLTexture resolveTexture;
942     glBindTexture(GL_TEXTURE_2D, resolveTexture);
943     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
944     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
945     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
946                            0);
947     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
948                       GL_NEAREST);
949     ASSERT_GL_NO_ERROR();
950 
951     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
952     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
953 }
954 
955 // Check the size of a multisample array texture in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,TextureSizeInShader)956 TEST_P(TextureMultisampleArrayWebGLTest, TextureSizeInShader)
957 {
958     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
959 
960     constexpr char kFS[] = R"(#version 310 es
961 #extension GL_OES_texture_storage_multisample_2d_array : require
962 
963 uniform highp sampler2DMSArray tex;
964 out highp vec4 my_FragColor;
965 
966 void main() {
967         my_FragColor = (textureSize(tex) == ivec3(8, 4, 2)) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
968 })";
969 
970     ANGLE_GL_PROGRAM(texSizeProgram, essl31_shaders::vs::Simple(), kFS);
971 
972     GLint texLocation = glGetUniformLocation(texSizeProgram, "tex");
973     ASSERT_GE(texLocation, 0);
974 
975     const GLsizei kWidth  = 8;
976     const GLsizei kHeight = 4;
977 
978     std::vector<GLenum> testFormats = {GL_RGBA8};
979     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
980 
981     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
982     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
983                                  kWidth, kHeight, 2, GL_TRUE);
984     ASSERT_GL_NO_ERROR();
985 
986     drawQuad(texSizeProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
987     ASSERT_GL_NO_ERROR();
988 
989     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
990 }
991 
992 // Clear the layers of a multisample array texture, and then sample all the samples from all the
993 // layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,SimpleTexelFetch)994 TEST_P(TextureMultisampleArrayWebGLTest, SimpleTexelFetch)
995 {
996     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
997 
998     ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
999                      blitArrayTextureLayerFragmentShader());
1000 
1001     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
1002     ASSERT_GE(texLocation, 0);
1003     GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
1004     ASSERT_GE(layerLocation, 0);
1005     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
1006     ASSERT_GE(layerLocation, 0);
1007 
1008     const GLsizei kWidth      = 4;
1009     const GLsizei kHeight     = 4;
1010     const GLsizei kLayerCount = 2;
1011 
1012     std::vector<GLenum> testFormats = {GL_RGBA8};
1013     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
1014 
1015     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
1016     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8,
1017                                  kWidth, kHeight, kLayerCount, GL_TRUE);
1018     ASSERT_GL_NO_ERROR();
1019 
1020     // Clear layer zero to green and layer one to blue.
1021     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1022     std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
1023     for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
1024     {
1025         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
1026         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1027         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
1028         const GLColor &clearColor = clearColors[i];
1029         glClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f,
1030                      clearColor.A / 255.0f);
1031         glClear(GL_COLOR_BUFFER_BIT);
1032         ASSERT_GL_NO_ERROR();
1033     }
1034 
1035     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1036     glUseProgram(texelFetchProgram);
1037     glViewport(0, 0, kWidth, kHeight);
1038     for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
1039     {
1040         glUniform1i(layerLocation, layer);
1041         for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
1042         {
1043             glUniform1i(sampleNumLocation, sampleNum);
1044             drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1045             ASSERT_GL_NO_ERROR();
1046             EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1047         }
1048     }
1049 }
1050 
1051 // Clear the layers of an integer multisample array texture, and then sample all the samples from
1052 // all the layers in a shader.
TEST_P(TextureMultisampleArrayWebGLTest,IntegerTexelFetch)1053 TEST_P(TextureMultisampleArrayWebGLTest, IntegerTexelFetch)
1054 {
1055     ANGLE_SKIP_TEST_IF(!requestArrayExtension());
1056 
1057     ANGLE_GL_PROGRAM(texelFetchProgram, essl31_shaders::vs::Passthrough(),
1058                      blitIntArrayTextureLayerFragmentShader());
1059 
1060     GLint texLocation = glGetUniformLocation(texelFetchProgram, "tex");
1061     ASSERT_GE(texLocation, 0);
1062     GLint layerLocation = glGetUniformLocation(texelFetchProgram, "layer");
1063     ASSERT_GE(layerLocation, 0);
1064     GLint sampleNumLocation = glGetUniformLocation(texelFetchProgram, "sampleNum");
1065     ASSERT_GE(layerLocation, 0);
1066 
1067     const GLsizei kWidth      = 4;
1068     const GLsizei kHeight     = 4;
1069     const GLsizei kLayerCount = 2;
1070 
1071     std::vector<GLenum> testFormats = {GL_RGBA8I};
1072     GLint samplesToUse = getSamplesToUse(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, testFormats);
1073 
1074     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, mTexture);
1075     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samplesToUse, GL_RGBA8I,
1076                                  kWidth, kHeight, kLayerCount, GL_TRUE);
1077     ASSERT_GL_NO_ERROR();
1078 
1079     // Clear layer zero to green and layer one to blue.
1080     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1081     std::vector<GLColor> clearColors = {{GLColor::green, GLColor::blue}};
1082     for (GLint i = 0; static_cast<GLsizei>(i) < kLayerCount; ++i)
1083     {
1084         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, 0, i);
1085         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1086         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, status);
1087         std::array<GLint, 4> intColor;
1088         for (size_t j = 0; j < intColor.size(); ++j)
1089         {
1090             intColor[j] = clearColors[i][j] / 255;
1091         }
1092         glClearBufferiv(GL_COLOR, 0, intColor.data());
1093         ASSERT_GL_NO_ERROR();
1094     }
1095 
1096     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1097     glUseProgram(texelFetchProgram);
1098     glViewport(0, 0, kWidth, kHeight);
1099     for (GLint layer = 0; static_cast<GLsizei>(layer) < kLayerCount; ++layer)
1100     {
1101         glUniform1i(layerLocation, layer);
1102         for (GLint sampleNum = 0; sampleNum < samplesToUse; ++sampleNum)
1103         {
1104             glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1105             glClear(GL_COLOR_BUFFER_BIT);
1106             glUniform1i(sampleNumLocation, sampleNum);
1107             drawQuad(texelFetchProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1108             ASSERT_GL_NO_ERROR();
1109             EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, clearColors[layer]);
1110         }
1111     }
1112 }
1113 
1114 class TextureSampleShadingTest : public ANGLETest<>
1115 {
1116   protected:
TextureSampleShadingTest()1117     TextureSampleShadingTest() {}
1118 };
1119 
1120 // Test that sample shading actually produces different interpolations per sample.  Note that
1121 // variables such as gl_SampleID and gl_SamplePosition are avoided, as well as the |sample|
1122 // qualifier as they automatically enable sample shading.
TEST_P(TextureSampleShadingTest,Basic)1123 TEST_P(TextureSampleShadingTest, Basic)
1124 {
1125     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
1126 
1127     constexpr GLsizei kSize        = 1;
1128     constexpr GLsizei kSampleCount = 4;
1129 
1130     // Create a multisampled texture and framebuffer.
1131     GLFramebuffer msaaFBO;
1132     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1133 
1134     GLTexture msaaTexture;
1135     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1136     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
1137                               false);
1138     ASSERT_GL_NO_ERROR();
1139     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1140                            msaaTexture, 0);
1141     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1142 
1143     // Enable sample shading and draw a gradient.
1144     glEnable(GL_SAMPLE_SHADING_OES);
1145     glMinSampleShadingOES(1.0f);
1146 
1147     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1148                      essl31_shaders::fs::RedGreenGradient());
1149     glViewport(0, 0, kSize, kSize);
1150     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1151     ASSERT_GL_NO_ERROR();
1152 
1153     // Create a buffer for verification.
1154     constexpr GLsizei kPixelChannels = 4;
1155     constexpr GLsizei kBufferSize =
1156         kSize * kSize * kSampleCount * kPixelChannels * sizeof(uint32_t);
1157     GLBuffer buffer;
1158     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
1159     glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
1160     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
1161 
1162     // Issue a dispatch call that copies the multisampled texture into a buffer.
1163     constexpr char kCS[] = R"(#version 310 es
1164 layout(local_size_x=4, local_size_y=1, local_size_z=1) in;
1165 
1166 uniform highp sampler2DMS imageIn;
1167 layout(std430, binding = 0) buffer dataOut {
1168     uint data[];
1169 };
1170 
1171 void main()
1172 {
1173     int sampleIndex = int(gl_GlobalInvocationID.x) % 4;
1174 
1175     vec4 color = texelFetch(imageIn, ivec2(0), sampleIndex);
1176     uvec4 unnormalized = uvec4(color * 255.0);
1177 
1178     int outIndex = sampleIndex * 4;
1179 
1180     data[outIndex    ] = unnormalized.r;
1181     data[outIndex + 1] = unnormalized.g;
1182     data[outIndex + 2] = unnormalized.b;
1183     data[outIndex + 3] = unnormalized.a;
1184 })";
1185 
1186     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1187     glUseProgram(program);
1188 
1189     // Bind the multisampled texture as sampler.
1190     GLint imageLocation = glGetUniformLocation(program, "imageIn");
1191     ASSERT_GE(imageLocation, 0);
1192 
1193     glActiveTexture(GL_TEXTURE0);
1194     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1195     glUniform1i(imageLocation, 0);
1196 
1197     glDispatchCompute(1, 1, 1);
1198     EXPECT_GL_NO_ERROR();
1199 
1200     // Verify that the buffer has correct data.
1201     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1202 
1203     const uint32_t *ptr = reinterpret_cast<uint32_t *>(
1204         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
1205     constexpr GLColor kExpectedColors[4] = {
1206         GLColor(96, 32, 0, 255),
1207         GLColor(223, 96, 0, 255),
1208         GLColor(32, 159, 0, 255),
1209         GLColor(159, 223, 0, 255),
1210     };
1211     for (GLsizei pixel = 0; pixel < kSampleCount; ++pixel)
1212     {
1213         for (GLsizei channel = 0; channel < kPixelChannels; ++channel)
1214         {
1215             EXPECT_NEAR(ptr[pixel * kPixelChannels + channel], kExpectedColors[pixel][channel], 1)
1216                 << pixel << " " << channel;
1217         }
1218     }
1219 
1220     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1221 }
1222 
1223 // Test that sample shading actually produces different interpolations per sample when |sample| is
1224 // missing from the shader.  Both varyings and I/O blocks are tested.  When |centroid| is specified,
1225 // |sample| shouldn't be added.
TEST_P(TextureSampleShadingTest,NoSampleQualifier)1226 TEST_P(TextureSampleShadingTest, NoSampleQualifier)
1227 {
1228     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
1229     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
1230     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
1231     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1232 
1233     constexpr GLsizei kSize        = 1;
1234     constexpr GLsizei kSampleCount = 4;
1235 
1236     // Create a multisampled texture and framebuffer.
1237     GLFramebuffer msaaFBO;
1238     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1239 
1240     GLTexture msaaTexture;
1241     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1242     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
1243                               false);
1244     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1245                            msaaTexture, 0);
1246     ASSERT_GL_NO_ERROR();
1247     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1248 
1249     // Enable sample shading and draw
1250     glEnable(GL_SAMPLE_SHADING_OES);
1251     glMinSampleShadingOES(1.0f);
1252 
1253     constexpr char kVS[] = R"(#version 310 es
1254 #extension GL_OES_shader_multisample_interpolation : require
1255 #extension GL_EXT_shader_io_blocks : require
1256 
1257 in mediump vec2 position;
1258 out mediump vec2 gradient;
1259 centroid out mediump vec2 constant;
1260 out Block
1261 {
1262     centroid mediump vec2 constant2;
1263     mediump vec2 gradient2;
1264     sample mediump vec2 gradient3;
1265 };
1266 
1267 out Inactive
1268 {
1269     mediump vec2 gradient4;
1270 };
1271 
1272 void main()
1273 {
1274     gradient = position;
1275     gradient2 = position;
1276     gradient3 = position;
1277     constant = position;
1278     constant2 = position;
1279     gl_Position = vec4(position, 0, 1);
1280 })";
1281 
1282     constexpr char kFS[] = R"(#version 310 es
1283 #extension GL_OES_shader_multisample_interpolation : require
1284 #extension GL_OES_sample_variables : require
1285 #extension GL_EXT_shader_io_blocks : require
1286 
1287 in highp vec2 gradient;
1288 centroid in highp vec2 constant;
1289 in Block
1290 {
1291     centroid mediump vec2 constant2;
1292     mediump vec2 gradient2;
1293     sample mediump vec2 gradient3;
1294 };
1295 
1296 in Inactive2
1297 {
1298     mediump vec2 gradient4;
1299 };
1300 
1301 out mediump vec4 color;
1302 
1303 void main()
1304 {
1305     bool left = gl_SampleID == 0 || gl_SampleID == 2;
1306     bool top = gl_SampleID == 0 || gl_SampleID == 1;
1307 
1308     color = vec4(0);
1309 
1310     if (left)
1311         color.r = gradient.x < -0.1 && gradient2.x < -0.1 && gradient3.x < -0.1 ? 1. : 0.;
1312     else
1313         color.r = gradient.x > 0.1 && gradient2.x > 0.1 && gradient3.x > 0.1 ? 1. : 0.;
1314 
1315     if (top)
1316         color.g = gradient.y < -0.1 && gradient2.y < -0.1 && gradient3.y < -0.1 ? 1. : 0.;
1317     else
1318         color.g = gradient.y > 0.1 && gradient2.y > 0.1 && gradient3.y > 0.1 ? 1. : 0.;
1319 
1320     // centroid doesn't exactly behave consistently between implementations.  In particular, it does
1321     // _not_ necessarily evaluage the varying at the pixel center.  As a result, there isn't much
1322     // that can be verified here.  We'd rely on SPIR-V validation to make sure Sample is not added
1323     // to ids that already have Centroid specified (in the Vulkan backend)
1324     color.b = abs(constant.x) < 1. && abs(constant.y) < 1. ? 1. : 0.;
1325     color.a = abs(constant2.x) < 1. && abs(constant2.y) < 1. ? 1. : 0.;
1326 })";
1327 
1328     ANGLE_GL_PROGRAM(program, kVS, kFS);
1329     glViewport(0, 0, kSize, kSize);
1330     drawQuad(program, "position", 0.5f);
1331     ASSERT_GL_NO_ERROR();
1332 
1333     // Resolve the framebuffer
1334     GLFramebuffer fbo;
1335     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1336 
1337     GLTexture texture;
1338     glBindTexture(GL_TEXTURE_2D, texture);
1339     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
1340     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1341     ASSERT_GL_NO_ERROR();
1342     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1343 
1344     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
1345 
1346     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1347 
1348     // Ensure the test passed on every sample location
1349     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
1350     ASSERT_GL_NO_ERROR();
1351 }
1352 
1353 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMultisampleTest);
1354 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(TextureMultisampleTest);
1355 
1356 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NegativeTextureMultisampleTest);
1357 ANGLE_INSTANTIATE_TEST_ES3(NegativeTextureMultisampleTest);
1358 
1359 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMultisampleArrayWebGLTest);
1360 ANGLE_INSTANTIATE_TEST_ES31(TextureMultisampleArrayWebGLTest);
1361 
1362 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSampleShadingTest);
1363 ANGLE_INSTANTIATE_TEST_ES31(TextureSampleShadingTest);
1364 }  // anonymous namespace
1365