blob: d3abeee2310af5e280ec0ce8c3b12fb88630600d [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
121 GLRenderbuffer rbo;
122 glBindRenderbuffer(GL_RENDERBUFFER, rbo.get());
123 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
124
125 GLFramebuffer fbo;
126 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
127 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo.get());
128
129 GLTexture texture;
130 glBindTexture(GL_TEXTURE_2D, texture.get());
131
132 if (internalFormat == format)
133 {
134 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, textureData);
135 }
136 else
137 {
138 if (getClientMajorVersion() >= 3)
139 {
140 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
141 }
142 else
143 {
144 ASSERT_TRUE(extensionEnabled("GL_EXT_texture_storage"));
145 glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
146 }
147 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, textureData);
148 }
149
150 if (!texturingEnabled)
151 {
152 // Depending on the entry point and client version, different errors may be generated
153 ASSERT_GLENUM_NE(GL_NO_ERROR, glGetError());
154
155 // Two errors may be generated in the glTexStorage + glTexSubImage case, clear the
156 // second error
157 glGetError();
158
159 return;
160 }
161 ASSERT_GL_NO_ERROR();
162
163 glUniform1i(glGetUniformLocation(samplingProgram.get(), "tex"), 0);
164 glUniform4fv(glGetUniformLocation(samplingProgram.get(), "subtractor"), 1, floatData);
165
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
168 drawQuad(samplingProgram.get(), "position", 0.5f, 1.0f, true);
169 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
170
171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
172 drawQuad(samplingProgram.get(), "position", 0.5f, 1.0f, true);
173
174 if (linearSamplingEnabled)
175 {
176 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
177 }
178 else
179 {
180 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
181 }
182
183 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(),
184 0);
185 glBindTexture(GL_TEXTURE_2D, 0);
186 if (!renderingEnabled)
187 {
188 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
189 glCheckFramebufferStatus(GL_FRAMEBUFFER));
190 return;
191 }
192 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
193
194 const std::string renderingVs =
195 "attribute vec4 position;\n"
196 "void main()\n"
197 "{\n"
198 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
199 "}\n";
200
201 const std::string renderingFs =
202 "precision mediump float;\n"
203 "uniform vec4 writeValue;\n"
204 "void main()\n"
205 "{\n"
206 " gl_FragColor = writeValue;\n"
207 "}\n";
208
209 ANGLE_GL_PROGRAM(renderingProgram, renderingVs, renderingFs);
210 glUseProgram(renderingProgram.get());
211
212 glUniform4fv(glGetUniformLocation(renderingProgram.get(), "writeValue"), 1, floatData);
213
214 drawQuad(renderingProgram.get(), "position", 0.5f, 1.0f, true);
215
216 EXPECT_PIXEL_COLOR32F_NEAR(
217 0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f);
218 }
219
Jamie Madillcad97ee2017-02-02 18:52:44 -0500220 // Called from RenderingFeedbackLoopWithDrawBuffersEXT.
221 void drawBuffersEXTFeedbackLoop(GLuint program,
222 const std::array<GLenum, 2> &drawBuffers,
223 GLenum expectedError);
224
Jamie Madill07be8bf2017-02-02 19:59:57 -0500225 // Called from RenderingFeedbackLoopWithDrawBuffers.
226 void drawBuffersFeedbackLoop(GLuint program,
227 const std::array<GLenum, 2> &drawBuffers,
228 GLenum expectedError);
229
Geoff Langc339c4e2016-11-29 10:37:36 -0500230 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
Geoff Langc287ea62016-09-16 14:46:51 -0400231};
232
Corentin Wallezfd456442016-12-21 17:57:00 -0500233class WebGL2CompatibilityTest : public WebGLCompatibilityTest
234{
235};
236
Geoff Langc287ea62016-09-16 14:46:51 -0400237// Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so
238// the GL extension should always be present
239TEST_P(WebGLCompatibilityTest, ExtensionStringExposed)
240{
241 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
242}
243
244// Verify that all extension entry points are available
245TEST_P(WebGLCompatibilityTest, EntryPoints)
246{
Geoff Langc339c4e2016-11-29 10:37:36 -0500247 if (extensionEnabled("GL_ANGLE_request_extension"))
Geoff Langc287ea62016-09-16 14:46:51 -0400248 {
Geoff Langc339c4e2016-11-29 10:37:36 -0500249 EXPECT_NE(nullptr, eglGetProcAddress("glRequestExtensionANGLE"));
Geoff Langc287ea62016-09-16 14:46:51 -0400250 }
251}
252
253// WebGL 1 allows GL_DEPTH_STENCIL_ATTACHMENT as a valid binding point. Make sure it is usable,
254// even in ES2 contexts.
255TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint)
256{
257 GLRenderbuffer renderbuffer;
258 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
259 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
260
261 GLFramebuffer framebuffer;
262 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
263 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
264 renderbuffer.get());
265
266 EXPECT_GL_NO_ERROR();
267}
268
269// Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION
270TEST_P(WebGLCompatibilityTest, EnableExtensionValidation)
271{
Geoff Langc339c4e2016-11-29 10:37:36 -0500272 glRequestExtensionANGLE("invalid_extension_string");
Geoff Langc287ea62016-09-16 14:46:51 -0400273 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
274}
275
276// Test enabling the GL_OES_element_index_uint extension
277TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices)
278{
279 if (getClientMajorVersion() != 2)
280 {
281 // This test only works on ES2 where uint indices are not available by default
282 return;
283 }
284
285 EXPECT_FALSE(extensionEnabled("GL_OES_element_index_uint"));
286
287 GLBuffer indexBuffer;
288 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
289
290 GLuint data[] = {0, 1, 2, 1, 3, 2};
291 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
292
293 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
294 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
295 glUseProgram(program.get());
296
Jamie Madille7b96342017-06-23 15:06:08 -0400297 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
Geoff Langc287ea62016-09-16 14:46:51 -0400298 EXPECT_GL_ERROR(GL_INVALID_ENUM);
299
Geoff Langc339c4e2016-11-29 10:37:36 -0500300 if (extensionRequestable("GL_OES_element_index_uint"))
Geoff Langc287ea62016-09-16 14:46:51 -0400301 {
Geoff Langc339c4e2016-11-29 10:37:36 -0500302 glRequestExtensionANGLE("GL_OES_element_index_uint");
Geoff Langc287ea62016-09-16 14:46:51 -0400303 EXPECT_GL_NO_ERROR();
304 EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint"));
305
Jamie Madille7b96342017-06-23 15:06:08 -0400306 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
Geoff Langc287ea62016-09-16 14:46:51 -0400307 EXPECT_GL_NO_ERROR();
308 }
309}
310
Geoff Langff5c63e2017-04-12 15:26:54 -0400311// Test enabling the GL_OES_standard_derivatives extension
312TEST_P(WebGLCompatibilityTest, EnableExtensionStandardDerivitives)
313{
314 EXPECT_FALSE(extensionEnabled("GL_OES_standard_derivatives"));
315
316 const std::string source =
317 "#extension GL_OES_standard_derivatives : require\n"
318 "void main() { gl_FragColor = vec4(dFdx(vec2(1.0, 1.0)).x, 1, 0, 1); }\n";
319 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
320
321 if (extensionRequestable("GL_OES_standard_derivatives"))
322 {
323 glRequestExtensionANGLE("GL_OES_standard_derivatives");
324 EXPECT_GL_NO_ERROR();
325 EXPECT_TRUE(extensionEnabled("GL_OES_standard_derivatives"));
326
327 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
328 ASSERT_NE(0u, shader);
329 glDeleteShader(shader);
330 }
331}
332
333// Test enabling the GL_EXT_shader_texture_lod extension
334TEST_P(WebGLCompatibilityTest, EnableExtensionTextureLOD)
335{
336 EXPECT_FALSE(extensionEnabled("GL_EXT_shader_texture_lod"));
337
338 const std::string source =
339 "#extension GL_EXT_shader_texture_lod : require\n"
340 "uniform sampler2D u_texture;\n"
341 "void main() {\n"
342 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
343 "0.0));\n"
344 "}\n";
345 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
346
347 if (extensionRequestable("GL_EXT_shader_texture_lod"))
348 {
349 glRequestExtensionANGLE("GL_EXT_shader_texture_lod");
350 EXPECT_GL_NO_ERROR();
351 EXPECT_TRUE(extensionEnabled("GL_EXT_shader_texture_lod"));
352
353 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
354 ASSERT_NE(0u, shader);
355 glDeleteShader(shader);
356 }
357}
358
359// Test enabling the GL_EXT_frag_depth extension
360TEST_P(WebGLCompatibilityTest, EnableExtensionFragDepth)
361{
362 EXPECT_FALSE(extensionEnabled("GL_EXT_frag_depth"));
363
364 const std::string source =
365 "#extension GL_EXT_frag_depth : require\n"
366 "void main() {\n"
367 " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
368 " gl_FragDepthEXT = 1.0;\n"
369 "}\n";
370 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, source));
371
372 if (extensionRequestable("GL_EXT_frag_depth"))
373 {
374 glRequestExtensionANGLE("GL_EXT_frag_depth");
375 EXPECT_GL_NO_ERROR();
376 EXPECT_TRUE(extensionEnabled("GL_EXT_frag_depth"));
377
378 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
379 ASSERT_NE(0u, shader);
380 glDeleteShader(shader);
381 }
382}
383
Geoff Langd7d526a2017-02-21 16:48:43 -0500384// Test enabling the GL_EXT_texture_filter_anisotropic extension
385TEST_P(WebGLCompatibilityTest, EnableExtensionTextureFilterAnisotropic)
386{
387 EXPECT_FALSE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
388
389 GLfloat maxAnisotropy = 0.0f;
390 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
391 EXPECT_GL_ERROR(GL_INVALID_ENUM);
392
393 GLTexture texture;
394 glBindTexture(GL_TEXTURE_2D, texture.get());
395 ASSERT_GL_NO_ERROR();
396
397 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
398 EXPECT_GL_ERROR(GL_INVALID_ENUM);
399
400 GLfloat currentAnisotropy = 0.0f;
401 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
402 EXPECT_GL_ERROR(GL_INVALID_ENUM);
403
404 if (extensionRequestable("GL_EXT_texture_filter_anisotropic"))
405 {
406 glRequestExtensionANGLE("GL_EXT_texture_filter_anisotropic");
407 EXPECT_GL_NO_ERROR();
408 EXPECT_TRUE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
409
410 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
411 ASSERT_GL_NO_ERROR();
412 EXPECT_GE(maxAnisotropy, 2.0f);
413
414 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
415 ASSERT_GL_NO_ERROR();
416 EXPECT_EQ(1.0f, currentAnisotropy);
417
418 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
419 ASSERT_GL_NO_ERROR();
420 }
421}
422
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700423// Verify that shaders are of a compatible spec when the extension is enabled.
424TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec)
425{
426 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
427
428 // Use of reserved _webgl prefix should fail when the shader specification is for WebGL.
429 const std::string &vert =
430 "struct Foo {\n"
431 " int _webgl_bar;\n"
432 "};\n"
433 "void main()\n"
434 "{\n"
435 " Foo foo = Foo(1);\n"
436 "}";
437
438 // Default fragement shader.
439 const std::string &frag =
440 "void main()\n"
441 "{\n"
442 " gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n"
443 "}";
444
445 GLuint program = CompileProgram(vert, frag);
446 EXPECT_EQ(0u, program);
447 glDeleteProgram(program);
448}
449
Geoff Lang3fab7632017-09-26 15:45:54 -0400450// Test enabling the GL_NV_pixel_buffer_object extension
451TEST_P(WebGLCompatibilityTest, EnablePixelBufferObjectExtensions)
452{
453 EXPECT_FALSE(extensionEnabled("GL_NV_pixel_buffer_object"));
454 EXPECT_FALSE(extensionEnabled("GL_OES_mapbuffer"));
455 EXPECT_FALSE(extensionEnabled("GL_EXT_map_buffer_range"));
456
457 // These extensions become core in in ES3/WebGL2.
458 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
459
460 GLBuffer buffer;
461 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
462 EXPECT_GL_ERROR(GL_INVALID_ENUM);
463
464 if (extensionRequestable("GL_NV_pixel_buffer_object"))
465 {
466 glRequestExtensionANGLE("GL_NV_pixel_buffer_object");
467 EXPECT_GL_NO_ERROR();
468
469 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
470 EXPECT_GL_NO_ERROR();
471
472 glBufferData(GL_PIXEL_PACK_BUFFER, 4, nullptr, GL_STATIC_DRAW);
473 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
474 EXPECT_GL_NO_ERROR();
475 }
476}
477
478// Test enabling the GL_OES_mapbuffer and GL_EXT_map_buffer_range extensions
479TEST_P(WebGLCompatibilityTest, EnableMapBufferExtensions)
480{
481 EXPECT_FALSE(extensionEnabled("GL_OES_mapbuffer"));
482 EXPECT_FALSE(extensionEnabled("GL_EXT_map_buffer_range"));
483
484 // These extensions become core in in ES3/WebGL2.
485 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
486
487 GLBuffer buffer;
488 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
489 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4, nullptr, GL_STATIC_DRAW);
490
491 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
492 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
493
494 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
495 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
496
497 GLint access = 0;
498 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
499 EXPECT_GL_ERROR(GL_INVALID_ENUM);
500
501 if (extensionRequestable("GL_OES_mapbuffer"))
502 {
503 glRequestExtensionANGLE("GL_OES_mapbuffer");
504 EXPECT_GL_NO_ERROR();
505
506 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
507 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
508 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
509 EXPECT_GL_NO_ERROR();
510 }
511
512 if (extensionRequestable("GL_EXT_map_buffer_range"))
513 {
514 glRequestExtensionANGLE("GL_EXT_map_buffer_range");
515 EXPECT_GL_NO_ERROR();
516
517 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
518 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
519 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
520 EXPECT_GL_NO_ERROR();
521 }
522}
523
Geoff Lang8c7133c2017-09-26 17:31:10 -0400524// Test enabling the GL_OES_fbo_render_mipmap extension
525TEST_P(WebGLCompatibilityTest, EnableRenderMipmapExtension)
526{
527 EXPECT_FALSE(extensionEnabled("GL_OES_fbo_render_mipmap"));
528
529 // This extensions become core in in ES3/WebGL2.
530 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
531
532 GLTexture texture;
533 glBindTexture(GL_TEXTURE_2D, texture);
534 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
535 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
536
537 GLFramebuffer fbo;
538 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
539 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
540 EXPECT_GL_NO_ERROR();
541
542 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
543 EXPECT_GL_ERROR(GL_INVALID_VALUE);
544
545 if (extensionRequestable("GL_OES_fbo_render_mipmap"))
546 {
547 glRequestExtensionANGLE("GL_OES_fbo_render_mipmap");
548 EXPECT_GL_NO_ERROR();
549
550 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
551 EXPECT_GL_NO_ERROR();
552 }
553}
554
Geoff Lang50cac572017-09-26 17:37:43 -0400555// Test enabling the GL_EXT_blend_minmax extension
556TEST_P(WebGLCompatibilityTest, EnableBlendMinMaxExtension)
557{
558 EXPECT_FALSE(extensionEnabled("GL_EXT_blend_minmax"));
559
560 // This extensions become core in in ES3/WebGL2.
561 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
562
563 glBlendEquation(GL_MIN);
564 EXPECT_GL_ERROR(GL_INVALID_ENUM);
565
566 glBlendEquation(GL_MAX);
567 EXPECT_GL_ERROR(GL_INVALID_ENUM);
568
569 if (extensionRequestable("GL_EXT_blend_minmax"))
570 {
571 glRequestExtensionANGLE("GL_EXT_blend_minmax");
572 EXPECT_GL_NO_ERROR();
573
574 glBlendEquation(GL_MIN);
575 glBlendEquation(GL_MAX);
576 EXPECT_GL_NO_ERROR();
577 }
578}
579
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400580// Test enabling the query extensions
581TEST_P(WebGLCompatibilityTest, EnableQueryExtensions)
582{
583 EXPECT_FALSE(extensionEnabled("GL_EXT_occlusion_query_boolean"));
584 EXPECT_FALSE(extensionEnabled("GL_EXT_disjoint_timer_query"));
585 EXPECT_FALSE(extensionEnabled("GL_CHROMIUM_sync_query"));
586
587 // This extensions become core in in ES3/WebGL2.
588 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
589
590 GLQueryEXT badQuery;
591
592 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, badQuery);
593 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
594
595 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, badQuery);
596 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
597
598 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, badQuery);
599 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
600
601 glQueryCounterEXT(GL_TIMESTAMP_EXT, badQuery);
602 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
603
604 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, badQuery);
605 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
606
607 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
608 {
609 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
610 EXPECT_GL_NO_ERROR();
611
612 GLQueryEXT query;
613 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
614 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
615 EXPECT_GL_NO_ERROR();
616 }
617
618 if (extensionRequestable("GL_EXT_disjoint_timer_query"))
619 {
620 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
621 EXPECT_GL_NO_ERROR();
622
623 GLQueryEXT query1;
624 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
625 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
626 EXPECT_GL_NO_ERROR();
627
628 GLQueryEXT query2;
629 glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
630 EXPECT_GL_NO_ERROR();
631 }
632
633 if (extensionRequestable("GL_CHROMIUM_sync_query"))
634 {
635 glRequestExtensionANGLE("GL_CHROMIUM_sync_query");
636 EXPECT_GL_NO_ERROR();
637
638 GLQueryEXT query;
639 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query);
640 glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
641 EXPECT_GL_NO_ERROR();
642 }
643}
644
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400645// Verify that the context generates the correct error when the framebuffer attachments are
646// different sizes
647TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMissmatch)
648{
649 GLFramebuffer fbo;
650 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
651
652 GLTexture textures[2];
653 glBindTexture(GL_TEXTURE_2D, textures[0]);
654 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
655 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
656
657 ASSERT_GL_NO_ERROR();
658 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
659
660 GLRenderbuffer renderbuffer;
661 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
662 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3);
663 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
664
665 ASSERT_GL_NO_ERROR();
666 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
667 glCheckFramebufferStatus(GL_FRAMEBUFFER));
668
669 if (extensionRequestable("GL_EXT_draw_buffers"))
670 {
671 glRequestExtensionANGLE("GL_EXT_draw_buffers");
672 EXPECT_GL_NO_ERROR();
673 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
674
675 glBindTexture(GL_TEXTURE_2D, textures[1]);
676 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
677 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
678 ASSERT_GL_NO_ERROR();
679
680 ASSERT_GL_NO_ERROR();
681 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
682 glCheckFramebufferStatus(GL_FRAMEBUFFER));
683
684 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
685
686 ASSERT_GL_NO_ERROR();
687 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
688
689 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
690
691 ASSERT_GL_NO_ERROR();
692 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
693 glCheckFramebufferStatus(GL_FRAMEBUFFER));
694 }
695}
696
Corentin Wallez327411e2016-12-09 11:09:17 -0500697// Test that client-side array buffers are forbidden in WebGL mode
698TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer)
699{
700 const std::string &vert =
701 "attribute vec3 a_pos;\n"
702 "void main()\n"
703 "{\n"
704 " gl_Position = vec4(a_pos, 1.0);\n"
705 "}\n";
706
707 const std::string &frag =
708 "precision highp float;\n"
709 "void main()\n"
710 "{\n"
711 " gl_FragColor = vec4(1.0);\n"
712 "}\n";
713
714 ANGLE_GL_PROGRAM(program, vert, frag);
715
716 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
717 ASSERT_NE(-1, posLocation);
718 glUseProgram(program.get());
719
720 const auto &vertices = GetQuadVertices();
Corentin Wallezfd456442016-12-21 17:57:00 -0500721 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
Corentin Wallez327411e2016-12-09 11:09:17 -0500722 glEnableVertexAttribArray(posLocation);
723
724 ASSERT_GL_NO_ERROR();
725 glDrawArrays(GL_TRIANGLES, 0, 6);
726 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
727}
728
729// Test that client-side element array buffers are forbidden in WebGL mode
730TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
731{
732 const std::string &vert =
733 "attribute vec3 a_pos;\n"
734 "void main()\n"
735 "{\n"
736 " gl_Position = vec4(a_pos, 1.0);\n"
737 "}\n";
738
739 const std::string &frag =
740 "precision highp float;\n"
741 "void main()\n"
742 "{\n"
743 " gl_FragColor = vec4(1.0);\n"
744 "}\n";
745
746 ANGLE_GL_PROGRAM(program, vert, frag);
747
748 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
749 ASSERT_NE(-1, posLocation);
750 glUseProgram(program.get());
751
752 const auto &vertices = GetQuadVertices();
753
754 GLBuffer vertexBuffer;
755 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
756 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
757 GL_STATIC_DRAW);
758
759 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
760 glEnableVertexAttribArray(posLocation);
761
Corentin Wallez327411e2016-12-09 11:09:17 -0500762 ASSERT_GL_NO_ERROR();
Corentin Wallezded1b5a2017-03-09 18:58:48 -0500763
764 // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also
765 // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate
766 // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check.
767 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void*>(intptr_t(1)));
Corentin Wallez327411e2016-12-09 11:09:17 -0500768 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
769}
770
Corentin Wallez672f7f32017-06-15 17:42:17 -0400771// Test that client-side array buffers are forbidden even if the program doesn't use the attribute
772TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBufferEvenNotUsedOnes)
773{
774 const std::string &vert =
775 "void main()\n"
776 "{\n"
777 " gl_Position = vec4(1.0);\n"
778 "}\n";
779
780 const std::string &frag =
781 "precision highp float;\n"
782 "void main()\n"
783 "{\n"
784 " gl_FragColor = vec4(1.0);\n"
785 "}\n";
786
787 ANGLE_GL_PROGRAM(program, vert, frag);
788
789 glUseProgram(program.get());
790
791 const auto &vertices = GetQuadVertices();
792 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
793 glEnableVertexAttribArray(0);
794
795 ASSERT_GL_NO_ERROR();
796 glDrawArrays(GL_TRIANGLES, 0, 6);
797 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
798}
799
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500800// Tests the WebGL requirement of having the same stencil mask, writemask and ref for fron and back
801TEST_P(WebGLCompatibilityTest, RequiresSameStencilMaskAndRef)
802{
803 // Run the test in an FBO to make sure we have some stencil bits.
804 GLRenderbuffer renderbuffer;
805 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
806 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
807
808 GLFramebuffer framebuffer;
809 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
810 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
811 renderbuffer.get());
812
813 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
814 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
815 glUseProgram(program.get());
816 ASSERT_GL_NO_ERROR();
817
818 // Having ref and mask the same for front and back is valid.
819 glStencilMask(255);
820 glStencilFunc(GL_ALWAYS, 0, 255);
821 glDrawArrays(GL_TRIANGLES, 0, 6);
822 ASSERT_GL_NO_ERROR();
823
824 // Having a different front - back write mask generates an error.
825 glStencilMaskSeparate(GL_FRONT, 1);
826 glDrawArrays(GL_TRIANGLES, 0, 6);
827 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
828
829 // Setting both write masks separately to the same value is valid.
830 glStencilMaskSeparate(GL_BACK, 1);
831 glDrawArrays(GL_TRIANGLES, 0, 6);
832 ASSERT_GL_NO_ERROR();
833
834 // Having a different stencil front - back mask generates an error
835 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
836 glDrawArrays(GL_TRIANGLES, 0, 6);
837 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
838
839 // Setting both masks separately to the same value is valid.
840 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
841 glDrawArrays(GL_TRIANGLES, 0, 6);
842 ASSERT_GL_NO_ERROR();
843
844 // Having a different stencil front - back reference generates an error
845 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
846 glDrawArrays(GL_TRIANGLES, 0, 6);
847 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
848
849 // Setting both references separately to the same value is valid.
850 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
851 glDrawArrays(GL_TRIANGLES, 0, 6);
852 ASSERT_GL_NO_ERROR();
853
854 // Using different stencil funcs, everything being equal is valid.
855 glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
856 glDrawArrays(GL_TRIANGLES, 0, 6);
857 ASSERT_GL_NO_ERROR();
858}
859
Corentin Wallez506fc9c2016-12-21 16:53:33 -0500860// Test that GL_FIXED is forbidden
861TEST_P(WebGLCompatibilityTest, ForbidsGLFixed)
862{
863 GLBuffer buffer;
864 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
865 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
866
867 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
868 ASSERT_GL_NO_ERROR();
869
870 glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr);
871 EXPECT_GL_ERROR(GL_INVALID_ENUM);
872}
873
874// Test the WebGL limit of 255 for the attribute stride
875TEST_P(WebGLCompatibilityTest, MaxStride)
876{
877 GLBuffer buffer;
878 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
879 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
880
881 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr);
882 ASSERT_GL_NO_ERROR();
883
884 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr);
885 EXPECT_GL_ERROR(GL_INVALID_VALUE);
886}
887
Corentin Wallezfd456442016-12-21 17:57:00 -0500888// Test the checks for OOB reads in the vertex buffers, non-instanced version
889TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
890{
891 const std::string &vert =
892 "attribute float a_pos;\n"
893 "void main()\n"
894 "{\n"
895 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
896 "}\n";
897
898 const std::string &frag =
899 "precision highp float;\n"
900 "void main()\n"
901 "{\n"
902 " gl_FragColor = vec4(1.0);\n"
903 "}\n";
904
905 ANGLE_GL_PROGRAM(program, vert, frag);
906
907 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
908 ASSERT_NE(-1, posLocation);
909 glUseProgram(program.get());
910
911 GLBuffer buffer;
912 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
913 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
914
915 glEnableVertexAttribArray(posLocation);
916
917 const uint8_t* zeroOffset = nullptr;
918
919 // Test touching the last element is valid.
920 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
921 glDrawArrays(GL_POINTS, 0, 4);
922 ASSERT_GL_NO_ERROR();
923
924 // Test touching the last element + 1 is invalid.
925 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
926 glDrawArrays(GL_POINTS, 0, 4);
927 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
928
929 // Test touching the last element is valid, using a stride.
930 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
931 glDrawArrays(GL_POINTS, 0, 4);
932 ASSERT_GL_NO_ERROR();
933
934 // Test touching the last element + 1 is invalid, using a stride.
935 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
936 glDrawArrays(GL_POINTS, 0, 4);
937 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
938
939 // Test any offset is valid if no vertices are drawn.
940 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
941 glDrawArrays(GL_POINTS, 0, 0);
942 ASSERT_GL_NO_ERROR();
943}
944
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500945// Test the checks for OOB reads in the index buffer
946TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
Geoff Lang5f319a42017-01-09 16:49:19 -0500947{
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500948 const std::string &vert =
949 "attribute float a_pos;\n"
950 "void main()\n"
951 "{\n"
952 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
953 "}\n";
Geoff Lang5f319a42017-01-09 16:49:19 -0500954
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500955 const std::string &frag =
956 "precision highp float;\n"
957 "void main()\n"
958 "{\n"
959 " gl_FragColor = vec4(1.0);\n"
960 "}\n";
961
962 ANGLE_GL_PROGRAM(program, vert, frag);
963
964 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
965 ASSERT_NE(-1, posLocation);
966 glUseProgram(program.get());
967
968 GLBuffer vertexBuffer;
969 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
970 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
971
972 glEnableVertexAttribArray(posLocation);
973
974 const uint8_t *zeroOffset = nullptr;
975 const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
976
977 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset);
978
979 GLBuffer indexBuffer;
980 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
981 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
Geoff Lang5f319a42017-01-09 16:49:19 -0500982 ASSERT_GL_NO_ERROR();
983
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500984 // Test touching the last index is valid
985 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
986 ASSERT_GL_NO_ERROR();
Geoff Lang5f319a42017-01-09 16:49:19 -0500987
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500988 // Test touching the last + 1 element is invalid
989 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
990 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang5f319a42017-01-09 16:49:19 -0500991
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500992 // Test any offset if valid if count is zero
993 glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
994 ASSERT_GL_NO_ERROR();
Corentin Wallezfe9306a2017-02-01 17:41:05 -0500995
996 // Test touching the first index is valid
997 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
998 ASSERT_GL_NO_ERROR();
999
1000 // Test touching the first - 1 index is invalid
1001 // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was
1002 // the historic behavior of WebGL implementations
1003 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1);
1004 EXPECT_GL_ERROR(GL_INVALID_VALUE);
Geoff Lang5f319a42017-01-09 16:49:19 -05001005}
1006
Frank Henigman6137ddc2017-02-10 18:55:07 -05001007// Test depth range with 'near' more or less than 'far.'
1008TEST_P(WebGLCompatibilityTest, DepthRange)
1009{
1010 glDepthRangef(0, 1);
1011 ASSERT_GL_NO_ERROR();
1012
1013 glDepthRangef(.5, .5);
1014 ASSERT_GL_NO_ERROR();
1015
1016 glDepthRangef(1, 0);
1017 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1018}
1019
Frank Henigman146e8a12017-03-02 23:22:37 -05001020// Test all blend function combinations.
1021// In WebGL it is invalid to combine constant color with constant alpha.
1022TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
1023{
1024 constexpr GLenum srcFunc[] = {
1025 GL_ZERO,
1026 GL_ONE,
1027 GL_SRC_COLOR,
1028 GL_ONE_MINUS_SRC_COLOR,
1029 GL_DST_COLOR,
1030 GL_ONE_MINUS_DST_COLOR,
1031 GL_SRC_ALPHA,
1032 GL_ONE_MINUS_SRC_ALPHA,
1033 GL_DST_ALPHA,
1034 GL_ONE_MINUS_DST_ALPHA,
1035 GL_CONSTANT_COLOR,
1036 GL_ONE_MINUS_CONSTANT_COLOR,
1037 GL_CONSTANT_ALPHA,
1038 GL_ONE_MINUS_CONSTANT_ALPHA,
1039 GL_SRC_ALPHA_SATURATE,
1040 };
1041
1042 constexpr GLenum dstFunc[] = {
1043 GL_ZERO, GL_ONE,
1044 GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
1045 GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
1046 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1047 GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
1048 GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
1049 GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
1050 };
1051
1052 for (GLenum src : srcFunc)
1053 {
1054 for (GLenum dst : dstFunc)
1055 {
1056 glBlendFunc(src, dst);
1057 CheckBlendFunctions(src, dst);
1058 glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE);
1059 CheckBlendFunctions(src, dst);
1060 }
1061 }
1062}
1063
Geoff Langfc32e8b2017-05-31 14:16:59 -04001064// Test that binding/querying uniforms and attributes with invalid names generates errors
1065TEST_P(WebGLCompatibilityTest, InvalidAttributeAndUniformNames)
1066{
1067 const std::string validAttribName =
1068 "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1069 const std::string validUniformName =
1070 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
Geoff Langa71a98e2017-06-19 15:15:00 -04001071 std::vector<char> invalidSet = {'"', '$', '`', '@', '\''};
1072 if (getClientMajorVersion() < 3)
1073 {
1074 invalidSet.push_back('\\');
1075 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04001076
1077 std::string vert = "attribute float ";
1078 vert += validAttribName;
1079 vert +=
1080 ";\n"
1081 "void main()\n"
1082 "{\n"
1083 " gl_Position = vec4(1.0);\n"
1084 "}\n";
1085
1086 std::string frag =
1087 "precision highp float;\n"
1088 "uniform vec4 ";
1089 frag += validUniformName;
Geoff Langcab92ee2017-07-19 17:32:07 -04001090 // Insert illegal characters into comments
Geoff Langfc32e8b2017-05-31 14:16:59 -04001091 frag +=
1092 ";\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001093 " // $ \" @ /*\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001094 "void main()\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001095 "{/*\n"
1096 " ` @ $\n"
1097 " */gl_FragColor = vec4(1.0);\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001098 "}\n";
1099
1100 ANGLE_GL_PROGRAM(program, vert, frag);
1101 EXPECT_GL_NO_ERROR();
1102
1103 for (char invalidChar : invalidSet)
1104 {
1105 std::string invalidName = validAttribName + invalidChar;
1106 glGetAttribLocation(program, invalidName.c_str());
1107 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1108 << "glGetAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1109
1110 glBindAttribLocation(program, 0, invalidName.c_str());
1111 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1112 << "glBindAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1113 }
1114
1115 for (char invalidChar : invalidSet)
1116 {
1117 std::string invalidName = validUniformName + invalidChar;
1118 glGetUniformLocation(program, invalidName.c_str());
1119 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1120 << "glGetUniformLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1121 }
1122
1123 for (char invalidChar : invalidSet)
1124 {
1125 std::string invalidAttribName = validAttribName + invalidChar;
1126 const char *invalidVert[] = {
1127 "attribute float ",
1128 invalidAttribName.c_str(),
1129 ";\n",
1130 "void main()\n",
1131 "{\n",
1132 " gl_Position = vec4(1.0);\n",
1133 "}\n",
1134 };
1135
1136 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1137 glShaderSource(shader, static_cast<GLsizei>(ArraySize(invalidVert)), invalidVert, nullptr);
1138 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1139 glDeleteShader(shader);
1140 }
1141}
1142
Geoff Langcab92ee2017-07-19 17:32:07 -04001143// Test that line continuation is handled correctly when valdiating shader source
1144TEST_P(WebGL2CompatibilityTest, ShaderSourceLineContinuation)
1145{
1146 const char *validVert =
1147 "#version 300 es\n"
1148 "precision mediump float;\n"
1149 "\n"
1150 "void main ()\n"
1151 "{\n"
1152 " float f\\\n"
1153 "oo = 1.0;\n"
1154 " gl_Position = vec4(foo);\n"
1155 "}\n";
1156
1157 const char *invalidVert =
1158 "#version 300 es\n"
1159 "precision mediump float;\n"
1160 "\n"
1161 "void main ()\n"
1162 "{\n"
1163 " float f\\$\n"
1164 "oo = 1.0;\n"
1165 " gl_Position = vec4(foo);\n"
1166 "}\n";
1167
1168 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1169 glShaderSource(shader, 1, &validVert, nullptr);
1170 EXPECT_GL_NO_ERROR();
1171 glShaderSource(shader, 1, &invalidVert, nullptr);
1172 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1173 glDeleteShader(shader);
1174}
1175
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001176// Tests bindAttribLocations for reserved prefixes and length limits
1177TEST_P(WebGLCompatibilityTest, BindAttribLocationLimitation)
1178{
1179 constexpr int maxLocStringLength = 256;
1180 const std::string tooLongString(maxLocStringLength + 1, '_');
1181
1182 glBindAttribLocation(0, 0, "_webgl_var");
1183
1184 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1185
1186 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
1187
1188 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1189}
1190
Corentin Wallezfd456442016-12-21 17:57:00 -05001191// Test the checks for OOB reads in the vertex buffers, instanced version
1192TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
1193{
1194 const std::string &vert =
1195 "attribute float a_pos;\n"
Geoff Lang407d4e72017-04-12 14:54:11 -04001196 "attribute float a_w;\n"
Corentin Wallezfd456442016-12-21 17:57:00 -05001197 "void main()\n"
1198 "{\n"
Geoff Lang407d4e72017-04-12 14:54:11 -04001199 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
Corentin Wallezfd456442016-12-21 17:57:00 -05001200 "}\n";
1201
1202 const std::string &frag =
1203 "precision highp float;\n"
1204 "void main()\n"
1205 "{\n"
1206 " gl_FragColor = vec4(1.0);\n"
1207 "}\n";
1208
1209 ANGLE_GL_PROGRAM(program, vert, frag);
1210
1211 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1212 ASSERT_NE(-1, posLocation);
Geoff Lang407d4e72017-04-12 14:54:11 -04001213
1214 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
1215 ASSERT_NE(-1, wLocation);
1216
Corentin Wallezfd456442016-12-21 17:57:00 -05001217 glUseProgram(program.get());
1218
1219 GLBuffer buffer;
1220 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1221 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1222
1223 glEnableVertexAttribArray(posLocation);
1224 glVertexAttribDivisor(posLocation, 1);
1225
Geoff Lang407d4e72017-04-12 14:54:11 -04001226 glEnableVertexAttribArray(wLocation);
1227 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1228 glVertexAttribDivisor(wLocation, 0);
1229
Corentin Wallezfd456442016-12-21 17:57:00 -05001230 const uint8_t* zeroOffset = nullptr;
1231
1232 // Test touching the last element is valid.
1233 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1234 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1235 ASSERT_GL_NO_ERROR();
1236
1237 // Test touching the last element + 1 is invalid.
1238 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1239 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1240 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1241
1242 // Test touching the last element is valid, using a stride.
1243 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1244 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1245 ASSERT_GL_NO_ERROR();
1246
1247 // Test touching the last element + 1 is invalid, using a stride.
1248 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1249 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1250 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1251
1252 // Test any offset is valid if no vertices are drawn.
1253 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1254 glDrawArraysInstanced(GL_POINTS, 0, 1, 0);
1255 ASSERT_GL_NO_ERROR();
1256}
1257
Corentin Wallez0dc97812017-06-22 14:38:44 -04001258// Test that having no attributes with a zero divisor is valid in WebGL2
Geoff Lang407d4e72017-04-12 14:54:11 -04001259TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor)
1260{
1261 const std::string &vert =
1262 "attribute float a_pos;\n"
1263 "void main()\n"
1264 "{\n"
1265 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1266 "}\n";
1267
1268 const std::string &frag =
1269 "precision highp float;\n"
1270 "void main()\n"
1271 "{\n"
1272 " gl_FragColor = vec4(1.0);\n"
1273 "}\n";
1274
1275 ANGLE_GL_PROGRAM(program, vert, frag);
1276
1277 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1278 ASSERT_NE(-1, posLocation);
1279
1280 glUseProgram(program.get());
1281
1282 GLBuffer buffer;
1283 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1284 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1285
1286 glEnableVertexAttribArray(posLocation);
1287 glVertexAttribDivisor(posLocation, 1);
1288
Geoff Lang407d4e72017-04-12 14:54:11 -04001289 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
1290 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
Geoff Lang407d4e72017-04-12 14:54:11 -04001291 ASSERT_GL_NO_ERROR();
1292}
1293
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001294// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
1295TEST_P(WebGLCompatibilityTest, NPOT)
1296{
1297 EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
1298
1299 // Create a texture and set an NPOT mip 0, should always be acceptable.
1300 GLTexture texture;
1301 glBindTexture(GL_TEXTURE_2D, texture.get());
1302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1303 ASSERT_GL_NO_ERROR();
1304
1305 // Try setting an NPOT mip 1 and verify the error if WebGL 1
1306 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1307 if (getClientMajorVersion() < 3)
1308 {
1309 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1310 }
1311 else
1312 {
1313 ASSERT_GL_NO_ERROR();
1314 }
1315
1316 if (extensionRequestable("GL_OES_texture_npot"))
1317 {
1318 glRequestExtensionANGLE("GL_OES_texture_npot");
1319 ASSERT_GL_NO_ERROR();
1320
1321 // Try again to set NPOT mip 1
1322 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1323 ASSERT_GL_NO_ERROR();
1324 }
1325}
1326
Jamie Madillcad97ee2017-02-02 18:52:44 -05001327template <typename T>
1328void FillTexture2D(GLuint texture,
1329 GLsizei width,
1330 GLsizei height,
1331 const T &onePixelData,
1332 GLint level,
1333 GLint internalFormat,
1334 GLenum format,
1335 GLenum type)
1336{
1337 std::vector<T> allPixelsData(width * height, onePixelData);
1338
1339 glBindTexture(GL_TEXTURE_2D, texture);
1340 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
1341 allPixelsData.data());
1342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1343 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1344 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1345 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1346}
1347
Frank Henigman875bbba2017-02-08 16:38:17 -05001348// Test that unset gl_Position defaults to (0,0,0,0).
1349TEST_P(WebGLCompatibilityTest, DefaultPosition)
1350{
1351 // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set,
1352 // and green otherwise. The center of each quadrant will be red if and only if all
1353 // four corners are red.
1354 const std::string vertexShader =
1355 "attribute vec3 pos;\n"
1356 "varying vec4 color;\n"
1357 "void main() {\n"
1358 " if (gl_Position == vec4(0,0,0,0)) {\n"
1359 " color = vec4(1,0,0,1);\n"
1360 " } else {\n"
1361 " color = vec4(0,1,0,1);\n"
1362 " }\n"
1363 " gl_Position = vec4(pos,1);\n"
1364 "}\n";
1365
1366 const std::string fragmentShader =
1367 "precision mediump float;\n"
1368 "varying vec4 color;\n"
1369 "void main() {\n"
1370 " gl_FragColor = color;\n"
1371 "}\n";
1372
1373 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1374 drawQuad(program.get(), "pos", 0.0f, 1.0f, true);
1375 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1376 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1377 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1378 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1379}
1380
Jamie Madilla4595b82017-01-11 17:36:34 -05001381// Tests that a rendering feedback loop triggers a GL error under WebGL.
1382// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
1383TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
1384{
1385 const std::string vertexShader =
1386 "attribute vec4 a_position;\n"
1387 "varying vec2 v_texCoord;\n"
1388 "void main() {\n"
1389 " gl_Position = a_position;\n"
1390 " v_texCoord = (a_position.xy * 0.5) + 0.5;\n"
1391 "}\n";
1392
1393 const std::string fragmentShader =
1394 "precision mediump float;\n"
1395 "varying vec2 v_texCoord;\n"
1396 "uniform sampler2D u_texture;\n"
1397 "void main() {\n"
1398 " // Shader swizzles color channels so we can tell if the draw succeeded.\n"
1399 " gl_FragColor = texture2D(u_texture, v_texCoord).gbra;\n"
1400 "}\n";
1401
1402 GLTexture texture;
Jamie Madillcad97ee2017-02-02 18:52:44 -05001403 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05001404
1405 ASSERT_GL_NO_ERROR();
1406
1407 GLFramebuffer framebuffer;
1408 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1409 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1410
1411 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1412
1413 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1414
1415 GLint uniformLoc = glGetUniformLocation(program.get(), "u_texture");
1416 ASSERT_NE(-1, uniformLoc);
1417
1418 glUseProgram(program.get());
1419 glUniform1i(uniformLoc, 0);
1420 glDisable(GL_BLEND);
1421 glDisable(GL_DEPTH_TEST);
1422 ASSERT_GL_NO_ERROR();
1423
1424 // Drawing with a texture that is also bound to the current framebuffer should fail
1425 glBindTexture(GL_TEXTURE_2D, texture.get());
1426 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1427 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1428
1429 // Ensure that the texture contents did not change after the previous render
1430 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1431 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1432 ASSERT_GL_NO_ERROR();
1433 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1434
1435 // Drawing when texture is bound to an inactive uniform should succeed
1436 GLTexture texture2;
Jamie Madillcad97ee2017-02-02 18:52:44 -05001437 FillTexture2D(texture2.get(), 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05001438
1439 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1440 glActiveTexture(GL_TEXTURE1);
1441 glBindTexture(GL_TEXTURE_2D, texture.get());
1442 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1443 ASSERT_GL_NO_ERROR();
1444 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1445}
1446
Bryan Bernhart58806562017-01-05 13:09:31 -08001447// Test for the max draw buffers and color attachments.
1448TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
1449{
1450 // This test only applies to ES2.
1451 if (getClientMajorVersion() != 2)
1452 {
1453 return;
1454 }
1455
1456 GLFramebuffer fbo[2];
1457 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0].get());
1458
1459 // Test that is valid when we bind with a single attachment point.
1460 GLTexture texture;
1461 glBindTexture(GL_TEXTURE_2D, texture.get());
1462 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1463 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1464 ASSERT_GL_NO_ERROR();
1465
1466 // Test that enabling the draw buffers extension will allow us to bind with a non-zero
1467 // attachment point.
1468 if (extensionRequestable("GL_EXT_draw_buffers"))
1469 {
1470 glRequestExtensionANGLE("GL_EXT_draw_buffers");
1471 EXPECT_GL_NO_ERROR();
1472 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
1473
1474 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1].get());
1475
1476 GLTexture texture2;
1477 glBindTexture(GL_TEXTURE_2D, texture2.get());
1478 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1479 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2.get(),
1480 0);
1481 ASSERT_GL_NO_ERROR();
1482 }
1483}
1484
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05001485// Test that the offset in the index buffer is forced to be a multiple of the element size
1486TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction)
1487{
1488 const std::string &vert =
1489 "attribute vec3 a_pos;\n"
1490 "void main()\n"
1491 "{\n"
1492 " gl_Position = vec4(a_pos, 1.0);\n"
1493 "}\n";
1494
1495 const std::string &frag =
1496 "precision highp float;\n"
1497 "void main()\n"
1498 "{\n"
1499 " gl_FragColor = vec4(1.0);\n"
1500 "}\n";
1501
1502 ANGLE_GL_PROGRAM(program, vert, frag);
1503
1504 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1505 ASSERT_NE(-1, posLocation);
1506 glUseProgram(program.get());
1507
1508 const auto &vertices = GetQuadVertices();
1509
1510 GLBuffer vertexBuffer;
1511 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1512 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1513 GL_STATIC_DRAW);
1514
1515 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1516 glEnableVertexAttribArray(posLocation);
1517
1518 GLBuffer indexBuffer;
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001519 const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0, 0};
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05001520 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1521 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
1522
1523 ASSERT_GL_NO_ERROR();
1524
1525 const char *zeroIndices = nullptr;
1526
1527 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices);
1528 ASSERT_GL_NO_ERROR();
1529
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001530 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05001531 ASSERT_GL_NO_ERROR();
1532
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001533 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices + 1);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05001534 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1535}
1536
1537// Test that the offset and stride in the vertex buffer is forced to be a multiple of the element
1538// size
1539TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction)
1540{
1541 const char *zeroOffset = nullptr;
1542
1543 // Base case, vector of two floats
1544 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset);
1545 ASSERT_GL_NO_ERROR();
1546
1547 // Test setting a non-multiple offset
1548 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1);
1549 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1550 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2);
1551 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1552 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3);
1553 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1554
1555 // Test setting a non-multiple stride
1556 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset);
1557 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1558 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset);
1559 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1560 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset);
1561 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1562}
1563
Jamie Madillcad97ee2017-02-02 18:52:44 -05001564void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program,
1565 const std::array<GLenum, 2> &drawBuffers,
1566 GLenum expectedError)
1567{
1568 glDrawBuffersEXT(2, drawBuffers.data());
1569
1570 // Make sure framebuffer is complete before feedback loop detection
1571 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1572
1573 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
1574
1575 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
1576 // it should be NO_ERROR"
1577 EXPECT_GL_ERROR(expectedError);
1578}
1579
1580// This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers.
1581// Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html
1582TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT)
1583{
1584 const std::string vertexShader =
1585 "attribute vec4 aPosition;\n"
1586 "varying vec2 texCoord;\n"
1587 "void main() {\n"
1588 " gl_Position = aPosition;\n"
1589 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
1590 "}\n";
1591
1592 const std::string fragmentShader =
1593 "#extension GL_EXT_draw_buffers : require\n"
1594 "precision mediump float;\n"
1595 "uniform sampler2D tex;\n"
1596 "varying vec2 texCoord;\n"
1597 "void main() {\n"
1598 " gl_FragData[0] = texture2D(tex, texCoord);\n"
1599 " gl_FragData[1] = texture2D(tex, texCoord);\n"
1600 "}\n";
1601
1602 GLsizei width = 8;
1603 GLsizei height = 8;
1604
1605 // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers
1606 // extension and gl_FragData semantics are changed to enforce indexing by zero always.
1607 // TODO(jmadill): This extension should be disabled in WebGL 2 contexts.
1608 if (/*!extensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2)
1609 {
1610 // No WEBGL_draw_buffers support -- this is legal.
1611 return;
1612 }
1613
1614 GLint maxDrawBuffers = 0;
1615 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1616
1617 if (maxDrawBuffers < 2)
1618 {
1619 std::cout << "Test skipped because MAX_DRAW_BUFFERS is too small." << std::endl;
1620 return;
1621 }
1622
1623 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1624 glUseProgram(program.get());
1625 glViewport(0, 0, width, height);
1626
1627 GLTexture tex0;
1628 GLTexture tex1;
1629 GLFramebuffer fbo;
1630 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1631 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1632 ASSERT_GL_NO_ERROR();
1633
1634 glBindTexture(GL_TEXTURE_2D, tex1.get());
1635 GLint texLoc = glGetUniformLocation(program.get(), "tex");
1636 ASSERT_NE(-1, texLoc);
1637 glUniform1i(texLoc, 0);
1638 ASSERT_GL_NO_ERROR();
1639
1640 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
1641 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
1642 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
1643 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
1644
1645 drawBuffersEXTFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}},
1646 GL_INVALID_OPERATION);
1647 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
1648 GL_INVALID_OPERATION);
1649 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
1650}
1651
Jamie Madill07be8bf2017-02-02 19:59:57 -05001652// Test tests that texture copying feedback loops are properly rejected in WebGL.
1653// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
1654TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
1655{
1656 GLTexture texture;
1657 glBindTexture(GL_TEXTURE_2D, texture.get());
1658 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1659 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1660 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1661 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1663
1664 GLTexture texture2;
1665 glBindTexture(GL_TEXTURE_2D, texture2.get());
1666 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1669 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1670 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1671
1672 GLFramebuffer framebuffer;
1673 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1674 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1675
1676 // framebuffer should be FRAMEBUFFER_COMPLETE.
1677 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1678 ASSERT_GL_NO_ERROR();
1679
1680 // testing copyTexImage2D
1681
1682 // copyTexImage2D to same texture but different level
1683 glBindTexture(GL_TEXTURE_2D, texture.get());
1684 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
1685 EXPECT_GL_NO_ERROR();
1686
1687 // copyTexImage2D to same texture same level, invalid feedback loop
1688 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
1689 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1690
1691 // copyTexImage2D to different texture
1692 glBindTexture(GL_TEXTURE_2D, texture2.get());
1693 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
1694 EXPECT_GL_NO_ERROR();
1695
1696 // testing copyTexSubImage2D
1697
1698 // copyTexSubImage2D to same texture but different level
1699 glBindTexture(GL_TEXTURE_2D, texture.get());
1700 glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
1701 EXPECT_GL_NO_ERROR();
1702
1703 // copyTexSubImage2D to same texture same level, invalid feedback loop
1704 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
1705 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1706
1707 // copyTexSubImage2D to different texture
1708 glBindTexture(GL_TEXTURE_2D, texture2.get());
1709 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
1710 EXPECT_GL_NO_ERROR();
1711}
1712
1713void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program,
1714 const std::array<GLenum, 2> &drawBuffers,
1715 GLenum expectedError)
1716{
1717 glDrawBuffers(2, drawBuffers.data());
1718
1719 // Make sure framebuffer is complete before feedback loop detection
1720 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1721
1722 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
1723
1724 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
1725 // it should be NO_ERROR"
1726 EXPECT_GL_ERROR(expectedError);
1727}
1728
Yuly Novikov817232e2017-02-22 18:36:10 -05001729// Tests invariance matching rules between built in varyings.
1730// Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html.
1731TEST_P(WebGLCompatibilityTest, BuiltInInvariant)
1732{
1733 const std::string vertexShaderVariant =
1734 "varying vec4 v_varying;\n"
1735 "void main()\n"
1736 "{\n"
1737 " gl_PointSize = 1.0;\n"
1738 " gl_Position = v_varying;\n"
1739 "}";
1740 const std::string fragmentShaderInvariantGlFragCoord =
1741 "invariant gl_FragCoord;\n"
1742 "void main()\n"
1743 "{\n"
1744 " gl_FragColor = gl_FragCoord;\n"
1745 "}";
1746 const std::string fragmentShaderInvariantGlPointCoord =
1747 "invariant gl_PointCoord;\n"
1748 "void main()\n"
1749 "{\n"
1750 " gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);\n"
1751 "}";
1752
1753 GLuint program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlFragCoord);
1754 EXPECT_EQ(0u, program);
1755
1756 program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlPointCoord);
1757 EXPECT_EQ(0u, program);
1758}
1759
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04001760// Tests global namespace conflicts between uniforms and attributes.
1761// Based on WebGL test conformance/glsl/misc/shaders-with-name-conflicts.html.
1762TEST_P(WebGLCompatibilityTest, GlobalNamesConflict)
1763{
1764 const std::string vertexShader =
1765 "attribute vec4 foo;\n"
1766 "void main()\n"
1767 "{\n"
1768 " gl_Position = foo;\n"
1769 "}";
1770 const std::string fragmentShader =
1771 "precision mediump float;\n"
1772 "uniform vec4 foo;\n"
1773 "void main()\n"
1774 "{\n"
1775 " gl_FragColor = foo;\n"
1776 "}";
1777
1778 GLuint program = CompileProgram(vertexShader, fragmentShader);
1779 EXPECT_EQ(0u, program);
1780}
1781
Geoff Lang966c9402017-04-18 12:38:27 -04001782// Test dimension and image size validation of compressed textures
1783TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
1784{
1785 if (extensionRequestable("GL_EXT_texture_compression_dxt1"))
1786 {
1787 glRequestExtensionANGLE("GL_EXT_texture_compression_dxt1");
1788 }
1789
1790 if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
1791 {
1792 std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available."
1793 << std::endl;
1794 return;
1795 }
1796
1797 constexpr uint8_t CompressedImageDXT1[] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
1798
1799 GLTexture texture;
1800 glBindTexture(GL_TEXTURE_2D, texture);
1801
1802 // Regular case, verify that it works
1803 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
1804 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1805 ASSERT_GL_NO_ERROR();
1806
1807 // Test various dimensions that are not valid
1808 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3, 4, 0,
1809 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1810 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1811
1812 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 3, 0,
1813 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1814 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1815
1816 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
1817 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1818 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1819
1820 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
1821 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1822 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1823
1824 // Test various image sizes that are not valid
1825 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
1826 sizeof(CompressedImageDXT1) - 1, CompressedImageDXT1);
1827 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1828
1829 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
1830 sizeof(CompressedImageDXT1) + 1, CompressedImageDXT1);
1831 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1832
1833 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 0,
1834 CompressedImageDXT1);
1835 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1836
1837 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0, 0,
1838 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1839 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1840
1841 // Fill a full mip chain and verify that it works
1842 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
1843 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1844 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
1845 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1846 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
1847 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1848 ASSERT_GL_NO_ERROR();
1849
1850 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
1851 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1852 ASSERT_GL_NO_ERROR();
1853
1854 // Test that non-block size sub-uploads are not valid for the 0 mip
1855 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
1856 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1857 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1858
1859 // Test that non-block size sub-uploads are valid for if they fill the whole mip
1860 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
1861 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1862 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, 1, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
1863 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1864 ASSERT_GL_NO_ERROR();
1865
1866 // Test that if the format miss-matches the texture, an error is generated
1867 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
1868 sizeof(CompressedImageDXT1), CompressedImageDXT1);
1869 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1870}
1871
Geoff Lang677bb6f2017-04-05 12:40:40 -04001872TEST_P(WebGLCompatibilityTest, L32FTextures)
1873{
1874 constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f};
1875 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 1.0f};
1876
1877 for (auto extension : FloatingPointTextureExtensions)
1878 {
1879 if (strlen(extension) > 0 && extensionRequestable(extension))
1880 {
1881 glRequestExtensionANGLE(extension);
1882 ASSERT_GL_NO_ERROR();
1883 }
1884
1885 // Unsized L 32F
1886 {
1887 bool texture = extensionEnabled("GL_OES_texture_float");
1888 bool filter = extensionEnabled("GL_OES_texture_float_linear");
1889 bool render = false;
1890 TestFloatTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, texture, filter, render,
1891 textureData, readPixelData);
1892 }
1893
1894 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
1895 {
1896 // Sized L 32F
1897 bool texture = extensionEnabled("GL_OES_texture_float") &&
1898 extensionEnabled("GL_EXT_texture_storage");
1899 bool filter = extensionEnabled("GL_OES_texture_float_linear");
1900 bool render = false;
1901 TestFloatTextureFormat(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT, texture, filter,
1902 render, textureData, readPixelData);
1903 }
1904 }
1905}
1906
1907TEST_P(WebGLCompatibilityTest, A32FTextures)
1908{
1909 constexpr float textureData[] = {33.33f, 0.0f, 0.0f, 0.0f};
1910 constexpr float readPixelData[] = {0.0f, 0.0f, 0.0f, textureData[0]};
1911
1912 for (auto extension : FloatingPointTextureExtensions)
1913 {
1914 if (strlen(extension) > 0 && extensionRequestable(extension))
1915 {
1916 glRequestExtensionANGLE(extension);
1917 ASSERT_GL_NO_ERROR();
1918 }
1919
1920 // Unsized A 32F
1921 {
1922 bool texture = extensionEnabled("GL_OES_texture_float");
1923 bool filter = extensionEnabled("GL_OES_texture_float_linear");
1924 bool render = false;
1925 TestFloatTextureFormat(GL_ALPHA, GL_ALPHA, GL_FLOAT, texture, filter, render,
1926 textureData, readPixelData);
1927 }
1928
1929 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
1930 {
1931 // Sized A 32F
1932 bool texture = extensionEnabled("GL_OES_texture_float") &&
1933 extensionEnabled("GL_EXT_texture_storage");
1934 bool filter = extensionEnabled("GL_OES_texture_float_linear");
1935 bool render = false;
1936 TestFloatTextureFormat(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT, texture, filter, render,
1937 textureData, readPixelData);
1938 }
1939 }
1940}
1941
1942TEST_P(WebGLCompatibilityTest, LA32FTextures)
1943{
1944 constexpr float textureData[] = {-0.21f, 15.1f, 0.0f, 0.0f};
1945 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0],
1946 textureData[1]};
1947
1948 for (auto extension : FloatingPointTextureExtensions)
1949 {
1950 if (strlen(extension) > 0 && extensionRequestable(extension))
1951 {
1952 glRequestExtensionANGLE(extension);
1953 ASSERT_GL_NO_ERROR();
1954 }
1955
1956 // Unsized LA 32F
1957 {
1958 bool texture = extensionEnabled("GL_OES_texture_float");
1959 bool filter = extensionEnabled("GL_OES_texture_float_linear");
1960 bool render = false;
1961 TestFloatTextureFormat(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
1962 filter, render, textureData, readPixelData);
1963 }
1964
1965 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
1966 {
1967 // Sized LA 32F
1968 bool texture = extensionEnabled("GL_OES_texture_float") &&
1969 extensionEnabled("GL_EXT_texture_storage");
1970 bool filter = extensionEnabled("GL_OES_texture_float_linear");
1971 bool render = false;
1972 TestFloatTextureFormat(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
1973 filter, render, textureData, readPixelData);
1974 }
1975 }
1976}
1977
1978TEST_P(WebGLCompatibilityTest, R32FTextures)
1979{
1980 constexpr float data[] = {1000.0f, 0.0f, 0.0f, 1.0f};
1981
1982 for (auto extension : FloatingPointTextureExtensions)
1983 {
1984 if (strlen(extension) > 0 && extensionRequestable(extension))
1985 {
1986 glRequestExtensionANGLE(extension);
1987 ASSERT_GL_NO_ERROR();
1988 }
1989
1990 // Unsized R 32F
1991 {
1992 bool texture =
1993 extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg");
1994 bool filter = extensionEnabled("GL_OES_texture_float_linear");
1995 bool render = extensionEnabled("GL_EXT_color_buffer_float");
1996 TestFloatTextureFormat(GL_RED, GL_RED, GL_FLOAT, texture, filter, render, data, data);
1997 }
1998
1999 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2000 {
2001 // Sized R 32F
2002 bool texture =
2003 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2004 extensionEnabled("GL_EXT_texture_rg") &&
2005 extensionEnabled("GL_EXT_texture_storage"));
2006 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2007 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2008 TestFloatTextureFormat(GL_R32F, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2009 }
2010 }
2011}
2012
2013TEST_P(WebGLCompatibilityTest, RG32FTextures)
2014{
2015 constexpr float data[] = {1000.0f, -0.001f, 0.0f, 1.0f};
2016
2017 for (auto extension : FloatingPointTextureExtensions)
2018 {
2019 if (strlen(extension) > 0 && extensionRequestable(extension))
2020 {
2021 glRequestExtensionANGLE(extension);
2022 ASSERT_GL_NO_ERROR();
2023 }
2024
2025 // Unsized RG 32F
2026 {
2027 bool texture =
2028 (extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg"));
2029 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2030 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2031 TestFloatTextureFormat(GL_RG, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2032 }
2033
2034 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2035 {
2036 // Sized RG 32F
2037 bool texture =
2038 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2039 extensionEnabled("GL_EXT_texture_rg") &&
2040 extensionEnabled("GL_EXT_texture_storage"));
2041 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2042 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2043 TestFloatTextureFormat(GL_RG32F, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2044 }
2045 }
2046}
2047
2048TEST_P(WebGLCompatibilityTest, RGB32FTextures)
2049{
Geoff Lang40762ef2017-05-08 13:47:03 -04002050 if (IsLinux() && IsIntel())
2051 {
2052 std::cout << "Test skipped on Linux Intel." << std::endl;
2053 return;
2054 }
2055
Geoff Lang677bb6f2017-04-05 12:40:40 -04002056 constexpr float data[] = {1000.0f, -500.0f, 10.0f, 1.0f};
2057
2058 for (auto extension : FloatingPointTextureExtensions)
2059 {
2060 if (strlen(extension) > 0 && extensionRequestable(extension))
2061 {
2062 glRequestExtensionANGLE(extension);
2063 ASSERT_GL_NO_ERROR();
2064 }
2065
2066 // Unsized RGB 32F
2067 {
2068 bool texture = extensionEnabled("GL_OES_texture_float");
2069 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2070 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2071 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_FLOAT, texture, filter, render, data, data);
2072 }
2073
2074 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2075 {
2076 // Sized RGBA 32F
2077 bool texture =
2078 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2079 extensionEnabled("GL_EXT_texture_storage"));
2080 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2081 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2082 TestFloatTextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT, texture, filter, render, data,
2083 data);
2084 }
2085 }
2086}
2087
2088TEST_P(WebGLCompatibilityTest, RGBA32FTextures)
2089{
2090 constexpr float data[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2091
2092 for (auto extension : FloatingPointTextureExtensions)
2093 {
2094 if (strlen(extension) > 0 && extensionRequestable(extension))
2095 {
2096 glRequestExtensionANGLE(extension);
2097 ASSERT_GL_NO_ERROR();
2098 }
2099
2100 // Unsized RGBA 32F
2101 {
2102 bool texture = extensionEnabled("GL_OES_texture_float");
2103 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2104 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2105 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2106 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_FLOAT, texture, filter, render, data, data);
2107 }
2108
2109 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2110 {
2111 // Sized RGBA 32F
2112 bool texture =
2113 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2114 extensionEnabled("GL_EXT_texture_storage"));
2115 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2116 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2117 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2118 TestFloatTextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT, texture, filter, render, data,
2119 data);
2120 }
2121 }
2122}
2123
2124TEST_P(WebGLCompatibilityTest, R16FTextures)
2125{
2126 constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
2127 const GLushort textureData[] = {
2128 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2129 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2130
2131 for (auto extension : FloatingPointTextureExtensions)
2132 {
2133 if (strlen(extension) > 0 && extensionRequestable(extension))
2134 {
2135 glRequestExtensionANGLE(extension);
2136 ASSERT_GL_NO_ERROR();
2137 }
2138
2139 // Unsized R 16F (OES)
2140 {
2141 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2142 extensionEnabled("GL_EXT_texture_rg");
2143 bool filter = getClientMajorVersion() >= 3 ||
2144 extensionEnabled("GL_OES_texture_half_float_linear");
2145 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2146 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render,
2147 textureData, readPixelsData);
2148 }
2149
2150 // Unsized R 16F
2151 {
2152 bool texture = false;
2153 bool filter = false;
2154 bool render = false;
2155 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2156 textureData, readPixelsData);
2157 }
2158
2159 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2160 {
2161 // Sized R 16F
2162 bool texture = getClientMajorVersion() >= 3;
2163 bool filter = getClientMajorVersion() >= 3 ||
2164 extensionEnabled("GL_OES_texture_half_float_linear");
2165 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2166 extensionEnabled("GL_EXT_color_buffer_float");
2167 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2168 textureData, readPixelsData);
2169 }
2170 }
2171}
2172
2173TEST_P(WebGLCompatibilityTest, RG16FTextures)
2174{
2175 constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f};
2176 const GLushort textureData[] = {
2177 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2178 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2179
2180 for (auto extension : FloatingPointTextureExtensions)
2181 {
2182 if (strlen(extension) > 0 && extensionRequestable(extension))
2183 {
2184 glRequestExtensionANGLE(extension);
2185 ASSERT_GL_NO_ERROR();
2186 }
2187
2188 // Unsized RG 16F (OES)
2189 {
2190 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2191 extensionEnabled("GL_EXT_texture_rg");
2192 bool filter = getClientMajorVersion() >= 3 ||
2193 extensionEnabled("GL_OES_texture_half_float_linear");
2194 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") &&
2195 extensionEnabled("GL_EXT_texture_rg");
2196 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render,
2197 textureData, readPixelsData);
2198 }
2199
2200 // Unsized RG 16F
2201 {
2202 bool texture = false;
2203 bool filter = false;
2204 bool render = false;
2205 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2206 textureData, readPixelsData);
2207 }
2208
2209 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2210 {
2211 // Sized RG 16F
2212 bool texture = getClientMajorVersion() >= 3;
2213 bool filter = getClientMajorVersion() >= 3 ||
2214 extensionEnabled("GL_OES_texture_half_float_linear");
2215 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2216 extensionEnabled("GL_EXT_color_buffer_float");
2217 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2218 textureData, readPixelsData);
2219 }
2220 }
2221}
2222
2223TEST_P(WebGLCompatibilityTest, RGB16FTextures)
2224{
Geoff Lang40762ef2017-05-08 13:47:03 -04002225 if (IsOzone() && IsIntel())
2226 {
2227 std::cout << "Test skipped on Intel Ozone." << std::endl;
2228 return;
2229 }
2230
Geoff Lang677bb6f2017-04-05 12:40:40 -04002231 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f};
2232 const GLushort textureData[] = {
2233 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2234 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2235
2236 for (auto extension : FloatingPointTextureExtensions)
2237 {
2238 if (strlen(extension) > 0 && extensionRequestable(extension))
2239 {
2240 glRequestExtensionANGLE(extension);
2241 ASSERT_GL_NO_ERROR();
2242 }
2243
2244 // Unsized RGB 16F (OES)
2245 {
2246 bool texture = extensionEnabled("GL_OES_texture_half_float");
2247 bool filter = getClientMajorVersion() >= 3 ||
2248 extensionEnabled("GL_OES_texture_half_float_linear");
2249 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2250 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render,
2251 textureData, readPixelsData);
2252 }
2253
2254 // Unsized RGB 16F
2255 {
2256 bool texture = false;
2257 bool filter = false;
2258 bool render = false;
2259 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2260 textureData, readPixelsData);
2261 }
2262
2263 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2264 {
2265 // Sized RGB 16F
2266 bool texture = getClientMajorVersion() >= 3;
2267 bool filter = getClientMajorVersion() >= 3 ||
2268 extensionEnabled("GL_OES_texture_half_float_linear");
2269 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2270 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2271 textureData, readPixelsData);
2272 }
2273 }
2274}
2275
2276TEST_P(WebGLCompatibilityTest, RGBA16FTextures)
2277{
Geoff Lang40762ef2017-05-08 13:47:03 -04002278 if (IsOzone() && IsIntel())
2279 {
2280 std::cout << "Test skipped on Intel Ozone." << std::endl;
2281 return;
2282 }
2283
Geoff Lang677bb6f2017-04-05 12:40:40 -04002284 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2285 const GLushort textureData[] = {
2286 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2287 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2288
2289 for (auto extension : FloatingPointTextureExtensions)
2290 {
2291 if (strlen(extension) > 0 && extensionRequestable(extension))
2292 {
2293 glRequestExtensionANGLE(extension);
2294 ASSERT_GL_NO_ERROR();
2295 }
2296
2297 // Unsized RGBA 16F (OES)
2298 {
2299 bool texture = extensionEnabled("GL_OES_texture_half_float");
2300 bool filter = getClientMajorVersion() >= 3 ||
2301 extensionEnabled("GL_OES_texture_half_float_linear");
2302 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2303 extensionEnabled("GL_EXT_color_buffer_float");
2304 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render,
2305 textureData, readPixelsData);
2306 }
2307
2308 // Unsized RGBA 16F
2309 {
2310 bool texture = false;
2311 bool filter = false;
2312 bool render = false;
2313 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2314 textureData, readPixelsData);
2315 }
2316
2317 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2318 {
2319 // Sized RGBA 16F
2320 bool texture = getClientMajorVersion() >= 3;
2321 bool filter = getClientMajorVersion() >= 3 ||
2322 extensionEnabled("GL_OES_texture_half_float_linear");
2323 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2324 extensionEnabled("GL_EXT_color_buffer_float");
2325 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2326 textureData, readPixelsData);
2327 }
2328 }
2329}
2330
Geoff Lang6e898aa2017-06-02 11:17:26 -04002331// Test that when GL_CHROMIUM_color_buffer_float_rgb[a] is enabled, sized GL_RGB[A]_32F formats are
2332// accepted by glTexImage2D
2333TEST_P(WebGLCompatibilityTest, SizedRGBA32FFormats)
2334{
2335 if (getClientMajorVersion() != 2)
2336 {
2337 std::cout << "Test skipped because it is only valid for WebGL1 contexts." << std::endl;
2338 return;
2339 }
2340
2341 if (!extensionRequestable("GL_OES_texture_float"))
2342 {
2343 std::cout << "Test skipped because GL_OES_texture_float is not requestable." << std::endl;
2344 return;
2345 }
2346 glRequestExtensionANGLE("GL_OES_texture_float");
2347 ASSERT_GL_NO_ERROR();
2348
2349 GLTexture texture;
2350 glBindTexture(GL_TEXTURE_2D, texture);
2351
2352 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2353 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2354
2355 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2356 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2357
2358 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgba"))
2359 {
2360 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgba");
2361 ASSERT_GL_NO_ERROR();
2362
2363 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2364 EXPECT_GL_NO_ERROR();
2365 }
2366
2367 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgb"))
2368 {
2369 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgb");
2370 ASSERT_GL_NO_ERROR();
2371
2372 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2373 EXPECT_GL_NO_ERROR();
2374 }
2375}
2376
Jamie Madill07be8bf2017-02-02 19:59:57 -05002377// This tests that rendering feedback loops works as expected with WebGL 2.
2378// Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html
2379TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers)
2380{
2381 const std::string vertexShader =
2382 "#version 300 es\n"
2383 "in vec4 aPosition;\n"
2384 "out vec2 texCoord;\n"
2385 "void main() {\n"
2386 " gl_Position = aPosition;\n"
2387 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2388 "}\n";
2389
2390 const std::string fragmentShader =
2391 "#version 300 es\n"
2392 "precision mediump float;\n"
2393 "uniform sampler2D tex;\n"
2394 "in vec2 texCoord;\n"
2395 "out vec4 oColor;\n"
2396 "void main() {\n"
2397 " oColor = texture(tex, texCoord);\n"
2398 "}\n";
2399
2400 GLsizei width = 8;
2401 GLsizei height = 8;
2402
2403 GLint maxDrawBuffers = 0;
2404 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2405 // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS.
2406 ASSERT_GE(maxDrawBuffers, 2);
2407
2408 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2409 glUseProgram(program.get());
2410 glViewport(0, 0, width, height);
2411
2412 GLTexture tex0;
2413 GLTexture tex1;
2414 GLFramebuffer fbo;
2415 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2416 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2417 ASSERT_GL_NO_ERROR();
2418
2419 glBindTexture(GL_TEXTURE_2D, tex1.get());
2420 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2421 ASSERT_NE(-1, texLoc);
2422 glUniform1i(texLoc, 0);
2423
2424 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
2425 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2426 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2427 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
2428 ASSERT_GL_NO_ERROR();
2429
2430 drawBuffersFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION);
2431 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
2432 GL_INVALID_OPERATION);
2433 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
2434}
2435
Jamie Madill1d37bc52017-02-02 19:59:58 -05002436// This test covers detection of rendering feedback loops between the FBO and a depth Texture.
2437// Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html
2438TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil)
2439{
2440 const std::string vertexShader =
2441 "#version 300 es\n"
2442 "in vec4 aPosition;\n"
2443 "out vec2 texCoord;\n"
2444 "void main() {\n"
2445 " gl_Position = aPosition;\n"
2446 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2447 "}\n";
2448
2449 const std::string fragmentShader =
2450 "#version 300 es\n"
2451 "precision mediump float;\n"
2452 "uniform sampler2D tex;\n"
2453 "in vec2 texCoord;\n"
2454 "out vec4 oColor;\n"
2455 "void main() {\n"
2456 " oColor = texture(tex, texCoord);\n"
2457 "}\n";
2458
2459 GLsizei width = 8;
2460 GLsizei height = 8;
2461
2462 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2463 glUseProgram(program.get());
2464
2465 glViewport(0, 0, width, height);
2466
2467 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2468 glUniform1i(texLoc, 0);
2469
2470 // Create textures and allocate storage
2471 GLTexture tex0;
2472 GLTexture tex1;
2473 GLRenderbuffer rb;
2474 FillTexture2D(tex0.get(), width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2475 FillTexture2D(tex1.get(), width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
2476 GL_UNSIGNED_INT);
2477 glBindRenderbuffer(GL_RENDERBUFFER, rb.get());
2478 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
2479 ASSERT_GL_NO_ERROR();
2480
2481 GLFramebuffer fbo;
2482 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2483 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2484
2485 // Test rendering and sampling feedback loop for depth buffer
2486 glBindTexture(GL_TEXTURE_2D, tex1.get());
2487 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1.get(), 0);
2488 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2489
2490 // The same image is used as depth buffer during rendering.
2491 glEnable(GL_DEPTH_TEST);
2492 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2493 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2494
2495 // The same image is used as depth buffer. But depth mask is false.
2496 glDepthMask(GL_FALSE);
2497 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2498 EXPECT_GL_NO_ERROR();
2499
2500 // The same image is used as depth buffer. But depth test is not enabled during rendering.
2501 glDepthMask(GL_TRUE);
2502 glDisable(GL_DEPTH_TEST);
2503 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2504 EXPECT_GL_NO_ERROR();
2505
2506 // Test rendering and sampling feedback loop for stencil buffer
2507 glBindTexture(GL_RENDERBUFFER, rb.get());
2508 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
2509 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb.get());
2510 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2511 constexpr GLint stencilClearValue = 0x40;
2512 glClearBufferiv(GL_STENCIL, 0, &stencilClearValue);
2513
2514 // The same image is used as stencil buffer during rendering.
2515 glEnable(GL_STENCIL_TEST);
2516 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2517 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2518
2519 // The same image is used as stencil buffer. But stencil mask is zero.
2520 glStencilMask(0x0);
2521 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2522 EXPECT_GL_NO_ERROR();
2523
2524 // The same image is used as stencil buffer. But stencil test is not enabled during rendering.
2525 glStencilMask(0xffff);
2526 glDisable(GL_STENCIL_TEST);
2527 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
2528 EXPECT_GL_NO_ERROR();
2529}
2530
Jamie Madillfd3dd432017-02-02 19:59:59 -05002531// The source and the target for CopyTexSubImage3D are the same 3D texture.
2532// But the level of the 3D texture != the level of the read attachment.
2533TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels)
2534{
2535 GLTexture texture;
2536 GLFramebuffer framebuffer;
2537
2538 glBindTexture(GL_TEXTURE_3D, texture.get());
2539 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2540
2541 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2542 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2543 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
2544 ASSERT_GL_NO_ERROR();
2545
2546 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
2547 EXPECT_GL_NO_ERROR();
2548}
2549
2550// The source and the target for CopyTexSubImage3D are the same 3D texture.
2551// But the zoffset of the 3D texture != the layer of the read attachment.
2552TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers)
2553{
2554 GLTexture texture;
2555 GLFramebuffer framebuffer;
2556
2557 glBindTexture(GL_TEXTURE_3D, texture.get());
2558 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2559
2560 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2561 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 1);
2562 ASSERT_GL_NO_ERROR();
2563
2564 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2);
2565 EXPECT_GL_NO_ERROR();
2566}
2567
2568// The source and the target for CopyTexSubImage3D are the same 3D texture.
2569// And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment.
2570TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D)
2571{
2572 GLTexture texture;
2573 GLFramebuffer framebuffer;
2574
2575 glBindTexture(GL_TEXTURE_3D, texture.get());
2576 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2577
2578 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2579 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2580 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2581 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 1, 0);
2582 ASSERT_GL_NO_ERROR();
2583
2584 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
2585 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2586}
2587
Corentin Wallez59c41592017-07-11 13:19:54 -04002588// Verify that errors are generated when there isn't a defined conversion between the clear type and
2589// the buffer type.
Geoff Lang76e65652017-03-27 14:58:02 -04002590TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity)
2591{
2592 if (IsD3D11())
2593 {
2594 std::cout << "Test skipped because it generates D3D11 runtime warnings." << std::endl;
2595 return;
2596 }
2597
2598 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
2599 constexpr int clearInt[] = {0, 0, 0, 0};
2600 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
2601
2602 GLTexture texture;
2603 GLFramebuffer framebuffer;
2604
2605 glBindTexture(GL_TEXTURE_2D, texture.get());
2606 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2607
2608 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2609 ASSERT_GL_NO_ERROR();
2610
2611 // Unsigned integer buffer
2612 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr);
2613 ASSERT_GL_NO_ERROR();
2614
2615 glClearBufferfv(GL_COLOR, 0, clearFloat);
2616 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2617
2618 glClearBufferiv(GL_COLOR, 0, clearInt);
2619 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2620
2621 glClearBufferuiv(GL_COLOR, 0, clearUint);
2622 EXPECT_GL_NO_ERROR();
2623
2624 glClear(GL_COLOR_BUFFER_BIT);
2625 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2626
2627 // Integer buffer
2628 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr);
2629 ASSERT_GL_NO_ERROR();
2630
2631 glClearBufferfv(GL_COLOR, 0, clearFloat);
2632 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2633
2634 glClearBufferiv(GL_COLOR, 0, clearInt);
2635 EXPECT_GL_NO_ERROR();
2636
2637 glClearBufferuiv(GL_COLOR, 0, clearUint);
2638 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2639
2640 glClear(GL_COLOR_BUFFER_BIT);
2641 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2642
2643 // Float buffer
Geoff Lang677bb6f2017-04-05 12:40:40 -04002644 if (extensionRequestable("GL_EXT_color_buffer_float"))
2645 {
2646 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
2647 }
Geoff Lang76e65652017-03-27 14:58:02 -04002648
Geoff Lang677bb6f2017-04-05 12:40:40 -04002649 if (extensionEnabled("GL_EXT_color_buffer_float"))
2650 {
2651 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2652 ASSERT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04002653
Geoff Lang677bb6f2017-04-05 12:40:40 -04002654 glClearBufferfv(GL_COLOR, 0, clearFloat);
2655 EXPECT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04002656
Geoff Lang677bb6f2017-04-05 12:40:40 -04002657 glClearBufferiv(GL_COLOR, 0, clearInt);
2658 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang76e65652017-03-27 14:58:02 -04002659
Geoff Lang677bb6f2017-04-05 12:40:40 -04002660 glClearBufferuiv(GL_COLOR, 0, clearUint);
2661 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2662
2663 glClear(GL_COLOR_BUFFER_BIT);
2664 EXPECT_GL_NO_ERROR();
2665 }
Geoff Lang76e65652017-03-27 14:58:02 -04002666
2667 // Normalized uint buffer
2668 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2669 ASSERT_GL_NO_ERROR();
2670
2671 glClearBufferfv(GL_COLOR, 0, clearFloat);
2672 EXPECT_GL_NO_ERROR();
2673
2674 glClearBufferiv(GL_COLOR, 0, clearInt);
2675 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2676
2677 glClearBufferuiv(GL_COLOR, 0, clearUint);
2678 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2679
2680 glClear(GL_COLOR_BUFFER_BIT);
2681 EXPECT_GL_NO_ERROR();
2682}
2683
Corentin Wallez59c41592017-07-11 13:19:54 -04002684// Test the interaction of WebGL compatibility clears with default framebuffers
2685TEST_P(WebGL2CompatibilityTest, ClearBufferDefaultFramebuffer)
2686{
2687 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
2688 constexpr int clearInt[] = {0, 0, 0, 0};
2689 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
2690
2691 // glClear works as usual, this is also a regression test for a bug where we
2692 // iterated on maxDrawBuffers for default framebuffers, triggering an assert
2693 glClear(GL_COLOR_BUFFER_BIT);
2694 EXPECT_GL_NO_ERROR();
2695
2696 // Default framebuffers are normalized uints, so only glClearBufferfv works.
2697 glClearBufferfv(GL_COLOR, 0, clearFloat);
2698 EXPECT_GL_NO_ERROR();
2699
2700 glClearBufferiv(GL_COLOR, 0, clearInt);
2701 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2702
2703 glClearBufferuiv(GL_COLOR, 0, clearUint);
2704 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2705}
2706
Geoff Lange4915782017-04-12 15:19:07 -04002707// Verify that errors are generate when trying to blit from an image to itself
2708TEST_P(WebGL2CompatibilityTest, BlitFramebufferSameImage)
2709{
2710 GLTexture textures[2];
2711 glBindTexture(GL_TEXTURE_2D, textures[0]);
2712 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
2713 glBindTexture(GL_TEXTURE_2D, textures[1]);
2714 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
2715
2716 GLRenderbuffer renderbuffers[2];
2717 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
2718 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
2719 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
2720 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
2721
2722 GLFramebuffer framebuffers[2];
2723 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]);
2724 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]);
2725
2726 ASSERT_GL_NO_ERROR();
2727
2728 // Same texture
2729 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
2730 0);
2731 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
2732 0);
2733 ASSERT_GL_NO_ERROR();
2734 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2735 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2736
2737 // Same textures but different renderbuffers
2738 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2739 renderbuffers[0]);
2740 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2741 renderbuffers[1]);
2742 ASSERT_GL_NO_ERROR();
2743 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
2744 ASSERT_GL_NO_ERROR();
2745 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
2746 GL_NEAREST);
2747 ASSERT_GL_NO_ERROR();
2748 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
2749 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
2750 GL_NEAREST);
2751 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2752
2753 // Same renderbuffers but different textures
2754 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
2755 0);
2756 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1],
2757 0);
2758 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2759 renderbuffers[0]);
2760 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2761 renderbuffers[0]);
2762 ASSERT_GL_NO_ERROR();
2763 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2764 ASSERT_GL_NO_ERROR();
2765 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
2766 GL_NEAREST);
2767 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2768 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
2769 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
2770 GL_NEAREST);
2771 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2772}
2773
Geoff Lange0cff192017-05-30 13:04:56 -04002774// Verify that errors are generated when the fragment shader output doesn't match the bound color
2775// buffer types
2776TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch)
2777{
2778 const std::string vertexShader =
2779 "#version 300 es\n"
2780 "void main() {\n"
2781 " gl_Position = vec4(0, 0, 0, 1);\n"
2782 "}\n";
2783
2784 const std::string fragmentShader =
2785 "#version 300 es\n"
2786 "precision mediump float;\n"
2787 "layout(location = 0) out vec4 floatOutput;\n"
2788 "layout(location = 1) out uvec4 uintOutput;\n"
2789 "layout(location = 2) out ivec4 intOutput;\n"
2790 "void main() {\n"
2791 " floatOutput = vec4(0, 0, 0, 1);\n"
2792 " uintOutput = uvec4(0, 0, 0, 1);\n"
2793 " intOutput = ivec4(0, 0, 0, 1);\n"
2794 "}\n";
2795
2796 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2797 glUseProgram(program.get());
2798
2799 GLuint floatLocation = glGetFragDataLocation(program, "floatOutput");
2800 GLuint uintLocation = glGetFragDataLocation(program, "uintOutput");
2801 GLuint intLocation = glGetFragDataLocation(program, "intOutput");
2802
2803 GLFramebuffer fbo;
2804 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2805
2806 GLRenderbuffer floatRenderbuffer;
2807 glBindRenderbuffer(GL_RENDERBUFFER, floatRenderbuffer);
2808 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2809 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
2810 floatRenderbuffer);
2811
2812 GLRenderbuffer uintRenderbuffer;
2813 glBindRenderbuffer(GL_RENDERBUFFER, uintRenderbuffer);
2814 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 1, 1);
2815 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
2816 uintRenderbuffer);
2817
2818 GLRenderbuffer intRenderbuffer;
2819 glBindRenderbuffer(GL_RENDERBUFFER, intRenderbuffer);
2820 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 1, 1);
2821 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
2822 intRenderbuffer);
2823
2824 ASSERT_GL_NO_ERROR();
2825
2826 GLint maxDrawBuffers = 0;
2827 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2828 std::vector<GLenum> drawBuffers(static_cast<size_t>(maxDrawBuffers), GL_NONE);
2829 drawBuffers[floatLocation] = GL_COLOR_ATTACHMENT0 + floatLocation;
2830 drawBuffers[uintLocation] = GL_COLOR_ATTACHMENT0 + uintLocation;
2831 drawBuffers[intLocation] = GL_COLOR_ATTACHMENT0 + intLocation;
2832
2833 glDrawBuffers(maxDrawBuffers, drawBuffers.data());
2834
2835 // Check that the correct case generates no errors
2836 glDrawArrays(GL_TRIANGLES, 0, 6);
2837 EXPECT_GL_NO_ERROR();
2838
2839 // Unbind some buffers and verify that there are still no errors
2840 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
2841 0);
2842 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
2843 0);
2844 glDrawArrays(GL_TRIANGLES, 0, 6);
2845 EXPECT_GL_NO_ERROR();
2846
2847 // Swap the int and uint buffers to and verify that an error is generated
2848 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
2849 intRenderbuffer);
2850 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
2851 uintRenderbuffer);
2852 glDrawArrays(GL_TRIANGLES, 0, 6);
2853 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2854
2855 // Swap the float and uint buffers to and verify that an error is generated
2856 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
2857 floatRenderbuffer);
2858 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
2859 uintRenderbuffer);
2860 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
2861 intRenderbuffer);
2862 glDrawArrays(GL_TRIANGLES, 0, 6);
2863 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2864}
2865
Geoff Lang9ab5b822017-05-30 16:19:23 -04002866// Verify that errors are generated when the vertex shader intput doesn't match the bound attribute
2867// types
2868TEST_P(WebGL2CompatibilityTest, VertexShaderAttributeTypeMissmatch)
2869{
2870 const std::string vertexShader =
2871 "#version 300 es\n"
2872 "in vec4 floatInput;\n"
2873 "in uvec4 uintInput;\n"
2874 "in ivec4 intInput;\n"
2875 "void main() {\n"
2876 " gl_Position = vec4(floatInput.x, uintInput.x, intInput.x, 1);\n"
2877 "}\n";
2878
2879 const std::string fragmentShader =
2880 "#version 300 es\n"
2881 "precision mediump float;\n"
2882 "out vec4 outputColor;\n"
2883 "void main() {\n"
2884 " outputColor = vec4(0, 0, 0, 1);"
2885 "}\n";
2886
2887 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2888 glUseProgram(program.get());
2889
2890 GLint floatLocation = glGetAttribLocation(program, "floatInput");
2891 GLint uintLocation = glGetAttribLocation(program, "uintInput");
2892 GLint intLocation = glGetAttribLocation(program, "intInput");
2893
2894 // Default attributes are of float types
2895 glDrawArrays(GL_TRIANGLES, 0, 6);
2896 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2897
2898 // Set the default attributes to the correct types, should succeed
2899 glVertexAttribI4ui(uintLocation, 0, 0, 0, 1);
2900 glVertexAttribI4i(intLocation, 0, 0, 0, 1);
2901 glDrawArrays(GL_TRIANGLES, 0, 6);
2902 EXPECT_GL_NO_ERROR();
2903
2904 // Change the default float attribute to an integer, should fail
2905 glVertexAttribI4ui(floatLocation, 0, 0, 0, 1);
2906 glDrawArrays(GL_TRIANGLES, 0, 6);
2907 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2908
2909 // Use a buffer for some attributes
2910 GLBuffer buffer;
2911 glBindBuffer(GL_ARRAY_BUFFER, buffer);
2912 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
2913 glEnableVertexAttribArray(floatLocation);
2914 glVertexAttribPointer(floatLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
2915 glDrawArrays(GL_TRIANGLES, 0, 6);
2916 EXPECT_GL_NO_ERROR();
2917
2918 // Use a float pointer attrib for a uint input
2919 glEnableVertexAttribArray(uintLocation);
2920 glVertexAttribPointer(uintLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
2921 glDrawArrays(GL_TRIANGLES, 0, 6);
2922 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2923
2924 // Use a uint pointer for the uint input
2925 glVertexAttribIPointer(uintLocation, 4, GL_UNSIGNED_INT, 0, nullptr);
2926 glDrawArrays(GL_TRIANGLES, 0, 6);
2927 EXPECT_GL_NO_ERROR();
2928}
2929
Corentin Walleze7557742017-06-01 13:09:57 -04002930// Tests the WebGL removal of undefined behavior when attachments aren't written to.
2931TEST_P(WebGLCompatibilityTest, DrawBuffers)
2932{
Corentin Walleze7557742017-06-01 13:09:57 -04002933 // Make sure we can use at least 4 attachments for the tests.
2934 bool useEXT = false;
2935 if (getClientMajorVersion() < 3)
2936 {
2937 if (!extensionRequestable("GL_EXT_draw_buffers"))
2938 {
2939 std::cout << "Test skipped because draw buffers are not available" << std::endl;
2940 return;
2941 }
2942
2943 glRequestExtensionANGLE("GL_EXT_draw_buffers");
2944 useEXT = true;
2945 EXPECT_GL_NO_ERROR();
2946 }
2947
2948 GLint maxDrawBuffers = 0;
2949 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2950 if (maxDrawBuffers < 4)
2951 {
2952 std::cout << "Test skipped because MAX_DRAW_BUFFERS is too small." << std::endl;
2953 return;
2954 }
2955
2956 // Clears all the renderbuffers to red.
2957 auto ClearEverythingToRed = [](GLRenderbuffer *renderbuffers) {
2958 GLFramebuffer clearFBO;
2959 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, clearFBO);
2960
2961 glClearColor(1, 0, 0, 1);
2962 for (int i = 0; i < 4; ++i)
2963 {
2964 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2965 renderbuffers[i]);
2966 glClear(GL_COLOR_BUFFER_BIT);
2967 }
2968 ASSERT_GL_NO_ERROR();
2969 };
2970
2971 // Checks that the renderbuffers specified by mask have the correct color
2972 auto CheckColors = [](GLRenderbuffer *renderbuffers, int mask, GLColor color) {
2973 GLFramebuffer readFBO;
2974 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2975
2976 for (int i = 0; i < 4; ++i)
2977 {
2978 if (mask & (1 << i))
2979 {
2980 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2981 GL_RENDERBUFFER, renderbuffers[i]);
2982 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
2983 }
2984 }
2985 ASSERT_GL_NO_ERROR();
2986 };
2987
2988 // Depending on whether we are using the extension or ES3, a different entrypoint must be called
2989 auto DrawBuffers = [](bool useEXT, int numBuffers, GLenum *buffers) {
2990 if (useEXT)
2991 {
2992 glDrawBuffersEXT(numBuffers, buffers);
2993 }
2994 else
2995 {
2996 glDrawBuffers(numBuffers, buffers);
2997 }
2998 };
2999
3000 // Initialized the test framebuffer
3001 GLFramebuffer drawFBO;
3002 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3003
3004 GLRenderbuffer renderbuffers[4];
3005 for (int i = 0; i < 4; ++i)
3006 {
3007 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
3008 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
3009 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER,
3010 renderbuffers[i]);
3011 }
3012
3013 ASSERT_GL_NO_ERROR();
3014
3015 const char *vertESSL1 =
3016 "attribute vec4 a_pos;\n"
3017 "void main()\n"
3018 "{\n"
3019 " gl_Position = a_pos;\n"
3020 "}\n";
3021 const char *vertESSL3 =
3022 "#version 300 es\n"
3023 "in vec4 a_pos;\n"
3024 "void main()\n"
3025 "{\n"
3026 " gl_Position = a_pos;\n"
3027 "}\n";
3028
3029 GLenum allDrawBuffers[] = {
3030 GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3031 };
3032
3033 GLenum halfDrawBuffers[] = {
3034 GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3035 };
3036
3037 // Test that when using gl_FragColor, only the first attachment is written to.
3038 const char *fragESSL1 =
3039 "precision highp float;\n"
3040 "void main()\n"
3041 "{\n"
3042 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3043 "}\n";
3044 ANGLE_GL_PROGRAM(programESSL1, vertESSL1, fragESSL1);
3045
3046 {
3047 ClearEverythingToRed(renderbuffers);
3048
3049 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3050 DrawBuffers(useEXT, 4, allDrawBuffers);
3051 drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
3052 ASSERT_GL_NO_ERROR();
3053
3054 CheckColors(renderbuffers, 0b0001, GLColor::green);
3055 CheckColors(renderbuffers, 0b1110, GLColor::red);
3056 }
3057
3058 // Test that when using gl_FragColor, but the first draw buffer is 0, then no attachment is
3059 // written to.
3060 {
3061 ClearEverythingToRed(renderbuffers);
3062
3063 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3064 DrawBuffers(useEXT, 4, halfDrawBuffers);
3065 drawQuad(programESSL1, "a_pos", 0.5, 1.0, true);
3066 ASSERT_GL_NO_ERROR();
3067
3068 CheckColors(renderbuffers, 0b1111, GLColor::red);
3069 }
3070
3071 // Test what happens when rendering to a subset of the outputs. There is a behavior difference
3072 // between the extension and ES3. In the extension gl_FragData is implicitly declared as an
3073 // array of size MAX_DRAW_BUFFERS, so the WebGL spec stipulates that elements not written to
3074 // should default to 0. On the contrary, in ES3 outputs are specified one by one, so
3075 // attachments not declared in the shader should not be written to.
3076 const char *writeOddOutputsVert;
3077 const char *writeOddOutputsFrag;
3078 GLColor unwrittenColor;
3079 if (useEXT)
3080 {
3081 // In the extension, when an attachment isn't written to, it should get 0's
3082 unwrittenColor = GLColor(0, 0, 0, 0);
3083 writeOddOutputsVert = vertESSL1;
3084 writeOddOutputsFrag =
3085 "#extension GL_EXT_draw_buffers : require\n"
3086 "precision highp float;\n"
3087 "void main()\n"
3088 "{\n"
3089 " gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3090 " gl_FragData[3] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3091 "}\n";
3092 }
3093 else
3094 {
3095 // In ES3 if an attachment isn't declared, it shouldn't get written and should be red
3096 // because of the preceding clears.
3097 unwrittenColor = GLColor::red;
3098 writeOddOutputsVert = vertESSL3;
3099 writeOddOutputsFrag =
3100 "#version 300 es\n"
3101 "precision highp float;\n"
3102 "layout(location = 1) out vec4 output1;"
3103 "layout(location = 3) out vec4 output2;"
3104 "void main()\n"
3105 "{\n"
3106 " output1 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3107 " output2 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3108 "}\n";
3109 }
3110 ANGLE_GL_PROGRAM(writeOddOutputsProgram, writeOddOutputsVert, writeOddOutputsFrag);
3111
3112 // Test that attachments not written to get the "unwritten" color
3113 {
3114 ClearEverythingToRed(renderbuffers);
3115
3116 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3117 DrawBuffers(useEXT, 4, allDrawBuffers);
3118 drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
3119 ASSERT_GL_NO_ERROR();
3120
3121 CheckColors(renderbuffers, 0b1010, GLColor::green);
3122 CheckColors(renderbuffers, 0b0101, unwrittenColor);
3123 }
3124
3125 // Test that attachments not written to get the "unwritten" color but that even when the
3126 // extension is used, disabled attachments are not written at all and stay red.
3127 {
3128 ClearEverythingToRed(renderbuffers);
3129
3130 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3131 DrawBuffers(useEXT, 4, halfDrawBuffers);
3132 drawQuad(writeOddOutputsProgram, "a_pos", 0.5, 1.0, true);
3133 ASSERT_GL_NO_ERROR();
3134
3135 CheckColors(renderbuffers, 0b1000, GLColor::green);
3136 CheckColors(renderbuffers, 0b0100, unwrittenColor);
3137 CheckColors(renderbuffers, 0b0011, GLColor::red);
3138 }
3139}
3140
Geoff Lang536eca12017-09-13 11:23:35 -04003141// Test that it's possible to generate mipmaps on unsized floating point textures once the
3142// extensions have been enabled
3143TEST_P(WebGLCompatibilityTest, GenerateMipmapUnsizedFloatingPointTexture)
3144{
3145 if (extensionRequestable("GL_OES_texture_float"))
3146 {
3147 glRequestExtensionANGLE("GL_OES_texture_float");
3148 }
3149 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3150
3151 GLTexture texture;
3152 glBindTexture(GL_TEXTURE_2D, texture);
3153
3154 constexpr GLColor32F data[4] = {
3155 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3156 };
3157 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_FLOAT, data);
3158 ASSERT_GL_NO_ERROR();
3159
3160 glGenerateMipmap(GL_TEXTURE_2D);
3161 EXPECT_GL_NO_ERROR();
3162}
3163// Test that it's possible to generate mipmaps on unsized floating point textures once the
3164// extensions have been enabled
3165TEST_P(WebGLCompatibilityTest, GenerateMipmapSizedFloatingPointTexture)
3166{
3167 if (extensionRequestable("GL_OES_texture_float"))
3168 {
3169 glRequestExtensionANGLE("GL_OES_texture_float");
3170 }
3171 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3172
3173 if (extensionRequestable("GL_EXT_texture_storage"))
3174 {
3175 glRequestExtensionANGLE("GL_EXT_texture_storage");
3176 }
3177 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_storage"));
3178
3179 GLTexture texture;
3180 glBindTexture(GL_TEXTURE_2D, texture);
3181
3182 constexpr GLColor32F data[4] = {
3183 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3184 };
3185 glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA32F, 2, 2);
3186 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, data);
3187 ASSERT_GL_NO_ERROR();
3188
3189 glGenerateMipmap(GL_TEXTURE_2D);
3190 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3191
3192 if (extensionRequestable("GL_EXT_color_buffer_float"))
3193 {
3194 // Format is renderable but not filterable
3195 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3196 glGenerateMipmap(GL_TEXTURE_2D);
3197 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3198 }
3199
3200 if (extensionRequestable("GL_EXT_color_buffer_float_linear"))
3201 {
3202 // Format is renderable but not filterable
3203 glRequestExtensionANGLE("GL_EXT_color_buffer_float_linear");
3204
3205 if (extensionEnabled("GL_EXT_color_buffer_float"))
3206 {
3207 // Format is filterable and renderable
3208 glGenerateMipmap(GL_TEXTURE_2D);
3209 EXPECT_GL_NO_ERROR();
3210 }
3211 else
3212 {
3213 // Format is filterable but not renderable
3214 glGenerateMipmap(GL_TEXTURE_2D);
3215 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3216 }
3217 }
3218}
3219
Frank Henigmanfccbac22017-05-28 17:29:26 -04003220// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
3221// qualifiers.
3222TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch)
3223{
3224 const std::string vertexShader =
3225 "#version 300 es\n"
3226 "uniform Block { mediump vec4 val; };\n"
3227 "void main() { gl_Position = val; }\n";
3228 const std::string fragmentShader =
3229 "#version 300 es\n"
3230 "uniform Block { highp vec4 val; };\n"
3231 "out highp vec4 out_FragColor;\n"
3232 "void main() { out_FragColor = val; }\n";
3233
3234 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
3235 ASSERT_NE(0u, vs);
3236 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
3237 ASSERT_NE(0u, fs);
3238
3239 GLuint program = glCreateProgram();
3240
3241 glAttachShader(program, vs);
3242 glDeleteShader(vs);
3243 glAttachShader(program, fs);
3244 glDeleteShader(fs);
3245
3246 glLinkProgram(program);
3247 GLint linkStatus;
3248 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3249 ASSERT_EQ(0, linkStatus);
3250
3251 glDeleteProgram(program);
3252}
3253
Geoff Lang69df2422017-07-05 12:42:31 -04003254// Test no attribute vertex shaders
3255TEST_P(WebGL2CompatibilityTest, NoAttributeVertexShader)
3256{
3257 const std::string vertexShader =
3258 "#version 300 es\n"
3259 "void main()\n"
3260 "{\n"
3261 "\n"
3262 " ivec2 xy = ivec2(gl_VertexID % 2, (gl_VertexID / 2 + gl_VertexID / 3) % 2);\n"
3263 " gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1);\n"
3264 "}";
3265 const std::string fragmentShader =
3266 "#version 300 es\n"
3267 "precision mediump float;\n"
3268 "out vec4 result;\n"
3269 "void main()\n"
3270 "{\n"
3271 " result = vec4(0, 1, 0, 1);\n"
3272 "}";
3273
3274 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3275 glUseProgram(program);
3276
3277 glDrawArrays(GL_TRIANGLES, 0, 6);
3278 ASSERT_GL_NO_ERROR();
3279 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3280}
3281
Brandon Jonesed5b46f2017-07-21 08:39:17 -07003282// Tests bindAttribLocations for length limit
3283TEST_P(WebGL2CompatibilityTest, BindAttribLocationLimitation)
3284{
3285 constexpr int maxLocStringLength = 1024;
3286 const std::string tooLongString(maxLocStringLength + 1, '_');
3287
3288 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
3289
3290 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3291}
3292
Geoff Langc287ea62016-09-16 14:46:51 -04003293// Use this to select which configurations (e.g. which renderer, which GLES major version) these
3294// tests should be run against.
3295ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
3296 ES2_D3D9(),
3297 ES2_D3D11(),
3298 ES3_D3D11(),
Geoff Langc287ea62016-09-16 14:46:51 -04003299 ES2_OPENGL(),
3300 ES3_OPENGL(),
3301 ES2_OPENGLES(),
3302 ES3_OPENGLES());
3303
Jamie Madill07be8bf2017-02-02 19:59:57 -05003304ANGLE_INSTANTIATE_TEST(WebGL2CompatibilityTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Geoff Langc287ea62016-09-16 14:46:51 -04003305} // namespace