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