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