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