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