blob: 6163b6d6b338b305939cc05aa48a0410f074cac9 [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 Lang2348e212017-09-27 17:46:25 -0400893// Test enabling the GL_OES_get_program_binary extension
894TEST_P(WebGLCompatibilityTest, EnableProgramBinaryExtension)
895{
896 EXPECT_FALSE(extensionEnabled("GL_OES_get_program_binary"));
897
898 // This extensions become core in in ES3/WebGL2.
899 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
900
901 GLint result = 0;
902 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
903 EXPECT_GL_ERROR(GL_INVALID_ENUM);
904
905 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
906 EXPECT_GL_ERROR(GL_INVALID_ENUM);
907
908 const std::string &vert =
909 "void main()\n"
910 "{\n"
911 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
912 "}\n";
913 const std::string &frag =
914 "precision highp float;\n"
915 "void main()\n"
916 "{\n"
917 " gl_FragColor = vec4(1.0);\n"
918 "}\n";
919 ANGLE_GL_PROGRAM(program, vert, frag);
920
921 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &result);
922 EXPECT_GL_ERROR(GL_INVALID_ENUM);
923
924 uint8_t tempArray[512];
925 GLenum tempFormat = 0;
926 GLsizei tempLength = 0;
927 glGetProgramBinaryOES(program, static_cast<GLsizei>(ArraySize(tempArray)), &tempLength,
928 &tempFormat, tempArray);
929 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
930
931 if (extensionRequestable("GL_OES_get_program_binary"))
932 {
933 glRequestExtensionANGLE("GL_OES_get_program_binary");
934 EXPECT_GL_NO_ERROR();
935
936 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
937 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
938 EXPECT_GL_NO_ERROR();
939
940 GLint binaryLength = 0;
941 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
942 EXPECT_GL_NO_ERROR();
943
944 GLenum binaryFormat;
945 GLsizei writeLength = 0;
946 std::vector<uint8_t> binary(binaryLength);
947 glGetProgramBinaryOES(program, binaryLength, &writeLength, &binaryFormat, binary.data());
948 EXPECT_GL_NO_ERROR();
949
950 glProgramBinaryOES(program, binaryFormat, binary.data(), binaryLength);
951 EXPECT_GL_NO_ERROR();
952 }
953}
954
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400955// Verify that the context generates the correct error when the framebuffer attachments are
956// different sizes
Corentin Wallezc3bc9842017-10-11 15:15:59 -0400957TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch)
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400958{
959 GLFramebuffer fbo;
960 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
961
962 GLTexture textures[2];
963 glBindTexture(GL_TEXTURE_2D, textures[0]);
964 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
965 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
966
967 ASSERT_GL_NO_ERROR();
968 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
969
970 GLRenderbuffer renderbuffer;
971 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
972 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3);
973 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
974
975 ASSERT_GL_NO_ERROR();
976 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
977 glCheckFramebufferStatus(GL_FRAMEBUFFER));
978
979 if (extensionRequestable("GL_EXT_draw_buffers"))
980 {
981 glRequestExtensionANGLE("GL_EXT_draw_buffers");
982 EXPECT_GL_NO_ERROR();
983 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
984
985 glBindTexture(GL_TEXTURE_2D, textures[1]);
986 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
987 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
988 ASSERT_GL_NO_ERROR();
989
990 ASSERT_GL_NO_ERROR();
991 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
992 glCheckFramebufferStatus(GL_FRAMEBUFFER));
993
994 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
995
996 ASSERT_GL_NO_ERROR();
997 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
998
999 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1000
1001 ASSERT_GL_NO_ERROR();
1002 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1003 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1004 }
1005}
1006
Corentin Wallez327411e2016-12-09 11:09:17 -05001007// Test that client-side array buffers are forbidden in WebGL mode
1008TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer)
1009{
1010 const std::string &vert =
1011 "attribute vec3 a_pos;\n"
1012 "void main()\n"
1013 "{\n"
1014 " gl_Position = vec4(a_pos, 1.0);\n"
1015 "}\n";
1016
1017 const std::string &frag =
1018 "precision highp float;\n"
1019 "void main()\n"
1020 "{\n"
1021 " gl_FragColor = vec4(1.0);\n"
1022 "}\n";
1023
1024 ANGLE_GL_PROGRAM(program, vert, frag);
1025
1026 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1027 ASSERT_NE(-1, posLocation);
1028 glUseProgram(program.get());
1029
1030 const auto &vertices = GetQuadVertices();
Corentin Wallezfd456442016-12-21 17:57:00 -05001031 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
Corentin Wallez327411e2016-12-09 11:09:17 -05001032 glEnableVertexAttribArray(posLocation);
1033
1034 ASSERT_GL_NO_ERROR();
1035 glDrawArrays(GL_TRIANGLES, 0, 6);
1036 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1037}
1038
1039// Test that client-side element array buffers are forbidden in WebGL mode
1040TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
1041{
1042 const std::string &vert =
1043 "attribute vec3 a_pos;\n"
1044 "void main()\n"
1045 "{\n"
1046 " gl_Position = vec4(a_pos, 1.0);\n"
1047 "}\n";
1048
1049 const std::string &frag =
1050 "precision highp float;\n"
1051 "void main()\n"
1052 "{\n"
1053 " gl_FragColor = vec4(1.0);\n"
1054 "}\n";
1055
1056 ANGLE_GL_PROGRAM(program, vert, frag);
1057
1058 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1059 ASSERT_NE(-1, posLocation);
1060 glUseProgram(program.get());
1061
1062 const auto &vertices = GetQuadVertices();
1063
1064 GLBuffer vertexBuffer;
1065 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1066 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1067 GL_STATIC_DRAW);
1068
1069 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1070 glEnableVertexAttribArray(posLocation);
1071
Corentin Wallez327411e2016-12-09 11:09:17 -05001072 ASSERT_GL_NO_ERROR();
Corentin Wallezded1b5a2017-03-09 18:58:48 -05001073
1074 // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also
1075 // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate
1076 // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check.
1077 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void*>(intptr_t(1)));
Corentin Wallez327411e2016-12-09 11:09:17 -05001078 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1079}
1080
Corentin Wallez672f7f32017-06-15 17:42:17 -04001081// Test that client-side array buffers are forbidden even if the program doesn't use the attribute
1082TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBufferEvenNotUsedOnes)
1083{
1084 const std::string &vert =
1085 "void main()\n"
1086 "{\n"
1087 " gl_Position = vec4(1.0);\n"
1088 "}\n";
1089
1090 const std::string &frag =
1091 "precision highp float;\n"
1092 "void main()\n"
1093 "{\n"
1094 " gl_FragColor = vec4(1.0);\n"
1095 "}\n";
1096
1097 ANGLE_GL_PROGRAM(program, vert, frag);
1098
1099 glUseProgram(program.get());
1100
1101 const auto &vertices = GetQuadVertices();
1102 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
1103 glEnableVertexAttribArray(0);
1104
1105 ASSERT_GL_NO_ERROR();
1106 glDrawArrays(GL_TRIANGLES, 0, 6);
1107 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1108}
1109
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001110// Tests the WebGL requirement of having the same stencil mask, writemask and ref for fron and back
1111TEST_P(WebGLCompatibilityTest, RequiresSameStencilMaskAndRef)
1112{
1113 // Run the test in an FBO to make sure we have some stencil bits.
1114 GLRenderbuffer renderbuffer;
1115 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
1116 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
1117
1118 GLFramebuffer framebuffer;
1119 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1120 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1121 renderbuffer.get());
1122
1123 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
1124 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
1125 glUseProgram(program.get());
1126 ASSERT_GL_NO_ERROR();
1127
1128 // Having ref and mask the same for front and back is valid.
1129 glStencilMask(255);
1130 glStencilFunc(GL_ALWAYS, 0, 255);
1131 glDrawArrays(GL_TRIANGLES, 0, 6);
1132 ASSERT_GL_NO_ERROR();
1133
1134 // Having a different front - back write mask generates an error.
1135 glStencilMaskSeparate(GL_FRONT, 1);
1136 glDrawArrays(GL_TRIANGLES, 0, 6);
1137 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1138
1139 // Setting both write masks separately to the same value is valid.
1140 glStencilMaskSeparate(GL_BACK, 1);
1141 glDrawArrays(GL_TRIANGLES, 0, 6);
1142 ASSERT_GL_NO_ERROR();
1143
1144 // Having a different stencil front - back mask generates an error
1145 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
1146 glDrawArrays(GL_TRIANGLES, 0, 6);
1147 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1148
1149 // Setting both masks separately to the same value is valid.
1150 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
1151 glDrawArrays(GL_TRIANGLES, 0, 6);
1152 ASSERT_GL_NO_ERROR();
1153
1154 // Having a different stencil front - back reference generates an error
1155 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
1156 glDrawArrays(GL_TRIANGLES, 0, 6);
1157 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1158
1159 // Setting both references separately to the same value is valid.
1160 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
1161 glDrawArrays(GL_TRIANGLES, 0, 6);
1162 ASSERT_GL_NO_ERROR();
1163
1164 // Using different stencil funcs, everything being equal is valid.
1165 glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
1166 glDrawArrays(GL_TRIANGLES, 0, 6);
1167 ASSERT_GL_NO_ERROR();
1168}
1169
Corentin Wallez506fc9c2016-12-21 16:53:33 -05001170// Test that GL_FIXED is forbidden
1171TEST_P(WebGLCompatibilityTest, ForbidsGLFixed)
1172{
1173 GLBuffer buffer;
1174 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1175 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1176
1177 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1178 ASSERT_GL_NO_ERROR();
1179
1180 glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr);
1181 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1182}
1183
1184// Test the WebGL limit of 255 for the attribute stride
1185TEST_P(WebGLCompatibilityTest, MaxStride)
1186{
1187 GLBuffer buffer;
1188 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1189 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
1190
1191 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr);
1192 ASSERT_GL_NO_ERROR();
1193
1194 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr);
1195 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1196}
1197
Corentin Wallezfd456442016-12-21 17:57:00 -05001198// Test the checks for OOB reads in the vertex buffers, non-instanced version
1199TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
1200{
1201 const std::string &vert =
1202 "attribute float a_pos;\n"
1203 "void main()\n"
1204 "{\n"
1205 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1206 "}\n";
1207
1208 const std::string &frag =
1209 "precision highp float;\n"
1210 "void main()\n"
1211 "{\n"
1212 " gl_FragColor = vec4(1.0);\n"
1213 "}\n";
1214
1215 ANGLE_GL_PROGRAM(program, vert, frag);
Corentin Wallezfd456442016-12-21 17:57:00 -05001216 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1217 ASSERT_NE(-1, posLocation);
1218 glUseProgram(program.get());
1219
1220 GLBuffer buffer;
1221 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1222 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1223
1224 glEnableVertexAttribArray(posLocation);
1225
1226 const uint8_t* zeroOffset = nullptr;
1227
1228 // Test touching the last element is valid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001229 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
Corentin Wallezfd456442016-12-21 17:57:00 -05001230 glDrawArrays(GL_POINTS, 0, 4);
1231 ASSERT_GL_NO_ERROR();
1232
1233 // Test touching the last element + 1 is invalid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001234 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
Corentin Wallezfd456442016-12-21 17:57:00 -05001235 glDrawArrays(GL_POINTS, 0, 4);
1236 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1237
1238 // Test touching the last element is valid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001239 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
Corentin Wallezfd456442016-12-21 17:57:00 -05001240 glDrawArrays(GL_POINTS, 0, 4);
1241 ASSERT_GL_NO_ERROR();
1242
1243 // Test touching the last element + 1 is invalid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001244 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
Corentin Wallezfd456442016-12-21 17:57:00 -05001245 glDrawArrays(GL_POINTS, 0, 4);
1246 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1247
1248 // Test any offset is valid if no vertices are drawn.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001249 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
Corentin Wallezfd456442016-12-21 17:57:00 -05001250 glDrawArrays(GL_POINTS, 0, 0);
1251 ASSERT_GL_NO_ERROR();
Corentin Wallez91c8de82017-10-12 16:32:44 -04001252
1253 // Test a case of overflow that could give a max vertex that's negative
1254 constexpr GLint kIntMax = std::numeric_limits<GLint>::max();
1255 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 0);
1256 glDrawArrays(GL_POINTS, kIntMax, kIntMax);
1257 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1258}
1259
1260// Test the checks for OOB reads in the vertex buffers, instanced version
1261TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
1262{
1263 const std::string &vert =
1264 "attribute float a_pos;\n"
1265 "attribute float a_w;\n"
1266 "void main()\n"
1267 "{\n"
1268 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1269 "}\n";
1270
1271 const std::string &frag =
1272 "precision highp float;\n"
1273 "void main()\n"
1274 "{\n"
1275 " gl_FragColor = vec4(1.0);\n"
1276 "}\n";
1277
1278 ANGLE_GL_PROGRAM(program, vert, frag);
1279 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1280 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
1281 ASSERT_NE(-1, posLocation);
1282 ASSERT_NE(-1, wLocation);
1283 glUseProgram(program.get());
1284
1285 GLBuffer buffer;
1286 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1287 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1288
1289 glEnableVertexAttribArray(posLocation);
1290 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1291 glVertexAttribDivisor(posLocation, 0);
1292
1293 glEnableVertexAttribArray(wLocation);
1294 glVertexAttribDivisor(wLocation, 1);
1295
1296 const uint8_t* zeroOffset = nullptr;
1297
1298 // Test touching the last element is valid.
1299 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1300 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1301 ASSERT_GL_NO_ERROR();
1302
1303 // Test touching the last element + 1 is invalid.
1304 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1305 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1306 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1307
1308 // Test touching the last element is valid, using a stride.
1309 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1310 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1311 ASSERT_GL_NO_ERROR();
1312
1313 // Test touching the last element + 1 is invalid, using a stride.
1314 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1315 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1316 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1317
1318 // Test any offset is valid if no vertices are drawn.
1319 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1320 glDrawArraysInstanced(GL_POINTS, 0, 0, 1);
1321 ASSERT_GL_NO_ERROR();
1322
1323 // Test any offset is valid if no primitives are drawn.
1324 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1325 glDrawArraysInstanced(GL_POINTS, 0, 1, 0);
1326 ASSERT_GL_NO_ERROR();
1327}
1328
1329// Test the checks for OOB reads in the vertex buffers, ANGLE_instanced_arrays version
1330TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsInstancedANGLE)
1331{
1332 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_ANGLE_instanced_arrays"));
1333 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
1334 EXPECT_GL_NO_ERROR();
1335
1336 const std::string &vert =
1337 "attribute float a_pos;\n"
1338 "attribute float a_w;\n"
1339 "void main()\n"
1340 "{\n"
1341 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1342 "}\n";
1343
1344 const std::string &frag =
1345 "precision highp float;\n"
1346 "void main()\n"
1347 "{\n"
1348 " gl_FragColor = vec4(1.0);\n"
1349 "}\n";
1350
1351 ANGLE_GL_PROGRAM(program, vert, frag);
1352 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1353 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
1354 ASSERT_NE(-1, posLocation);
1355 ASSERT_NE(-1, wLocation);
1356 glUseProgram(program.get());
1357
1358 GLBuffer buffer;
1359 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1360 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1361
1362 glEnableVertexAttribArray(posLocation);
1363 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1364 glVertexAttribDivisorANGLE(posLocation, 0);
1365
1366 glEnableVertexAttribArray(wLocation);
1367 glVertexAttribDivisorANGLE(wLocation, 1);
1368
1369 const uint8_t* zeroOffset = nullptr;
1370
1371 // Test touching the last element is valid.
1372 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1373 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1374 ASSERT_GL_NO_ERROR();
1375
1376 // Test touching the last element + 1 is invalid.
1377 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1378 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1379 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1380
1381 // Test touching the last element is valid, using a stride.
1382 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1383 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1384 ASSERT_GL_NO_ERROR();
1385
1386 // Test touching the last element + 1 is invalid, using a stride.
1387 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1388 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1389 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1390
1391 // Test any offset is valid if no vertices are drawn.
1392 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1393 glDrawArraysInstancedANGLE(GL_POINTS, 0, 0, 1);
1394 ASSERT_GL_NO_ERROR();
1395
1396 // Test any offset is valid if no primitives are drawn.
1397 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1398 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 0);
1399 ASSERT_GL_NO_ERROR();
Corentin Wallezfd456442016-12-21 17:57:00 -05001400}
1401
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001402// Test the checks for OOB reads in the index buffer
1403TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
Geoff Lang5f319a42017-01-09 16:49:19 -05001404{
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001405 const std::string &vert =
1406 "attribute float a_pos;\n"
1407 "void main()\n"
1408 "{\n"
1409 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1410 "}\n";
Geoff Lang5f319a42017-01-09 16:49:19 -05001411
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001412 const std::string &frag =
1413 "precision highp float;\n"
1414 "void main()\n"
1415 "{\n"
1416 " gl_FragColor = vec4(1.0);\n"
1417 "}\n";
1418
1419 ANGLE_GL_PROGRAM(program, vert, frag);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001420 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1421 ASSERT_NE(-1, posLocation);
1422 glUseProgram(program.get());
1423
1424 GLBuffer vertexBuffer;
1425 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1426 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1427
1428 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001429 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001430
1431 const uint8_t *zeroOffset = nullptr;
1432 const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
1433
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001434 GLBuffer indexBuffer;
1435 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1436 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
Geoff Lang5f319a42017-01-09 16:49:19 -05001437 ASSERT_GL_NO_ERROR();
1438
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001439 // Test touching the last index is valid
1440 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1441 ASSERT_GL_NO_ERROR();
Geoff Lang5f319a42017-01-09 16:49:19 -05001442
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001443 // Test touching the last + 1 element is invalid
1444 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
1445 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang5f319a42017-01-09 16:49:19 -05001446
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001447 // Test any offset if valid if count is zero
1448 glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
1449 ASSERT_GL_NO_ERROR();
Corentin Wallezfe9306a2017-02-01 17:41:05 -05001450
1451 // Test touching the first index is valid
1452 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1453 ASSERT_GL_NO_ERROR();
1454
1455 // Test touching the first - 1 index is invalid
1456 // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was
1457 // the historic behavior of WebGL implementations
1458 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1);
1459 EXPECT_GL_ERROR(GL_INVALID_VALUE);
Geoff Lang5f319a42017-01-09 16:49:19 -05001460}
1461
Corentin Wallez91c8de82017-10-12 16:32:44 -04001462// Test the checks for OOB in vertex buffers caused by indices, non-instanced version
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001463TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInVertexBuffer)
1464{
1465 const std::string &vert =
1466 "attribute float a_pos;\n"
1467 "void main()\n"
1468 "{\n"
1469 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1470 "}\n";
1471
1472 const std::string &frag =
1473 "precision highp float;\n"
1474 "void main()\n"
1475 "{\n"
1476 " gl_FragColor = vec4(1.0);\n"
1477 "}\n";
1478
1479 ANGLE_GL_PROGRAM(program, vert, frag);
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001480 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1481 ASSERT_NE(-1, posLocation);
1482 glUseProgram(program.get());
1483
1484 GLBuffer vertexBuffer;
1485 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1486 glBufferData(GL_ARRAY_BUFFER, 8, nullptr, GL_STATIC_DRAW);
1487
1488 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001489 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001490
1491 const uint8_t *zeroOffset = nullptr;
1492 const uint8_t testIndices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 255};
1493
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001494 GLBuffer indexBuffer;
1495 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1496 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(testIndices), testIndices, GL_STATIC_DRAW);
1497 ASSERT_GL_NO_ERROR();
1498
1499 // Test touching the end of the vertex buffer is valid
1500 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 7);
1501 ASSERT_GL_NO_ERROR();
1502
1503 // Test touching just after the end of the vertex buffer is invalid
1504 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 8);
1505 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1506
1507 // Test touching the whole vertex buffer is valid
1508 glDrawElements(GL_POINTS, 8, GL_UNSIGNED_BYTE, zeroOffset + 0);
1509 ASSERT_GL_NO_ERROR();
1510
1511 // Test an index that would be negative
1512 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 9);
1513 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1514}
1515
Frank Henigman6137ddc2017-02-10 18:55:07 -05001516// Test depth range with 'near' more or less than 'far.'
1517TEST_P(WebGLCompatibilityTest, DepthRange)
1518{
1519 glDepthRangef(0, 1);
1520 ASSERT_GL_NO_ERROR();
1521
1522 glDepthRangef(.5, .5);
1523 ASSERT_GL_NO_ERROR();
1524
1525 glDepthRangef(1, 0);
1526 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1527}
1528
Frank Henigman146e8a12017-03-02 23:22:37 -05001529// Test all blend function combinations.
1530// In WebGL it is invalid to combine constant color with constant alpha.
1531TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
1532{
1533 constexpr GLenum srcFunc[] = {
1534 GL_ZERO,
1535 GL_ONE,
1536 GL_SRC_COLOR,
1537 GL_ONE_MINUS_SRC_COLOR,
1538 GL_DST_COLOR,
1539 GL_ONE_MINUS_DST_COLOR,
1540 GL_SRC_ALPHA,
1541 GL_ONE_MINUS_SRC_ALPHA,
1542 GL_DST_ALPHA,
1543 GL_ONE_MINUS_DST_ALPHA,
1544 GL_CONSTANT_COLOR,
1545 GL_ONE_MINUS_CONSTANT_COLOR,
1546 GL_CONSTANT_ALPHA,
1547 GL_ONE_MINUS_CONSTANT_ALPHA,
1548 GL_SRC_ALPHA_SATURATE,
1549 };
1550
1551 constexpr GLenum dstFunc[] = {
1552 GL_ZERO, GL_ONE,
1553 GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
1554 GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
1555 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1556 GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
1557 GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
1558 GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
1559 };
1560
1561 for (GLenum src : srcFunc)
1562 {
1563 for (GLenum dst : dstFunc)
1564 {
1565 glBlendFunc(src, dst);
1566 CheckBlendFunctions(src, dst);
1567 glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE);
1568 CheckBlendFunctions(src, dst);
1569 }
1570 }
1571}
1572
Geoff Langfc32e8b2017-05-31 14:16:59 -04001573// Test that binding/querying uniforms and attributes with invalid names generates errors
1574TEST_P(WebGLCompatibilityTest, InvalidAttributeAndUniformNames)
1575{
1576 const std::string validAttribName =
1577 "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1578 const std::string validUniformName =
1579 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
Geoff Langa71a98e2017-06-19 15:15:00 -04001580 std::vector<char> invalidSet = {'"', '$', '`', '@', '\''};
1581 if (getClientMajorVersion() < 3)
1582 {
1583 invalidSet.push_back('\\');
1584 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04001585
1586 std::string vert = "attribute float ";
1587 vert += validAttribName;
1588 vert +=
1589 ";\n"
1590 "void main()\n"
1591 "{\n"
1592 " gl_Position = vec4(1.0);\n"
1593 "}\n";
1594
1595 std::string frag =
1596 "precision highp float;\n"
1597 "uniform vec4 ";
1598 frag += validUniformName;
Geoff Langcab92ee2017-07-19 17:32:07 -04001599 // Insert illegal characters into comments
Geoff Langfc32e8b2017-05-31 14:16:59 -04001600 frag +=
1601 ";\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001602 " // $ \" @ /*\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001603 "void main()\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001604 "{/*\n"
1605 " ` @ $\n"
1606 " */gl_FragColor = vec4(1.0);\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001607 "}\n";
1608
1609 ANGLE_GL_PROGRAM(program, vert, frag);
1610 EXPECT_GL_NO_ERROR();
1611
1612 for (char invalidChar : invalidSet)
1613 {
1614 std::string invalidName = validAttribName + invalidChar;
1615 glGetAttribLocation(program, invalidName.c_str());
1616 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1617 << "glGetAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1618
1619 glBindAttribLocation(program, 0, invalidName.c_str());
1620 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1621 << "glBindAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1622 }
1623
1624 for (char invalidChar : invalidSet)
1625 {
1626 std::string invalidName = validUniformName + invalidChar;
1627 glGetUniformLocation(program, invalidName.c_str());
1628 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1629 << "glGetUniformLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1630 }
1631
1632 for (char invalidChar : invalidSet)
1633 {
1634 std::string invalidAttribName = validAttribName + invalidChar;
1635 const char *invalidVert[] = {
1636 "attribute float ",
1637 invalidAttribName.c_str(),
1638 ";\n",
1639 "void main()\n",
1640 "{\n",
1641 " gl_Position = vec4(1.0);\n",
1642 "}\n",
1643 };
1644
1645 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1646 glShaderSource(shader, static_cast<GLsizei>(ArraySize(invalidVert)), invalidVert, nullptr);
1647 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1648 glDeleteShader(shader);
1649 }
1650}
1651
Geoff Langcab92ee2017-07-19 17:32:07 -04001652// Test that line continuation is handled correctly when valdiating shader source
Bryan Bernhart (Intel Americas Inc)335d8bf2017-10-23 15:41:43 -07001653TEST_P(WebGLCompatibilityTest, ShaderSourceLineContinuation)
1654{
1655 // Verify that a line continuation character (i.e. backslash) cannot be used
1656 // within a preprocessor directive in a ES2 context.
1657 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1658
1659 const char *validVert =
1660 "#define foo this is a test\n"
1661 "precision mediump float;\n"
1662 "void main()\n"
1663 "{\n"
1664 " gl_Position = vec4(1.0);\n"
1665 "}\n";
1666
1667 const char *invalidVert =
1668 "#define foo this \\n"
1669 " is a test\n"
1670 "precision mediump float;\n"
1671 "void main()\n"
1672 "{\n"
1673 " gl_Position = vec4(1.0);\n"
1674 "}\n";
1675
1676 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1677 glShaderSource(shader, 1, &validVert, nullptr);
1678 EXPECT_GL_NO_ERROR();
1679
1680 glShaderSource(shader, 1, &invalidVert, nullptr);
1681 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1682 glDeleteShader(shader);
1683}
1684
1685// Test that line continuation is handled correctly when valdiating shader source
Geoff Langcab92ee2017-07-19 17:32:07 -04001686TEST_P(WebGL2CompatibilityTest, ShaderSourceLineContinuation)
1687{
1688 const char *validVert =
1689 "#version 300 es\n"
1690 "precision mediump float;\n"
1691 "\n"
1692 "void main ()\n"
1693 "{\n"
1694 " float f\\\n"
1695 "oo = 1.0;\n"
1696 " gl_Position = vec4(foo);\n"
1697 "}\n";
1698
1699 const char *invalidVert =
1700 "#version 300 es\n"
1701 "precision mediump float;\n"
1702 "\n"
1703 "void main ()\n"
1704 "{\n"
1705 " float f\\$\n"
1706 "oo = 1.0;\n"
1707 " gl_Position = vec4(foo);\n"
1708 "}\n";
1709
1710 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1711 glShaderSource(shader, 1, &validVert, nullptr);
1712 EXPECT_GL_NO_ERROR();
1713 glShaderSource(shader, 1, &invalidVert, nullptr);
1714 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1715 glDeleteShader(shader);
1716}
1717
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001718// Tests bindAttribLocations for reserved prefixes and length limits
1719TEST_P(WebGLCompatibilityTest, BindAttribLocationLimitation)
1720{
1721 constexpr int maxLocStringLength = 256;
1722 const std::string tooLongString(maxLocStringLength + 1, '_');
1723
1724 glBindAttribLocation(0, 0, "_webgl_var");
1725
1726 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1727
1728 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
1729
1730 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1731}
1732
Corentin Wallez0dc97812017-06-22 14:38:44 -04001733// Test that having no attributes with a zero divisor is valid in WebGL2
Geoff Lang407d4e72017-04-12 14:54:11 -04001734TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor)
1735{
1736 const std::string &vert =
1737 "attribute float a_pos;\n"
1738 "void main()\n"
1739 "{\n"
1740 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1741 "}\n";
1742
1743 const std::string &frag =
1744 "precision highp float;\n"
1745 "void main()\n"
1746 "{\n"
1747 " gl_FragColor = vec4(1.0);\n"
1748 "}\n";
1749
1750 ANGLE_GL_PROGRAM(program, vert, frag);
1751
1752 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1753 ASSERT_NE(-1, posLocation);
1754
1755 glUseProgram(program.get());
1756
1757 GLBuffer buffer;
1758 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1759 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1760
1761 glEnableVertexAttribArray(posLocation);
1762 glVertexAttribDivisor(posLocation, 1);
1763
Geoff Lang407d4e72017-04-12 14:54:11 -04001764 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
1765 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
Geoff Lang407d4e72017-04-12 14:54:11 -04001766 ASSERT_GL_NO_ERROR();
1767}
1768
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001769// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
1770TEST_P(WebGLCompatibilityTest, NPOT)
1771{
1772 EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
1773
1774 // Create a texture and set an NPOT mip 0, should always be acceptable.
1775 GLTexture texture;
1776 glBindTexture(GL_TEXTURE_2D, texture.get());
1777 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1778 ASSERT_GL_NO_ERROR();
1779
1780 // Try setting an NPOT mip 1 and verify the error if WebGL 1
1781 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1782 if (getClientMajorVersion() < 3)
1783 {
1784 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1785 }
1786 else
1787 {
1788 ASSERT_GL_NO_ERROR();
1789 }
1790
1791 if (extensionRequestable("GL_OES_texture_npot"))
1792 {
1793 glRequestExtensionANGLE("GL_OES_texture_npot");
1794 ASSERT_GL_NO_ERROR();
1795
1796 // Try again to set NPOT mip 1
1797 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1798 ASSERT_GL_NO_ERROR();
1799 }
1800}
1801
Jamie Madillcad97ee2017-02-02 18:52:44 -05001802template <typename T>
1803void FillTexture2D(GLuint texture,
1804 GLsizei width,
1805 GLsizei height,
1806 const T &onePixelData,
1807 GLint level,
1808 GLint internalFormat,
1809 GLenum format,
1810 GLenum type)
1811{
1812 std::vector<T> allPixelsData(width * height, onePixelData);
1813
1814 glBindTexture(GL_TEXTURE_2D, texture);
1815 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
1816 allPixelsData.data());
1817 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1818 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1819 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1820 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1821}
1822
Frank Henigman875bbba2017-02-08 16:38:17 -05001823// Test that unset gl_Position defaults to (0,0,0,0).
1824TEST_P(WebGLCompatibilityTest, DefaultPosition)
1825{
1826 // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set,
1827 // and green otherwise. The center of each quadrant will be red if and only if all
1828 // four corners are red.
1829 const std::string vertexShader =
1830 "attribute vec3 pos;\n"
1831 "varying vec4 color;\n"
1832 "void main() {\n"
1833 " if (gl_Position == vec4(0,0,0,0)) {\n"
1834 " color = vec4(1,0,0,1);\n"
1835 " } else {\n"
1836 " color = vec4(0,1,0,1);\n"
1837 " }\n"
1838 " gl_Position = vec4(pos,1);\n"
1839 "}\n";
1840
1841 const std::string fragmentShader =
1842 "precision mediump float;\n"
1843 "varying vec4 color;\n"
1844 "void main() {\n"
1845 " gl_FragColor = color;\n"
1846 "}\n";
1847
1848 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1849 drawQuad(program.get(), "pos", 0.0f, 1.0f, true);
1850 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1851 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1852 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1853 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1854}
1855
Jamie Madilla4595b82017-01-11 17:36:34 -05001856// Tests that a rendering feedback loop triggers a GL error under WebGL.
1857// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
1858TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
1859{
1860 const std::string vertexShader =
1861 "attribute vec4 a_position;\n"
1862 "varying vec2 v_texCoord;\n"
1863 "void main() {\n"
1864 " gl_Position = a_position;\n"
1865 " v_texCoord = (a_position.xy * 0.5) + 0.5;\n"
1866 "}\n";
1867
1868 const std::string fragmentShader =
1869 "precision mediump float;\n"
1870 "varying vec2 v_texCoord;\n"
1871 "uniform sampler2D u_texture;\n"
1872 "void main() {\n"
1873 " // Shader swizzles color channels so we can tell if the draw succeeded.\n"
1874 " gl_FragColor = texture2D(u_texture, v_texCoord).gbra;\n"
1875 "}\n";
1876
1877 GLTexture texture;
Jamie Madillcad97ee2017-02-02 18:52:44 -05001878 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05001879
1880 ASSERT_GL_NO_ERROR();
1881
1882 GLFramebuffer framebuffer;
1883 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1884 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1885
1886 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1887
1888 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1889
1890 GLint uniformLoc = glGetUniformLocation(program.get(), "u_texture");
1891 ASSERT_NE(-1, uniformLoc);
1892
1893 glUseProgram(program.get());
1894 glUniform1i(uniformLoc, 0);
1895 glDisable(GL_BLEND);
1896 glDisable(GL_DEPTH_TEST);
1897 ASSERT_GL_NO_ERROR();
1898
1899 // Drawing with a texture that is also bound to the current framebuffer should fail
1900 glBindTexture(GL_TEXTURE_2D, texture.get());
1901 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1902 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1903
1904 // Ensure that the texture contents did not change after the previous render
1905 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1906 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1907 ASSERT_GL_NO_ERROR();
1908 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1909
1910 // Drawing when texture is bound to an inactive uniform should succeed
1911 GLTexture texture2;
Jamie Madillcad97ee2017-02-02 18:52:44 -05001912 FillTexture2D(texture2.get(), 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05001913
1914 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1915 glActiveTexture(GL_TEXTURE1);
1916 glBindTexture(GL_TEXTURE_2D, texture.get());
1917 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1918 ASSERT_GL_NO_ERROR();
1919 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1920}
1921
Bryan Bernhart58806562017-01-05 13:09:31 -08001922// Test for the max draw buffers and color attachments.
1923TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
1924{
1925 // This test only applies to ES2.
1926 if (getClientMajorVersion() != 2)
1927 {
1928 return;
1929 }
1930
1931 GLFramebuffer fbo[2];
1932 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0].get());
1933
1934 // Test that is valid when we bind with a single attachment point.
1935 GLTexture texture;
1936 glBindTexture(GL_TEXTURE_2D, texture.get());
1937 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1938 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1939 ASSERT_GL_NO_ERROR();
1940
1941 // Test that enabling the draw buffers extension will allow us to bind with a non-zero
1942 // attachment point.
1943 if (extensionRequestable("GL_EXT_draw_buffers"))
1944 {
1945 glRequestExtensionANGLE("GL_EXT_draw_buffers");
1946 EXPECT_GL_NO_ERROR();
1947 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
1948
1949 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1].get());
1950
1951 GLTexture texture2;
1952 glBindTexture(GL_TEXTURE_2D, texture2.get());
1953 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1954 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2.get(),
1955 0);
1956 ASSERT_GL_NO_ERROR();
1957 }
1958}
1959
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05001960// Test that the offset in the index buffer is forced to be a multiple of the element size
1961TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction)
1962{
1963 const std::string &vert =
1964 "attribute vec3 a_pos;\n"
1965 "void main()\n"
1966 "{\n"
1967 " gl_Position = vec4(a_pos, 1.0);\n"
1968 "}\n";
1969
1970 const std::string &frag =
1971 "precision highp float;\n"
1972 "void main()\n"
1973 "{\n"
1974 " gl_FragColor = vec4(1.0);\n"
1975 "}\n";
1976
1977 ANGLE_GL_PROGRAM(program, vert, frag);
1978
1979 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1980 ASSERT_NE(-1, posLocation);
1981 glUseProgram(program.get());
1982
1983 const auto &vertices = GetQuadVertices();
1984
1985 GLBuffer vertexBuffer;
1986 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1987 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1988 GL_STATIC_DRAW);
1989
1990 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1991 glEnableVertexAttribArray(posLocation);
1992
1993 GLBuffer indexBuffer;
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001994 const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0, 0};
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05001995 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1996 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
1997
1998 ASSERT_GL_NO_ERROR();
1999
2000 const char *zeroIndices = nullptr;
2001
2002 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices);
2003 ASSERT_GL_NO_ERROR();
2004
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002005 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002006 ASSERT_GL_NO_ERROR();
2007
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002008 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices + 1);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002009 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2010}
2011
2012// Test that the offset and stride in the vertex buffer is forced to be a multiple of the element
2013// size
2014TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction)
2015{
2016 const char *zeroOffset = nullptr;
2017
2018 // Base case, vector of two floats
2019 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset);
2020 ASSERT_GL_NO_ERROR();
2021
2022 // Test setting a non-multiple offset
2023 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1);
2024 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2025 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2);
2026 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2027 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3);
2028 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2029
2030 // Test setting a non-multiple stride
2031 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset);
2032 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2033 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset);
2034 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2035 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset);
2036 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2037}
2038
Jamie Madillcad97ee2017-02-02 18:52:44 -05002039void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program,
2040 const std::array<GLenum, 2> &drawBuffers,
2041 GLenum expectedError)
2042{
2043 glDrawBuffersEXT(2, drawBuffers.data());
2044
2045 // Make sure framebuffer is complete before feedback loop detection
2046 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2047
2048 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2049
2050 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2051 // it should be NO_ERROR"
2052 EXPECT_GL_ERROR(expectedError);
2053}
2054
2055// This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers.
2056// Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html
2057TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT)
2058{
2059 const std::string vertexShader =
2060 "attribute vec4 aPosition;\n"
2061 "varying vec2 texCoord;\n"
2062 "void main() {\n"
2063 " gl_Position = aPosition;\n"
2064 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2065 "}\n";
2066
2067 const std::string fragmentShader =
2068 "#extension GL_EXT_draw_buffers : require\n"
2069 "precision mediump float;\n"
2070 "uniform sampler2D tex;\n"
2071 "varying vec2 texCoord;\n"
2072 "void main() {\n"
2073 " gl_FragData[0] = texture2D(tex, texCoord);\n"
2074 " gl_FragData[1] = texture2D(tex, texCoord);\n"
2075 "}\n";
2076
2077 GLsizei width = 8;
2078 GLsizei height = 8;
2079
2080 // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers
2081 // extension and gl_FragData semantics are changed to enforce indexing by zero always.
2082 // TODO(jmadill): This extension should be disabled in WebGL 2 contexts.
2083 if (/*!extensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2)
2084 {
2085 // No WEBGL_draw_buffers support -- this is legal.
2086 return;
2087 }
2088
2089 GLint maxDrawBuffers = 0;
2090 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2091
2092 if (maxDrawBuffers < 2)
2093 {
2094 std::cout << "Test skipped because MAX_DRAW_BUFFERS is too small." << std::endl;
2095 return;
2096 }
2097
2098 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2099 glUseProgram(program.get());
2100 glViewport(0, 0, width, height);
2101
2102 GLTexture tex0;
2103 GLTexture tex1;
2104 GLFramebuffer fbo;
2105 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2106 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2107 ASSERT_GL_NO_ERROR();
2108
2109 glBindTexture(GL_TEXTURE_2D, tex1.get());
2110 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2111 ASSERT_NE(-1, texLoc);
2112 glUniform1i(texLoc, 0);
2113 ASSERT_GL_NO_ERROR();
2114
2115 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
2116 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2117 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2118 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
2119
2120 drawBuffersEXTFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}},
2121 GL_INVALID_OPERATION);
2122 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
2123 GL_INVALID_OPERATION);
2124 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
2125}
2126
Jamie Madill07be8bf2017-02-02 19:59:57 -05002127// Test tests that texture copying feedback loops are properly rejected in WebGL.
2128// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
2129TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
2130{
2131 GLTexture texture;
2132 glBindTexture(GL_TEXTURE_2D, texture.get());
2133 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2138
2139 GLTexture texture2;
2140 glBindTexture(GL_TEXTURE_2D, texture2.get());
2141 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2143 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2146
2147 GLFramebuffer framebuffer;
2148 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2149 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2150
2151 // framebuffer should be FRAMEBUFFER_COMPLETE.
2152 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2153 ASSERT_GL_NO_ERROR();
2154
2155 // testing copyTexImage2D
2156
2157 // copyTexImage2D to same texture but different level
2158 glBindTexture(GL_TEXTURE_2D, texture.get());
2159 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
2160 EXPECT_GL_NO_ERROR();
2161
2162 // copyTexImage2D to same texture same level, invalid feedback loop
2163 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2164 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2165
2166 // copyTexImage2D to different texture
2167 glBindTexture(GL_TEXTURE_2D, texture2.get());
2168 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2169 EXPECT_GL_NO_ERROR();
2170
2171 // testing copyTexSubImage2D
2172
2173 // copyTexSubImage2D to same texture but different level
2174 glBindTexture(GL_TEXTURE_2D, texture.get());
2175 glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
2176 EXPECT_GL_NO_ERROR();
2177
2178 // copyTexSubImage2D to same texture same level, invalid feedback loop
2179 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2180 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2181
2182 // copyTexSubImage2D to different texture
2183 glBindTexture(GL_TEXTURE_2D, texture2.get());
2184 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2185 EXPECT_GL_NO_ERROR();
2186}
2187
2188void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program,
2189 const std::array<GLenum, 2> &drawBuffers,
2190 GLenum expectedError)
2191{
2192 glDrawBuffers(2, drawBuffers.data());
2193
2194 // Make sure framebuffer is complete before feedback loop detection
2195 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2196
2197 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2198
2199 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2200 // it should be NO_ERROR"
2201 EXPECT_GL_ERROR(expectedError);
2202}
2203
Yuly Novikov817232e2017-02-22 18:36:10 -05002204// Tests invariance matching rules between built in varyings.
2205// Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html.
2206TEST_P(WebGLCompatibilityTest, BuiltInInvariant)
2207{
2208 const std::string vertexShaderVariant =
2209 "varying vec4 v_varying;\n"
2210 "void main()\n"
2211 "{\n"
2212 " gl_PointSize = 1.0;\n"
2213 " gl_Position = v_varying;\n"
2214 "}";
2215 const std::string fragmentShaderInvariantGlFragCoord =
2216 "invariant gl_FragCoord;\n"
2217 "void main()\n"
2218 "{\n"
2219 " gl_FragColor = gl_FragCoord;\n"
2220 "}";
2221 const std::string fragmentShaderInvariantGlPointCoord =
2222 "invariant gl_PointCoord;\n"
2223 "void main()\n"
2224 "{\n"
2225 " gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);\n"
2226 "}";
2227
2228 GLuint program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlFragCoord);
2229 EXPECT_EQ(0u, program);
2230
2231 program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlPointCoord);
2232 EXPECT_EQ(0u, program);
2233}
2234
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04002235// Tests global namespace conflicts between uniforms and attributes.
2236// Based on WebGL test conformance/glsl/misc/shaders-with-name-conflicts.html.
2237TEST_P(WebGLCompatibilityTest, GlobalNamesConflict)
2238{
2239 const std::string vertexShader =
2240 "attribute vec4 foo;\n"
2241 "void main()\n"
2242 "{\n"
2243 " gl_Position = foo;\n"
2244 "}";
2245 const std::string fragmentShader =
2246 "precision mediump float;\n"
2247 "uniform vec4 foo;\n"
2248 "void main()\n"
2249 "{\n"
2250 " gl_FragColor = foo;\n"
2251 "}";
2252
2253 GLuint program = CompileProgram(vertexShader, fragmentShader);
2254 EXPECT_EQ(0u, program);
2255}
2256
Geoff Lang966c9402017-04-18 12:38:27 -04002257// Test dimension and image size validation of compressed textures
2258TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
2259{
2260 if (extensionRequestable("GL_EXT_texture_compression_dxt1"))
2261 {
2262 glRequestExtensionANGLE("GL_EXT_texture_compression_dxt1");
2263 }
2264
2265 if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
2266 {
2267 std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available."
2268 << std::endl;
2269 return;
2270 }
2271
2272 constexpr uint8_t CompressedImageDXT1[] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
2273
2274 GLTexture texture;
2275 glBindTexture(GL_TEXTURE_2D, texture);
2276
2277 // Regular case, verify that it works
2278 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2279 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2280 ASSERT_GL_NO_ERROR();
2281
2282 // Test various dimensions that are not valid
2283 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3, 4, 0,
2284 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2285 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2286
2287 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 3, 0,
2288 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2289 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2290
2291 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2292 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2293 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2294
2295 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2296 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2297 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2298
2299 // Test various image sizes that are not valid
2300 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2301 sizeof(CompressedImageDXT1) - 1, CompressedImageDXT1);
2302 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2303
2304 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2305 sizeof(CompressedImageDXT1) + 1, CompressedImageDXT1);
2306 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2307
2308 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 0,
2309 CompressedImageDXT1);
2310 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2311
2312 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0, 0,
2313 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2314 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2315
2316 // Fill a full mip chain and verify that it works
2317 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2318 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2319 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2320 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2321 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2322 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2323 ASSERT_GL_NO_ERROR();
2324
2325 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2326 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2327 ASSERT_GL_NO_ERROR();
2328
2329 // Test that non-block size sub-uploads are not valid for the 0 mip
2330 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2331 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2332 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2333
2334 // Test that non-block size sub-uploads are valid for if they fill the whole mip
2335 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2336 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2337 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, 1, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2338 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2339 ASSERT_GL_NO_ERROR();
2340
2341 // Test that if the format miss-matches the texture, an error is generated
2342 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
2343 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2344 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2345}
2346
Geoff Lang677bb6f2017-04-05 12:40:40 -04002347TEST_P(WebGLCompatibilityTest, L32FTextures)
2348{
2349 constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f};
2350 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 1.0f};
2351
2352 for (auto extension : FloatingPointTextureExtensions)
2353 {
2354 if (strlen(extension) > 0 && extensionRequestable(extension))
2355 {
2356 glRequestExtensionANGLE(extension);
2357 ASSERT_GL_NO_ERROR();
2358 }
2359
2360 // Unsized L 32F
2361 {
2362 bool texture = extensionEnabled("GL_OES_texture_float");
2363 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2364 bool render = false;
2365 TestFloatTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, texture, filter, render,
2366 textureData, readPixelData);
2367 }
2368
2369 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2370 {
2371 // Sized L 32F
2372 bool texture = extensionEnabled("GL_OES_texture_float") &&
2373 extensionEnabled("GL_EXT_texture_storage");
2374 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2375 bool render = false;
2376 TestFloatTextureFormat(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT, texture, filter,
2377 render, textureData, readPixelData);
2378 }
2379 }
2380}
2381
2382TEST_P(WebGLCompatibilityTest, A32FTextures)
2383{
2384 constexpr float textureData[] = {33.33f, 0.0f, 0.0f, 0.0f};
2385 constexpr float readPixelData[] = {0.0f, 0.0f, 0.0f, textureData[0]};
2386
2387 for (auto extension : FloatingPointTextureExtensions)
2388 {
2389 if (strlen(extension) > 0 && extensionRequestable(extension))
2390 {
2391 glRequestExtensionANGLE(extension);
2392 ASSERT_GL_NO_ERROR();
2393 }
2394
2395 // Unsized A 32F
2396 {
2397 bool texture = extensionEnabled("GL_OES_texture_float");
2398 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2399 bool render = false;
2400 TestFloatTextureFormat(GL_ALPHA, GL_ALPHA, GL_FLOAT, texture, filter, render,
2401 textureData, readPixelData);
2402 }
2403
2404 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2405 {
2406 // Sized A 32F
2407 bool texture = extensionEnabled("GL_OES_texture_float") &&
2408 extensionEnabled("GL_EXT_texture_storage");
2409 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2410 bool render = false;
2411 TestFloatTextureFormat(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT, texture, filter, render,
2412 textureData, readPixelData);
2413 }
2414 }
2415}
2416
2417TEST_P(WebGLCompatibilityTest, LA32FTextures)
2418{
2419 constexpr float textureData[] = {-0.21f, 15.1f, 0.0f, 0.0f};
2420 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0],
2421 textureData[1]};
2422
2423 for (auto extension : FloatingPointTextureExtensions)
2424 {
2425 if (strlen(extension) > 0 && extensionRequestable(extension))
2426 {
2427 glRequestExtensionANGLE(extension);
2428 ASSERT_GL_NO_ERROR();
2429 }
2430
2431 // Unsized LA 32F
2432 {
2433 bool texture = extensionEnabled("GL_OES_texture_float");
2434 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2435 bool render = false;
2436 TestFloatTextureFormat(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2437 filter, render, textureData, readPixelData);
2438 }
2439
2440 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2441 {
2442 // Sized LA 32F
2443 bool texture = extensionEnabled("GL_OES_texture_float") &&
2444 extensionEnabled("GL_EXT_texture_storage");
2445 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2446 bool render = false;
2447 TestFloatTextureFormat(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2448 filter, render, textureData, readPixelData);
2449 }
2450 }
2451}
2452
2453TEST_P(WebGLCompatibilityTest, R32FTextures)
2454{
2455 constexpr float data[] = {1000.0f, 0.0f, 0.0f, 1.0f};
2456
2457 for (auto extension : FloatingPointTextureExtensions)
2458 {
2459 if (strlen(extension) > 0 && extensionRequestable(extension))
2460 {
2461 glRequestExtensionANGLE(extension);
2462 ASSERT_GL_NO_ERROR();
2463 }
2464
2465 // Unsized R 32F
2466 {
2467 bool texture =
2468 extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg");
2469 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2470 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2471 TestFloatTextureFormat(GL_RED, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2472 }
2473
2474 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2475 {
2476 // Sized R 32F
2477 bool texture =
2478 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2479 extensionEnabled("GL_EXT_texture_rg") &&
2480 extensionEnabled("GL_EXT_texture_storage"));
2481 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2482 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2483 TestFloatTextureFormat(GL_R32F, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2484 }
2485 }
2486}
2487
2488TEST_P(WebGLCompatibilityTest, RG32FTextures)
2489{
2490 constexpr float data[] = {1000.0f, -0.001f, 0.0f, 1.0f};
2491
2492 for (auto extension : FloatingPointTextureExtensions)
2493 {
2494 if (strlen(extension) > 0 && extensionRequestable(extension))
2495 {
2496 glRequestExtensionANGLE(extension);
2497 ASSERT_GL_NO_ERROR();
2498 }
2499
2500 // Unsized RG 32F
2501 {
2502 bool texture =
2503 (extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg"));
2504 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2505 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2506 TestFloatTextureFormat(GL_RG, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2507 }
2508
2509 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2510 {
2511 // Sized RG 32F
2512 bool texture =
2513 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2514 extensionEnabled("GL_EXT_texture_rg") &&
2515 extensionEnabled("GL_EXT_texture_storage"));
2516 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2517 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2518 TestFloatTextureFormat(GL_RG32F, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2519 }
2520 }
2521}
2522
2523TEST_P(WebGLCompatibilityTest, RGB32FTextures)
2524{
Geoff Lang40762ef2017-05-08 13:47:03 -04002525 if (IsLinux() && IsIntel())
2526 {
2527 std::cout << "Test skipped on Linux Intel." << std::endl;
2528 return;
2529 }
2530
Geoff Lang677bb6f2017-04-05 12:40:40 -04002531 constexpr float data[] = {1000.0f, -500.0f, 10.0f, 1.0f};
2532
2533 for (auto extension : FloatingPointTextureExtensions)
2534 {
2535 if (strlen(extension) > 0 && extensionRequestable(extension))
2536 {
2537 glRequestExtensionANGLE(extension);
2538 ASSERT_GL_NO_ERROR();
2539 }
2540
2541 // Unsized RGB 32F
2542 {
2543 bool texture = extensionEnabled("GL_OES_texture_float");
2544 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2545 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2546 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_FLOAT, texture, filter, render, data, data);
2547 }
2548
2549 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2550 {
2551 // Sized RGBA 32F
2552 bool texture =
2553 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2554 extensionEnabled("GL_EXT_texture_storage"));
2555 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2556 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2557 TestFloatTextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT, texture, filter, render, data,
2558 data);
2559 }
2560 }
2561}
2562
2563TEST_P(WebGLCompatibilityTest, RGBA32FTextures)
2564{
2565 constexpr float data[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2566
2567 for (auto extension : FloatingPointTextureExtensions)
2568 {
2569 if (strlen(extension) > 0 && extensionRequestable(extension))
2570 {
2571 glRequestExtensionANGLE(extension);
2572 ASSERT_GL_NO_ERROR();
2573 }
2574
2575 // Unsized RGBA 32F
2576 {
2577 bool texture = extensionEnabled("GL_OES_texture_float");
2578 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2579 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2580 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2581 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_FLOAT, texture, filter, render, data, data);
2582 }
2583
2584 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2585 {
2586 // Sized RGBA 32F
2587 bool texture =
2588 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2589 extensionEnabled("GL_EXT_texture_storage"));
2590 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2591 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2592 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2593 TestFloatTextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT, texture, filter, render, data,
2594 data);
2595 }
2596 }
2597}
2598
2599TEST_P(WebGLCompatibilityTest, R16FTextures)
2600{
2601 constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
2602 const GLushort textureData[] = {
2603 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2604 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2605
2606 for (auto extension : FloatingPointTextureExtensions)
2607 {
2608 if (strlen(extension) > 0 && extensionRequestable(extension))
2609 {
2610 glRequestExtensionANGLE(extension);
2611 ASSERT_GL_NO_ERROR();
2612 }
2613
2614 // Unsized R 16F (OES)
2615 {
2616 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2617 extensionEnabled("GL_EXT_texture_rg");
2618 bool filter = getClientMajorVersion() >= 3 ||
2619 extensionEnabled("GL_OES_texture_half_float_linear");
2620 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2621 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render,
2622 textureData, readPixelsData);
2623 }
2624
2625 // Unsized R 16F
2626 {
2627 bool texture = false;
2628 bool filter = false;
2629 bool render = false;
2630 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2631 textureData, readPixelsData);
2632 }
2633
2634 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2635 {
2636 // Sized R 16F
2637 bool texture = getClientMajorVersion() >= 3;
2638 bool filter = getClientMajorVersion() >= 3 ||
2639 extensionEnabled("GL_OES_texture_half_float_linear");
2640 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2641 extensionEnabled("GL_EXT_color_buffer_float");
2642 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2643 textureData, readPixelsData);
2644 }
2645 }
2646}
2647
2648TEST_P(WebGLCompatibilityTest, RG16FTextures)
2649{
2650 constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f};
2651 const GLushort textureData[] = {
2652 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2653 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2654
2655 for (auto extension : FloatingPointTextureExtensions)
2656 {
2657 if (strlen(extension) > 0 && extensionRequestable(extension))
2658 {
2659 glRequestExtensionANGLE(extension);
2660 ASSERT_GL_NO_ERROR();
2661 }
2662
2663 // Unsized RG 16F (OES)
2664 {
2665 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2666 extensionEnabled("GL_EXT_texture_rg");
2667 bool filter = getClientMajorVersion() >= 3 ||
2668 extensionEnabled("GL_OES_texture_half_float_linear");
2669 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") &&
2670 extensionEnabled("GL_EXT_texture_rg");
2671 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render,
2672 textureData, readPixelsData);
2673 }
2674
2675 // Unsized RG 16F
2676 {
2677 bool texture = false;
2678 bool filter = false;
2679 bool render = false;
2680 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2681 textureData, readPixelsData);
2682 }
2683
2684 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2685 {
2686 // Sized RG 16F
2687 bool texture = getClientMajorVersion() >= 3;
2688 bool filter = getClientMajorVersion() >= 3 ||
2689 extensionEnabled("GL_OES_texture_half_float_linear");
2690 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2691 extensionEnabled("GL_EXT_color_buffer_float");
2692 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2693 textureData, readPixelsData);
2694 }
2695 }
2696}
2697
2698TEST_P(WebGLCompatibilityTest, RGB16FTextures)
2699{
Geoff Lang40762ef2017-05-08 13:47:03 -04002700 if (IsOzone() && IsIntel())
2701 {
2702 std::cout << "Test skipped on Intel Ozone." << std::endl;
2703 return;
2704 }
2705
Geoff Lang677bb6f2017-04-05 12:40:40 -04002706 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f};
2707 const GLushort textureData[] = {
2708 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2709 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2710
2711 for (auto extension : FloatingPointTextureExtensions)
2712 {
2713 if (strlen(extension) > 0 && extensionRequestable(extension))
2714 {
2715 glRequestExtensionANGLE(extension);
2716 ASSERT_GL_NO_ERROR();
2717 }
2718
2719 // Unsized RGB 16F (OES)
2720 {
2721 bool texture = extensionEnabled("GL_OES_texture_half_float");
2722 bool filter = getClientMajorVersion() >= 3 ||
2723 extensionEnabled("GL_OES_texture_half_float_linear");
2724 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2725 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render,
2726 textureData, readPixelsData);
2727 }
2728
2729 // Unsized RGB 16F
2730 {
2731 bool texture = false;
2732 bool filter = false;
2733 bool render = false;
2734 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2735 textureData, readPixelsData);
2736 }
2737
2738 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2739 {
2740 // Sized RGB 16F
2741 bool texture = getClientMajorVersion() >= 3;
2742 bool filter = getClientMajorVersion() >= 3 ||
2743 extensionEnabled("GL_OES_texture_half_float_linear");
2744 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2745 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2746 textureData, readPixelsData);
2747 }
2748 }
2749}
2750
2751TEST_P(WebGLCompatibilityTest, RGBA16FTextures)
2752{
Geoff Lang40762ef2017-05-08 13:47:03 -04002753 if (IsOzone() && IsIntel())
2754 {
2755 std::cout << "Test skipped on Intel Ozone." << std::endl;
2756 return;
2757 }
2758
Geoff Lang677bb6f2017-04-05 12:40:40 -04002759 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2760 const GLushort textureData[] = {
2761 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2762 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2763
2764 for (auto extension : FloatingPointTextureExtensions)
2765 {
2766 if (strlen(extension) > 0 && extensionRequestable(extension))
2767 {
2768 glRequestExtensionANGLE(extension);
2769 ASSERT_GL_NO_ERROR();
2770 }
2771
2772 // Unsized RGBA 16F (OES)
2773 {
2774 bool texture = extensionEnabled("GL_OES_texture_half_float");
2775 bool filter = getClientMajorVersion() >= 3 ||
2776 extensionEnabled("GL_OES_texture_half_float_linear");
2777 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2778 extensionEnabled("GL_EXT_color_buffer_float");
2779 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render,
2780 textureData, readPixelsData);
2781 }
2782
2783 // Unsized RGBA 16F
2784 {
2785 bool texture = false;
2786 bool filter = false;
2787 bool render = false;
2788 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2789 textureData, readPixelsData);
2790 }
2791
2792 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2793 {
2794 // Sized RGBA 16F
2795 bool texture = getClientMajorVersion() >= 3;
2796 bool filter = getClientMajorVersion() >= 3 ||
2797 extensionEnabled("GL_OES_texture_half_float_linear");
2798 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2799 extensionEnabled("GL_EXT_color_buffer_float");
2800 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2801 textureData, readPixelsData);
2802 }
2803 }
2804}
2805
Geoff Lang6e898aa2017-06-02 11:17:26 -04002806// Test that when GL_CHROMIUM_color_buffer_float_rgb[a] is enabled, sized GL_RGB[A]_32F formats are
2807// accepted by glTexImage2D
2808TEST_P(WebGLCompatibilityTest, SizedRGBA32FFormats)
2809{
2810 if (getClientMajorVersion() != 2)
2811 {
2812 std::cout << "Test skipped because it is only valid for WebGL1 contexts." << std::endl;
2813 return;
2814 }
2815
2816 if (!extensionRequestable("GL_OES_texture_float"))
2817 {
2818 std::cout << "Test skipped because GL_OES_texture_float is not requestable." << std::endl;
2819 return;
2820 }
2821 glRequestExtensionANGLE("GL_OES_texture_float");
2822 ASSERT_GL_NO_ERROR();
2823
2824 GLTexture texture;
2825 glBindTexture(GL_TEXTURE_2D, texture);
2826
2827 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2828 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2829
2830 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2831 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2832
2833 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgba"))
2834 {
2835 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgba");
2836 ASSERT_GL_NO_ERROR();
2837
2838 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2839 EXPECT_GL_NO_ERROR();
2840 }
2841
2842 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgb"))
2843 {
2844 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgb");
2845 ASSERT_GL_NO_ERROR();
2846
2847 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2848 EXPECT_GL_NO_ERROR();
2849 }
2850}
2851
Jamie Madill07be8bf2017-02-02 19:59:57 -05002852// This tests that rendering feedback loops works as expected with WebGL 2.
2853// Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html
2854TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers)
2855{
2856 const std::string vertexShader =
2857 "#version 300 es\n"
2858 "in vec4 aPosition;\n"
2859 "out vec2 texCoord;\n"
2860 "void main() {\n"
2861 " gl_Position = aPosition;\n"
2862 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2863 "}\n";
2864
2865 const std::string fragmentShader =
2866 "#version 300 es\n"
2867 "precision mediump float;\n"
2868 "uniform sampler2D tex;\n"
2869 "in vec2 texCoord;\n"
2870 "out vec4 oColor;\n"
2871 "void main() {\n"
2872 " oColor = texture(tex, texCoord);\n"
2873 "}\n";
2874
2875 GLsizei width = 8;
2876 GLsizei height = 8;
2877
2878 GLint maxDrawBuffers = 0;
2879 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2880 // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS.
2881 ASSERT_GE(maxDrawBuffers, 2);
2882
2883 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2884 glUseProgram(program.get());
2885 glViewport(0, 0, width, height);
2886
2887 GLTexture tex0;
2888 GLTexture tex1;
2889 GLFramebuffer fbo;
2890 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2891 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2892 ASSERT_GL_NO_ERROR();
2893
2894 glBindTexture(GL_TEXTURE_2D, tex1.get());
2895 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2896 ASSERT_NE(-1, texLoc);
2897 glUniform1i(texLoc, 0);
2898
2899 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
2900 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2901 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2902 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
2903 ASSERT_GL_NO_ERROR();
2904
2905 drawBuffersFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION);
2906 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
2907 GL_INVALID_OPERATION);
2908 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
2909}
2910
Jamie Madill1d37bc52017-02-02 19:59:58 -05002911// This test covers detection of rendering feedback loops between the FBO and a depth Texture.
2912// Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html
2913TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil)
2914{
2915 const std::string vertexShader =
2916 "#version 300 es\n"
2917 "in vec4 aPosition;\n"
2918 "out vec2 texCoord;\n"
2919 "void main() {\n"
2920 " gl_Position = aPosition;\n"
2921 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2922 "}\n";
2923
2924 const std::string fragmentShader =
2925 "#version 300 es\n"
2926 "precision mediump float;\n"
2927 "uniform sampler2D tex;\n"
2928 "in vec2 texCoord;\n"
2929 "out vec4 oColor;\n"
2930 "void main() {\n"
2931 " oColor = texture(tex, texCoord);\n"
2932 "}\n";
2933
2934 GLsizei width = 8;
2935 GLsizei height = 8;
2936
2937 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2938 glUseProgram(program.get());
2939
2940 glViewport(0, 0, width, height);
2941
2942 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2943 glUniform1i(texLoc, 0);
2944
2945 // Create textures and allocate storage
2946 GLTexture tex0;
2947 GLTexture tex1;
2948 GLRenderbuffer rb;
2949 FillTexture2D(tex0.get(), width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2950 FillTexture2D(tex1.get(), width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
2951 GL_UNSIGNED_INT);
2952 glBindRenderbuffer(GL_RENDERBUFFER, rb.get());
2953 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
2954 ASSERT_GL_NO_ERROR();
2955
2956 GLFramebuffer fbo;
2957 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2958 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2959
2960 // Test rendering and sampling feedback loop for depth buffer
2961 glBindTexture(GL_TEXTURE_2D, tex1.get());
2962 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1.get(), 0);
2963 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2964
2965 // The same image is used as depth buffer during rendering.
2966 glEnable(GL_DEPTH_TEST);
2967 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2968 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2969
2970 // The same image is used as depth buffer. But depth mask is false.
2971 glDepthMask(GL_FALSE);
2972 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2973 EXPECT_GL_NO_ERROR();
2974
2975 // The same image is used as depth buffer. But depth test is not enabled during rendering.
2976 glDepthMask(GL_TRUE);
2977 glDisable(GL_DEPTH_TEST);
2978 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2979 EXPECT_GL_NO_ERROR();
2980
2981 // Test rendering and sampling feedback loop for stencil buffer
2982 glBindTexture(GL_RENDERBUFFER, rb.get());
2983 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
2984 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb.get());
2985 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2986 constexpr GLint stencilClearValue = 0x40;
2987 glClearBufferiv(GL_STENCIL, 0, &stencilClearValue);
2988
2989 // The same image is used as stencil buffer during rendering.
2990 glEnable(GL_STENCIL_TEST);
2991 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2992 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2993
2994 // The same image is used as stencil buffer. But stencil mask is zero.
2995 glStencilMask(0x0);
2996 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2997 EXPECT_GL_NO_ERROR();
2998
2999 // The same image is used as stencil buffer. But stencil test is not enabled during rendering.
3000 glStencilMask(0xffff);
3001 glDisable(GL_STENCIL_TEST);
3002 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3003 EXPECT_GL_NO_ERROR();
3004}
3005
Jamie Madillfd3dd432017-02-02 19:59:59 -05003006// The source and the target for CopyTexSubImage3D are the same 3D texture.
3007// But the level of the 3D texture != the level of the read attachment.
3008TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels)
3009{
3010 GLTexture texture;
3011 GLFramebuffer framebuffer;
3012
3013 glBindTexture(GL_TEXTURE_3D, texture.get());
3014 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3015
3016 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3017 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3018 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
3019 ASSERT_GL_NO_ERROR();
3020
3021 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3022 EXPECT_GL_NO_ERROR();
3023}
3024
3025// The source and the target for CopyTexSubImage3D are the same 3D texture.
3026// But the zoffset of the 3D texture != the layer of the read attachment.
3027TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers)
3028{
3029 GLTexture texture;
3030 GLFramebuffer framebuffer;
3031
3032 glBindTexture(GL_TEXTURE_3D, texture.get());
3033 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3034
3035 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3036 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 1);
3037 ASSERT_GL_NO_ERROR();
3038
3039 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2);
3040 EXPECT_GL_NO_ERROR();
3041}
3042
3043// The source and the target for CopyTexSubImage3D are the same 3D texture.
3044// And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment.
3045TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D)
3046{
3047 GLTexture texture;
3048 GLFramebuffer framebuffer;
3049
3050 glBindTexture(GL_TEXTURE_3D, texture.get());
3051 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3052
3053 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3054 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3055 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3056 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 1, 0);
3057 ASSERT_GL_NO_ERROR();
3058
3059 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3060 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3061}
3062
Corentin Wallez59c41592017-07-11 13:19:54 -04003063// Verify that errors are generated when there isn't a defined conversion between the clear type and
3064// the buffer type.
Geoff Lang76e65652017-03-27 14:58:02 -04003065TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity)
3066{
3067 if (IsD3D11())
3068 {
3069 std::cout << "Test skipped because it generates D3D11 runtime warnings." << std::endl;
3070 return;
3071 }
3072
3073 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3074 constexpr int clearInt[] = {0, 0, 0, 0};
3075 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3076
3077 GLTexture texture;
3078 GLFramebuffer framebuffer;
3079
3080 glBindTexture(GL_TEXTURE_2D, texture.get());
3081 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3082
3083 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
3084 ASSERT_GL_NO_ERROR();
3085
3086 // Unsigned integer buffer
3087 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr);
3088 ASSERT_GL_NO_ERROR();
3089
3090 glClearBufferfv(GL_COLOR, 0, clearFloat);
3091 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3092
3093 glClearBufferiv(GL_COLOR, 0, clearInt);
3094 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3095
3096 glClearBufferuiv(GL_COLOR, 0, clearUint);
3097 EXPECT_GL_NO_ERROR();
3098
3099 glClear(GL_COLOR_BUFFER_BIT);
3100 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3101
3102 // Integer buffer
3103 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr);
3104 ASSERT_GL_NO_ERROR();
3105
3106 glClearBufferfv(GL_COLOR, 0, clearFloat);
3107 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3108
3109 glClearBufferiv(GL_COLOR, 0, clearInt);
3110 EXPECT_GL_NO_ERROR();
3111
3112 glClearBufferuiv(GL_COLOR, 0, clearUint);
3113 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3114
3115 glClear(GL_COLOR_BUFFER_BIT);
3116 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3117
3118 // Float buffer
Geoff Lang677bb6f2017-04-05 12:40:40 -04003119 if (extensionRequestable("GL_EXT_color_buffer_float"))
3120 {
3121 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3122 }
Geoff Lang76e65652017-03-27 14:58:02 -04003123
Geoff Lang677bb6f2017-04-05 12:40:40 -04003124 if (extensionEnabled("GL_EXT_color_buffer_float"))
3125 {
3126 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
3127 ASSERT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003128
Geoff Lang677bb6f2017-04-05 12:40:40 -04003129 glClearBufferfv(GL_COLOR, 0, clearFloat);
3130 EXPECT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003131
Geoff Lang677bb6f2017-04-05 12:40:40 -04003132 glClearBufferiv(GL_COLOR, 0, clearInt);
3133 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang76e65652017-03-27 14:58:02 -04003134
Geoff Lang677bb6f2017-04-05 12:40:40 -04003135 glClearBufferuiv(GL_COLOR, 0, clearUint);
3136 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3137
3138 glClear(GL_COLOR_BUFFER_BIT);
3139 EXPECT_GL_NO_ERROR();
3140 }
Geoff Lang76e65652017-03-27 14:58:02 -04003141
3142 // Normalized uint buffer
3143 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3144 ASSERT_GL_NO_ERROR();
3145
3146 glClearBufferfv(GL_COLOR, 0, clearFloat);
3147 EXPECT_GL_NO_ERROR();
3148
3149 glClearBufferiv(GL_COLOR, 0, clearInt);
3150 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3151
3152 glClearBufferuiv(GL_COLOR, 0, clearUint);
3153 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3154
3155 glClear(GL_COLOR_BUFFER_BIT);
3156 EXPECT_GL_NO_ERROR();
3157}
3158
Corentin Wallez59c41592017-07-11 13:19:54 -04003159// Test the interaction of WebGL compatibility clears with default framebuffers
3160TEST_P(WebGL2CompatibilityTest, ClearBufferDefaultFramebuffer)
3161{
3162 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3163 constexpr int clearInt[] = {0, 0, 0, 0};
3164 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3165
3166 // glClear works as usual, this is also a regression test for a bug where we
3167 // iterated on maxDrawBuffers for default framebuffers, triggering an assert
3168 glClear(GL_COLOR_BUFFER_BIT);
3169 EXPECT_GL_NO_ERROR();
3170
3171 // Default framebuffers are normalized uints, so only glClearBufferfv works.
3172 glClearBufferfv(GL_COLOR, 0, clearFloat);
3173 EXPECT_GL_NO_ERROR();
3174
3175 glClearBufferiv(GL_COLOR, 0, clearInt);
3176 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3177
3178 glClearBufferuiv(GL_COLOR, 0, clearUint);
3179 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3180}
3181
Geoff Lange4915782017-04-12 15:19:07 -04003182// Verify that errors are generate when trying to blit from an image to itself
3183TEST_P(WebGL2CompatibilityTest, BlitFramebufferSameImage)
3184{
3185 GLTexture textures[2];
3186 glBindTexture(GL_TEXTURE_2D, textures[0]);
3187 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3188 glBindTexture(GL_TEXTURE_2D, textures[1]);
3189 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3190
3191 GLRenderbuffer renderbuffers[2];
3192 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
3193 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3194 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
3195 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3196
3197 GLFramebuffer framebuffers[2];
3198 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]);
3199 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]);
3200
3201 ASSERT_GL_NO_ERROR();
3202
3203 // Same texture
3204 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3205 0);
3206 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3207 0);
3208 ASSERT_GL_NO_ERROR();
3209 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3210 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3211
3212 // Same textures but different renderbuffers
3213 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3214 renderbuffers[0]);
3215 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3216 renderbuffers[1]);
3217 ASSERT_GL_NO_ERROR();
3218 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3219 ASSERT_GL_NO_ERROR();
3220 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3221 GL_NEAREST);
3222 ASSERT_GL_NO_ERROR();
3223 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3224 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3225 GL_NEAREST);
3226 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3227
3228 // Same renderbuffers but different textures
3229 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3230 0);
3231 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1],
3232 0);
3233 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3234 renderbuffers[0]);
3235 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3236 renderbuffers[0]);
3237 ASSERT_GL_NO_ERROR();
3238 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3239 ASSERT_GL_NO_ERROR();
3240 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3241 GL_NEAREST);
3242 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3243 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3244 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3245 GL_NEAREST);
3246 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3247}
3248
Geoff Lange0cff192017-05-30 13:04:56 -04003249// Verify that errors are generated when the fragment shader output doesn't match the bound color
3250// buffer types
3251TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch)
3252{
3253 const std::string vertexShader =
3254 "#version 300 es\n"
3255 "void main() {\n"
3256 " gl_Position = vec4(0, 0, 0, 1);\n"
3257 "}\n";
3258
3259 const std::string fragmentShader =
3260 "#version 300 es\n"
3261 "precision mediump float;\n"
3262 "layout(location = 0) out vec4 floatOutput;\n"
3263 "layout(location = 1) out uvec4 uintOutput;\n"
3264 "layout(location = 2) out ivec4 intOutput;\n"
3265 "void main() {\n"
3266 " floatOutput = vec4(0, 0, 0, 1);\n"
3267 " uintOutput = uvec4(0, 0, 0, 1);\n"
3268 " intOutput = ivec4(0, 0, 0, 1);\n"
3269 "}\n";
3270
3271 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3272 glUseProgram(program.get());
3273
3274 GLuint floatLocation = glGetFragDataLocation(program, "floatOutput");
3275 GLuint uintLocation = glGetFragDataLocation(program, "uintOutput");
3276 GLuint intLocation = glGetFragDataLocation(program, "intOutput");
3277
3278 GLFramebuffer fbo;
3279 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3280
3281 GLRenderbuffer floatRenderbuffer;
3282 glBindRenderbuffer(GL_RENDERBUFFER, floatRenderbuffer);
3283 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
3284 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3285 floatRenderbuffer);
3286
3287 GLRenderbuffer uintRenderbuffer;
3288 glBindRenderbuffer(GL_RENDERBUFFER, uintRenderbuffer);
3289 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 1, 1);
3290 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3291 uintRenderbuffer);
3292
3293 GLRenderbuffer intRenderbuffer;
3294 glBindRenderbuffer(GL_RENDERBUFFER, intRenderbuffer);
3295 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 1, 1);
3296 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3297 intRenderbuffer);
3298
3299 ASSERT_GL_NO_ERROR();
3300
3301 GLint maxDrawBuffers = 0;
3302 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3303 std::vector<GLenum> drawBuffers(static_cast<size_t>(maxDrawBuffers), GL_NONE);
3304 drawBuffers[floatLocation] = GL_COLOR_ATTACHMENT0 + floatLocation;
3305 drawBuffers[uintLocation] = GL_COLOR_ATTACHMENT0 + uintLocation;
3306 drawBuffers[intLocation] = GL_COLOR_ATTACHMENT0 + intLocation;
3307
3308 glDrawBuffers(maxDrawBuffers, drawBuffers.data());
3309
3310 // Check that the correct case generates no errors
3311 glDrawArrays(GL_TRIANGLES, 0, 6);
3312 EXPECT_GL_NO_ERROR();
3313
3314 // Unbind some buffers and verify that there are still no errors
3315 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3316 0);
3317 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3318 0);
3319 glDrawArrays(GL_TRIANGLES, 0, 6);
3320 EXPECT_GL_NO_ERROR();
3321
3322 // Swap the int and uint buffers to and verify that an error is generated
3323 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3324 intRenderbuffer);
3325 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3326 uintRenderbuffer);
3327 glDrawArrays(GL_TRIANGLES, 0, 6);
3328 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3329
3330 // Swap the float and uint buffers to and verify that an error is generated
3331 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3332 floatRenderbuffer);
3333 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3334 uintRenderbuffer);
3335 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3336 intRenderbuffer);
3337 glDrawArrays(GL_TRIANGLES, 0, 6);
3338 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3339}
3340
Geoff Lang9ab5b822017-05-30 16:19:23 -04003341// Verify that errors are generated when the vertex shader intput doesn't match the bound attribute
3342// types
Corentin Wallezc3bc9842017-10-11 15:15:59 -04003343TEST_P(WebGL2CompatibilityTest, VertexShaderAttributeTypeMismatch)
Geoff Lang9ab5b822017-05-30 16:19:23 -04003344{
3345 const std::string vertexShader =
3346 "#version 300 es\n"
3347 "in vec4 floatInput;\n"
3348 "in uvec4 uintInput;\n"
3349 "in ivec4 intInput;\n"
3350 "void main() {\n"
3351 " gl_Position = vec4(floatInput.x, uintInput.x, intInput.x, 1);\n"
3352 "}\n";
3353
3354 const std::string fragmentShader =
3355 "#version 300 es\n"
3356 "precision mediump float;\n"
3357 "out vec4 outputColor;\n"
3358 "void main() {\n"
3359 " outputColor = vec4(0, 0, 0, 1);"
3360 "}\n";
3361
3362 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3363 glUseProgram(program.get());
3364
3365 GLint floatLocation = glGetAttribLocation(program, "floatInput");
3366 GLint uintLocation = glGetAttribLocation(program, "uintInput");
3367 GLint intLocation = glGetAttribLocation(program, "intInput");
3368
3369 // Default attributes are of float types
3370 glDrawArrays(GL_TRIANGLES, 0, 6);
3371 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3372
3373 // Set the default attributes to the correct types, should succeed
3374 glVertexAttribI4ui(uintLocation, 0, 0, 0, 1);
3375 glVertexAttribI4i(intLocation, 0, 0, 0, 1);
3376 glDrawArrays(GL_TRIANGLES, 0, 6);
3377 EXPECT_GL_NO_ERROR();
3378
3379 // Change the default float attribute to an integer, should fail
3380 glVertexAttribI4ui(floatLocation, 0, 0, 0, 1);
3381 glDrawArrays(GL_TRIANGLES, 0, 6);
3382 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3383
3384 // Use a buffer for some attributes
3385 GLBuffer buffer;
3386 glBindBuffer(GL_ARRAY_BUFFER, buffer);
3387 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
3388 glEnableVertexAttribArray(floatLocation);
3389 glVertexAttribPointer(floatLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3390 glDrawArrays(GL_TRIANGLES, 0, 6);
3391 EXPECT_GL_NO_ERROR();
3392
3393 // Use a float pointer attrib for a uint input
3394 glEnableVertexAttribArray(uintLocation);
3395 glVertexAttribPointer(uintLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3396 glDrawArrays(GL_TRIANGLES, 0, 6);
3397 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3398
3399 // Use a uint pointer for the uint input
3400 glVertexAttribIPointer(uintLocation, 4, GL_UNSIGNED_INT, 0, nullptr);
3401 glDrawArrays(GL_TRIANGLES, 0, 6);
3402 EXPECT_GL_NO_ERROR();
3403}
3404
Corentin Walleze7557742017-06-01 13:09:57 -04003405// Tests the WebGL removal of undefined behavior when attachments aren't written to.
3406TEST_P(WebGLCompatibilityTest, DrawBuffers)
3407{
Corentin Walleze7557742017-06-01 13:09:57 -04003408 // Make sure we can use at least 4 attachments for the tests.
3409 bool useEXT = false;
3410 if (getClientMajorVersion() < 3)
3411 {
3412 if (!extensionRequestable("GL_EXT_draw_buffers"))
3413 {
3414 std::cout << "Test skipped because draw buffers are not available" << std::endl;
3415 return;
3416 }
3417
3418 glRequestExtensionANGLE("GL_EXT_draw_buffers");
3419 useEXT = true;
3420 EXPECT_GL_NO_ERROR();
3421 }
3422
3423 GLint maxDrawBuffers = 0;
3424 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3425 if (maxDrawBuffers < 4)
3426 {
3427 std::cout << "Test skipped because MAX_DRAW_BUFFERS is too small." << std::endl;
3428 return;
3429 }
3430
3431 // Clears all the renderbuffers to red.
3432 auto ClearEverythingToRed = [](GLRenderbuffer *renderbuffers) {
3433 GLFramebuffer clearFBO;
3434 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, clearFBO);
3435
3436 glClearColor(1, 0, 0, 1);
3437 for (int i = 0; i < 4; ++i)
3438 {
3439 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
3440 renderbuffers[i]);
3441 glClear(GL_COLOR_BUFFER_BIT);
3442 }
3443 ASSERT_GL_NO_ERROR();
3444 };
3445
3446 // Checks that the renderbuffers specified by mask have the correct color
3447 auto CheckColors = [](GLRenderbuffer *renderbuffers, int mask, GLColor color) {
3448 GLFramebuffer readFBO;
3449 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
3450
3451 for (int i = 0; i < 4; ++i)
3452 {
3453 if (mask & (1 << i))
3454 {
3455 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3456 GL_RENDERBUFFER, renderbuffers[i]);
3457 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
3458 }
3459 }
3460 ASSERT_GL_NO_ERROR();
3461 };
3462
3463 // Depending on whether we are using the extension or ES3, a different entrypoint must be called
3464 auto DrawBuffers = [](bool useEXT, int numBuffers, GLenum *buffers) {
3465 if (useEXT)
3466 {
3467 glDrawBuffersEXT(numBuffers, buffers);
3468 }
3469 else
3470 {
3471 glDrawBuffers(numBuffers, buffers);
3472 }
3473 };
3474
3475 // Initialized the test framebuffer
3476 GLFramebuffer drawFBO;
3477 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3478
3479 GLRenderbuffer renderbuffers[4];
3480 for (int i = 0; i < 4; ++i)
3481 {
3482 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
Geoff Langd84a00b2017-10-27 17:27:26 -04003483 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
Corentin Walleze7557742017-06-01 13:09:57 -04003484 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER,
3485 renderbuffers[i]);
3486 }
3487
3488 ASSERT_GL_NO_ERROR();
3489
3490 const char *vertESSL1 =
3491 "attribute vec4 a_pos;\n"
3492 "void main()\n"
3493 "{\n"
3494 " gl_Position = a_pos;\n"
3495 "}\n";
3496 const char *vertESSL3 =
3497 "#version 300 es\n"
3498 "in vec4 a_pos;\n"
3499 "void main()\n"
3500 "{\n"
3501 " gl_Position = a_pos;\n"
3502 "}\n";
3503
3504 GLenum allDrawBuffers[] = {
3505 GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3506 };
3507
3508 GLenum halfDrawBuffers[] = {
3509 GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3510 };
3511
3512 // Test that when using gl_FragColor, only the first attachment is written to.
3513 const char *fragESSL1 =
3514 "precision highp float;\n"
3515 "void main()\n"
3516 "{\n"
3517 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3518 "}\n";
3519 ANGLE_GL_PROGRAM(programESSL1, vertESSL1, fragESSL1);
3520
3521 {
3522 ClearEverythingToRed(renderbuffers);
3523
3524 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3525 DrawBuffers(useEXT, 4, allDrawBuffers);
3526 drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
3527 ASSERT_GL_NO_ERROR();
3528
3529 CheckColors(renderbuffers, 0b0001, GLColor::green);
3530 CheckColors(renderbuffers, 0b1110, GLColor::red);
3531 }
3532
3533 // Test that when using gl_FragColor, but the first draw buffer is 0, then no attachment is
3534 // written to.
3535 {
3536 ClearEverythingToRed(renderbuffers);
3537
3538 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3539 DrawBuffers(useEXT, 4, halfDrawBuffers);
3540 drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
3541 ASSERT_GL_NO_ERROR();
3542
3543 CheckColors(renderbuffers, 0b1111, GLColor::red);
3544 }
3545
3546 // Test what happens when rendering to a subset of the outputs. There is a behavior difference
3547 // between the extension and ES3. In the extension gl_FragData is implicitly declared as an
3548 // array of size MAX_DRAW_BUFFERS, so the WebGL spec stipulates that elements not written to
3549 // should default to 0. On the contrary, in ES3 outputs are specified one by one, so
3550 // attachments not declared in the shader should not be written to.
3551 const char *writeOddOutputsVert;
3552 const char *writeOddOutputsFrag;
3553 GLColor unwrittenColor;
3554 if (useEXT)
3555 {
3556 // In the extension, when an attachment isn't written to, it should get 0's
3557 unwrittenColor = GLColor(0, 0, 0, 0);
3558 writeOddOutputsVert = vertESSL1;
3559 writeOddOutputsFrag =
3560 "#extension GL_EXT_draw_buffers : require\n"
3561 "precision highp float;\n"
3562 "void main()\n"
3563 "{\n"
3564 " gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3565 " gl_FragData[3] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3566 "}\n";
3567 }
3568 else
3569 {
3570 // In ES3 if an attachment isn't declared, it shouldn't get written and should be red
3571 // because of the preceding clears.
3572 unwrittenColor = GLColor::red;
3573 writeOddOutputsVert = vertESSL3;
3574 writeOddOutputsFrag =
3575 "#version 300 es\n"
3576 "precision highp float;\n"
3577 "layout(location = 1) out vec4 output1;"
3578 "layout(location = 3) out vec4 output2;"
3579 "void main()\n"
3580 "{\n"
3581 " output1 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3582 " output2 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3583 "}\n";
3584 }
3585 ANGLE_GL_PROGRAM(writeOddOutputsProgram, writeOddOutputsVert, writeOddOutputsFrag);
3586
3587 // Test that attachments not written to get the "unwritten" color
3588 {
3589 ClearEverythingToRed(renderbuffers);
3590
3591 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3592 DrawBuffers(useEXT, 4, allDrawBuffers);
3593 drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
3594 ASSERT_GL_NO_ERROR();
3595
3596 CheckColors(renderbuffers, 0b1010, GLColor::green);
3597 CheckColors(renderbuffers, 0b0101, unwrittenColor);
3598 }
3599
3600 // Test that attachments not written to get the "unwritten" color but that even when the
3601 // extension is used, disabled attachments are not written at all and stay red.
3602 {
3603 ClearEverythingToRed(renderbuffers);
3604
3605 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3606 DrawBuffers(useEXT, 4, halfDrawBuffers);
3607 drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
3608 ASSERT_GL_NO_ERROR();
3609
3610 CheckColors(renderbuffers, 0b1000, GLColor::green);
3611 CheckColors(renderbuffers, 0b0100, unwrittenColor);
3612 CheckColors(renderbuffers, 0b0011, GLColor::red);
3613 }
3614}
3615
Geoff Lang536eca12017-09-13 11:23:35 -04003616// Test that it's possible to generate mipmaps on unsized floating point textures once the
3617// extensions have been enabled
3618TEST_P(WebGLCompatibilityTest, GenerateMipmapUnsizedFloatingPointTexture)
3619{
3620 if (extensionRequestable("GL_OES_texture_float"))
3621 {
3622 glRequestExtensionANGLE("GL_OES_texture_float");
3623 }
3624 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3625
3626 GLTexture texture;
3627 glBindTexture(GL_TEXTURE_2D, texture);
3628
3629 constexpr GLColor32F data[4] = {
3630 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3631 };
3632 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_FLOAT, data);
3633 ASSERT_GL_NO_ERROR();
3634
3635 glGenerateMipmap(GL_TEXTURE_2D);
3636 EXPECT_GL_NO_ERROR();
3637}
3638// Test that it's possible to generate mipmaps on unsized floating point textures once the
3639// extensions have been enabled
3640TEST_P(WebGLCompatibilityTest, GenerateMipmapSizedFloatingPointTexture)
3641{
3642 if (extensionRequestable("GL_OES_texture_float"))
3643 {
3644 glRequestExtensionANGLE("GL_OES_texture_float");
3645 }
3646 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3647
3648 if (extensionRequestable("GL_EXT_texture_storage"))
3649 {
3650 glRequestExtensionANGLE("GL_EXT_texture_storage");
3651 }
3652 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_storage"));
3653
3654 GLTexture texture;
3655 glBindTexture(GL_TEXTURE_2D, texture);
3656
3657 constexpr GLColor32F data[4] = {
3658 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3659 };
3660 glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA32F, 2, 2);
3661 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, data);
3662 ASSERT_GL_NO_ERROR();
3663
3664 glGenerateMipmap(GL_TEXTURE_2D);
3665 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3666
3667 if (extensionRequestable("GL_EXT_color_buffer_float"))
3668 {
3669 // Format is renderable but not filterable
3670 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3671 glGenerateMipmap(GL_TEXTURE_2D);
3672 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3673 }
3674
3675 if (extensionRequestable("GL_EXT_color_buffer_float_linear"))
3676 {
3677 // Format is renderable but not filterable
3678 glRequestExtensionANGLE("GL_EXT_color_buffer_float_linear");
3679
3680 if (extensionEnabled("GL_EXT_color_buffer_float"))
3681 {
3682 // Format is filterable and renderable
3683 glGenerateMipmap(GL_TEXTURE_2D);
3684 EXPECT_GL_NO_ERROR();
3685 }
3686 else
3687 {
3688 // Format is filterable but not renderable
3689 glGenerateMipmap(GL_TEXTURE_2D);
3690 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3691 }
3692 }
3693}
3694
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003695// Verify that a texture format is only allowed with extension enabled.
3696void WebGLCompatibilityTest::validateTexImageExtensionFormat(GLenum format,
3697 const std::string &extName)
3698{
3699 // Verify texture format fails by default.
3700 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
3701 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3702
3703 if (extensionRequestable(extName))
3704 {
3705 // Verify texture format is allowed once extension is enabled.
3706 glRequestExtensionANGLE(extName.c_str());
3707 EXPECT_TRUE(extensionEnabled(extName));
3708
3709 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
3710 ASSERT_GL_NO_ERROR();
3711 }
3712}
3713
Geoff Lang86f81162017-10-30 15:10:45 -04003714// Test enabling various non-compressed texture format extensions
3715TEST_P(WebGLCompatibilityTest, EnableTextureFormatExtensions)
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003716{
Geoff Lang2c5c41f2017-10-31 10:58:09 -04003717 ANGLE_SKIP_TEST_IF(IsOzone());
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003718 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
3719
3720 GLTexture texture;
3721 glBindTexture(GL_TEXTURE_2D, texture.get());
3722
3723 // Verify valid format is allowed.
3724 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3725 ASSERT_GL_NO_ERROR();
3726
3727 // Verify invalid format fails.
3728 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA32F, GL_UNSIGNED_BYTE, nullptr);
3729 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3730
3731 // Verify formats from enableable extensions.
Geoff Lang660b28c2017-10-30 12:58:56 -04003732 if (!IsOpenGLES())
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003733 {
3734 validateTexImageExtensionFormat(GL_RED_EXT, "GL_EXT_texture_rg");
3735 }
3736
3737 validateTexImageExtensionFormat(GL_SRGB_EXT, "GL_EXT_texture_sRGB");
3738 validateTexImageExtensionFormat(GL_BGRA_EXT, "GL_EXT_texture_format_BGRA8888");
3739}
3740
Geoff Lang86f81162017-10-30 15:10:45 -04003741void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum format,
3742 GLsizei width,
3743 GLsizei height,
3744 GLsizei blockSize,
3745 const std::string &extName,
3746 bool subImageAllowed)
3747{
3748 std::vector<GLubyte> data(blockSize, 0u);
3749
3750 GLTexture texture;
3751 glBindTexture(GL_TEXTURE_2D, texture.get());
3752
3753 // Verify texture format fails by default.
3754 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
3755 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3756
3757 if (extensionRequestable(extName))
3758 {
3759 // Verify texture format is allowed once extension is enabled.
3760 glRequestExtensionANGLE(extName.c_str());
3761 EXPECT_TRUE(extensionEnabled(extName));
3762
3763 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
3764 EXPECT_GL_NO_ERROR();
3765
3766 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, blockSize,
3767 data.data());
3768 if (subImageAllowed)
3769 {
3770 EXPECT_GL_NO_ERROR();
3771 }
3772 else
3773 {
3774 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3775 }
3776 }
3777}
3778
3779// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT
3780TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB)
3781{
3782 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8,
3783 "GL_EXT_texture_compression_dxt1", true);
3784}
3785
3786// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
3787TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGBA)
3788{
3789 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8,
3790 "GL_EXT_texture_compression_dxt1", true);
3791}
3792
3793// Test enabling GL_ANGLE_texture_compression_dxt3
3794TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3)
3795{
3796 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 16,
3797 "GL_ANGLE_texture_compression_dxt3", true);
3798}
3799
3800// Test enabling GL_ANGLE_texture_compression_dxt5
3801TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5)
3802{
3803 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 16,
3804 "GL_ANGLE_texture_compression_dxt5", true);
3805}
3806
3807// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
3808TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGB)
3809{
3810 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8,
3811 "GL_EXT_texture_compression_s3tc_srgb", true);
3812}
3813
3814// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
3815TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGBA)
3816{
3817 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8,
3818 "GL_EXT_texture_compression_s3tc_srgb", true);
3819}
3820
3821// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
3822TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3SRGBA)
3823{
3824 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16,
3825 "GL_EXT_texture_compression_s3tc_srgb", true);
3826}
3827
3828// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
3829TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5SRGBA)
3830{
3831 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16,
3832 "GL_EXT_texture_compression_s3tc_srgb", true);
3833}
3834
3835// Test enabling GL_OES_compressed_ETC1_RGB8_texture
3836TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionETC1)
3837{
3838 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_OES, 4, 4, 8,
3839 "GL_OES_compressed_ETC1_RGB8_texture", false);
3840}
3841
3842// Test enabling GL_ANGLE_lossy_etc_decode
3843TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionLossyDecode)
3844{
3845 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 8,
3846 "GL_ANGLE_lossy_etc_decode", true);
3847}
3848
Frank Henigmanfccbac22017-05-28 17:29:26 -04003849// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
3850// qualifiers.
3851TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch)
3852{
3853 const std::string vertexShader =
3854 "#version 300 es\n"
3855 "uniform Block { mediump vec4 val; };\n"
3856 "void main() { gl_Position = val; }\n";
3857 const std::string fragmentShader =
3858 "#version 300 es\n"
3859 "uniform Block { highp vec4 val; };\n"
3860 "out highp vec4 out_FragColor;\n"
3861 "void main() { out_FragColor = val; }\n";
3862
3863 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
3864 ASSERT_NE(0u, vs);
3865 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
3866 ASSERT_NE(0u, fs);
3867
3868 GLuint program = glCreateProgram();
3869
3870 glAttachShader(program, vs);
3871 glDeleteShader(vs);
3872 glAttachShader(program, fs);
3873 glDeleteShader(fs);
3874
3875 glLinkProgram(program);
3876 GLint linkStatus;
3877 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3878 ASSERT_EQ(0, linkStatus);
3879
3880 glDeleteProgram(program);
3881}
3882
Geoff Lang69df2422017-07-05 12:42:31 -04003883// Test no attribute vertex shaders
3884TEST_P(WebGL2CompatibilityTest, NoAttributeVertexShader)
3885{
3886 const std::string vertexShader =
3887 "#version 300 es\n"
3888 "void main()\n"
3889 "{\n"
3890 "\n"
3891 " ivec2 xy = ivec2(gl_VertexID % 2, (gl_VertexID / 2 + gl_VertexID / 3) % 2);\n"
3892 " gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1);\n"
3893 "}";
3894 const std::string fragmentShader =
3895 "#version 300 es\n"
3896 "precision mediump float;\n"
3897 "out vec4 result;\n"
3898 "void main()\n"
3899 "{\n"
3900 " result = vec4(0, 1, 0, 1);\n"
3901 "}";
3902
3903 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3904 glUseProgram(program);
3905
3906 glDrawArrays(GL_TRIANGLES, 0, 6);
3907 ASSERT_GL_NO_ERROR();
3908 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3909}
3910
Brandon Jonesed5b46f2017-07-21 08:39:17 -07003911// Tests bindAttribLocations for length limit
3912TEST_P(WebGL2CompatibilityTest, BindAttribLocationLimitation)
3913{
3914 constexpr int maxLocStringLength = 1024;
3915 const std::string tooLongString(maxLocStringLength + 1, '_');
3916
3917 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
3918
3919 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3920}
3921
Geoff Langc287ea62016-09-16 14:46:51 -04003922// Use this to select which configurations (e.g. which renderer, which GLES major version) these
3923// tests should be run against.
3924ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
3925 ES2_D3D9(),
3926 ES2_D3D11(),
3927 ES3_D3D11(),
Geoff Langc287ea62016-09-16 14:46:51 -04003928 ES2_OPENGL(),
3929 ES3_OPENGL(),
3930 ES2_OPENGLES(),
3931 ES3_OPENGLES());
3932
Jamie Madill07be8bf2017-02-02 19:59:57 -05003933ANGLE_INSTANTIATE_TEST(WebGL2CompatibilityTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Geoff Langc287ea62016-09-16 14:46:51 -04003934} // namespace