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