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