blob: 3b517c1630e2fda991aa97b03557703a560947a5 [file] [log] [blame]
Geoff Langc287ea62016-09-16 14:46:51 -04001//
2// Copyright 2015 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// WebGLCompatibilityTest.cpp : Tests of the GL_ANGLE_webgl_compatibility extension.
8
9#include "test_utils/ANGLETest.h"
10
Geoff Lang677bb6f2017-04-05 12:40:40 -040011#include "common/mathutil.h"
Geoff Langc287ea62016-09-16 14:46:51 -040012#include "test_utils/gl_raii.h"
13
Frank Henigman146e8a12017-03-02 23:22:37 -050014namespace
15{
16
17bool ConstantColorAndAlphaBlendFunctions(GLenum first, GLenum second)
18{
19 return (first == GL_CONSTANT_COLOR || first == GL_ONE_MINUS_CONSTANT_COLOR) &&
20 (second == GL_CONSTANT_ALPHA || second == GL_ONE_MINUS_CONSTANT_ALPHA);
21}
22
23void CheckBlendFunctions(GLenum src, GLenum dst)
24{
25 if (ConstantColorAndAlphaBlendFunctions(src, dst) ||
26 ConstantColorAndAlphaBlendFunctions(dst, src))
27 {
28 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
29 }
30 else
31 {
32 ASSERT_GL_NO_ERROR();
33 }
34}
35
Geoff Lang677bb6f2017-04-05 12:40:40 -040036// Extensions that affect the ability to use floating point textures
37constexpr const char *FloatingPointTextureExtensions[] = {
38 "",
39 "GL_EXT_texture_storage",
Geoff Lang677bb6f2017-04-05 12:40:40 -040040 "GL_OES_texture_half_float",
41 "GL_OES_texture_half_float_linear",
42 "GL_EXT_color_buffer_half_float",
Geoff Lang7d4602f2017-09-13 10:45:09 -040043 "GL_OES_texture_float",
44 "GL_OES_texture_float_linear",
Geoff Lang677bb6f2017-04-05 12:40:40 -040045 "GL_EXT_color_buffer_float",
46 "GL_CHROMIUM_color_buffer_float_rgba",
47 "GL_CHROMIUM_color_buffer_float_rgb",
48};
49
Frank Henigman146e8a12017-03-02 23:22:37 -050050} // namespace
51
Geoff Langc287ea62016-09-16 14:46:51 -040052namespace angle
53{
54
55class WebGLCompatibilityTest : public ANGLETest
56{
57 protected:
58 WebGLCompatibilityTest()
59 {
60 setWindowWidth(128);
61 setWindowHeight(128);
62 setConfigRedBits(8);
63 setConfigGreenBits(8);
64 setConfigBlueBits(8);
65 setConfigAlphaBits(8);
66 setWebGLCompatibilityEnabled(true);
67 }
68
69 void SetUp() override
70 {
71 ANGLETest::SetUp();
Geoff Langc339c4e2016-11-29 10:37:36 -050072 glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
73 eglGetProcAddress("glRequestExtensionANGLE"));
Geoff Langc287ea62016-09-16 14:46:51 -040074 }
75
Geoff Lang677bb6f2017-04-05 12:40:40 -040076 template <typename T>
77 void TestFloatTextureFormat(GLenum internalFormat,
78 GLenum format,
79 GLenum type,
80 bool texturingEnabled,
81 bool linearSamplingEnabled,
82 bool renderingEnabled,
83 const T textureData[4],
84 const float floatData[4])
85 {
86 ASSERT_GL_NO_ERROR();
87
88 const std::string samplingVs =
89 "attribute vec4 position;\n"
90 "varying vec2 texcoord;\n"
91 "void main()\n"
92 "{\n"
93 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
94 " texcoord = (position.xy * 0.5) + 0.5;\n"
95 "}\n";
96
97 const std::string samplingFs =
98 "precision mediump float;\n"
99 "uniform sampler2D tex;\n"
100 "uniform vec4 subtractor;\n"
101 "varying vec2 texcoord;\n"
102 "void main()\n"
103 "{\n"
104 " vec4 color = texture2D(tex, texcoord);\n"
105 " if (abs(color.r - subtractor.r) +\n"
106 " abs(color.g - subtractor.g) +\n"
107 " abs(color.b - subtractor.b) +\n"
108 " abs(color.a - subtractor.a) < 8.0)\n"
109 " {\n"
110 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
111 " }\n"
112 " else\n"
113 " {\n"
114 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
115 " }\n"
116 "}\n";
117
118 ANGLE_GL_PROGRAM(samplingProgram, samplingVs, samplingFs);
119 glUseProgram(samplingProgram.get());
120
Geoff Langd84a00b2017-10-27 17:27:26 -0400121 // Need RGBA8 renderbuffers for enough precision on the readback
122 if (extensionRequestable("GL_OES_rgb8_rgba8"))
123 {
124 glRequestExtensionANGLE("GL_OES_rgb8_rgba8");
125 }
126 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_rgb8_rgba8") && getClientMajorVersion() < 3);
127 ASSERT_GL_NO_ERROR();
128
Geoff Lang677bb6f2017-04-05 12:40:40 -0400129 GLRenderbuffer rbo;
130 glBindRenderbuffer(GL_RENDERBUFFER, rbo.get());
131 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
132
133 GLFramebuffer fbo;
134 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
135 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo.get());
136
137 GLTexture texture;
138 glBindTexture(GL_TEXTURE_2D, texture.get());
139
140 if (internalFormat == format)
141 {
142 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, textureData);
143 }
144 else
145 {
146 if (getClientMajorVersion() >= 3)
147 {
148 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
149 }
150 else
151 {
152 ASSERT_TRUE(extensionEnabled("GL_EXT_texture_storage"));
153 glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
154 }
155 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, textureData);
156 }
157
158 if (!texturingEnabled)
159 {
160 // Depending on the entry point and client version, different errors may be generated
161 ASSERT_GLENUM_NE(GL_NO_ERROR, glGetError());
162
163 // Two errors may be generated in the glTexStorage + glTexSubImage case, clear the
164 // second error
165 glGetError();
166
167 return;
168 }
169 ASSERT_GL_NO_ERROR();
170
171 glUniform1i(glGetUniformLocation(samplingProgram.get(), "tex"), 0);
172 glUniform4fv(glGetUniformLocation(samplingProgram.get(), "subtractor"), 1, floatData);
173
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
176 drawQuad(samplingProgram.get(), "position", 0.5f, 1.0f, true);
177 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
178
179 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
180 drawQuad(samplingProgram.get(), "position", 0.5f, 1.0f, true);
181
182 if (linearSamplingEnabled)
183 {
184 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
185 }
186 else
187 {
188 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
189 }
190
191 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(),
192 0);
193 glBindTexture(GL_TEXTURE_2D, 0);
194 if (!renderingEnabled)
195 {
196 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
197 glCheckFramebufferStatus(GL_FRAMEBUFFER));
198 return;
199 }
200 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
201
202 const std::string renderingVs =
203 "attribute vec4 position;\n"
204 "void main()\n"
205 "{\n"
206 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
207 "}\n";
208
209 const std::string renderingFs =
210 "precision mediump float;\n"
211 "uniform vec4 writeValue;\n"
212 "void main()\n"
213 "{\n"
214 " gl_FragColor = writeValue;\n"
215 "}\n";
216
217 ANGLE_GL_PROGRAM(renderingProgram, renderingVs, renderingFs);
218 glUseProgram(renderingProgram.get());
219
220 glUniform4fv(glGetUniformLocation(renderingProgram.get(), "writeValue"), 1, floatData);
221
222 drawQuad(renderingProgram.get(), "position", 0.5f, 1.0f, true);
223
224 EXPECT_PIXEL_COLOR32F_NEAR(
225 0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f);
226 }
227
Jamie Madillcad97ee2017-02-02 18:52:44 -0500228 // Called from RenderingFeedbackLoopWithDrawBuffersEXT.
229 void drawBuffersEXTFeedbackLoop(GLuint program,
230 const std::array<GLenum, 2> &drawBuffers,
231 GLenum expectedError);
232
Jamie Madill07be8bf2017-02-02 19:59:57 -0500233 // Called from RenderingFeedbackLoopWithDrawBuffers.
234 void drawBuffersFeedbackLoop(GLuint program,
235 const std::array<GLenum, 2> &drawBuffers,
236 GLenum expectedError);
237
Geoff Lang86f81162017-10-30 15:10:45 -0400238 // Called from Enable[Compressed]TextureFormatExtensions
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -0700239 void validateTexImageExtensionFormat(GLenum format, const std::string &extName);
Geoff Lang86f81162017-10-30 15:10:45 -0400240 void validateCompressedTexImageExtensionFormat(GLenum format,
241 GLsizei width,
242 GLsizei height,
243 GLsizei blockSize,
244 const std::string &extName,
245 bool subImageAllowed);
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -0700246
Geoff Langc339c4e2016-11-29 10:37:36 -0500247 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
Geoff Langc287ea62016-09-16 14:46:51 -0400248};
249
Corentin Wallezfd456442016-12-21 17:57:00 -0500250class WebGL2CompatibilityTest : public WebGLCompatibilityTest
251{
252};
253
Geoff Langc287ea62016-09-16 14:46:51 -0400254// Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so
255// the GL extension should always be present
256TEST_P(WebGLCompatibilityTest, ExtensionStringExposed)
257{
258 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
259}
260
261// Verify that all extension entry points are available
262TEST_P(WebGLCompatibilityTest, EntryPoints)
263{
Geoff Langc339c4e2016-11-29 10:37:36 -0500264 if (extensionEnabled("GL_ANGLE_request_extension"))
Geoff Langc287ea62016-09-16 14:46:51 -0400265 {
Geoff Langc339c4e2016-11-29 10:37:36 -0500266 EXPECT_NE(nullptr, eglGetProcAddress("glRequestExtensionANGLE"));
Geoff Langc287ea62016-09-16 14:46:51 -0400267 }
268}
269
270// WebGL 1 allows GL_DEPTH_STENCIL_ATTACHMENT as a valid binding point. Make sure it is usable,
271// even in ES2 contexts.
272TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint)
273{
274 GLRenderbuffer renderbuffer;
275 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
276 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
277
278 GLFramebuffer framebuffer;
279 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
280 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
281 renderbuffer.get());
282
283 EXPECT_GL_NO_ERROR();
284}
285
286// Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION
287TEST_P(WebGLCompatibilityTest, EnableExtensionValidation)
288{
Geoff Langc339c4e2016-11-29 10:37:36 -0500289 glRequestExtensionANGLE("invalid_extension_string");
Geoff Langc287ea62016-09-16 14:46:51 -0400290 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
291}
292
293// Test enabling the GL_OES_element_index_uint extension
294TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices)
295{
296 if (getClientMajorVersion() != 2)
297 {
298 // This test only works on ES2 where uint indices are not available by default
299 return;
300 }
301
302 EXPECT_FALSE(extensionEnabled("GL_OES_element_index_uint"));
303
304 GLBuffer indexBuffer;
305 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
306
307 GLuint data[] = {0, 1, 2, 1, 3, 2};
308 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
309
310 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
311 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
312 glUseProgram(program.get());
313
Jamie Madille7b96342017-06-23 15:06:08 -0400314 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
Geoff Langc287ea62016-09-16 14:46:51 -0400315 EXPECT_GL_ERROR(GL_INVALID_ENUM);
316
Geoff Langc339c4e2016-11-29 10:37:36 -0500317 if (extensionRequestable("GL_OES_element_index_uint"))
Geoff Langc287ea62016-09-16 14:46:51 -0400318 {
Geoff Langc339c4e2016-11-29 10:37:36 -0500319 glRequestExtensionANGLE("GL_OES_element_index_uint");
Geoff Langc287ea62016-09-16 14:46:51 -0400320 EXPECT_GL_NO_ERROR();
321 EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint"));
322
Jamie Madille7b96342017-06-23 15:06:08 -0400323 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
Geoff Langc287ea62016-09-16 14:46:51 -0400324 EXPECT_GL_NO_ERROR();
325 }
326}
327
Geoff Langff5c63e2017-04-12 15:26:54 -0400328// Test enabling the GL_OES_standard_derivatives extension
329TEST_P(WebGLCompatibilityTest, EnableExtensionStandardDerivitives)
330{
331 EXPECT_FALSE(extensionEnabled("GL_OES_standard_derivatives"));
332
333 const std::string source =
334 "#extension GL_OES_standard_derivatives : require\n"
335 "void main() { gl_FragColor = vec4(dFdx(vec2(1.0, 1.0)).x, 1, 0, 1); }\n";
336 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
337
338 if (extensionRequestable("GL_OES_standard_derivatives"))
339 {
340 glRequestExtensionANGLE("GL_OES_standard_derivatives");
341 EXPECT_GL_NO_ERROR();
342 EXPECT_TRUE(extensionEnabled("GL_OES_standard_derivatives"));
343
344 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
345 ASSERT_NE(0u, shader);
346 glDeleteShader(shader);
347 }
348}
349
350// Test enabling the GL_EXT_shader_texture_lod extension
351TEST_P(WebGLCompatibilityTest, EnableExtensionTextureLOD)
352{
353 EXPECT_FALSE(extensionEnabled("GL_EXT_shader_texture_lod"));
354
355 const std::string source =
356 "#extension GL_EXT_shader_texture_lod : require\n"
357 "uniform sampler2D u_texture;\n"
358 "void main() {\n"
359 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
360 "0.0));\n"
361 "}\n";
362 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
363
364 if (extensionRequestable("GL_EXT_shader_texture_lod"))
365 {
366 glRequestExtensionANGLE("GL_EXT_shader_texture_lod");
367 EXPECT_GL_NO_ERROR();
368 EXPECT_TRUE(extensionEnabled("GL_EXT_shader_texture_lod"));
369
370 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
371 ASSERT_NE(0u, shader);
372 glDeleteShader(shader);
373 }
374}
375
376// Test enabling the GL_EXT_frag_depth extension
377TEST_P(WebGLCompatibilityTest, EnableExtensionFragDepth)
378{
379 EXPECT_FALSE(extensionEnabled("GL_EXT_frag_depth"));
380
381 const std::string source =
382 "#extension GL_EXT_frag_depth : require\n"
383 "void main() {\n"
384 " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
385 " gl_FragDepthEXT = 1.0;\n"
386 "}\n";
387 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
388
389 if (extensionRequestable("GL_EXT_frag_depth"))
390 {
391 glRequestExtensionANGLE("GL_EXT_frag_depth");
392 EXPECT_GL_NO_ERROR();
393 EXPECT_TRUE(extensionEnabled("GL_EXT_frag_depth"));
394
395 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
396 ASSERT_NE(0u, shader);
397 glDeleteShader(shader);
398 }
399}
400
Geoff Langd7d526a2017-02-21 16:48:43 -0500401// Test enabling the GL_EXT_texture_filter_anisotropic extension
402TEST_P(WebGLCompatibilityTest, EnableExtensionTextureFilterAnisotropic)
403{
404 EXPECT_FALSE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
405
406 GLfloat maxAnisotropy = 0.0f;
407 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
408 EXPECT_GL_ERROR(GL_INVALID_ENUM);
409
410 GLTexture texture;
411 glBindTexture(GL_TEXTURE_2D, texture.get());
412 ASSERT_GL_NO_ERROR();
413
414 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
415 EXPECT_GL_ERROR(GL_INVALID_ENUM);
416
417 GLfloat currentAnisotropy = 0.0f;
418 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
419 EXPECT_GL_ERROR(GL_INVALID_ENUM);
420
421 if (extensionRequestable("GL_EXT_texture_filter_anisotropic"))
422 {
423 glRequestExtensionANGLE("GL_EXT_texture_filter_anisotropic");
424 EXPECT_GL_NO_ERROR();
425 EXPECT_TRUE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
426
427 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
428 ASSERT_GL_NO_ERROR();
429 EXPECT_GE(maxAnisotropy, 2.0f);
430
431 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
432 ASSERT_GL_NO_ERROR();
433 EXPECT_EQ(1.0f, currentAnisotropy);
434
435 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
436 ASSERT_GL_NO_ERROR();
437 }
438}
439
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700440// Verify that shaders are of a compatible spec when the extension is enabled.
441TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec)
442{
443 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
444
445 // Use of reserved _webgl prefix should fail when the shader specification is for WebGL.
446 const std::string &vert =
447 "struct Foo {\n"
448 " int _webgl_bar;\n"
449 "};\n"
450 "void main()\n"
451 "{\n"
452 " Foo foo = Foo(1);\n"
453 "}";
454
455 // Default fragement shader.
456 const std::string &frag =
457 "void main()\n"
458 "{\n"
459 " gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n"
460 "}";
461
462 GLuint program = CompileProgram(vert, frag);
463 EXPECT_EQ(0u, program);
464 glDeleteProgram(program);
465}
466
Geoff Lang3fab7632017-09-26 15:45:54 -0400467// Test enabling the GL_NV_pixel_buffer_object extension
468TEST_P(WebGLCompatibilityTest, EnablePixelBufferObjectExtensions)
469{
470 EXPECT_FALSE(extensionEnabled("GL_NV_pixel_buffer_object"));
471 EXPECT_FALSE(extensionEnabled("GL_OES_mapbuffer"));
472 EXPECT_FALSE(extensionEnabled("GL_EXT_map_buffer_range"));
473
474 // These extensions become core in in ES3/WebGL2.
475 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
476
477 GLBuffer buffer;
478 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
479 EXPECT_GL_ERROR(GL_INVALID_ENUM);
480
481 if (extensionRequestable("GL_NV_pixel_buffer_object"))
482 {
483 glRequestExtensionANGLE("GL_NV_pixel_buffer_object");
484 EXPECT_GL_NO_ERROR();
485
486 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
487 EXPECT_GL_NO_ERROR();
488
489 glBufferData(GL_PIXEL_PACK_BUFFER, 4, nullptr, GL_STATIC_DRAW);
490 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
491 EXPECT_GL_NO_ERROR();
492 }
493}
494
495// Test enabling the GL_OES_mapbuffer and GL_EXT_map_buffer_range extensions
496TEST_P(WebGLCompatibilityTest, EnableMapBufferExtensions)
497{
498 EXPECT_FALSE(extensionEnabled("GL_OES_mapbuffer"));
499 EXPECT_FALSE(extensionEnabled("GL_EXT_map_buffer_range"));
500
501 // These extensions become core in in ES3/WebGL2.
502 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
503
504 GLBuffer buffer;
505 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
506 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4, nullptr, GL_STATIC_DRAW);
507
508 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
509 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
510
511 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
512 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
513
514 GLint access = 0;
515 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
516 EXPECT_GL_ERROR(GL_INVALID_ENUM);
517
518 if (extensionRequestable("GL_OES_mapbuffer"))
519 {
520 glRequestExtensionANGLE("GL_OES_mapbuffer");
521 EXPECT_GL_NO_ERROR();
522
523 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
524 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
525 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
526 EXPECT_GL_NO_ERROR();
527 }
528
529 if (extensionRequestable("GL_EXT_map_buffer_range"))
530 {
531 glRequestExtensionANGLE("GL_EXT_map_buffer_range");
532 EXPECT_GL_NO_ERROR();
533
534 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
535 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
536 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
537 EXPECT_GL_NO_ERROR();
538 }
539}
540
Geoff Lang8c7133c2017-09-26 17:31:10 -0400541// Test enabling the GL_OES_fbo_render_mipmap extension
542TEST_P(WebGLCompatibilityTest, EnableRenderMipmapExtension)
543{
544 EXPECT_FALSE(extensionEnabled("GL_OES_fbo_render_mipmap"));
545
546 // This extensions become core in in ES3/WebGL2.
547 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
548
549 GLTexture texture;
550 glBindTexture(GL_TEXTURE_2D, texture);
551 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
552 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
553
554 GLFramebuffer fbo;
555 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
556 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
557 EXPECT_GL_NO_ERROR();
558
559 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
560 EXPECT_GL_ERROR(GL_INVALID_VALUE);
561
562 if (extensionRequestable("GL_OES_fbo_render_mipmap"))
563 {
564 glRequestExtensionANGLE("GL_OES_fbo_render_mipmap");
565 EXPECT_GL_NO_ERROR();
566
567 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
568 EXPECT_GL_NO_ERROR();
569 }
570}
571
Geoff Lang50cac572017-09-26 17:37:43 -0400572// Test enabling the GL_EXT_blend_minmax extension
573TEST_P(WebGLCompatibilityTest, EnableBlendMinMaxExtension)
574{
575 EXPECT_FALSE(extensionEnabled("GL_EXT_blend_minmax"));
576
577 // This extensions become core in in ES3/WebGL2.
578 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
579
580 glBlendEquation(GL_MIN);
581 EXPECT_GL_ERROR(GL_INVALID_ENUM);
582
583 glBlendEquation(GL_MAX);
584 EXPECT_GL_ERROR(GL_INVALID_ENUM);
585
586 if (extensionRequestable("GL_EXT_blend_minmax"))
587 {
588 glRequestExtensionANGLE("GL_EXT_blend_minmax");
589 EXPECT_GL_NO_ERROR();
590
591 glBlendEquation(GL_MIN);
592 glBlendEquation(GL_MAX);
593 EXPECT_GL_NO_ERROR();
594 }
595}
596
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400597// Test enabling the query extensions
598TEST_P(WebGLCompatibilityTest, EnableQueryExtensions)
599{
Jamie Madill8b92c532018-03-22 01:05:02 -0400600 // Seems to be causing a device lost. http://anglebug.com/2423
601 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
602
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400603 EXPECT_FALSE(extensionEnabled("GL_EXT_occlusion_query_boolean"));
604 EXPECT_FALSE(extensionEnabled("GL_EXT_disjoint_timer_query"));
605 EXPECT_FALSE(extensionEnabled("GL_CHROMIUM_sync_query"));
606
607 // This extensions become core in in ES3/WebGL2.
608 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
609
610 GLQueryEXT badQuery;
611
612 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, badQuery);
613 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
614
615 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, badQuery);
616 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
617
618 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, badQuery);
619 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
620
621 glQueryCounterEXT(GL_TIMESTAMP_EXT, badQuery);
622 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
623
624 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, badQuery);
625 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
626
627 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
628 {
629 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
630 EXPECT_GL_NO_ERROR();
631
632 GLQueryEXT query;
633 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
634 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
635 EXPECT_GL_NO_ERROR();
636 }
637
638 if (extensionRequestable("GL_EXT_disjoint_timer_query"))
639 {
640 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
641 EXPECT_GL_NO_ERROR();
642
643 GLQueryEXT query1;
644 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
645 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
646 EXPECT_GL_NO_ERROR();
647
648 GLQueryEXT query2;
649 glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
650 EXPECT_GL_NO_ERROR();
651 }
652
653 if (extensionRequestable("GL_CHROMIUM_sync_query"))
654 {
655 glRequestExtensionANGLE("GL_CHROMIUM_sync_query");
656 EXPECT_GL_NO_ERROR();
657
658 GLQueryEXT query;
659 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query);
660 glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
661 EXPECT_GL_NO_ERROR();
662 }
663}
664
Geoff Lang488130e2017-09-27 13:53:11 -0400665// Test enabling the GL_ANGLE_framebuffer_multisample extension
666TEST_P(WebGLCompatibilityTest, EnableFramebufferMultisampleExtension)
667{
668 EXPECT_FALSE(extensionEnabled("GL_ANGLE_framebuffer_multisample"));
669
670 // This extensions become core in in ES3/WebGL2.
671 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
672
673 GLint maxSamples = 0;
674 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
675 EXPECT_GL_ERROR(GL_INVALID_ENUM);
676
677 GLRenderbuffer renderbuffer;
678 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
679 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA4, 1, 1);
680 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
681
682 if (extensionRequestable("GL_ANGLE_framebuffer_multisample"))
683 {
684 glRequestExtensionANGLE("GL_ANGLE_framebuffer_multisample");
685 EXPECT_GL_NO_ERROR();
686
687 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
688 EXPECT_GL_NO_ERROR();
689
690 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, maxSamples, GL_RGBA4, 1, 1);
691 EXPECT_GL_NO_ERROR();
692 }
693}
694
Geoff Lang63c5a592017-09-27 14:08:16 -0400695// Test enabling the GL_ANGLE_instanced_arrays extension
696TEST_P(WebGLCompatibilityTest, EnableInstancedArraysExtension)
697{
698 EXPECT_FALSE(extensionEnabled("GL_ANGLE_instanced_arrays"));
699
700 // This extensions become core in in ES3/WebGL2.
701 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
702
703 GLint divisor = 0;
704 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
705 EXPECT_GL_ERROR(GL_INVALID_ENUM);
706
707 glVertexAttribDivisorANGLE(0, 1);
708 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
709
710 if (extensionRequestable("GL_ANGLE_instanced_arrays"))
711 {
712 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
713 EXPECT_GL_NO_ERROR();
714
715 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
716 glVertexAttribDivisorANGLE(0, 1);
717 EXPECT_GL_NO_ERROR();
718 }
719}
720
Geoff Lang000dab82017-09-27 14:27:07 -0400721// Test enabling the GL_ANGLE_pack_reverse_row_order extension
722TEST_P(WebGLCompatibilityTest, EnablePackReverseRowOrderExtension)
723{
724 EXPECT_FALSE(extensionEnabled("GL_ANGLE_pack_reverse_row_order"));
725
726 GLint result = 0;
727 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result);
728 EXPECT_GL_ERROR(GL_INVALID_ENUM);
729
730 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE);
731 EXPECT_GL_ERROR(GL_INVALID_ENUM);
732
733 if (extensionRequestable("GL_ANGLE_pack_reverse_row_order"))
734 {
735 glRequestExtensionANGLE("GL_ANGLE_pack_reverse_row_order");
736 EXPECT_GL_NO_ERROR();
737
738 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result);
739 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE);
740 EXPECT_GL_NO_ERROR();
741 }
742}
743
744// Test enabling the GL_EXT_unpack_subimage extension
745TEST_P(WebGLCompatibilityTest, EnablePackUnpackSubImageExtension)
746{
747 EXPECT_FALSE(extensionEnabled("GL_EXT_unpack_subimage"));
748
749 // This extensions become core in in ES3/WebGL2.
750 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
751
752 constexpr GLenum parameters[] = {
753 GL_UNPACK_ROW_LENGTH_EXT, GL_UNPACK_SKIP_ROWS_EXT, GL_UNPACK_SKIP_PIXELS_EXT,
754 };
755
756 for (GLenum param : parameters)
757 {
758 GLint resultI = 0;
759 glGetIntegerv(param, &resultI);
760 EXPECT_GL_ERROR(GL_INVALID_ENUM);
761
762 GLfloat resultF = 0.0f;
763 glGetFloatv(param, &resultF);
764 EXPECT_GL_ERROR(GL_INVALID_ENUM);
765
766 glPixelStorei(param, 0);
767 EXPECT_GL_ERROR(GL_INVALID_ENUM);
768 }
769
770 if (extensionRequestable("GL_EXT_unpack_subimage"))
771 {
772 glRequestExtensionANGLE("GL_EXT_unpack_subimage");
773 EXPECT_GL_NO_ERROR();
774
775 for (GLenum param : parameters)
776 {
777 GLint resultI = 0;
778 glGetIntegerv(param, &resultI);
779
780 GLfloat resultF = 0.0f;
781 glGetFloatv(param, &resultF);
782
783 glPixelStorei(param, 0);
784
785 EXPECT_GL_NO_ERROR();
786 }
787 }
788}
789
Geoff Lang4751aab2017-10-30 15:14:52 -0400790TEST_P(WebGLCompatibilityTest, EnableTextureRectangle)
791{
792 EXPECT_FALSE(extensionEnabled("GL_ANGLE_texture_rectangle"));
793
794 GLTexture texture;
795 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture);
796 EXPECT_GL_ERROR(GL_INVALID_ENUM);
797
798 GLint minFilter = 0;
799 glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, &minFilter);
800 EXPECT_GL_ERROR(GL_INVALID_ENUM);
801
802 if (extensionRequestable("GL_ANGLE_texture_rectangle"))
803 {
804 glRequestExtensionANGLE("GL_ANGLE_texture_rectangle");
805 EXPECT_GL_NO_ERROR();
806
807 EXPECT_TRUE(extensionEnabled("GL_ANGLE_texture_rectangle"));
808
809 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture);
810 EXPECT_GL_NO_ERROR();
811
812 glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
813 nullptr);
814 EXPECT_GL_NO_ERROR();
815 }
816}
817
Geoff Lang000dab82017-09-27 14:27:07 -0400818// Test enabling the GL_NV_pack_subimage extension
819TEST_P(WebGLCompatibilityTest, EnablePackPackSubImageExtension)
820{
821 EXPECT_FALSE(extensionEnabled("GL_NV_pack_subimage"));
822
823 // This extensions become core in in ES3/WebGL2.
824 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
825
826 constexpr GLenum parameters[] = {
827 GL_PACK_ROW_LENGTH, GL_PACK_SKIP_ROWS, GL_PACK_SKIP_PIXELS,
828 };
829
830 for (GLenum param : parameters)
831 {
832 GLint resultI = 0;
833 glGetIntegerv(param, &resultI);
834 EXPECT_GL_ERROR(GL_INVALID_ENUM);
835
836 GLfloat resultF = 0.0f;
837 glGetFloatv(param, &resultF);
838 EXPECT_GL_ERROR(GL_INVALID_ENUM);
839
840 glPixelStorei(param, 0);
841 EXPECT_GL_ERROR(GL_INVALID_ENUM);
842 }
843
844 if (extensionRequestable("GL_NV_pack_subimage"))
845 {
846 glRequestExtensionANGLE("GL_NV_pack_subimage");
847 EXPECT_GL_NO_ERROR();
848
849 for (GLenum param : parameters)
850 {
851 GLint resultI = 0;
852 glGetIntegerv(param, &resultI);
853
854 GLfloat resultF = 0.0f;
855 glGetFloatv(param, &resultF);
856
857 glPixelStorei(param, 0);
858
859 EXPECT_GL_NO_ERROR();
860 }
861 }
862}
863
Geoff Langd84a00b2017-10-27 17:27:26 -0400864TEST_P(WebGLCompatibilityTest, EnableRGB8RGBA8Extension)
865{
866 EXPECT_FALSE(extensionEnabled("GL_OES_rgb8_rgba8"));
867
868 // This extensions become core in in ES3/WebGL2.
869 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
870
871 GLRenderbuffer renderbuffer;
872 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
873 EXPECT_GL_NO_ERROR();
874
875 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1);
876 EXPECT_GL_ERROR(GL_INVALID_ENUM);
877
878 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
879 EXPECT_GL_ERROR(GL_INVALID_ENUM);
880
881 if (extensionRequestable("GL_OES_rgb8_rgba8"))
882 {
883 glRequestExtensionANGLE("GL_OES_rgb8_rgba8");
884 EXPECT_GL_NO_ERROR();
885
886 EXPECT_TRUE(extensionEnabled("GL_OES_rgb8_rgba8"));
887
888 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1);
889 EXPECT_GL_NO_ERROR();
890
891 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
892 EXPECT_GL_NO_ERROR();
893 }
894}
895
Geoff Lange8afa902017-09-27 15:00:43 -0400896// Test enabling the GL_ANGLE_framebuffer_blit extension
897TEST_P(WebGLCompatibilityTest, EnableFramebufferBlitExtension)
898{
899 EXPECT_FALSE(extensionEnabled("GL_ANGLE_framebuffer_blit"));
900
901 // This extensions become core in in ES3/WebGL2.
902 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
903
904 GLFramebuffer fbo;
905
906 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
907 EXPECT_GL_ERROR(GL_INVALID_ENUM);
908
909 GLint result;
910 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result);
911 EXPECT_GL_ERROR(GL_INVALID_ENUM);
912
913 glBlitFramebufferANGLE(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
914 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
915
916 if (extensionRequestable("GL_ANGLE_framebuffer_blit"))
917 {
918 glRequestExtensionANGLE("GL_ANGLE_framebuffer_blit");
919 EXPECT_GL_NO_ERROR();
920
921 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
922 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result);
923 EXPECT_GL_NO_ERROR();
924 }
925}
926
Geoff Lang2348e212017-09-27 17:46:25 -0400927// Test enabling the GL_OES_get_program_binary extension
928TEST_P(WebGLCompatibilityTest, EnableProgramBinaryExtension)
929{
930 EXPECT_FALSE(extensionEnabled("GL_OES_get_program_binary"));
931
932 // This extensions become core in in ES3/WebGL2.
933 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
934
935 GLint result = 0;
936 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
937 EXPECT_GL_ERROR(GL_INVALID_ENUM);
938
939 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
940 EXPECT_GL_ERROR(GL_INVALID_ENUM);
941
942 const std::string &vert =
943 "void main()\n"
944 "{\n"
945 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
946 "}\n";
947 const std::string &frag =
948 "precision highp float;\n"
949 "void main()\n"
950 "{\n"
951 " gl_FragColor = vec4(1.0);\n"
952 "}\n";
953 ANGLE_GL_PROGRAM(program, vert, frag);
954
955 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &result);
956 EXPECT_GL_ERROR(GL_INVALID_ENUM);
957
958 uint8_t tempArray[512];
959 GLenum tempFormat = 0;
960 GLsizei tempLength = 0;
961 glGetProgramBinaryOES(program, static_cast<GLsizei>(ArraySize(tempArray)), &tempLength,
962 &tempFormat, tempArray);
963 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
964
965 if (extensionRequestable("GL_OES_get_program_binary"))
966 {
967 glRequestExtensionANGLE("GL_OES_get_program_binary");
968 EXPECT_GL_NO_ERROR();
969
970 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
971 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
972 EXPECT_GL_NO_ERROR();
973
974 GLint binaryLength = 0;
975 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
976 EXPECT_GL_NO_ERROR();
977
978 GLenum binaryFormat;
979 GLsizei writeLength = 0;
980 std::vector<uint8_t> binary(binaryLength);
981 glGetProgramBinaryOES(program, binaryLength, &writeLength, &binaryFormat, binary.data());
982 EXPECT_GL_NO_ERROR();
983
984 glProgramBinaryOES(program, binaryFormat, binary.data(), binaryLength);
985 EXPECT_GL_NO_ERROR();
986 }
987}
988
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400989// Verify that the context generates the correct error when the framebuffer attachments are
990// different sizes
Corentin Wallezc3bc9842017-10-11 15:15:59 -0400991TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch)
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400992{
993 GLFramebuffer fbo;
994 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
995
996 GLTexture textures[2];
997 glBindTexture(GL_TEXTURE_2D, textures[0]);
998 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
999 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
1000
1001 ASSERT_GL_NO_ERROR();
1002 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1003
1004 GLRenderbuffer renderbuffer;
1005 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1006 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3);
1007 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
1008
1009 ASSERT_GL_NO_ERROR();
1010 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1011 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1012
1013 if (extensionRequestable("GL_EXT_draw_buffers"))
1014 {
1015 glRequestExtensionANGLE("GL_EXT_draw_buffers");
1016 EXPECT_GL_NO_ERROR();
1017 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
1018
1019 glBindTexture(GL_TEXTURE_2D, textures[1]);
1020 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1021 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
1022 ASSERT_GL_NO_ERROR();
1023
1024 ASSERT_GL_NO_ERROR();
1025 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1026 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1027
1028 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
1029
1030 ASSERT_GL_NO_ERROR();
1031 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1032
1033 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1034
1035 ASSERT_GL_NO_ERROR();
1036 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1037 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1038 }
1039}
1040
Corentin Wallez327411e2016-12-09 11:09:17 -05001041// Test that client-side array buffers are forbidden in WebGL mode
1042TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer)
1043{
1044 const std::string &vert =
1045 "attribute vec3 a_pos;\n"
1046 "void main()\n"
1047 "{\n"
1048 " gl_Position = vec4(a_pos, 1.0);\n"
1049 "}\n";
1050
1051 const std::string &frag =
1052 "precision highp float;\n"
1053 "void main()\n"
1054 "{\n"
1055 " gl_FragColor = vec4(1.0);\n"
1056 "}\n";
1057
1058 ANGLE_GL_PROGRAM(program, vert, frag);
1059
1060 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1061 ASSERT_NE(-1, posLocation);
1062 glUseProgram(program.get());
1063
1064 const auto &vertices = GetQuadVertices();
Corentin Wallezfd456442016-12-21 17:57:00 -05001065 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
Corentin Wallez327411e2016-12-09 11:09:17 -05001066 glEnableVertexAttribArray(posLocation);
1067
1068 ASSERT_GL_NO_ERROR();
1069 glDrawArrays(GL_TRIANGLES, 0, 6);
1070 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1071}
1072
1073// Test that client-side element array buffers are forbidden in WebGL mode
1074TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
1075{
1076 const std::string &vert =
1077 "attribute vec3 a_pos;\n"
1078 "void main()\n"
1079 "{\n"
1080 " gl_Position = vec4(a_pos, 1.0);\n"
1081 "}\n";
1082
1083 const std::string &frag =
1084 "precision highp float;\n"
1085 "void main()\n"
1086 "{\n"
1087 " gl_FragColor = vec4(1.0);\n"
1088 "}\n";
1089
1090 ANGLE_GL_PROGRAM(program, vert, frag);
1091
1092 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1093 ASSERT_NE(-1, posLocation);
1094 glUseProgram(program.get());
1095
1096 const auto &vertices = GetQuadVertices();
1097
1098 GLBuffer vertexBuffer;
1099 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1100 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1101 GL_STATIC_DRAW);
1102
1103 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1104 glEnableVertexAttribArray(posLocation);
1105
Corentin Wallez327411e2016-12-09 11:09:17 -05001106 ASSERT_GL_NO_ERROR();
Corentin Wallezded1b5a2017-03-09 18:58:48 -05001107
1108 // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also
1109 // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate
1110 // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check.
1111 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void*>(intptr_t(1)));
Corentin Wallez327411e2016-12-09 11:09:17 -05001112 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1113}
1114
Corentin Wallez672f7f32017-06-15 17:42:17 -04001115// Test that client-side array buffers are forbidden even if the program doesn't use the attribute
1116TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBufferEvenNotUsedOnes)
1117{
1118 const std::string &vert =
1119 "void main()\n"
1120 "{\n"
1121 " gl_Position = vec4(1.0);\n"
1122 "}\n";
1123
1124 const std::string &frag =
1125 "precision highp float;\n"
1126 "void main()\n"
1127 "{\n"
1128 " gl_FragColor = vec4(1.0);\n"
1129 "}\n";
1130
1131 ANGLE_GL_PROGRAM(program, vert, frag);
1132
1133 glUseProgram(program.get());
1134
1135 const auto &vertices = GetQuadVertices();
1136 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
1137 glEnableVertexAttribArray(0);
1138
1139 ASSERT_GL_NO_ERROR();
1140 glDrawArrays(GL_TRIANGLES, 0, 6);
1141 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1142}
1143
Geoff Langfb052642017-10-24 13:42:09 -04001144// Test that passing a null pixel data pointer to TexSubImage calls generates an INVALID_VALUE error
1145TEST_P(WebGLCompatibilityTest, NullPixelDataForSubImage)
1146{
1147 // glTexSubImage2D
1148 {
1149 GLTexture texture;
1150 glBindTexture(GL_TEXTURE_2D, texture);
1151
1152 // TexImage with null data - OK
1153 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1154 EXPECT_GL_NO_ERROR();
1155
1156 // TexSubImage with zero size and null data - OK
1157 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1158 EXPECT_GL_NO_ERROR();
1159
1160 // TexSubImage with non-zero size and null data - Invalid value
1161 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1162 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1163 }
1164
1165 // glTexSubImage3D
1166 if (getClientMajorVersion() >= 3)
1167 {
1168 GLTexture texture;
1169 glBindTexture(GL_TEXTURE_3D, texture);
1170
1171 // TexImage with null data - OK
1172 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1173 EXPECT_GL_NO_ERROR();
1174
1175 // TexSubImage with zero size and null data - OK
1176 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1177 EXPECT_GL_NO_ERROR();
1178
1179 // TexSubImage with non-zero size and null data - Invalid value
1180 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1181 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1182 }
1183}
1184
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001185// Tests the WebGL requirement of having the same stencil mask, writemask and ref for fron and back
1186TEST_P(WebGLCompatibilityTest, RequiresSameStencilMaskAndRef)
1187{
1188 // Run the test in an FBO to make sure we have some stencil bits.
1189 GLRenderbuffer renderbuffer;
1190 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
1191 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
1192
1193 GLFramebuffer framebuffer;
1194 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1195 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1196 renderbuffer.get());
1197
1198 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
1199 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
1200 glUseProgram(program.get());
1201 ASSERT_GL_NO_ERROR();
1202
1203 // Having ref and mask the same for front and back is valid.
1204 glStencilMask(255);
1205 glStencilFunc(GL_ALWAYS, 0, 255);
1206 glDrawArrays(GL_TRIANGLES, 0, 6);
1207 ASSERT_GL_NO_ERROR();
1208
1209 // Having a different front - back write mask generates an error.
1210 glStencilMaskSeparate(GL_FRONT, 1);
1211 glDrawArrays(GL_TRIANGLES, 0, 6);
1212 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1213
1214 // Setting both write masks separately to the same value is valid.
1215 glStencilMaskSeparate(GL_BACK, 1);
1216 glDrawArrays(GL_TRIANGLES, 0, 6);
1217 ASSERT_GL_NO_ERROR();
1218
1219 // Having a different stencil front - back mask generates an error
1220 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
1221 glDrawArrays(GL_TRIANGLES, 0, 6);
1222 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1223
1224 // Setting both masks separately to the same value is valid.
1225 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
1226 glDrawArrays(GL_TRIANGLES, 0, 6);
1227 ASSERT_GL_NO_ERROR();
1228
1229 // Having a different stencil front - back reference generates an error
1230 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
1231 glDrawArrays(GL_TRIANGLES, 0, 6);
1232 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1233
1234 // Setting both references separately to the same value is valid.
1235 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
1236 glDrawArrays(GL_TRIANGLES, 0, 6);
1237 ASSERT_GL_NO_ERROR();
1238
1239 // Using different stencil funcs, everything being equal is valid.
1240 glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
1241 glDrawArrays(GL_TRIANGLES, 0, 6);
1242 ASSERT_GL_NO_ERROR();
1243}
1244
Corentin Wallez506fc9c2016-12-21 16:53:33 -05001245// Test that GL_FIXED is forbidden
1246TEST_P(WebGLCompatibilityTest, ForbidsGLFixed)
1247{
1248 GLBuffer buffer;
1249 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1250 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1251
1252 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1253 ASSERT_GL_NO_ERROR();
1254
1255 glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr);
1256 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1257}
1258
1259// Test the WebGL limit of 255 for the attribute stride
1260TEST_P(WebGLCompatibilityTest, MaxStride)
1261{
1262 GLBuffer buffer;
1263 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1264 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
1265
1266 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr);
1267 ASSERT_GL_NO_ERROR();
1268
1269 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr);
1270 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1271}
1272
Corentin Wallezfd456442016-12-21 17:57:00 -05001273// Test the checks for OOB reads in the vertex buffers, non-instanced version
1274TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
1275{
1276 const std::string &vert =
1277 "attribute float a_pos;\n"
1278 "void main()\n"
1279 "{\n"
1280 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1281 "}\n";
1282
1283 const std::string &frag =
1284 "precision highp float;\n"
1285 "void main()\n"
1286 "{\n"
1287 " gl_FragColor = vec4(1.0);\n"
1288 "}\n";
1289
1290 ANGLE_GL_PROGRAM(program, vert, frag);
Corentin Wallezfd456442016-12-21 17:57:00 -05001291 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1292 ASSERT_NE(-1, posLocation);
1293 glUseProgram(program.get());
1294
1295 GLBuffer buffer;
1296 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1297 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1298
1299 glEnableVertexAttribArray(posLocation);
1300
1301 const uint8_t* zeroOffset = nullptr;
1302
1303 // Test touching the last element is valid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001304 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
Corentin Wallezfd456442016-12-21 17:57:00 -05001305 glDrawArrays(GL_POINTS, 0, 4);
1306 ASSERT_GL_NO_ERROR();
1307
1308 // Test touching the last element + 1 is invalid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001309 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
Corentin Wallezfd456442016-12-21 17:57:00 -05001310 glDrawArrays(GL_POINTS, 0, 4);
1311 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1312
1313 // Test touching the last element is valid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001314 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
Corentin Wallezfd456442016-12-21 17:57:00 -05001315 glDrawArrays(GL_POINTS, 0, 4);
1316 ASSERT_GL_NO_ERROR();
1317
1318 // Test touching the last element + 1 is invalid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001319 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
Corentin Wallezfd456442016-12-21 17:57:00 -05001320 glDrawArrays(GL_POINTS, 0, 4);
1321 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1322
1323 // Test any offset is valid if no vertices are drawn.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001324 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
Corentin Wallezfd456442016-12-21 17:57:00 -05001325 glDrawArrays(GL_POINTS, 0, 0);
1326 ASSERT_GL_NO_ERROR();
Corentin Wallez91c8de82017-10-12 16:32:44 -04001327
1328 // Test a case of overflow that could give a max vertex that's negative
1329 constexpr GLint kIntMax = std::numeric_limits<GLint>::max();
1330 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 0);
1331 glDrawArrays(GL_POINTS, kIntMax, kIntMax);
1332 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1333}
1334
1335// Test the checks for OOB reads in the vertex buffers, instanced version
1336TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
1337{
1338 const std::string &vert =
1339 "attribute float a_pos;\n"
1340 "attribute float a_w;\n"
1341 "void main()\n"
1342 "{\n"
1343 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1344 "}\n";
1345
1346 const std::string &frag =
1347 "precision highp float;\n"
1348 "void main()\n"
1349 "{\n"
1350 " gl_FragColor = vec4(1.0);\n"
1351 "}\n";
1352
1353 ANGLE_GL_PROGRAM(program, vert, frag);
1354 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1355 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
1356 ASSERT_NE(-1, posLocation);
1357 ASSERT_NE(-1, wLocation);
1358 glUseProgram(program.get());
1359
1360 GLBuffer buffer;
1361 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1362 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1363
1364 glEnableVertexAttribArray(posLocation);
1365 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1366 glVertexAttribDivisor(posLocation, 0);
1367
1368 glEnableVertexAttribArray(wLocation);
1369 glVertexAttribDivisor(wLocation, 1);
1370
1371 const uint8_t* zeroOffset = nullptr;
1372
1373 // Test touching the last element is valid.
1374 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1375 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1376 ASSERT_GL_NO_ERROR();
1377
1378 // Test touching the last element + 1 is invalid.
1379 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1380 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1381 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1382
1383 // Test touching the last element is valid, using a stride.
1384 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1385 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1386 ASSERT_GL_NO_ERROR();
1387
1388 // Test touching the last element + 1 is invalid, using a stride.
1389 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1390 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1391 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1392
1393 // Test any offset is valid if no vertices are drawn.
1394 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1395 glDrawArraysInstanced(GL_POINTS, 0, 0, 1);
1396 ASSERT_GL_NO_ERROR();
1397
1398 // Test any offset is valid if no primitives are drawn.
1399 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1400 glDrawArraysInstanced(GL_POINTS, 0, 1, 0);
1401 ASSERT_GL_NO_ERROR();
1402}
1403
1404// Test the checks for OOB reads in the vertex buffers, ANGLE_instanced_arrays version
1405TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsInstancedANGLE)
1406{
1407 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_ANGLE_instanced_arrays"));
1408 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
1409 EXPECT_GL_NO_ERROR();
1410
1411 const std::string &vert =
1412 "attribute float a_pos;\n"
1413 "attribute float a_w;\n"
1414 "void main()\n"
1415 "{\n"
1416 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1417 "}\n";
1418
1419 const std::string &frag =
1420 "precision highp float;\n"
1421 "void main()\n"
1422 "{\n"
1423 " gl_FragColor = vec4(1.0);\n"
1424 "}\n";
1425
1426 ANGLE_GL_PROGRAM(program, vert, frag);
1427 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1428 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
1429 ASSERT_NE(-1, posLocation);
1430 ASSERT_NE(-1, wLocation);
1431 glUseProgram(program.get());
1432
1433 GLBuffer buffer;
1434 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1435 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1436
1437 glEnableVertexAttribArray(posLocation);
1438 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1439 glVertexAttribDivisorANGLE(posLocation, 0);
1440
1441 glEnableVertexAttribArray(wLocation);
1442 glVertexAttribDivisorANGLE(wLocation, 1);
1443
1444 const uint8_t* zeroOffset = nullptr;
1445
1446 // Test touching the last element is valid.
1447 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1448 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1449 ASSERT_GL_NO_ERROR();
1450
1451 // Test touching the last element + 1 is invalid.
1452 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1453 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1454 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1455
1456 // Test touching the last element is valid, using a stride.
1457 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1458 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1459 ASSERT_GL_NO_ERROR();
1460
1461 // Test touching the last element + 1 is invalid, using a stride.
1462 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1463 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1464 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1465
1466 // Test any offset is valid if no vertices are drawn.
1467 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1468 glDrawArraysInstancedANGLE(GL_POINTS, 0, 0, 1);
1469 ASSERT_GL_NO_ERROR();
1470
1471 // Test any offset is valid if no primitives are drawn.
1472 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1473 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 0);
1474 ASSERT_GL_NO_ERROR();
Corentin Wallezfd456442016-12-21 17:57:00 -05001475}
1476
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001477// Test the checks for OOB reads in the index buffer
1478TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
Geoff Lang5f319a42017-01-09 16:49:19 -05001479{
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001480 const std::string &vert =
1481 "attribute float a_pos;\n"
1482 "void main()\n"
1483 "{\n"
1484 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1485 "}\n";
Geoff Lang5f319a42017-01-09 16:49:19 -05001486
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001487 const std::string &frag =
1488 "precision highp float;\n"
1489 "void main()\n"
1490 "{\n"
1491 " gl_FragColor = vec4(1.0);\n"
1492 "}\n";
1493
1494 ANGLE_GL_PROGRAM(program, vert, frag);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001495 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1496 ASSERT_NE(-1, posLocation);
1497 glUseProgram(program.get());
1498
1499 GLBuffer vertexBuffer;
1500 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1501 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1502
1503 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001504 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001505
1506 const uint8_t *zeroOffset = nullptr;
1507 const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
1508
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001509 GLBuffer indexBuffer;
1510 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1511 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
Geoff Lang5f319a42017-01-09 16:49:19 -05001512 ASSERT_GL_NO_ERROR();
1513
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001514 // Test touching the last index is valid
1515 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1516 ASSERT_GL_NO_ERROR();
Geoff Lang5f319a42017-01-09 16:49:19 -05001517
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001518 // Test touching the last + 1 element is invalid
1519 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
1520 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang5f319a42017-01-09 16:49:19 -05001521
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001522 // Test any offset if valid if count is zero
1523 glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
1524 ASSERT_GL_NO_ERROR();
Corentin Wallezfe9306a2017-02-01 17:41:05 -05001525
1526 // Test touching the first index is valid
1527 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1528 ASSERT_GL_NO_ERROR();
1529
1530 // Test touching the first - 1 index is invalid
1531 // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was
1532 // the historic behavior of WebGL implementations
1533 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1);
1534 EXPECT_GL_ERROR(GL_INVALID_VALUE);
Geoff Lang5f319a42017-01-09 16:49:19 -05001535}
1536
Corentin Wallez91c8de82017-10-12 16:32:44 -04001537// Test the checks for OOB in vertex buffers caused by indices, non-instanced version
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001538TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInVertexBuffer)
1539{
1540 const std::string &vert =
1541 "attribute float a_pos;\n"
1542 "void main()\n"
1543 "{\n"
1544 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1545 "}\n";
1546
1547 const std::string &frag =
1548 "precision highp float;\n"
1549 "void main()\n"
1550 "{\n"
1551 " gl_FragColor = vec4(1.0);\n"
1552 "}\n";
1553
1554 ANGLE_GL_PROGRAM(program, vert, frag);
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001555 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1556 ASSERT_NE(-1, posLocation);
1557 glUseProgram(program.get());
1558
1559 GLBuffer vertexBuffer;
1560 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1561 glBufferData(GL_ARRAY_BUFFER, 8, nullptr, GL_STATIC_DRAW);
1562
1563 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001564 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001565
1566 const uint8_t *zeroOffset = nullptr;
1567 const uint8_t testIndices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 255};
1568
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001569 GLBuffer indexBuffer;
1570 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1571 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(testIndices), testIndices, GL_STATIC_DRAW);
1572 ASSERT_GL_NO_ERROR();
1573
1574 // Test touching the end of the vertex buffer is valid
1575 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 7);
1576 ASSERT_GL_NO_ERROR();
1577
1578 // Test touching just after the end of the vertex buffer is invalid
1579 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 8);
1580 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1581
1582 // Test touching the whole vertex buffer is valid
1583 glDrawElements(GL_POINTS, 8, GL_UNSIGNED_BYTE, zeroOffset + 0);
1584 ASSERT_GL_NO_ERROR();
1585
1586 // Test an index that would be negative
1587 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 9);
1588 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1589}
1590
Frank Henigman6137ddc2017-02-10 18:55:07 -05001591// Test depth range with 'near' more or less than 'far.'
1592TEST_P(WebGLCompatibilityTest, DepthRange)
1593{
1594 glDepthRangef(0, 1);
1595 ASSERT_GL_NO_ERROR();
1596
1597 glDepthRangef(.5, .5);
1598 ASSERT_GL_NO_ERROR();
1599
1600 glDepthRangef(1, 0);
1601 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1602}
1603
Frank Henigman146e8a12017-03-02 23:22:37 -05001604// Test all blend function combinations.
1605// In WebGL it is invalid to combine constant color with constant alpha.
1606TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
1607{
1608 constexpr GLenum srcFunc[] = {
1609 GL_ZERO,
1610 GL_ONE,
1611 GL_SRC_COLOR,
1612 GL_ONE_MINUS_SRC_COLOR,
1613 GL_DST_COLOR,
1614 GL_ONE_MINUS_DST_COLOR,
1615 GL_SRC_ALPHA,
1616 GL_ONE_MINUS_SRC_ALPHA,
1617 GL_DST_ALPHA,
1618 GL_ONE_MINUS_DST_ALPHA,
1619 GL_CONSTANT_COLOR,
1620 GL_ONE_MINUS_CONSTANT_COLOR,
1621 GL_CONSTANT_ALPHA,
1622 GL_ONE_MINUS_CONSTANT_ALPHA,
1623 GL_SRC_ALPHA_SATURATE,
1624 };
1625
1626 constexpr GLenum dstFunc[] = {
1627 GL_ZERO, GL_ONE,
1628 GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
1629 GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
1630 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1631 GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
1632 GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
1633 GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
1634 };
1635
1636 for (GLenum src : srcFunc)
1637 {
1638 for (GLenum dst : dstFunc)
1639 {
1640 glBlendFunc(src, dst);
1641 CheckBlendFunctions(src, dst);
1642 glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE);
1643 CheckBlendFunctions(src, dst);
1644 }
1645 }
1646}
1647
Geoff Langfc32e8b2017-05-31 14:16:59 -04001648// Test that binding/querying uniforms and attributes with invalid names generates errors
1649TEST_P(WebGLCompatibilityTest, InvalidAttributeAndUniformNames)
1650{
1651 const std::string validAttribName =
1652 "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1653 const std::string validUniformName =
1654 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
Geoff Langa71a98e2017-06-19 15:15:00 -04001655 std::vector<char> invalidSet = {'"', '$', '`', '@', '\''};
1656 if (getClientMajorVersion() < 3)
1657 {
1658 invalidSet.push_back('\\');
1659 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04001660
1661 std::string vert = "attribute float ";
1662 vert += validAttribName;
1663 vert +=
1664 ";\n"
1665 "void main()\n"
1666 "{\n"
1667 " gl_Position = vec4(1.0);\n"
1668 "}\n";
1669
1670 std::string frag =
1671 "precision highp float;\n"
1672 "uniform vec4 ";
1673 frag += validUniformName;
Geoff Langcab92ee2017-07-19 17:32:07 -04001674 // Insert illegal characters into comments
Geoff Langfc32e8b2017-05-31 14:16:59 -04001675 frag +=
1676 ";\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001677 " // $ \" @ /*\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001678 "void main()\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001679 "{/*\n"
1680 " ` @ $\n"
1681 " */gl_FragColor = vec4(1.0);\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001682 "}\n";
1683
1684 ANGLE_GL_PROGRAM(program, vert, frag);
1685 EXPECT_GL_NO_ERROR();
1686
1687 for (char invalidChar : invalidSet)
1688 {
1689 std::string invalidName = validAttribName + invalidChar;
1690 glGetAttribLocation(program, invalidName.c_str());
1691 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1692 << "glGetAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1693
1694 glBindAttribLocation(program, 0, invalidName.c_str());
1695 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1696 << "glBindAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1697 }
1698
1699 for (char invalidChar : invalidSet)
1700 {
1701 std::string invalidName = validUniformName + invalidChar;
1702 glGetUniformLocation(program, invalidName.c_str());
1703 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1704 << "glGetUniformLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1705 }
1706
1707 for (char invalidChar : invalidSet)
1708 {
1709 std::string invalidAttribName = validAttribName + invalidChar;
1710 const char *invalidVert[] = {
1711 "attribute float ",
1712 invalidAttribName.c_str(),
1713 ";\n",
1714 "void main()\n",
1715 "{\n",
1716 " gl_Position = vec4(1.0);\n",
1717 "}\n",
1718 };
1719
1720 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1721 glShaderSource(shader, static_cast<GLsizei>(ArraySize(invalidVert)), invalidVert, nullptr);
1722 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1723 glDeleteShader(shader);
1724 }
1725}
1726
Geoff Langcab92ee2017-07-19 17:32:07 -04001727// Test that line continuation is handled correctly when valdiating shader source
Bryan Bernhart (Intel Americas Inc)335d8bf2017-10-23 15:41:43 -07001728TEST_P(WebGLCompatibilityTest, ShaderSourceLineContinuation)
1729{
1730 // Verify that a line continuation character (i.e. backslash) cannot be used
1731 // within a preprocessor directive in a ES2 context.
1732 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1733
1734 const char *validVert =
1735 "#define foo this is a test\n"
1736 "precision mediump float;\n"
1737 "void main()\n"
1738 "{\n"
1739 " gl_Position = vec4(1.0);\n"
1740 "}\n";
1741
1742 const char *invalidVert =
1743 "#define foo this \\n"
1744 " is a test\n"
1745 "precision mediump float;\n"
1746 "void main()\n"
1747 "{\n"
1748 " gl_Position = vec4(1.0);\n"
1749 "}\n";
1750
1751 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1752 glShaderSource(shader, 1, &validVert, nullptr);
1753 EXPECT_GL_NO_ERROR();
1754
1755 glShaderSource(shader, 1, &invalidVert, nullptr);
1756 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1757 glDeleteShader(shader);
1758}
1759
1760// Test that line continuation is handled correctly when valdiating shader source
Geoff Langcab92ee2017-07-19 17:32:07 -04001761TEST_P(WebGL2CompatibilityTest, ShaderSourceLineContinuation)
1762{
1763 const char *validVert =
1764 "#version 300 es\n"
1765 "precision mediump float;\n"
1766 "\n"
1767 "void main ()\n"
1768 "{\n"
1769 " float f\\\n"
1770 "oo = 1.0;\n"
1771 " gl_Position = vec4(foo);\n"
1772 "}\n";
1773
1774 const char *invalidVert =
1775 "#version 300 es\n"
1776 "precision mediump float;\n"
1777 "\n"
1778 "void main ()\n"
1779 "{\n"
1780 " float f\\$\n"
1781 "oo = 1.0;\n"
1782 " gl_Position = vec4(foo);\n"
1783 "}\n";
1784
1785 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1786 glShaderSource(shader, 1, &validVert, nullptr);
1787 EXPECT_GL_NO_ERROR();
1788 glShaderSource(shader, 1, &invalidVert, nullptr);
1789 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1790 glDeleteShader(shader);
1791}
1792
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001793// Tests bindAttribLocations for reserved prefixes and length limits
1794TEST_P(WebGLCompatibilityTest, BindAttribLocationLimitation)
1795{
1796 constexpr int maxLocStringLength = 256;
1797 const std::string tooLongString(maxLocStringLength + 1, '_');
1798
1799 glBindAttribLocation(0, 0, "_webgl_var");
1800
1801 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1802
1803 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
1804
1805 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1806}
1807
Corentin Wallez0dc97812017-06-22 14:38:44 -04001808// Test that having no attributes with a zero divisor is valid in WebGL2
Geoff Lang407d4e72017-04-12 14:54:11 -04001809TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor)
1810{
1811 const std::string &vert =
1812 "attribute float a_pos;\n"
1813 "void main()\n"
1814 "{\n"
1815 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1816 "}\n";
1817
1818 const std::string &frag =
1819 "precision highp float;\n"
1820 "void main()\n"
1821 "{\n"
1822 " gl_FragColor = vec4(1.0);\n"
1823 "}\n";
1824
1825 ANGLE_GL_PROGRAM(program, vert, frag);
1826
1827 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1828 ASSERT_NE(-1, posLocation);
1829
1830 glUseProgram(program.get());
1831
1832 GLBuffer buffer;
1833 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1834 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1835
1836 glEnableVertexAttribArray(posLocation);
1837 glVertexAttribDivisor(posLocation, 1);
1838
Geoff Lang407d4e72017-04-12 14:54:11 -04001839 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
1840 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
Geoff Lang407d4e72017-04-12 14:54:11 -04001841 ASSERT_GL_NO_ERROR();
1842}
1843
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001844// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
1845TEST_P(WebGLCompatibilityTest, NPOT)
1846{
1847 EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
1848
1849 // Create a texture and set an NPOT mip 0, should always be acceptable.
1850 GLTexture texture;
1851 glBindTexture(GL_TEXTURE_2D, texture.get());
1852 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1853 ASSERT_GL_NO_ERROR();
1854
1855 // Try setting an NPOT mip 1 and verify the error if WebGL 1
1856 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1857 if (getClientMajorVersion() < 3)
1858 {
1859 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1860 }
1861 else
1862 {
1863 ASSERT_GL_NO_ERROR();
1864 }
1865
1866 if (extensionRequestable("GL_OES_texture_npot"))
1867 {
1868 glRequestExtensionANGLE("GL_OES_texture_npot");
1869 ASSERT_GL_NO_ERROR();
1870
1871 // Try again to set NPOT mip 1
1872 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1873 ASSERT_GL_NO_ERROR();
1874 }
1875}
1876
Jamie Madillcad97ee2017-02-02 18:52:44 -05001877template <typename T>
1878void FillTexture2D(GLuint texture,
1879 GLsizei width,
1880 GLsizei height,
1881 const T &onePixelData,
1882 GLint level,
1883 GLint internalFormat,
1884 GLenum format,
1885 GLenum type)
1886{
1887 std::vector<T> allPixelsData(width * height, onePixelData);
1888
1889 glBindTexture(GL_TEXTURE_2D, texture);
1890 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
1891 allPixelsData.data());
1892 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1893 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1894 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1895 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1896}
1897
Frank Henigman875bbba2017-02-08 16:38:17 -05001898// Test that unset gl_Position defaults to (0,0,0,0).
1899TEST_P(WebGLCompatibilityTest, DefaultPosition)
1900{
1901 // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set,
1902 // and green otherwise. The center of each quadrant will be red if and only if all
1903 // four corners are red.
1904 const std::string vertexShader =
1905 "attribute vec3 pos;\n"
1906 "varying vec4 color;\n"
1907 "void main() {\n"
1908 " if (gl_Position == vec4(0,0,0,0)) {\n"
1909 " color = vec4(1,0,0,1);\n"
1910 " } else {\n"
1911 " color = vec4(0,1,0,1);\n"
1912 " }\n"
1913 " gl_Position = vec4(pos,1);\n"
1914 "}\n";
1915
1916 const std::string fragmentShader =
1917 "precision mediump float;\n"
1918 "varying vec4 color;\n"
1919 "void main() {\n"
1920 " gl_FragColor = color;\n"
1921 "}\n";
1922
1923 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1924 drawQuad(program.get(), "pos", 0.0f, 1.0f, true);
1925 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1926 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1927 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1928 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1929}
1930
Jamie Madilla4595b82017-01-11 17:36:34 -05001931// Tests that a rendering feedback loop triggers a GL error under WebGL.
1932// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
1933TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
1934{
1935 const std::string vertexShader =
1936 "attribute vec4 a_position;\n"
1937 "varying vec2 v_texCoord;\n"
1938 "void main() {\n"
1939 " gl_Position = a_position;\n"
1940 " v_texCoord = (a_position.xy * 0.5) + 0.5;\n"
1941 "}\n";
1942
1943 const std::string fragmentShader =
1944 "precision mediump float;\n"
1945 "varying vec2 v_texCoord;\n"
1946 "uniform sampler2D u_texture;\n"
1947 "void main() {\n"
1948 " // Shader swizzles color channels so we can tell if the draw succeeded.\n"
1949 " gl_FragColor = texture2D(u_texture, v_texCoord).gbra;\n"
1950 "}\n";
1951
1952 GLTexture texture;
Jamie Madillcad97ee2017-02-02 18:52:44 -05001953 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05001954
1955 ASSERT_GL_NO_ERROR();
1956
1957 GLFramebuffer framebuffer;
1958 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1959 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1960
1961 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1962
1963 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1964
1965 GLint uniformLoc = glGetUniformLocation(program.get(), "u_texture");
1966 ASSERT_NE(-1, uniformLoc);
1967
1968 glUseProgram(program.get());
1969 glUniform1i(uniformLoc, 0);
1970 glDisable(GL_BLEND);
1971 glDisable(GL_DEPTH_TEST);
1972 ASSERT_GL_NO_ERROR();
1973
1974 // Drawing with a texture that is also bound to the current framebuffer should fail
1975 glBindTexture(GL_TEXTURE_2D, texture.get());
1976 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1977 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1978
1979 // Ensure that the texture contents did not change after the previous render
1980 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1981 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1982 ASSERT_GL_NO_ERROR();
1983 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1984
1985 // Drawing when texture is bound to an inactive uniform should succeed
1986 GLTexture texture2;
Jamie Madillcad97ee2017-02-02 18:52:44 -05001987 FillTexture2D(texture2.get(), 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05001988
1989 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1990 glActiveTexture(GL_TEXTURE1);
1991 glBindTexture(GL_TEXTURE_2D, texture.get());
1992 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1993 ASSERT_GL_NO_ERROR();
1994 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1995}
1996
Bryan Bernhart58806562017-01-05 13:09:31 -08001997// Test for the max draw buffers and color attachments.
1998TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
1999{
2000 // This test only applies to ES2.
2001 if (getClientMajorVersion() != 2)
2002 {
2003 return;
2004 }
2005
2006 GLFramebuffer fbo[2];
2007 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0].get());
2008
2009 // Test that is valid when we bind with a single attachment point.
2010 GLTexture texture;
2011 glBindTexture(GL_TEXTURE_2D, texture.get());
2012 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2013 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2014 ASSERT_GL_NO_ERROR();
2015
2016 // Test that enabling the draw buffers extension will allow us to bind with a non-zero
2017 // attachment point.
2018 if (extensionRequestable("GL_EXT_draw_buffers"))
2019 {
2020 glRequestExtensionANGLE("GL_EXT_draw_buffers");
2021 EXPECT_GL_NO_ERROR();
2022 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
2023
2024 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1].get());
2025
2026 GLTexture texture2;
2027 glBindTexture(GL_TEXTURE_2D, texture2.get());
2028 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2029 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2.get(),
2030 0);
2031 ASSERT_GL_NO_ERROR();
2032 }
2033}
2034
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002035// Test that the offset in the index buffer is forced to be a multiple of the element size
2036TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction)
2037{
2038 const std::string &vert =
2039 "attribute vec3 a_pos;\n"
2040 "void main()\n"
2041 "{\n"
2042 " gl_Position = vec4(a_pos, 1.0);\n"
2043 "}\n";
2044
2045 const std::string &frag =
2046 "precision highp float;\n"
2047 "void main()\n"
2048 "{\n"
2049 " gl_FragColor = vec4(1.0);\n"
2050 "}\n";
2051
2052 ANGLE_GL_PROGRAM(program, vert, frag);
2053
2054 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
2055 ASSERT_NE(-1, posLocation);
2056 glUseProgram(program.get());
2057
2058 const auto &vertices = GetQuadVertices();
2059
2060 GLBuffer vertexBuffer;
2061 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
2062 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2063 GL_STATIC_DRAW);
2064
2065 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2066 glEnableVertexAttribArray(posLocation);
2067
2068 GLBuffer indexBuffer;
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002069 const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0, 0};
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002070 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
2071 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
2072
2073 ASSERT_GL_NO_ERROR();
2074
2075 const char *zeroIndices = nullptr;
2076
2077 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices);
2078 ASSERT_GL_NO_ERROR();
2079
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002080 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002081 ASSERT_GL_NO_ERROR();
2082
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002083 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices + 1);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002084 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2085}
2086
2087// Test that the offset and stride in the vertex buffer is forced to be a multiple of the element
2088// size
2089TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction)
2090{
2091 const char *zeroOffset = nullptr;
2092
2093 // Base case, vector of two floats
2094 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset);
2095 ASSERT_GL_NO_ERROR();
2096
2097 // Test setting a non-multiple offset
2098 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1);
2099 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2100 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2);
2101 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2102 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3);
2103 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2104
2105 // Test setting a non-multiple stride
2106 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset);
2107 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2108 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset);
2109 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2110 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset);
2111 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2112}
2113
Jamie Madillcad97ee2017-02-02 18:52:44 -05002114void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program,
2115 const std::array<GLenum, 2> &drawBuffers,
2116 GLenum expectedError)
2117{
2118 glDrawBuffersEXT(2, drawBuffers.data());
2119
2120 // Make sure framebuffer is complete before feedback loop detection
2121 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2122
2123 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2124
2125 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2126 // it should be NO_ERROR"
2127 EXPECT_GL_ERROR(expectedError);
2128}
2129
2130// This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers.
2131// Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html
2132TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT)
2133{
2134 const std::string vertexShader =
2135 "attribute vec4 aPosition;\n"
2136 "varying vec2 texCoord;\n"
2137 "void main() {\n"
2138 " gl_Position = aPosition;\n"
2139 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2140 "}\n";
2141
2142 const std::string fragmentShader =
2143 "#extension GL_EXT_draw_buffers : require\n"
2144 "precision mediump float;\n"
2145 "uniform sampler2D tex;\n"
2146 "varying vec2 texCoord;\n"
2147 "void main() {\n"
2148 " gl_FragData[0] = texture2D(tex, texCoord);\n"
2149 " gl_FragData[1] = texture2D(tex, texCoord);\n"
2150 "}\n";
2151
2152 GLsizei width = 8;
2153 GLsizei height = 8;
2154
2155 // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers
2156 // extension and gl_FragData semantics are changed to enforce indexing by zero always.
2157 // TODO(jmadill): This extension should be disabled in WebGL 2 contexts.
2158 if (/*!extensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2)
2159 {
2160 // No WEBGL_draw_buffers support -- this is legal.
2161 return;
2162 }
2163
2164 GLint maxDrawBuffers = 0;
2165 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2166
Yunchao He9550c602018-02-13 14:47:05 +08002167 // Test skipped because MAX_DRAW_BUFFERS is too small.
2168 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 2);
Jamie Madillcad97ee2017-02-02 18:52:44 -05002169
2170 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2171 glUseProgram(program.get());
2172 glViewport(0, 0, width, height);
2173
2174 GLTexture tex0;
2175 GLTexture tex1;
2176 GLFramebuffer fbo;
2177 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2178 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2179 ASSERT_GL_NO_ERROR();
2180
2181 glBindTexture(GL_TEXTURE_2D, tex1.get());
2182 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2183 ASSERT_NE(-1, texLoc);
2184 glUniform1i(texLoc, 0);
2185 ASSERT_GL_NO_ERROR();
2186
2187 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
2188 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2189 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2190 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
2191
2192 drawBuffersEXTFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}},
2193 GL_INVALID_OPERATION);
2194 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
2195 GL_INVALID_OPERATION);
2196 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
2197}
2198
Jamie Madill07be8bf2017-02-02 19:59:57 -05002199// Test tests that texture copying feedback loops are properly rejected in WebGL.
2200// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
2201TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
2202{
2203 GLTexture texture;
2204 glBindTexture(GL_TEXTURE_2D, texture.get());
2205 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2210
2211 GLTexture texture2;
2212 glBindTexture(GL_TEXTURE_2D, texture2.get());
2213 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2218
2219 GLFramebuffer framebuffer;
2220 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2221 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2222
2223 // framebuffer should be FRAMEBUFFER_COMPLETE.
2224 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2225 ASSERT_GL_NO_ERROR();
2226
2227 // testing copyTexImage2D
2228
2229 // copyTexImage2D to same texture but different level
2230 glBindTexture(GL_TEXTURE_2D, texture.get());
2231 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
2232 EXPECT_GL_NO_ERROR();
2233
2234 // copyTexImage2D to same texture same level, invalid feedback loop
2235 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2236 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2237
2238 // copyTexImage2D to different texture
2239 glBindTexture(GL_TEXTURE_2D, texture2.get());
2240 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2241 EXPECT_GL_NO_ERROR();
2242
2243 // testing copyTexSubImage2D
2244
2245 // copyTexSubImage2D to same texture but different level
2246 glBindTexture(GL_TEXTURE_2D, texture.get());
2247 glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
2248 EXPECT_GL_NO_ERROR();
2249
2250 // copyTexSubImage2D to same texture same level, invalid feedback loop
2251 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2252 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2253
2254 // copyTexSubImage2D to different texture
2255 glBindTexture(GL_TEXTURE_2D, texture2.get());
2256 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2257 EXPECT_GL_NO_ERROR();
2258}
2259
2260void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program,
2261 const std::array<GLenum, 2> &drawBuffers,
2262 GLenum expectedError)
2263{
2264 glDrawBuffers(2, drawBuffers.data());
2265
2266 // Make sure framebuffer is complete before feedback loop detection
2267 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2268
2269 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2270
2271 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2272 // it should be NO_ERROR"
2273 EXPECT_GL_ERROR(expectedError);
2274}
2275
Yuly Novikov817232e2017-02-22 18:36:10 -05002276// Tests invariance matching rules between built in varyings.
2277// Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html.
2278TEST_P(WebGLCompatibilityTest, BuiltInInvariant)
2279{
2280 const std::string vertexShaderVariant =
2281 "varying vec4 v_varying;\n"
2282 "void main()\n"
2283 "{\n"
2284 " gl_PointSize = 1.0;\n"
2285 " gl_Position = v_varying;\n"
2286 "}";
2287 const std::string fragmentShaderInvariantGlFragCoord =
2288 "invariant gl_FragCoord;\n"
2289 "void main()\n"
2290 "{\n"
2291 " gl_FragColor = gl_FragCoord;\n"
2292 "}";
2293 const std::string fragmentShaderInvariantGlPointCoord =
2294 "invariant gl_PointCoord;\n"
2295 "void main()\n"
2296 "{\n"
2297 " gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);\n"
2298 "}";
2299
2300 GLuint program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlFragCoord);
2301 EXPECT_EQ(0u, program);
2302
2303 program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlPointCoord);
2304 EXPECT_EQ(0u, program);
2305}
2306
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04002307// Tests global namespace conflicts between uniforms and attributes.
2308// Based on WebGL test conformance/glsl/misc/shaders-with-name-conflicts.html.
2309TEST_P(WebGLCompatibilityTest, GlobalNamesConflict)
2310{
2311 const std::string vertexShader =
2312 "attribute vec4 foo;\n"
2313 "void main()\n"
2314 "{\n"
2315 " gl_Position = foo;\n"
2316 "}";
2317 const std::string fragmentShader =
2318 "precision mediump float;\n"
2319 "uniform vec4 foo;\n"
2320 "void main()\n"
2321 "{\n"
2322 " gl_FragColor = foo;\n"
2323 "}";
2324
2325 GLuint program = CompileProgram(vertexShader, fragmentShader);
2326 EXPECT_EQ(0u, program);
2327}
2328
Geoff Lang966c9402017-04-18 12:38:27 -04002329// Test dimension and image size validation of compressed textures
2330TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
2331{
2332 if (extensionRequestable("GL_EXT_texture_compression_dxt1"))
2333 {
2334 glRequestExtensionANGLE("GL_EXT_texture_compression_dxt1");
2335 }
2336
Yunchao He9550c602018-02-13 14:47:05 +08002337 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_compression_dxt1"));
Geoff Lang966c9402017-04-18 12:38:27 -04002338
2339 constexpr uint8_t CompressedImageDXT1[] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
2340
2341 GLTexture texture;
2342 glBindTexture(GL_TEXTURE_2D, texture);
2343
2344 // Regular case, verify that it works
2345 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2346 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2347 ASSERT_GL_NO_ERROR();
2348
2349 // Test various dimensions that are not valid
2350 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3, 4, 0,
2351 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2352 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2353
2354 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 3, 0,
2355 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2356 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2357
2358 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2359 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2360 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2361
2362 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2363 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2364 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2365
2366 // Test various image sizes that are not valid
2367 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2368 sizeof(CompressedImageDXT1) - 1, CompressedImageDXT1);
2369 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2370
2371 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2372 sizeof(CompressedImageDXT1) + 1, CompressedImageDXT1);
2373 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2374
2375 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 0,
2376 CompressedImageDXT1);
2377 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2378
2379 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0, 0,
2380 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2381 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2382
2383 // Fill a full mip chain and verify that it works
2384 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2385 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2386 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2387 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2388 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2389 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2390 ASSERT_GL_NO_ERROR();
2391
2392 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2393 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2394 ASSERT_GL_NO_ERROR();
2395
2396 // Test that non-block size sub-uploads are not valid for the 0 mip
2397 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2398 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2399 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2400
2401 // Test that non-block size sub-uploads are valid for if they fill the whole mip
2402 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2403 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2404 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, 1, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2405 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2406 ASSERT_GL_NO_ERROR();
2407
2408 // Test that if the format miss-matches the texture, an error is generated
2409 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
2410 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2411 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2412}
2413
Geoff Lang677bb6f2017-04-05 12:40:40 -04002414TEST_P(WebGLCompatibilityTest, L32FTextures)
2415{
2416 constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f};
2417 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 1.0f};
2418
2419 for (auto extension : FloatingPointTextureExtensions)
2420 {
2421 if (strlen(extension) > 0 && extensionRequestable(extension))
2422 {
2423 glRequestExtensionANGLE(extension);
2424 ASSERT_GL_NO_ERROR();
2425 }
2426
2427 // Unsized L 32F
2428 {
2429 bool texture = extensionEnabled("GL_OES_texture_float");
2430 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2431 bool render = false;
2432 TestFloatTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, texture, filter, render,
2433 textureData, readPixelData);
2434 }
2435
2436 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2437 {
2438 // Sized L 32F
2439 bool texture = extensionEnabled("GL_OES_texture_float") &&
2440 extensionEnabled("GL_EXT_texture_storage");
2441 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2442 bool render = false;
2443 TestFloatTextureFormat(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT, texture, filter,
2444 render, textureData, readPixelData);
2445 }
2446 }
2447}
2448
2449TEST_P(WebGLCompatibilityTest, A32FTextures)
2450{
2451 constexpr float textureData[] = {33.33f, 0.0f, 0.0f, 0.0f};
2452 constexpr float readPixelData[] = {0.0f, 0.0f, 0.0f, textureData[0]};
2453
2454 for (auto extension : FloatingPointTextureExtensions)
2455 {
2456 if (strlen(extension) > 0 && extensionRequestable(extension))
2457 {
2458 glRequestExtensionANGLE(extension);
2459 ASSERT_GL_NO_ERROR();
2460 }
2461
2462 // Unsized A 32F
2463 {
2464 bool texture = extensionEnabled("GL_OES_texture_float");
2465 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2466 bool render = false;
2467 TestFloatTextureFormat(GL_ALPHA, GL_ALPHA, GL_FLOAT, texture, filter, render,
2468 textureData, readPixelData);
2469 }
2470
2471 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2472 {
2473 // Sized A 32F
2474 bool texture = extensionEnabled("GL_OES_texture_float") &&
2475 extensionEnabled("GL_EXT_texture_storage");
2476 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2477 bool render = false;
2478 TestFloatTextureFormat(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT, texture, filter, render,
2479 textureData, readPixelData);
2480 }
2481 }
2482}
2483
2484TEST_P(WebGLCompatibilityTest, LA32FTextures)
2485{
2486 constexpr float textureData[] = {-0.21f, 15.1f, 0.0f, 0.0f};
2487 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0],
2488 textureData[1]};
2489
2490 for (auto extension : FloatingPointTextureExtensions)
2491 {
2492 if (strlen(extension) > 0 && extensionRequestable(extension))
2493 {
2494 glRequestExtensionANGLE(extension);
2495 ASSERT_GL_NO_ERROR();
2496 }
2497
2498 // Unsized LA 32F
2499 {
2500 bool texture = extensionEnabled("GL_OES_texture_float");
2501 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2502 bool render = false;
2503 TestFloatTextureFormat(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2504 filter, render, textureData, readPixelData);
2505 }
2506
2507 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2508 {
2509 // Sized LA 32F
2510 bool texture = extensionEnabled("GL_OES_texture_float") &&
2511 extensionEnabled("GL_EXT_texture_storage");
2512 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2513 bool render = false;
2514 TestFloatTextureFormat(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2515 filter, render, textureData, readPixelData);
2516 }
2517 }
2518}
2519
2520TEST_P(WebGLCompatibilityTest, R32FTextures)
2521{
2522 constexpr float data[] = {1000.0f, 0.0f, 0.0f, 1.0f};
2523
2524 for (auto extension : FloatingPointTextureExtensions)
2525 {
2526 if (strlen(extension) > 0 && extensionRequestable(extension))
2527 {
2528 glRequestExtensionANGLE(extension);
2529 ASSERT_GL_NO_ERROR();
2530 }
2531
2532 // Unsized R 32F
2533 {
2534 bool texture =
2535 extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg");
2536 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2537 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2538 TestFloatTextureFormat(GL_RED, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2539 }
2540
2541 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2542 {
2543 // Sized R 32F
2544 bool texture =
2545 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2546 extensionEnabled("GL_EXT_texture_rg") &&
2547 extensionEnabled("GL_EXT_texture_storage"));
2548 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2549 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2550 TestFloatTextureFormat(GL_R32F, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2551 }
2552 }
2553}
2554
2555TEST_P(WebGLCompatibilityTest, RG32FTextures)
2556{
2557 constexpr float data[] = {1000.0f, -0.001f, 0.0f, 1.0f};
2558
2559 for (auto extension : FloatingPointTextureExtensions)
2560 {
2561 if (strlen(extension) > 0 && extensionRequestable(extension))
2562 {
2563 glRequestExtensionANGLE(extension);
2564 ASSERT_GL_NO_ERROR();
2565 }
2566
2567 // Unsized RG 32F
2568 {
2569 bool texture =
2570 (extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg"));
2571 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2572 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2573 TestFloatTextureFormat(GL_RG, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2574 }
2575
2576 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2577 {
2578 // Sized RG 32F
2579 bool texture =
2580 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2581 extensionEnabled("GL_EXT_texture_rg") &&
2582 extensionEnabled("GL_EXT_texture_storage"));
2583 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2584 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2585 TestFloatTextureFormat(GL_RG32F, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2586 }
2587 }
2588}
2589
2590TEST_P(WebGLCompatibilityTest, RGB32FTextures)
2591{
Yunchao He9550c602018-02-13 14:47:05 +08002592 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002593
Geoff Lang677bb6f2017-04-05 12:40:40 -04002594 constexpr float data[] = {1000.0f, -500.0f, 10.0f, 1.0f};
2595
2596 for (auto extension : FloatingPointTextureExtensions)
2597 {
2598 if (strlen(extension) > 0 && extensionRequestable(extension))
2599 {
2600 glRequestExtensionANGLE(extension);
2601 ASSERT_GL_NO_ERROR();
2602 }
2603
2604 // Unsized RGB 32F
2605 {
2606 bool texture = extensionEnabled("GL_OES_texture_float");
2607 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2608 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2609 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_FLOAT, texture, filter, render, data, data);
2610 }
2611
2612 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2613 {
2614 // Sized RGBA 32F
2615 bool texture =
2616 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2617 extensionEnabled("GL_EXT_texture_storage"));
2618 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2619 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2620 TestFloatTextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT, texture, filter, render, data,
2621 data);
2622 }
2623 }
2624}
2625
2626TEST_P(WebGLCompatibilityTest, RGBA32FTextures)
2627{
2628 constexpr float data[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2629
2630 for (auto extension : FloatingPointTextureExtensions)
2631 {
2632 if (strlen(extension) > 0 && extensionRequestable(extension))
2633 {
2634 glRequestExtensionANGLE(extension);
2635 ASSERT_GL_NO_ERROR();
2636 }
2637
2638 // Unsized RGBA 32F
2639 {
2640 bool texture = extensionEnabled("GL_OES_texture_float");
2641 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2642 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2643 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2644 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_FLOAT, texture, filter, render, data, data);
2645 }
2646
2647 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2648 {
2649 // Sized RGBA 32F
2650 bool texture =
2651 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2652 extensionEnabled("GL_EXT_texture_storage"));
2653 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2654 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2655 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2656 TestFloatTextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT, texture, filter, render, data,
2657 data);
2658 }
2659 }
2660}
2661
2662TEST_P(WebGLCompatibilityTest, R16FTextures)
2663{
2664 constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
2665 const GLushort textureData[] = {
2666 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2667 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2668
2669 for (auto extension : FloatingPointTextureExtensions)
2670 {
2671 if (strlen(extension) > 0 && extensionRequestable(extension))
2672 {
2673 glRequestExtensionANGLE(extension);
2674 ASSERT_GL_NO_ERROR();
2675 }
2676
2677 // Unsized R 16F (OES)
2678 {
2679 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2680 extensionEnabled("GL_EXT_texture_rg");
2681 bool filter = getClientMajorVersion() >= 3 ||
2682 extensionEnabled("GL_OES_texture_half_float_linear");
2683 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2684 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render,
2685 textureData, readPixelsData);
2686 }
2687
2688 // Unsized R 16F
2689 {
2690 bool texture = false;
2691 bool filter = false;
2692 bool render = false;
2693 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2694 textureData, readPixelsData);
2695 }
2696
2697 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2698 {
2699 // Sized R 16F
2700 bool texture = getClientMajorVersion() >= 3;
2701 bool filter = getClientMajorVersion() >= 3 ||
2702 extensionEnabled("GL_OES_texture_half_float_linear");
2703 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2704 extensionEnabled("GL_EXT_color_buffer_float");
2705 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2706 textureData, readPixelsData);
2707 }
2708 }
2709}
2710
2711TEST_P(WebGLCompatibilityTest, RG16FTextures)
2712{
2713 constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f};
2714 const GLushort textureData[] = {
2715 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2716 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2717
2718 for (auto extension : FloatingPointTextureExtensions)
2719 {
2720 if (strlen(extension) > 0 && extensionRequestable(extension))
2721 {
2722 glRequestExtensionANGLE(extension);
2723 ASSERT_GL_NO_ERROR();
2724 }
2725
2726 // Unsized RG 16F (OES)
2727 {
2728 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2729 extensionEnabled("GL_EXT_texture_rg");
2730 bool filter = getClientMajorVersion() >= 3 ||
2731 extensionEnabled("GL_OES_texture_half_float_linear");
2732 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") &&
2733 extensionEnabled("GL_EXT_texture_rg");
2734 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render,
2735 textureData, readPixelsData);
2736 }
2737
2738 // Unsized RG 16F
2739 {
2740 bool texture = false;
2741 bool filter = false;
2742 bool render = false;
2743 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2744 textureData, readPixelsData);
2745 }
2746
2747 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2748 {
2749 // Sized RG 16F
2750 bool texture = getClientMajorVersion() >= 3;
2751 bool filter = getClientMajorVersion() >= 3 ||
2752 extensionEnabled("GL_OES_texture_half_float_linear");
2753 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2754 extensionEnabled("GL_EXT_color_buffer_float");
2755 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2756 textureData, readPixelsData);
2757 }
2758 }
2759}
2760
2761TEST_P(WebGLCompatibilityTest, RGB16FTextures)
2762{
Yunchao He9550c602018-02-13 14:47:05 +08002763 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002764
Geoff Lang677bb6f2017-04-05 12:40:40 -04002765 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f};
2766 const GLushort textureData[] = {
2767 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2768 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2769
2770 for (auto extension : FloatingPointTextureExtensions)
2771 {
2772 if (strlen(extension) > 0 && extensionRequestable(extension))
2773 {
2774 glRequestExtensionANGLE(extension);
2775 ASSERT_GL_NO_ERROR();
2776 }
2777
2778 // Unsized RGB 16F (OES)
2779 {
2780 bool texture = extensionEnabled("GL_OES_texture_half_float");
2781 bool filter = getClientMajorVersion() >= 3 ||
2782 extensionEnabled("GL_OES_texture_half_float_linear");
2783 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2784 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render,
2785 textureData, readPixelsData);
2786 }
2787
2788 // Unsized RGB 16F
2789 {
2790 bool texture = false;
2791 bool filter = false;
2792 bool render = false;
2793 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2794 textureData, readPixelsData);
2795 }
2796
2797 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2798 {
2799 // Sized RGB 16F
2800 bool texture = getClientMajorVersion() >= 3;
2801 bool filter = getClientMajorVersion() >= 3 ||
2802 extensionEnabled("GL_OES_texture_half_float_linear");
2803 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2804 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2805 textureData, readPixelsData);
2806 }
2807 }
2808}
2809
2810TEST_P(WebGLCompatibilityTest, RGBA16FTextures)
2811{
Yunchao He9550c602018-02-13 14:47:05 +08002812 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002813
Geoff Lang677bb6f2017-04-05 12:40:40 -04002814 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2815 const GLushort textureData[] = {
2816 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2817 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2818
2819 for (auto extension : FloatingPointTextureExtensions)
2820 {
2821 if (strlen(extension) > 0 && extensionRequestable(extension))
2822 {
2823 glRequestExtensionANGLE(extension);
2824 ASSERT_GL_NO_ERROR();
2825 }
2826
2827 // Unsized RGBA 16F (OES)
2828 {
2829 bool texture = extensionEnabled("GL_OES_texture_half_float");
2830 bool filter = getClientMajorVersion() >= 3 ||
2831 extensionEnabled("GL_OES_texture_half_float_linear");
2832 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2833 extensionEnabled("GL_EXT_color_buffer_float");
2834 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render,
2835 textureData, readPixelsData);
2836 }
2837
2838 // Unsized RGBA 16F
2839 {
2840 bool texture = false;
2841 bool filter = false;
2842 bool render = false;
2843 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2844 textureData, readPixelsData);
2845 }
2846
2847 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2848 {
2849 // Sized RGBA 16F
2850 bool texture = getClientMajorVersion() >= 3;
2851 bool filter = getClientMajorVersion() >= 3 ||
2852 extensionEnabled("GL_OES_texture_half_float_linear");
2853 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2854 extensionEnabled("GL_EXT_color_buffer_float");
2855 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2856 textureData, readPixelsData);
2857 }
2858 }
2859}
2860
Geoff Lang6e898aa2017-06-02 11:17:26 -04002861// Test that when GL_CHROMIUM_color_buffer_float_rgb[a] is enabled, sized GL_RGB[A]_32F formats are
2862// accepted by glTexImage2D
2863TEST_P(WebGLCompatibilityTest, SizedRGBA32FFormats)
2864{
Yunchao He9550c602018-02-13 14:47:05 +08002865 // Test skipped because it is only valid for WebGL1 contexts.
2866 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
Geoff Lang6e898aa2017-06-02 11:17:26 -04002867
Yunchao He9550c602018-02-13 14:47:05 +08002868 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_OES_texture_float"));
2869
Geoff Lang6e898aa2017-06-02 11:17:26 -04002870 glRequestExtensionANGLE("GL_OES_texture_float");
2871 ASSERT_GL_NO_ERROR();
2872
2873 GLTexture texture;
2874 glBindTexture(GL_TEXTURE_2D, texture);
2875
2876 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2877 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2878
2879 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2880 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2881
2882 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgba"))
2883 {
2884 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgba");
2885 ASSERT_GL_NO_ERROR();
2886
2887 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2888 EXPECT_GL_NO_ERROR();
2889 }
2890
2891 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgb"))
2892 {
2893 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgb");
2894 ASSERT_GL_NO_ERROR();
2895
2896 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2897 EXPECT_GL_NO_ERROR();
2898 }
2899}
2900
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002901// Verify GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point.
2902TEST_P(WebGLCompatibilityTest, DepthStencilAttachment)
2903{
2904 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
2905
2906 // Test that attaching a bound texture succeeds.
2907 GLTexture texture;
2908 glBindTexture(GL_TEXTURE_2D, texture);
2909
2910 GLFramebuffer fbo;
2911 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2912
2913 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
2914
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002915 GLint attachmentType = 0;
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002916 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002917 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002918 EXPECT_GL_NO_ERROR();
2919 EXPECT_GLENUM_EQ(GL_TEXTURE, attachmentType);
2920
2921 // Test when if no attach object at the named attachment point and pname is not OBJECT_TYPE.
2922 GLFramebuffer fbo2;
2923 glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
2924
2925 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002926 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attachmentType);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002927 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2928}
2929
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002930// Verify framebuffer attachments return expected types when in an inconsistant state.
2931TEST_P(WebGLCompatibilityTest, FramebufferAttachmentConsistancy)
2932{
2933 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
2934
2935 GLFramebuffer fbo;
2936 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2937
2938 GLRenderbuffer rb1;
2939 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
2940
2941 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb1);
2942
2943 GLint attachmentType = 0;
2944 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
2945 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
2946
2947 EXPECT_GL_NO_ERROR();
2948 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
2949
2950 GLRenderbuffer rb2;
2951 glBindRenderbuffer(GL_RENDERBUFFER, rb2);
2952
2953 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2);
2954
2955 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
2956 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
2957
2958 EXPECT_GL_NO_ERROR();
2959 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -08002960
2961 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb2);
2962
2963 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
2964 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
2965
2966 EXPECT_GL_NO_ERROR();
2967 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
2968
2969 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2);
2970
2971 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
2972 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
2973
2974 EXPECT_GL_NO_ERROR();
2975 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002976}
2977
Jamie Madill07be8bf2017-02-02 19:59:57 -05002978// This tests that rendering feedback loops works as expected with WebGL 2.
2979// Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html
2980TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers)
2981{
2982 const std::string vertexShader =
2983 "#version 300 es\n"
2984 "in vec4 aPosition;\n"
2985 "out vec2 texCoord;\n"
2986 "void main() {\n"
2987 " gl_Position = aPosition;\n"
2988 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2989 "}\n";
2990
2991 const std::string fragmentShader =
2992 "#version 300 es\n"
2993 "precision mediump float;\n"
2994 "uniform sampler2D tex;\n"
2995 "in vec2 texCoord;\n"
2996 "out vec4 oColor;\n"
2997 "void main() {\n"
2998 " oColor = texture(tex, texCoord);\n"
2999 "}\n";
3000
3001 GLsizei width = 8;
3002 GLsizei height = 8;
3003
3004 GLint maxDrawBuffers = 0;
3005 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3006 // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS.
3007 ASSERT_GE(maxDrawBuffers, 2);
3008
3009 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3010 glUseProgram(program.get());
3011 glViewport(0, 0, width, height);
3012
3013 GLTexture tex0;
3014 GLTexture tex1;
3015 GLFramebuffer fbo;
3016 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3017 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3018 ASSERT_GL_NO_ERROR();
3019
3020 glBindTexture(GL_TEXTURE_2D, tex1.get());
3021 GLint texLoc = glGetUniformLocation(program.get(), "tex");
3022 ASSERT_NE(-1, texLoc);
3023 glUniform1i(texLoc, 0);
3024
3025 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
3026 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
3027 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
3028 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
3029 ASSERT_GL_NO_ERROR();
3030
3031 drawBuffersFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION);
3032 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
3033 GL_INVALID_OPERATION);
3034 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
3035}
3036
Jamie Madill1d37bc52017-02-02 19:59:58 -05003037// This test covers detection of rendering feedback loops between the FBO and a depth Texture.
3038// Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html
3039TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil)
3040{
3041 const std::string vertexShader =
3042 "#version 300 es\n"
3043 "in vec4 aPosition;\n"
3044 "out vec2 texCoord;\n"
3045 "void main() {\n"
3046 " gl_Position = aPosition;\n"
3047 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
3048 "}\n";
3049
3050 const std::string fragmentShader =
3051 "#version 300 es\n"
3052 "precision mediump float;\n"
3053 "uniform sampler2D tex;\n"
3054 "in vec2 texCoord;\n"
3055 "out vec4 oColor;\n"
3056 "void main() {\n"
3057 " oColor = texture(tex, texCoord);\n"
3058 "}\n";
3059
3060 GLsizei width = 8;
3061 GLsizei height = 8;
3062
3063 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3064 glUseProgram(program.get());
3065
3066 glViewport(0, 0, width, height);
3067
3068 GLint texLoc = glGetUniformLocation(program.get(), "tex");
3069 glUniform1i(texLoc, 0);
3070
3071 // Create textures and allocate storage
3072 GLTexture tex0;
3073 GLTexture tex1;
3074 GLRenderbuffer rb;
3075 FillTexture2D(tex0.get(), width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3076 FillTexture2D(tex1.get(), width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
3077 GL_UNSIGNED_INT);
3078 glBindRenderbuffer(GL_RENDERBUFFER, rb.get());
3079 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
3080 ASSERT_GL_NO_ERROR();
3081
3082 GLFramebuffer fbo;
3083 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
3084 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
3085
3086 // Test rendering and sampling feedback loop for depth buffer
3087 glBindTexture(GL_TEXTURE_2D, tex1.get());
3088 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1.get(), 0);
3089 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3090
3091 // The same image is used as depth buffer during rendering.
3092 glEnable(GL_DEPTH_TEST);
3093 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3094 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3095
3096 // The same image is used as depth buffer. But depth mask is false.
3097 glDepthMask(GL_FALSE);
3098 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3099 EXPECT_GL_NO_ERROR();
3100
3101 // The same image is used as depth buffer. But depth test is not enabled during rendering.
3102 glDepthMask(GL_TRUE);
3103 glDisable(GL_DEPTH_TEST);
3104 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3105 EXPECT_GL_NO_ERROR();
3106
3107 // Test rendering and sampling feedback loop for stencil buffer
3108 glBindTexture(GL_RENDERBUFFER, rb.get());
3109 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
3110 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb.get());
3111 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3112 constexpr GLint stencilClearValue = 0x40;
3113 glClearBufferiv(GL_STENCIL, 0, &stencilClearValue);
3114
3115 // The same image is used as stencil buffer during rendering.
3116 glEnable(GL_STENCIL_TEST);
3117 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3118 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3119
3120 // The same image is used as stencil buffer. But stencil mask is zero.
3121 glStencilMask(0x0);
3122 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3123 EXPECT_GL_NO_ERROR();
3124
3125 // The same image is used as stencil buffer. But stencil test is not enabled during rendering.
3126 glStencilMask(0xffff);
3127 glDisable(GL_STENCIL_TEST);
3128 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3129 EXPECT_GL_NO_ERROR();
3130}
3131
Jamie Madillfd3dd432017-02-02 19:59:59 -05003132// The source and the target for CopyTexSubImage3D are the same 3D texture.
3133// But the level of the 3D texture != the level of the read attachment.
3134TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels)
3135{
3136 GLTexture texture;
3137 GLFramebuffer framebuffer;
3138
3139 glBindTexture(GL_TEXTURE_3D, texture.get());
3140 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3141
3142 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3143 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3144 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
3145 ASSERT_GL_NO_ERROR();
3146
3147 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3148 EXPECT_GL_NO_ERROR();
3149}
3150
3151// The source and the target for CopyTexSubImage3D are the same 3D texture.
3152// But the zoffset of the 3D texture != the layer of the read attachment.
3153TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers)
3154{
3155 GLTexture texture;
3156 GLFramebuffer framebuffer;
3157
3158 glBindTexture(GL_TEXTURE_3D, texture.get());
3159 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3160
3161 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3162 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 1);
3163 ASSERT_GL_NO_ERROR();
3164
3165 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2);
3166 EXPECT_GL_NO_ERROR();
3167}
3168
3169// The source and the target for CopyTexSubImage3D are the same 3D texture.
3170// And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment.
3171TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D)
3172{
3173 GLTexture texture;
3174 GLFramebuffer framebuffer;
3175
3176 glBindTexture(GL_TEXTURE_3D, texture.get());
3177 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3178
3179 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3180 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3181 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3182 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 1, 0);
3183 ASSERT_GL_NO_ERROR();
3184
3185 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3186 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3187}
3188
Corentin Wallez59c41592017-07-11 13:19:54 -04003189// Verify that errors are generated when there isn't a defined conversion between the clear type and
3190// the buffer type.
Geoff Lang76e65652017-03-27 14:58:02 -04003191TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity)
3192{
Yunchao He9550c602018-02-13 14:47:05 +08003193 // Test skipped for D3D11 because it generates D3D11 runtime warnings.
3194 ANGLE_SKIP_TEST_IF(IsD3D11());
Geoff Lang76e65652017-03-27 14:58:02 -04003195
3196 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3197 constexpr int clearInt[] = {0, 0, 0, 0};
3198 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3199
3200 GLTexture texture;
3201 GLFramebuffer framebuffer;
3202
3203 glBindTexture(GL_TEXTURE_2D, texture.get());
3204 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3205
3206 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
3207 ASSERT_GL_NO_ERROR();
3208
3209 // Unsigned integer buffer
3210 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr);
3211 ASSERT_GL_NO_ERROR();
3212
3213 glClearBufferfv(GL_COLOR, 0, clearFloat);
3214 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3215
3216 glClearBufferiv(GL_COLOR, 0, clearInt);
3217 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3218
3219 glClearBufferuiv(GL_COLOR, 0, clearUint);
3220 EXPECT_GL_NO_ERROR();
3221
3222 glClear(GL_COLOR_BUFFER_BIT);
3223 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3224
3225 // Integer buffer
3226 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr);
3227 ASSERT_GL_NO_ERROR();
3228
3229 glClearBufferfv(GL_COLOR, 0, clearFloat);
3230 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3231
3232 glClearBufferiv(GL_COLOR, 0, clearInt);
3233 EXPECT_GL_NO_ERROR();
3234
3235 glClearBufferuiv(GL_COLOR, 0, clearUint);
3236 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3237
3238 glClear(GL_COLOR_BUFFER_BIT);
3239 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3240
3241 // Float buffer
Geoff Lang677bb6f2017-04-05 12:40:40 -04003242 if (extensionRequestable("GL_EXT_color_buffer_float"))
3243 {
3244 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3245 }
Geoff Lang76e65652017-03-27 14:58:02 -04003246
Geoff Lang677bb6f2017-04-05 12:40:40 -04003247 if (extensionEnabled("GL_EXT_color_buffer_float"))
3248 {
3249 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
3250 ASSERT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003251
Geoff Lang677bb6f2017-04-05 12:40:40 -04003252 glClearBufferfv(GL_COLOR, 0, clearFloat);
3253 EXPECT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003254
Geoff Lang677bb6f2017-04-05 12:40:40 -04003255 glClearBufferiv(GL_COLOR, 0, clearInt);
3256 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang76e65652017-03-27 14:58:02 -04003257
Geoff Lang677bb6f2017-04-05 12:40:40 -04003258 glClearBufferuiv(GL_COLOR, 0, clearUint);
3259 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3260
3261 glClear(GL_COLOR_BUFFER_BIT);
3262 EXPECT_GL_NO_ERROR();
3263 }
Geoff Lang76e65652017-03-27 14:58:02 -04003264
3265 // Normalized uint buffer
3266 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3267 ASSERT_GL_NO_ERROR();
3268
3269 glClearBufferfv(GL_COLOR, 0, clearFloat);
3270 EXPECT_GL_NO_ERROR();
3271
3272 glClearBufferiv(GL_COLOR, 0, clearInt);
3273 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3274
3275 glClearBufferuiv(GL_COLOR, 0, clearUint);
3276 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3277
3278 glClear(GL_COLOR_BUFFER_BIT);
3279 EXPECT_GL_NO_ERROR();
3280}
3281
Corentin Wallez59c41592017-07-11 13:19:54 -04003282// Test the interaction of WebGL compatibility clears with default framebuffers
3283TEST_P(WebGL2CompatibilityTest, ClearBufferDefaultFramebuffer)
3284{
3285 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3286 constexpr int clearInt[] = {0, 0, 0, 0};
3287 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3288
3289 // glClear works as usual, this is also a regression test for a bug where we
3290 // iterated on maxDrawBuffers for default framebuffers, triggering an assert
3291 glClear(GL_COLOR_BUFFER_BIT);
3292 EXPECT_GL_NO_ERROR();
3293
3294 // Default framebuffers are normalized uints, so only glClearBufferfv works.
3295 glClearBufferfv(GL_COLOR, 0, clearFloat);
3296 EXPECT_GL_NO_ERROR();
3297
3298 glClearBufferiv(GL_COLOR, 0, clearInt);
3299 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3300
3301 glClearBufferuiv(GL_COLOR, 0, clearUint);
3302 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3303}
3304
Geoff Lange4915782017-04-12 15:19:07 -04003305// Verify that errors are generate when trying to blit from an image to itself
3306TEST_P(WebGL2CompatibilityTest, BlitFramebufferSameImage)
3307{
3308 GLTexture textures[2];
3309 glBindTexture(GL_TEXTURE_2D, textures[0]);
3310 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3311 glBindTexture(GL_TEXTURE_2D, textures[1]);
3312 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3313
3314 GLRenderbuffer renderbuffers[2];
3315 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
3316 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3317 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
3318 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3319
3320 GLFramebuffer framebuffers[2];
3321 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]);
3322 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]);
3323
3324 ASSERT_GL_NO_ERROR();
3325
3326 // Same texture
3327 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3328 0);
3329 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3330 0);
3331 ASSERT_GL_NO_ERROR();
3332 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3333 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3334
3335 // Same textures but different renderbuffers
3336 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3337 renderbuffers[0]);
3338 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3339 renderbuffers[1]);
3340 ASSERT_GL_NO_ERROR();
3341 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3342 ASSERT_GL_NO_ERROR();
3343 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3344 GL_NEAREST);
3345 ASSERT_GL_NO_ERROR();
3346 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3347 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3348 GL_NEAREST);
3349 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3350
3351 // Same renderbuffers but different textures
3352 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3353 0);
3354 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1],
3355 0);
3356 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3357 renderbuffers[0]);
3358 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3359 renderbuffers[0]);
3360 ASSERT_GL_NO_ERROR();
3361 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3362 ASSERT_GL_NO_ERROR();
3363 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3364 GL_NEAREST);
3365 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3366 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3367 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3368 GL_NEAREST);
3369 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3370}
3371
Geoff Lange0cff192017-05-30 13:04:56 -04003372// Verify that errors are generated when the fragment shader output doesn't match the bound color
3373// buffer types
3374TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch)
3375{
3376 const std::string vertexShader =
3377 "#version 300 es\n"
3378 "void main() {\n"
3379 " gl_Position = vec4(0, 0, 0, 1);\n"
3380 "}\n";
3381
3382 const std::string fragmentShader =
3383 "#version 300 es\n"
3384 "precision mediump float;\n"
3385 "layout(location = 0) out vec4 floatOutput;\n"
3386 "layout(location = 1) out uvec4 uintOutput;\n"
3387 "layout(location = 2) out ivec4 intOutput;\n"
3388 "void main() {\n"
3389 " floatOutput = vec4(0, 0, 0, 1);\n"
3390 " uintOutput = uvec4(0, 0, 0, 1);\n"
3391 " intOutput = ivec4(0, 0, 0, 1);\n"
3392 "}\n";
3393
3394 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3395 glUseProgram(program.get());
3396
3397 GLuint floatLocation = glGetFragDataLocation(program, "floatOutput");
3398 GLuint uintLocation = glGetFragDataLocation(program, "uintOutput");
3399 GLuint intLocation = glGetFragDataLocation(program, "intOutput");
3400
3401 GLFramebuffer fbo;
3402 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3403
3404 GLRenderbuffer floatRenderbuffer;
3405 glBindRenderbuffer(GL_RENDERBUFFER, floatRenderbuffer);
3406 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
3407 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3408 floatRenderbuffer);
3409
3410 GLRenderbuffer uintRenderbuffer;
3411 glBindRenderbuffer(GL_RENDERBUFFER, uintRenderbuffer);
3412 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 1, 1);
3413 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3414 uintRenderbuffer);
3415
3416 GLRenderbuffer intRenderbuffer;
3417 glBindRenderbuffer(GL_RENDERBUFFER, intRenderbuffer);
3418 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 1, 1);
3419 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3420 intRenderbuffer);
3421
3422 ASSERT_GL_NO_ERROR();
3423
3424 GLint maxDrawBuffers = 0;
3425 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3426 std::vector<GLenum> drawBuffers(static_cast<size_t>(maxDrawBuffers), GL_NONE);
3427 drawBuffers[floatLocation] = GL_COLOR_ATTACHMENT0 + floatLocation;
3428 drawBuffers[uintLocation] = GL_COLOR_ATTACHMENT0 + uintLocation;
3429 drawBuffers[intLocation] = GL_COLOR_ATTACHMENT0 + intLocation;
3430
3431 glDrawBuffers(maxDrawBuffers, drawBuffers.data());
3432
3433 // Check that the correct case generates no errors
3434 glDrawArrays(GL_TRIANGLES, 0, 6);
3435 EXPECT_GL_NO_ERROR();
3436
3437 // Unbind some buffers and verify that there are still no errors
3438 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3439 0);
3440 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3441 0);
3442 glDrawArrays(GL_TRIANGLES, 0, 6);
3443 EXPECT_GL_NO_ERROR();
3444
3445 // Swap the int and uint buffers to and verify that an error is generated
3446 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3447 intRenderbuffer);
3448 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3449 uintRenderbuffer);
3450 glDrawArrays(GL_TRIANGLES, 0, 6);
3451 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3452
3453 // Swap the float and uint buffers to and verify that an error is generated
3454 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3455 floatRenderbuffer);
3456 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3457 uintRenderbuffer);
3458 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3459 intRenderbuffer);
3460 glDrawArrays(GL_TRIANGLES, 0, 6);
3461 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3462}
3463
Geoff Lang9ab5b822017-05-30 16:19:23 -04003464// Verify that errors are generated when the vertex shader intput doesn't match the bound attribute
3465// types
Corentin Wallezc3bc9842017-10-11 15:15:59 -04003466TEST_P(WebGL2CompatibilityTest, VertexShaderAttributeTypeMismatch)
Geoff Lang9ab5b822017-05-30 16:19:23 -04003467{
3468 const std::string vertexShader =
3469 "#version 300 es\n"
3470 "in vec4 floatInput;\n"
3471 "in uvec4 uintInput;\n"
3472 "in ivec4 intInput;\n"
3473 "void main() {\n"
3474 " gl_Position = vec4(floatInput.x, uintInput.x, intInput.x, 1);\n"
3475 "}\n";
3476
3477 const std::string fragmentShader =
3478 "#version 300 es\n"
3479 "precision mediump float;\n"
3480 "out vec4 outputColor;\n"
3481 "void main() {\n"
3482 " outputColor = vec4(0, 0, 0, 1);"
3483 "}\n";
3484
3485 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3486 glUseProgram(program.get());
3487
3488 GLint floatLocation = glGetAttribLocation(program, "floatInput");
3489 GLint uintLocation = glGetAttribLocation(program, "uintInput");
3490 GLint intLocation = glGetAttribLocation(program, "intInput");
3491
3492 // Default attributes are of float types
3493 glDrawArrays(GL_TRIANGLES, 0, 6);
3494 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3495
3496 // Set the default attributes to the correct types, should succeed
3497 glVertexAttribI4ui(uintLocation, 0, 0, 0, 1);
3498 glVertexAttribI4i(intLocation, 0, 0, 0, 1);
3499 glDrawArrays(GL_TRIANGLES, 0, 6);
3500 EXPECT_GL_NO_ERROR();
3501
3502 // Change the default float attribute to an integer, should fail
3503 glVertexAttribI4ui(floatLocation, 0, 0, 0, 1);
3504 glDrawArrays(GL_TRIANGLES, 0, 6);
3505 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3506
3507 // Use a buffer for some attributes
3508 GLBuffer buffer;
3509 glBindBuffer(GL_ARRAY_BUFFER, buffer);
3510 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
3511 glEnableVertexAttribArray(floatLocation);
3512 glVertexAttribPointer(floatLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3513 glDrawArrays(GL_TRIANGLES, 0, 6);
3514 EXPECT_GL_NO_ERROR();
3515
3516 // Use a float pointer attrib for a uint input
3517 glEnableVertexAttribArray(uintLocation);
3518 glVertexAttribPointer(uintLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3519 glDrawArrays(GL_TRIANGLES, 0, 6);
3520 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3521
3522 // Use a uint pointer for the uint input
3523 glVertexAttribIPointer(uintLocation, 4, GL_UNSIGNED_INT, 0, nullptr);
3524 glDrawArrays(GL_TRIANGLES, 0, 6);
3525 EXPECT_GL_NO_ERROR();
3526}
3527
Geoff Langfa125c92017-10-24 13:01:46 -04003528// Test that it's not possible to query the non-zero color attachments without the drawbuffers
3529// extension in WebGL1
3530TEST_P(WebGLCompatibilityTest, FramebufferAttachmentQuery)
3531{
3532 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
3533 ANGLE_SKIP_TEST_IF(extensionEnabled("GL_EXT_draw_buffers"));
3534
3535 GLFramebuffer fbo;
3536 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3537 EXPECT_GL_NO_ERROR();
3538
3539 GLint result;
3540 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
3541 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &result);
3542 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3543
3544 GLRenderbuffer renderbuffer;
3545 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3546 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
3547 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderbuffer);
3548 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3549}
3550
Corentin Walleze7557742017-06-01 13:09:57 -04003551// Tests the WebGL removal of undefined behavior when attachments aren't written to.
3552TEST_P(WebGLCompatibilityTest, DrawBuffers)
3553{
Corentin Walleze7557742017-06-01 13:09:57 -04003554 // Make sure we can use at least 4 attachments for the tests.
3555 bool useEXT = false;
3556 if (getClientMajorVersion() < 3)
3557 {
Yunchao He9550c602018-02-13 14:47:05 +08003558 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_EXT_draw_buffers"));
Corentin Walleze7557742017-06-01 13:09:57 -04003559
3560 glRequestExtensionANGLE("GL_EXT_draw_buffers");
3561 useEXT = true;
3562 EXPECT_GL_NO_ERROR();
3563 }
3564
3565 GLint maxDrawBuffers = 0;
3566 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
Yunchao He9550c602018-02-13 14:47:05 +08003567 // Test skipped because MAX_DRAW_BUFFERS is too small.
3568 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4);
Corentin Walleze7557742017-06-01 13:09:57 -04003569
3570 // Clears all the renderbuffers to red.
3571 auto ClearEverythingToRed = [](GLRenderbuffer *renderbuffers) {
3572 GLFramebuffer clearFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003573 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003574
3575 glClearColor(1, 0, 0, 1);
3576 for (int i = 0; i < 4; ++i)
3577 {
Geoff Lange8afa902017-09-27 15:00:43 -04003578 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
Corentin Walleze7557742017-06-01 13:09:57 -04003579 renderbuffers[i]);
3580 glClear(GL_COLOR_BUFFER_BIT);
3581 }
3582 ASSERT_GL_NO_ERROR();
3583 };
3584
3585 // Checks that the renderbuffers specified by mask have the correct color
3586 auto CheckColors = [](GLRenderbuffer *renderbuffers, int mask, GLColor color) {
3587 GLFramebuffer readFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003588 glBindFramebuffer(GL_FRAMEBUFFER, readFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003589
3590 for (int i = 0; i < 4; ++i)
3591 {
3592 if (mask & (1 << i))
3593 {
Geoff Lange8afa902017-09-27 15:00:43 -04003594 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
3595 renderbuffers[i]);
Corentin Walleze7557742017-06-01 13:09:57 -04003596 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
3597 }
3598 }
3599 ASSERT_GL_NO_ERROR();
3600 };
3601
3602 // Depending on whether we are using the extension or ES3, a different entrypoint must be called
3603 auto DrawBuffers = [](bool useEXT, int numBuffers, GLenum *buffers) {
3604 if (useEXT)
3605 {
3606 glDrawBuffersEXT(numBuffers, buffers);
3607 }
3608 else
3609 {
3610 glDrawBuffers(numBuffers, buffers);
3611 }
3612 };
3613
3614 // Initialized the test framebuffer
3615 GLFramebuffer drawFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003616 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003617
3618 GLRenderbuffer renderbuffers[4];
3619 for (int i = 0; i < 4; ++i)
3620 {
3621 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
Geoff Langd84a00b2017-10-27 17:27:26 -04003622 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
Geoff Lange8afa902017-09-27 15:00:43 -04003623 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER,
Corentin Walleze7557742017-06-01 13:09:57 -04003624 renderbuffers[i]);
3625 }
3626
3627 ASSERT_GL_NO_ERROR();
3628
3629 const char *vertESSL1 =
3630 "attribute vec4 a_pos;\n"
3631 "void main()\n"
3632 "{\n"
3633 " gl_Position = a_pos;\n"
3634 "}\n";
3635 const char *vertESSL3 =
3636 "#version 300 es\n"
3637 "in vec4 a_pos;\n"
3638 "void main()\n"
3639 "{\n"
3640 " gl_Position = a_pos;\n"
3641 "}\n";
3642
3643 GLenum allDrawBuffers[] = {
3644 GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3645 };
3646
3647 GLenum halfDrawBuffers[] = {
3648 GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3649 };
3650
3651 // Test that when using gl_FragColor, only the first attachment is written to.
3652 const char *fragESSL1 =
3653 "precision highp float;\n"
3654 "void main()\n"
3655 "{\n"
3656 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3657 "}\n";
3658 ANGLE_GL_PROGRAM(programESSL1, vertESSL1, fragESSL1);
3659
3660 {
3661 ClearEverythingToRed(renderbuffers);
3662
Geoff Lange8afa902017-09-27 15:00:43 -04003663 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003664 DrawBuffers(useEXT, 4, allDrawBuffers);
3665 drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
3666 ASSERT_GL_NO_ERROR();
3667
3668 CheckColors(renderbuffers, 0b0001, GLColor::green);
3669 CheckColors(renderbuffers, 0b1110, GLColor::red);
3670 }
3671
3672 // Test that when using gl_FragColor, but the first draw buffer is 0, then no attachment is
3673 // written to.
3674 {
3675 ClearEverythingToRed(renderbuffers);
3676
Geoff Lange8afa902017-09-27 15:00:43 -04003677 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003678 DrawBuffers(useEXT, 4, halfDrawBuffers);
3679 drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
3680 ASSERT_GL_NO_ERROR();
3681
3682 CheckColors(renderbuffers, 0b1111, GLColor::red);
3683 }
3684
3685 // Test what happens when rendering to a subset of the outputs. There is a behavior difference
3686 // between the extension and ES3. In the extension gl_FragData is implicitly declared as an
3687 // array of size MAX_DRAW_BUFFERS, so the WebGL spec stipulates that elements not written to
3688 // should default to 0. On the contrary, in ES3 outputs are specified one by one, so
3689 // attachments not declared in the shader should not be written to.
3690 const char *writeOddOutputsVert;
3691 const char *writeOddOutputsFrag;
3692 GLColor unwrittenColor;
3693 if (useEXT)
3694 {
3695 // In the extension, when an attachment isn't written to, it should get 0's
3696 unwrittenColor = GLColor(0, 0, 0, 0);
3697 writeOddOutputsVert = vertESSL1;
3698 writeOddOutputsFrag =
3699 "#extension GL_EXT_draw_buffers : require\n"
3700 "precision highp float;\n"
3701 "void main()\n"
3702 "{\n"
3703 " gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3704 " gl_FragData[3] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3705 "}\n";
3706 }
3707 else
3708 {
3709 // In ES3 if an attachment isn't declared, it shouldn't get written and should be red
3710 // because of the preceding clears.
3711 unwrittenColor = GLColor::red;
3712 writeOddOutputsVert = vertESSL3;
3713 writeOddOutputsFrag =
3714 "#version 300 es\n"
3715 "precision highp float;\n"
3716 "layout(location = 1) out vec4 output1;"
3717 "layout(location = 3) out vec4 output2;"
3718 "void main()\n"
3719 "{\n"
3720 " output1 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3721 " output2 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3722 "}\n";
3723 }
3724 ANGLE_GL_PROGRAM(writeOddOutputsProgram, writeOddOutputsVert, writeOddOutputsFrag);
3725
3726 // Test that attachments not written to get the "unwritten" color
3727 {
3728 ClearEverythingToRed(renderbuffers);
3729
Geoff Lange8afa902017-09-27 15:00:43 -04003730 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003731 DrawBuffers(useEXT, 4, allDrawBuffers);
3732 drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
3733 ASSERT_GL_NO_ERROR();
3734
3735 CheckColors(renderbuffers, 0b1010, GLColor::green);
3736 CheckColors(renderbuffers, 0b0101, unwrittenColor);
3737 }
3738
3739 // Test that attachments not written to get the "unwritten" color but that even when the
3740 // extension is used, disabled attachments are not written at all and stay red.
3741 {
3742 ClearEverythingToRed(renderbuffers);
3743
Geoff Lange8afa902017-09-27 15:00:43 -04003744 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003745 DrawBuffers(useEXT, 4, halfDrawBuffers);
3746 drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
3747 ASSERT_GL_NO_ERROR();
3748
3749 CheckColors(renderbuffers, 0b1000, GLColor::green);
3750 CheckColors(renderbuffers, 0b0100, unwrittenColor);
3751 CheckColors(renderbuffers, 0b0011, GLColor::red);
3752 }
3753}
3754
Geoff Lang536eca12017-09-13 11:23:35 -04003755// Test that it's possible to generate mipmaps on unsized floating point textures once the
3756// extensions have been enabled
3757TEST_P(WebGLCompatibilityTest, GenerateMipmapUnsizedFloatingPointTexture)
3758{
3759 if (extensionRequestable("GL_OES_texture_float"))
3760 {
3761 glRequestExtensionANGLE("GL_OES_texture_float");
3762 }
3763 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3764
3765 GLTexture texture;
3766 glBindTexture(GL_TEXTURE_2D, texture);
3767
3768 constexpr GLColor32F data[4] = {
3769 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3770 };
3771 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_FLOAT, data);
3772 ASSERT_GL_NO_ERROR();
3773
3774 glGenerateMipmap(GL_TEXTURE_2D);
3775 EXPECT_GL_NO_ERROR();
3776}
3777// Test that it's possible to generate mipmaps on unsized floating point textures once the
3778// extensions have been enabled
3779TEST_P(WebGLCompatibilityTest, GenerateMipmapSizedFloatingPointTexture)
3780{
3781 if (extensionRequestable("GL_OES_texture_float"))
3782 {
3783 glRequestExtensionANGLE("GL_OES_texture_float");
3784 }
3785 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3786
3787 if (extensionRequestable("GL_EXT_texture_storage"))
3788 {
3789 glRequestExtensionANGLE("GL_EXT_texture_storage");
3790 }
3791 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_storage"));
3792
3793 GLTexture texture;
3794 glBindTexture(GL_TEXTURE_2D, texture);
3795
3796 constexpr GLColor32F data[4] = {
3797 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3798 };
3799 glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA32F, 2, 2);
3800 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, data);
3801 ASSERT_GL_NO_ERROR();
3802
3803 glGenerateMipmap(GL_TEXTURE_2D);
3804 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3805
3806 if (extensionRequestable("GL_EXT_color_buffer_float"))
3807 {
3808 // Format is renderable but not filterable
3809 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3810 glGenerateMipmap(GL_TEXTURE_2D);
3811 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3812 }
3813
3814 if (extensionRequestable("GL_EXT_color_buffer_float_linear"))
3815 {
3816 // Format is renderable but not filterable
3817 glRequestExtensionANGLE("GL_EXT_color_buffer_float_linear");
3818
3819 if (extensionEnabled("GL_EXT_color_buffer_float"))
3820 {
3821 // Format is filterable and renderable
3822 glGenerateMipmap(GL_TEXTURE_2D);
3823 EXPECT_GL_NO_ERROR();
3824 }
3825 else
3826 {
3827 // Format is filterable but not renderable
3828 glGenerateMipmap(GL_TEXTURE_2D);
3829 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3830 }
3831 }
3832}
3833
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003834// Verify that a texture format is only allowed with extension enabled.
3835void WebGLCompatibilityTest::validateTexImageExtensionFormat(GLenum format,
3836 const std::string &extName)
3837{
3838 // Verify texture format fails by default.
3839 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
3840 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3841
3842 if (extensionRequestable(extName))
3843 {
3844 // Verify texture format is allowed once extension is enabled.
3845 glRequestExtensionANGLE(extName.c_str());
3846 EXPECT_TRUE(extensionEnabled(extName));
3847
3848 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
3849 ASSERT_GL_NO_ERROR();
3850 }
3851}
3852
Geoff Lang86f81162017-10-30 15:10:45 -04003853// Test enabling various non-compressed texture format extensions
3854TEST_P(WebGLCompatibilityTest, EnableTextureFormatExtensions)
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003855{
Geoff Lang2c5c41f2017-10-31 10:58:09 -04003856 ANGLE_SKIP_TEST_IF(IsOzone());
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003857 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
3858
3859 GLTexture texture;
3860 glBindTexture(GL_TEXTURE_2D, texture.get());
3861
3862 // Verify valid format is allowed.
3863 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3864 ASSERT_GL_NO_ERROR();
3865
3866 // Verify invalid format fails.
3867 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA32F, GL_UNSIGNED_BYTE, nullptr);
3868 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3869
3870 // Verify formats from enableable extensions.
Geoff Lang660b28c2017-10-30 12:58:56 -04003871 if (!IsOpenGLES())
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003872 {
3873 validateTexImageExtensionFormat(GL_RED_EXT, "GL_EXT_texture_rg");
3874 }
3875
3876 validateTexImageExtensionFormat(GL_SRGB_EXT, "GL_EXT_texture_sRGB");
3877 validateTexImageExtensionFormat(GL_BGRA_EXT, "GL_EXT_texture_format_BGRA8888");
3878}
3879
Geoff Lang86f81162017-10-30 15:10:45 -04003880void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum format,
3881 GLsizei width,
3882 GLsizei height,
3883 GLsizei blockSize,
3884 const std::string &extName,
3885 bool subImageAllowed)
3886{
3887 std::vector<GLubyte> data(blockSize, 0u);
3888
3889 GLTexture texture;
3890 glBindTexture(GL_TEXTURE_2D, texture.get());
3891
3892 // Verify texture format fails by default.
3893 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
3894 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3895
3896 if (extensionRequestable(extName))
3897 {
3898 // Verify texture format is allowed once extension is enabled.
3899 glRequestExtensionANGLE(extName.c_str());
3900 EXPECT_TRUE(extensionEnabled(extName));
3901
3902 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
3903 EXPECT_GL_NO_ERROR();
3904
3905 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, blockSize,
3906 data.data());
3907 if (subImageAllowed)
3908 {
3909 EXPECT_GL_NO_ERROR();
3910 }
3911 else
3912 {
3913 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3914 }
3915 }
3916}
3917
3918// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT
3919TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB)
3920{
3921 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8,
3922 "GL_EXT_texture_compression_dxt1", true);
3923}
3924
3925// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
3926TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGBA)
3927{
3928 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8,
3929 "GL_EXT_texture_compression_dxt1", true);
3930}
3931
3932// Test enabling GL_ANGLE_texture_compression_dxt3
3933TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3)
3934{
3935 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 16,
3936 "GL_ANGLE_texture_compression_dxt3", true);
3937}
3938
3939// Test enabling GL_ANGLE_texture_compression_dxt5
3940TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5)
3941{
3942 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 16,
3943 "GL_ANGLE_texture_compression_dxt5", true);
3944}
3945
3946// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
3947TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGB)
3948{
3949 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8,
3950 "GL_EXT_texture_compression_s3tc_srgb", true);
3951}
3952
3953// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
3954TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGBA)
3955{
3956 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8,
3957 "GL_EXT_texture_compression_s3tc_srgb", true);
3958}
3959
3960// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
3961TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3SRGBA)
3962{
3963 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16,
3964 "GL_EXT_texture_compression_s3tc_srgb", true);
3965}
3966
3967// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
3968TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5SRGBA)
3969{
3970 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16,
3971 "GL_EXT_texture_compression_s3tc_srgb", true);
3972}
3973
3974// Test enabling GL_OES_compressed_ETC1_RGB8_texture
3975TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionETC1)
3976{
3977 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_OES, 4, 4, 8,
3978 "GL_OES_compressed_ETC1_RGB8_texture", false);
3979}
3980
3981// Test enabling GL_ANGLE_lossy_etc_decode
3982TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionLossyDecode)
3983{
3984 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 8,
3985 "GL_ANGLE_lossy_etc_decode", true);
3986}
3987
Frank Henigmanfccbac22017-05-28 17:29:26 -04003988// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
3989// qualifiers.
3990TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch)
3991{
3992 const std::string vertexShader =
3993 "#version 300 es\n"
3994 "uniform Block { mediump vec4 val; };\n"
3995 "void main() { gl_Position = val; }\n";
3996 const std::string fragmentShader =
3997 "#version 300 es\n"
3998 "uniform Block { highp vec4 val; };\n"
3999 "out highp vec4 out_FragColor;\n"
4000 "void main() { out_FragColor = val; }\n";
4001
4002 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
4003 ASSERT_NE(0u, vs);
4004 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
4005 ASSERT_NE(0u, fs);
4006
4007 GLuint program = glCreateProgram();
4008
4009 glAttachShader(program, vs);
4010 glDeleteShader(vs);
4011 glAttachShader(program, fs);
4012 glDeleteShader(fs);
4013
4014 glLinkProgram(program);
4015 GLint linkStatus;
4016 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
4017 ASSERT_EQ(0, linkStatus);
4018
4019 glDeleteProgram(program);
4020}
4021
Geoff Lang69df2422017-07-05 12:42:31 -04004022// Test no attribute vertex shaders
4023TEST_P(WebGL2CompatibilityTest, NoAttributeVertexShader)
4024{
4025 const std::string vertexShader =
4026 "#version 300 es\n"
4027 "void main()\n"
4028 "{\n"
4029 "\n"
4030 " ivec2 xy = ivec2(gl_VertexID % 2, (gl_VertexID / 2 + gl_VertexID / 3) % 2);\n"
4031 " gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1);\n"
4032 "}";
4033 const std::string fragmentShader =
4034 "#version 300 es\n"
4035 "precision mediump float;\n"
4036 "out vec4 result;\n"
4037 "void main()\n"
4038 "{\n"
4039 " result = vec4(0, 1, 0, 1);\n"
4040 "}";
4041
4042 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
4043 glUseProgram(program);
4044
4045 glDrawArrays(GL_TRIANGLES, 0, 6);
4046 ASSERT_GL_NO_ERROR();
4047 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4048}
4049
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004050// Tests bindAttribLocations for length limit
4051TEST_P(WebGL2CompatibilityTest, BindAttribLocationLimitation)
4052{
4053 constexpr int maxLocStringLength = 1024;
4054 const std::string tooLongString(maxLocStringLength + 1, '_');
4055
4056 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
4057
4058 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4059}
4060
Geoff Langc287ea62016-09-16 14:46:51 -04004061// Use this to select which configurations (e.g. which renderer, which GLES major version) these
4062// tests should be run against.
4063ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
4064 ES2_D3D9(),
4065 ES2_D3D11(),
4066 ES3_D3D11(),
Geoff Langc287ea62016-09-16 14:46:51 -04004067 ES2_OPENGL(),
4068 ES3_OPENGL(),
4069 ES2_OPENGLES(),
4070 ES3_OPENGLES());
4071
Jamie Madill07be8bf2017-02-02 19:59:57 -05004072ANGLE_INSTANTIATE_TEST(WebGL2CompatibilityTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Geoff Langc287ea62016-09-16 14:46:51 -04004073} // namespace