blob: a777e24e8dfd7f1fce9dc9437fa879da6e03759d [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
Geoff Lang025aafd2017-10-30 15:16:37 -0400430// Test enabling the EGL image extensions
431TEST_P(WebGLCompatibilityTest, EnableExtensionEGLImage)
432{
433 EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image"));
434 EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external"));
435 EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external_essl3"));
436 EXPECT_FALSE(extensionEnabled("NV_EGL_stream_consumer_external"));
437
438 const std::string &fragES2 =
439 "#extension GL_OES_EGL_image_external : require\n"
440 "precision highp float;\n"
441 "uniform samplerExternalOES sampler;\n"
442 "void main()\n"
443 "{\n"
444 " gl_FragColor = texture2D(sampler, vec2(0, 0));\n"
445 "}";
446 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, fragES2));
447
448 const std::string &fragES3 =
449 "#version 300 es\n"
450 "#extension GL_OES_EGL_image_external : require\n"
451 "precision highp float;\n"
452 "uniform samplerExternalOES sampler;\n"
453 "void main()\n"
454 "{\n"
455 " gl_FragColor = texture(sampler, vec2(0, 0));\n"
456 "}";
457 if (getClientMajorVersion() > 3)
458 {
459 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, fragES3));
460 }
461
462 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
463 EXPECT_GL_ERROR(GL_INVALID_ENUM);
464
465 GLint result;
466 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result);
467 EXPECT_GL_ERROR(GL_INVALID_ENUM);
468
469 if (extensionRequestable("GL_OES_EGL_image_external"))
470 {
471 glRequestExtensionANGLE("GL_OES_EGL_image_external");
472 EXPECT_GL_NO_ERROR();
473 EXPECT_TRUE(extensionEnabled("GL_OES_EGL_image_external"));
474
475 EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, fragES2));
476
477 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
478 EXPECT_GL_NO_ERROR();
479
480 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result);
481 EXPECT_GL_NO_ERROR();
482
483 if (getClientMajorVersion() > 3 && extensionRequestable("GL_OES_EGL_image_external_essl3"))
484 {
485 glRequestExtensionANGLE("GL_OES_EGL_image_external_essl3");
486 EXPECT_GL_NO_ERROR();
487 EXPECT_TRUE(extensionEnabled("GL_OES_EGL_image_external_essl3"));
488
489 EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, fragES3));
490 }
491 else
492 {
493 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, fragES3));
494 }
495 }
496}
497
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700498// Verify that shaders are of a compatible spec when the extension is enabled.
499TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec)
500{
501 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
502
503 // Use of reserved _webgl prefix should fail when the shader specification is for WebGL.
504 const std::string &vert =
505 "struct Foo {\n"
506 " int _webgl_bar;\n"
507 "};\n"
508 "void main()\n"
509 "{\n"
510 " Foo foo = Foo(1);\n"
511 "}";
512
513 // Default fragement shader.
514 const std::string &frag =
515 "void main()\n"
516 "{\n"
517 " gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n"
518 "}";
519
520 GLuint program = CompileProgram(vert, frag);
521 EXPECT_EQ(0u, program);
522 glDeleteProgram(program);
523}
524
Geoff Lang3fab7632017-09-26 15:45:54 -0400525// Test enabling the GL_NV_pixel_buffer_object extension
526TEST_P(WebGLCompatibilityTest, EnablePixelBufferObjectExtensions)
527{
528 EXPECT_FALSE(extensionEnabled("GL_NV_pixel_buffer_object"));
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_PIXEL_PACK_BUFFER, buffer);
537 EXPECT_GL_ERROR(GL_INVALID_ENUM);
538
539 if (extensionRequestable("GL_NV_pixel_buffer_object"))
540 {
541 glRequestExtensionANGLE("GL_NV_pixel_buffer_object");
542 EXPECT_GL_NO_ERROR();
543
544 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
545 EXPECT_GL_NO_ERROR();
546
547 glBufferData(GL_PIXEL_PACK_BUFFER, 4, nullptr, GL_STATIC_DRAW);
548 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
549 EXPECT_GL_NO_ERROR();
550 }
551}
552
Geoff Langd54d3042017-11-07 14:56:07 -0500553// Test enabling the GL_EXT_texture_storage extension
554TEST_P(WebGLCompatibilityTest, EnableTextureStorage)
555{
556 EXPECT_FALSE(extensionEnabled("GL_EXT_texture_storage"));
557
558 GLTexture texture;
559 glBindTexture(GL_TEXTURE_2D, texture);
560
561 GLint result;
562 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result);
563 if (getClientMajorVersion() >= 3)
564 {
565 EXPECT_GL_NO_ERROR();
566 }
567 else
568 {
569 EXPECT_GL_ERROR(GL_INVALID_ENUM);
570 }
571
572 if (extensionRequestable("GL_EXT_texture_storage"))
573 {
574 glRequestExtensionANGLE("GL_EXT_texture_storage");
575 EXPECT_GL_NO_ERROR();
576 EXPECT_TRUE(extensionEnabled("GL_EXT_texture_storage"));
577
578 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result);
579 EXPECT_GL_NO_ERROR();
580
581 const GLenum alwaysAcceptableFormats[] = {
582 GL_ALPHA8_EXT, GL_LUMINANCE8_EXT, GL_LUMINANCE8_ALPHA8_EXT,
583 };
584 for (const auto &acceptableFormat : alwaysAcceptableFormats)
585 {
586 GLTexture localTexture;
587 glBindTexture(GL_TEXTURE_2D, localTexture);
588 glTexStorage2DEXT(GL_TEXTURE_2D, 1, acceptableFormat, 1, 1);
589 EXPECT_GL_NO_ERROR();
590 }
591 }
592}
593
Geoff Lang3fab7632017-09-26 15:45:54 -0400594// Test enabling the GL_OES_mapbuffer and GL_EXT_map_buffer_range extensions
595TEST_P(WebGLCompatibilityTest, EnableMapBufferExtensions)
596{
597 EXPECT_FALSE(extensionEnabled("GL_OES_mapbuffer"));
598 EXPECT_FALSE(extensionEnabled("GL_EXT_map_buffer_range"));
599
600 // These extensions become core in in ES3/WebGL2.
601 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
602
603 GLBuffer buffer;
604 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
605 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4, nullptr, GL_STATIC_DRAW);
606
607 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
608 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
609
610 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
611 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
612
613 GLint access = 0;
614 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
615 EXPECT_GL_ERROR(GL_INVALID_ENUM);
616
617 if (extensionRequestable("GL_OES_mapbuffer"))
618 {
619 glRequestExtensionANGLE("GL_OES_mapbuffer");
620 EXPECT_GL_NO_ERROR();
621
622 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
623 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
624 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
625 EXPECT_GL_NO_ERROR();
626 }
627
628 if (extensionRequestable("GL_EXT_map_buffer_range"))
629 {
630 glRequestExtensionANGLE("GL_EXT_map_buffer_range");
631 EXPECT_GL_NO_ERROR();
632
633 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
634 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
635 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
636 EXPECT_GL_NO_ERROR();
637 }
638}
639
Geoff Lang8c7133c2017-09-26 17:31:10 -0400640// Test enabling the GL_OES_fbo_render_mipmap extension
641TEST_P(WebGLCompatibilityTest, EnableRenderMipmapExtension)
642{
643 EXPECT_FALSE(extensionEnabled("GL_OES_fbo_render_mipmap"));
644
645 // This extensions become core in in ES3/WebGL2.
646 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
647
648 GLTexture texture;
649 glBindTexture(GL_TEXTURE_2D, texture);
650 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
651 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
652
653 GLFramebuffer fbo;
654 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
655 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
656 EXPECT_GL_NO_ERROR();
657
658 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
659 EXPECT_GL_ERROR(GL_INVALID_VALUE);
660
661 if (extensionRequestable("GL_OES_fbo_render_mipmap"))
662 {
663 glRequestExtensionANGLE("GL_OES_fbo_render_mipmap");
664 EXPECT_GL_NO_ERROR();
665
666 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
667 EXPECT_GL_NO_ERROR();
668 }
669}
670
Geoff Lang50cac572017-09-26 17:37:43 -0400671// Test enabling the GL_EXT_blend_minmax extension
672TEST_P(WebGLCompatibilityTest, EnableBlendMinMaxExtension)
673{
674 EXPECT_FALSE(extensionEnabled("GL_EXT_blend_minmax"));
675
676 // This extensions become core in in ES3/WebGL2.
677 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
678
679 glBlendEquation(GL_MIN);
680 EXPECT_GL_ERROR(GL_INVALID_ENUM);
681
682 glBlendEquation(GL_MAX);
683 EXPECT_GL_ERROR(GL_INVALID_ENUM);
684
685 if (extensionRequestable("GL_EXT_blend_minmax"))
686 {
687 glRequestExtensionANGLE("GL_EXT_blend_minmax");
688 EXPECT_GL_NO_ERROR();
689
690 glBlendEquation(GL_MIN);
691 glBlendEquation(GL_MAX);
692 EXPECT_GL_NO_ERROR();
693 }
694}
695
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400696// Test enabling the query extensions
697TEST_P(WebGLCompatibilityTest, EnableQueryExtensions)
698{
Jamie Madill8b92c532018-03-22 01:05:02 -0400699 // Seems to be causing a device lost. http://anglebug.com/2423
700 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
701
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400702 EXPECT_FALSE(extensionEnabled("GL_EXT_occlusion_query_boolean"));
703 EXPECT_FALSE(extensionEnabled("GL_EXT_disjoint_timer_query"));
704 EXPECT_FALSE(extensionEnabled("GL_CHROMIUM_sync_query"));
705
706 // This extensions become core in in ES3/WebGL2.
707 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
708
709 GLQueryEXT badQuery;
710
711 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, badQuery);
712 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
713
714 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, badQuery);
715 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
716
717 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, badQuery);
718 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
719
720 glQueryCounterEXT(GL_TIMESTAMP_EXT, badQuery);
721 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
722
723 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, badQuery);
724 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
725
726 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
727 {
728 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
729 EXPECT_GL_NO_ERROR();
730
731 GLQueryEXT query;
732 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
733 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
734 EXPECT_GL_NO_ERROR();
735 }
736
737 if (extensionRequestable("GL_EXT_disjoint_timer_query"))
738 {
739 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
740 EXPECT_GL_NO_ERROR();
741
742 GLQueryEXT query1;
743 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
744 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
745 EXPECT_GL_NO_ERROR();
746
747 GLQueryEXT query2;
748 glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
749 EXPECT_GL_NO_ERROR();
750 }
751
752 if (extensionRequestable("GL_CHROMIUM_sync_query"))
753 {
754 glRequestExtensionANGLE("GL_CHROMIUM_sync_query");
755 EXPECT_GL_NO_ERROR();
756
757 GLQueryEXT query;
758 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query);
759 glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
760 EXPECT_GL_NO_ERROR();
761 }
762}
763
Geoff Lang488130e2017-09-27 13:53:11 -0400764// Test enabling the GL_ANGLE_framebuffer_multisample extension
765TEST_P(WebGLCompatibilityTest, EnableFramebufferMultisampleExtension)
766{
767 EXPECT_FALSE(extensionEnabled("GL_ANGLE_framebuffer_multisample"));
768
769 // This extensions become core in in ES3/WebGL2.
770 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
771
772 GLint maxSamples = 0;
773 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
774 EXPECT_GL_ERROR(GL_INVALID_ENUM);
775
776 GLRenderbuffer renderbuffer;
777 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
778 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA4, 1, 1);
779 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
780
781 if (extensionRequestable("GL_ANGLE_framebuffer_multisample"))
782 {
783 glRequestExtensionANGLE("GL_ANGLE_framebuffer_multisample");
784 EXPECT_GL_NO_ERROR();
785
786 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
787 EXPECT_GL_NO_ERROR();
788
789 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, maxSamples, GL_RGBA4, 1, 1);
790 EXPECT_GL_NO_ERROR();
791 }
792}
793
Geoff Lang63c5a592017-09-27 14:08:16 -0400794// Test enabling the GL_ANGLE_instanced_arrays extension
795TEST_P(WebGLCompatibilityTest, EnableInstancedArraysExtension)
796{
797 EXPECT_FALSE(extensionEnabled("GL_ANGLE_instanced_arrays"));
798
799 // This extensions become core in in ES3/WebGL2.
800 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
801
802 GLint divisor = 0;
803 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
804 EXPECT_GL_ERROR(GL_INVALID_ENUM);
805
806 glVertexAttribDivisorANGLE(0, 1);
807 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
808
809 if (extensionRequestable("GL_ANGLE_instanced_arrays"))
810 {
811 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
812 EXPECT_GL_NO_ERROR();
813
814 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
815 glVertexAttribDivisorANGLE(0, 1);
816 EXPECT_GL_NO_ERROR();
817 }
818}
819
Geoff Lang000dab82017-09-27 14:27:07 -0400820// Test enabling the GL_ANGLE_pack_reverse_row_order extension
821TEST_P(WebGLCompatibilityTest, EnablePackReverseRowOrderExtension)
822{
823 EXPECT_FALSE(extensionEnabled("GL_ANGLE_pack_reverse_row_order"));
824
825 GLint result = 0;
826 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result);
827 EXPECT_GL_ERROR(GL_INVALID_ENUM);
828
829 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE);
830 EXPECT_GL_ERROR(GL_INVALID_ENUM);
831
832 if (extensionRequestable("GL_ANGLE_pack_reverse_row_order"))
833 {
834 glRequestExtensionANGLE("GL_ANGLE_pack_reverse_row_order");
835 EXPECT_GL_NO_ERROR();
836
837 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result);
838 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE);
839 EXPECT_GL_NO_ERROR();
840 }
841}
842
843// Test enabling the GL_EXT_unpack_subimage extension
844TEST_P(WebGLCompatibilityTest, EnablePackUnpackSubImageExtension)
845{
846 EXPECT_FALSE(extensionEnabled("GL_EXT_unpack_subimage"));
847
848 // This extensions become core in in ES3/WebGL2.
849 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
850
851 constexpr GLenum parameters[] = {
852 GL_UNPACK_ROW_LENGTH_EXT, GL_UNPACK_SKIP_ROWS_EXT, GL_UNPACK_SKIP_PIXELS_EXT,
853 };
854
855 for (GLenum param : parameters)
856 {
857 GLint resultI = 0;
858 glGetIntegerv(param, &resultI);
859 EXPECT_GL_ERROR(GL_INVALID_ENUM);
860
861 GLfloat resultF = 0.0f;
862 glGetFloatv(param, &resultF);
863 EXPECT_GL_ERROR(GL_INVALID_ENUM);
864
865 glPixelStorei(param, 0);
866 EXPECT_GL_ERROR(GL_INVALID_ENUM);
867 }
868
869 if (extensionRequestable("GL_EXT_unpack_subimage"))
870 {
871 glRequestExtensionANGLE("GL_EXT_unpack_subimage");
872 EXPECT_GL_NO_ERROR();
873
874 for (GLenum param : parameters)
875 {
876 GLint resultI = 0;
877 glGetIntegerv(param, &resultI);
878
879 GLfloat resultF = 0.0f;
880 glGetFloatv(param, &resultF);
881
882 glPixelStorei(param, 0);
883
884 EXPECT_GL_NO_ERROR();
885 }
886 }
887}
888
Geoff Lang4751aab2017-10-30 15:14:52 -0400889TEST_P(WebGLCompatibilityTest, EnableTextureRectangle)
890{
891 EXPECT_FALSE(extensionEnabled("GL_ANGLE_texture_rectangle"));
892
893 GLTexture texture;
894 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture);
895 EXPECT_GL_ERROR(GL_INVALID_ENUM);
896
897 GLint minFilter = 0;
898 glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, &minFilter);
899 EXPECT_GL_ERROR(GL_INVALID_ENUM);
900
901 if (extensionRequestable("GL_ANGLE_texture_rectangle"))
902 {
903 glRequestExtensionANGLE("GL_ANGLE_texture_rectangle");
904 EXPECT_GL_NO_ERROR();
905
906 EXPECT_TRUE(extensionEnabled("GL_ANGLE_texture_rectangle"));
907
908 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture);
909 EXPECT_GL_NO_ERROR();
910
911 glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
912 nullptr);
913 EXPECT_GL_NO_ERROR();
914 }
915}
916
Geoff Lang000dab82017-09-27 14:27:07 -0400917// Test enabling the GL_NV_pack_subimage extension
918TEST_P(WebGLCompatibilityTest, EnablePackPackSubImageExtension)
919{
920 EXPECT_FALSE(extensionEnabled("GL_NV_pack_subimage"));
921
922 // This extensions become core in in ES3/WebGL2.
923 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
924
925 constexpr GLenum parameters[] = {
926 GL_PACK_ROW_LENGTH, GL_PACK_SKIP_ROWS, GL_PACK_SKIP_PIXELS,
927 };
928
929 for (GLenum param : parameters)
930 {
931 GLint resultI = 0;
932 glGetIntegerv(param, &resultI);
933 EXPECT_GL_ERROR(GL_INVALID_ENUM);
934
935 GLfloat resultF = 0.0f;
936 glGetFloatv(param, &resultF);
937 EXPECT_GL_ERROR(GL_INVALID_ENUM);
938
939 glPixelStorei(param, 0);
940 EXPECT_GL_ERROR(GL_INVALID_ENUM);
941 }
942
943 if (extensionRequestable("GL_NV_pack_subimage"))
944 {
945 glRequestExtensionANGLE("GL_NV_pack_subimage");
946 EXPECT_GL_NO_ERROR();
947
948 for (GLenum param : parameters)
949 {
950 GLint resultI = 0;
951 glGetIntegerv(param, &resultI);
952
953 GLfloat resultF = 0.0f;
954 glGetFloatv(param, &resultF);
955
956 glPixelStorei(param, 0);
957
958 EXPECT_GL_NO_ERROR();
959 }
960 }
961}
962
Geoff Langd84a00b2017-10-27 17:27:26 -0400963TEST_P(WebGLCompatibilityTest, EnableRGB8RGBA8Extension)
964{
965 EXPECT_FALSE(extensionEnabled("GL_OES_rgb8_rgba8"));
966
967 // This extensions become core in in ES3/WebGL2.
968 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
969
970 GLRenderbuffer renderbuffer;
971 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
972 EXPECT_GL_NO_ERROR();
973
974 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1);
975 EXPECT_GL_ERROR(GL_INVALID_ENUM);
976
977 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
978 EXPECT_GL_ERROR(GL_INVALID_ENUM);
979
980 if (extensionRequestable("GL_OES_rgb8_rgba8"))
981 {
982 glRequestExtensionANGLE("GL_OES_rgb8_rgba8");
983 EXPECT_GL_NO_ERROR();
984
985 EXPECT_TRUE(extensionEnabled("GL_OES_rgb8_rgba8"));
986
987 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1);
988 EXPECT_GL_NO_ERROR();
989
990 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
991 EXPECT_GL_NO_ERROR();
992 }
993}
994
Geoff Lange8afa902017-09-27 15:00:43 -0400995// Test enabling the GL_ANGLE_framebuffer_blit extension
996TEST_P(WebGLCompatibilityTest, EnableFramebufferBlitExtension)
997{
998 EXPECT_FALSE(extensionEnabled("GL_ANGLE_framebuffer_blit"));
999
1000 // This extensions become core in in ES3/WebGL2.
1001 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1002
1003 GLFramebuffer fbo;
1004
1005 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
1006 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1007
1008 GLint result;
1009 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result);
1010 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1011
1012 glBlitFramebufferANGLE(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1013 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1014
1015 if (extensionRequestable("GL_ANGLE_framebuffer_blit"))
1016 {
1017 glRequestExtensionANGLE("GL_ANGLE_framebuffer_blit");
1018 EXPECT_GL_NO_ERROR();
1019
1020 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
1021 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result);
1022 EXPECT_GL_NO_ERROR();
1023 }
1024}
1025
Geoff Lang2348e212017-09-27 17:46:25 -04001026// Test enabling the GL_OES_get_program_binary extension
1027TEST_P(WebGLCompatibilityTest, EnableProgramBinaryExtension)
1028{
1029 EXPECT_FALSE(extensionEnabled("GL_OES_get_program_binary"));
1030
1031 // This extensions become core in in ES3/WebGL2.
1032 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1033
1034 GLint result = 0;
1035 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
1036 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1037
1038 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
1039 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1040
1041 const std::string &vert =
1042 "void main()\n"
1043 "{\n"
1044 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1045 "}\n";
1046 const std::string &frag =
1047 "precision highp float;\n"
1048 "void main()\n"
1049 "{\n"
1050 " gl_FragColor = vec4(1.0);\n"
1051 "}\n";
1052 ANGLE_GL_PROGRAM(program, vert, frag);
1053
1054 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &result);
1055 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1056
1057 uint8_t tempArray[512];
1058 GLenum tempFormat = 0;
1059 GLsizei tempLength = 0;
1060 glGetProgramBinaryOES(program, static_cast<GLsizei>(ArraySize(tempArray)), &tempLength,
1061 &tempFormat, tempArray);
1062 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1063
1064 if (extensionRequestable("GL_OES_get_program_binary"))
1065 {
1066 glRequestExtensionANGLE("GL_OES_get_program_binary");
1067 EXPECT_GL_NO_ERROR();
1068
1069 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
1070 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
1071 EXPECT_GL_NO_ERROR();
1072
1073 GLint binaryLength = 0;
1074 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
1075 EXPECT_GL_NO_ERROR();
1076
1077 GLenum binaryFormat;
1078 GLsizei writeLength = 0;
1079 std::vector<uint8_t> binary(binaryLength);
1080 glGetProgramBinaryOES(program, binaryLength, &writeLength, &binaryFormat, binary.data());
1081 EXPECT_GL_NO_ERROR();
1082
1083 glProgramBinaryOES(program, binaryFormat, binary.data(), binaryLength);
1084 EXPECT_GL_NO_ERROR();
1085 }
1086}
1087
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001088// Verify that the context generates the correct error when the framebuffer attachments are
1089// different sizes
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001090TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch)
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001091{
1092 GLFramebuffer fbo;
1093 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1094
1095 GLTexture textures[2];
1096 glBindTexture(GL_TEXTURE_2D, textures[0]);
1097 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1098 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
1099
1100 ASSERT_GL_NO_ERROR();
1101 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1102
1103 GLRenderbuffer renderbuffer;
1104 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1105 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3);
1106 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
1107
1108 ASSERT_GL_NO_ERROR();
1109 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1110 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1111
1112 if (extensionRequestable("GL_EXT_draw_buffers"))
1113 {
1114 glRequestExtensionANGLE("GL_EXT_draw_buffers");
1115 EXPECT_GL_NO_ERROR();
1116 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
1117
1118 glBindTexture(GL_TEXTURE_2D, textures[1]);
1119 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1120 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
1121 ASSERT_GL_NO_ERROR();
1122
1123 ASSERT_GL_NO_ERROR();
1124 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1125 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1126
1127 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
1128
1129 ASSERT_GL_NO_ERROR();
1130 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1131
1132 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1133
1134 ASSERT_GL_NO_ERROR();
1135 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1136 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1137 }
1138}
1139
Corentin Wallez327411e2016-12-09 11:09:17 -05001140// Test that client-side array buffers are forbidden in WebGL mode
1141TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer)
1142{
1143 const std::string &vert =
1144 "attribute vec3 a_pos;\n"
1145 "void main()\n"
1146 "{\n"
1147 " gl_Position = vec4(a_pos, 1.0);\n"
1148 "}\n";
1149
1150 const std::string &frag =
1151 "precision highp float;\n"
1152 "void main()\n"
1153 "{\n"
1154 " gl_FragColor = vec4(1.0);\n"
1155 "}\n";
1156
1157 ANGLE_GL_PROGRAM(program, vert, frag);
1158
1159 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1160 ASSERT_NE(-1, posLocation);
1161 glUseProgram(program.get());
1162
1163 const auto &vertices = GetQuadVertices();
Corentin Wallezfd456442016-12-21 17:57:00 -05001164 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
Corentin Wallez327411e2016-12-09 11:09:17 -05001165 glEnableVertexAttribArray(posLocation);
1166
1167 ASSERT_GL_NO_ERROR();
1168 glDrawArrays(GL_TRIANGLES, 0, 6);
1169 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1170}
1171
1172// Test that client-side element array buffers are forbidden in WebGL mode
1173TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
1174{
1175 const std::string &vert =
1176 "attribute vec3 a_pos;\n"
1177 "void main()\n"
1178 "{\n"
1179 " gl_Position = vec4(a_pos, 1.0);\n"
1180 "}\n";
1181
1182 const std::string &frag =
1183 "precision highp float;\n"
1184 "void main()\n"
1185 "{\n"
1186 " gl_FragColor = vec4(1.0);\n"
1187 "}\n";
1188
1189 ANGLE_GL_PROGRAM(program, vert, frag);
1190
1191 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1192 ASSERT_NE(-1, posLocation);
1193 glUseProgram(program.get());
1194
1195 const auto &vertices = GetQuadVertices();
1196
1197 GLBuffer vertexBuffer;
1198 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1199 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1200 GL_STATIC_DRAW);
1201
1202 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1203 glEnableVertexAttribArray(posLocation);
1204
Corentin Wallez327411e2016-12-09 11:09:17 -05001205 ASSERT_GL_NO_ERROR();
Corentin Wallezded1b5a2017-03-09 18:58:48 -05001206
1207 // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also
1208 // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate
1209 // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check.
1210 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void*>(intptr_t(1)));
Corentin Wallez327411e2016-12-09 11:09:17 -05001211 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1212}
1213
Corentin Wallez672f7f32017-06-15 17:42:17 -04001214// Test that client-side array buffers are forbidden even if the program doesn't use the attribute
1215TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBufferEvenNotUsedOnes)
1216{
1217 const std::string &vert =
1218 "void main()\n"
1219 "{\n"
1220 " gl_Position = vec4(1.0);\n"
1221 "}\n";
1222
1223 const std::string &frag =
1224 "precision highp float;\n"
1225 "void main()\n"
1226 "{\n"
1227 " gl_FragColor = vec4(1.0);\n"
1228 "}\n";
1229
1230 ANGLE_GL_PROGRAM(program, vert, frag);
1231
1232 glUseProgram(program.get());
1233
1234 const auto &vertices = GetQuadVertices();
1235 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
1236 glEnableVertexAttribArray(0);
1237
1238 ASSERT_GL_NO_ERROR();
1239 glDrawArrays(GL_TRIANGLES, 0, 6);
1240 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1241}
1242
Geoff Langfb052642017-10-24 13:42:09 -04001243// Test that passing a null pixel data pointer to TexSubImage calls generates an INVALID_VALUE error
1244TEST_P(WebGLCompatibilityTest, NullPixelDataForSubImage)
1245{
1246 // glTexSubImage2D
1247 {
1248 GLTexture texture;
1249 glBindTexture(GL_TEXTURE_2D, texture);
1250
1251 // TexImage with null data - OK
1252 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1253 EXPECT_GL_NO_ERROR();
1254
1255 // TexSubImage with zero size and null data - OK
1256 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1257 EXPECT_GL_NO_ERROR();
1258
1259 // TexSubImage with non-zero size and null data - Invalid value
1260 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1261 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1262 }
1263
1264 // glTexSubImage3D
1265 if (getClientMajorVersion() >= 3)
1266 {
1267 GLTexture texture;
1268 glBindTexture(GL_TEXTURE_3D, texture);
1269
1270 // TexImage with null data - OK
1271 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1272 EXPECT_GL_NO_ERROR();
1273
1274 // TexSubImage with zero size and null data - OK
1275 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1276 EXPECT_GL_NO_ERROR();
1277
1278 // TexSubImage with non-zero size and null data - Invalid value
1279 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1280 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1281 }
1282}
1283
Ken Russellb9f92502018-01-27 19:00:26 -08001284// Tests the WebGL requirement of having the same stencil mask, writemask and ref for front and back
1285// (when stencil testing is enabled)
1286void WebGLCompatibilityTest::TestDifferentStencilMaskAndRef(GLenum errIfMismatch)
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001287{
1288 // Run the test in an FBO to make sure we have some stencil bits.
1289 GLRenderbuffer renderbuffer;
1290 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
1291 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
1292
1293 GLFramebuffer framebuffer;
1294 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1295 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1296 renderbuffer.get());
1297
1298 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
1299 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
1300 glUseProgram(program.get());
1301 ASSERT_GL_NO_ERROR();
1302
1303 // Having ref and mask the same for front and back is valid.
1304 glStencilMask(255);
1305 glStencilFunc(GL_ALWAYS, 0, 255);
1306 glDrawArrays(GL_TRIANGLES, 0, 6);
1307 ASSERT_GL_NO_ERROR();
1308
1309 // Having a different front - back write mask generates an error.
1310 glStencilMaskSeparate(GL_FRONT, 1);
1311 glDrawArrays(GL_TRIANGLES, 0, 6);
Ken Russellb9f92502018-01-27 19:00:26 -08001312 EXPECT_GL_ERROR(errIfMismatch);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001313
1314 // Setting both write masks separately to the same value is valid.
1315 glStencilMaskSeparate(GL_BACK, 1);
1316 glDrawArrays(GL_TRIANGLES, 0, 6);
1317 ASSERT_GL_NO_ERROR();
1318
1319 // Having a different stencil front - back mask generates an error
1320 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
1321 glDrawArrays(GL_TRIANGLES, 0, 6);
Ken Russellb9f92502018-01-27 19:00:26 -08001322 EXPECT_GL_ERROR(errIfMismatch);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001323
1324 // Setting both masks separately to the same value is valid.
1325 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
1326 glDrawArrays(GL_TRIANGLES, 0, 6);
1327 ASSERT_GL_NO_ERROR();
1328
1329 // Having a different stencil front - back reference generates an error
1330 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
1331 glDrawArrays(GL_TRIANGLES, 0, 6);
Ken Russellb9f92502018-01-27 19:00:26 -08001332 EXPECT_GL_ERROR(errIfMismatch);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001333
1334 // Setting both references separately to the same value is valid.
1335 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
1336 glDrawArrays(GL_TRIANGLES, 0, 6);
1337 ASSERT_GL_NO_ERROR();
1338
1339 // Using different stencil funcs, everything being equal is valid.
1340 glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
1341 glDrawArrays(GL_TRIANGLES, 0, 6);
1342 ASSERT_GL_NO_ERROR();
1343}
Ken Russellb9f92502018-01-27 19:00:26 -08001344TEST_P(WebGLCompatibilityTest, StencilTestEnabledDisallowsDifferentStencilMaskAndRef)
1345{
1346 glEnable(GL_STENCIL_TEST);
1347 TestDifferentStencilMaskAndRef(GL_INVALID_OPERATION);
1348}
1349TEST_P(WebGLCompatibilityTest, StencilTestDisabledAllowsDifferentStencilMaskAndRef)
1350{
1351 glDisable(GL_STENCIL_TEST);
1352 TestDifferentStencilMaskAndRef(GL_NO_ERROR);
1353}
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001354
Corentin Wallez506fc9c2016-12-21 16:53:33 -05001355// Test that GL_FIXED is forbidden
1356TEST_P(WebGLCompatibilityTest, ForbidsGLFixed)
1357{
1358 GLBuffer buffer;
1359 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1360 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1361
1362 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1363 ASSERT_GL_NO_ERROR();
1364
1365 glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr);
1366 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1367}
1368
1369// Test the WebGL limit of 255 for the attribute stride
1370TEST_P(WebGLCompatibilityTest, MaxStride)
1371{
1372 GLBuffer buffer;
1373 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1374 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
1375
1376 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr);
1377 ASSERT_GL_NO_ERROR();
1378
1379 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr);
1380 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1381}
1382
Corentin Wallezfd456442016-12-21 17:57:00 -05001383// Test the checks for OOB reads in the vertex buffers, non-instanced version
1384TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
1385{
1386 const std::string &vert =
1387 "attribute float a_pos;\n"
1388 "void main()\n"
1389 "{\n"
1390 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1391 "}\n";
1392
Olli Etuaho5804dc82018-04-13 14:11:46 +03001393 ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
Corentin Wallezfd456442016-12-21 17:57:00 -05001394 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1395 ASSERT_NE(-1, posLocation);
1396 glUseProgram(program.get());
1397
1398 GLBuffer buffer;
1399 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1400 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1401
1402 glEnableVertexAttribArray(posLocation);
1403
1404 const uint8_t* zeroOffset = nullptr;
1405
1406 // Test touching the last element is valid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001407 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
Corentin Wallezfd456442016-12-21 17:57:00 -05001408 glDrawArrays(GL_POINTS, 0, 4);
1409 ASSERT_GL_NO_ERROR();
1410
1411 // Test touching the last element + 1 is invalid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001412 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
Corentin Wallezfd456442016-12-21 17:57:00 -05001413 glDrawArrays(GL_POINTS, 0, 4);
1414 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1415
1416 // Test touching the last element is valid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001417 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
Corentin Wallezfd456442016-12-21 17:57:00 -05001418 glDrawArrays(GL_POINTS, 0, 4);
1419 ASSERT_GL_NO_ERROR();
1420
1421 // Test touching the last element + 1 is invalid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001422 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
Corentin Wallezfd456442016-12-21 17:57:00 -05001423 glDrawArrays(GL_POINTS, 0, 4);
1424 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1425
1426 // Test any offset is valid if no vertices are drawn.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001427 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
Corentin Wallezfd456442016-12-21 17:57:00 -05001428 glDrawArrays(GL_POINTS, 0, 0);
1429 ASSERT_GL_NO_ERROR();
Corentin Wallez91c8de82017-10-12 16:32:44 -04001430
1431 // Test a case of overflow that could give a max vertex that's negative
1432 constexpr GLint kIntMax = std::numeric_limits<GLint>::max();
1433 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 0);
1434 glDrawArrays(GL_POINTS, kIntMax, kIntMax);
1435 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1436}
1437
1438// Test the checks for OOB reads in the vertex buffers, instanced version
1439TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
1440{
1441 const std::string &vert =
1442 "attribute float a_pos;\n"
1443 "attribute float a_w;\n"
1444 "void main()\n"
1445 "{\n"
1446 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1447 "}\n";
1448
Olli Etuaho5804dc82018-04-13 14:11:46 +03001449 ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
Corentin Wallez91c8de82017-10-12 16:32:44 -04001450 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1451 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
1452 ASSERT_NE(-1, posLocation);
1453 ASSERT_NE(-1, wLocation);
1454 glUseProgram(program.get());
1455
1456 GLBuffer buffer;
1457 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1458 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1459
1460 glEnableVertexAttribArray(posLocation);
1461 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1462 glVertexAttribDivisor(posLocation, 0);
1463
1464 glEnableVertexAttribArray(wLocation);
1465 glVertexAttribDivisor(wLocation, 1);
1466
1467 const uint8_t* zeroOffset = nullptr;
1468
1469 // Test touching the last element is valid.
1470 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1471 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1472 ASSERT_GL_NO_ERROR();
1473
1474 // Test touching the last element + 1 is invalid.
1475 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1476 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1477 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1478
1479 // Test touching the last element is valid, using a stride.
1480 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1481 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1482 ASSERT_GL_NO_ERROR();
1483
1484 // Test touching the last element + 1 is invalid, using a stride.
1485 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1486 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1487 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1488
1489 // Test any offset is valid if no vertices are drawn.
1490 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1491 glDrawArraysInstanced(GL_POINTS, 0, 0, 1);
1492 ASSERT_GL_NO_ERROR();
1493
1494 // Test any offset is valid if no primitives are drawn.
1495 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1496 glDrawArraysInstanced(GL_POINTS, 0, 1, 0);
1497 ASSERT_GL_NO_ERROR();
1498}
1499
1500// Test the checks for OOB reads in the vertex buffers, ANGLE_instanced_arrays version
1501TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsInstancedANGLE)
1502{
1503 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_ANGLE_instanced_arrays"));
1504 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
1505 EXPECT_GL_NO_ERROR();
1506
1507 const std::string &vert =
1508 "attribute float a_pos;\n"
1509 "attribute float a_w;\n"
1510 "void main()\n"
1511 "{\n"
1512 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1513 "}\n";
1514
Olli Etuaho5804dc82018-04-13 14:11:46 +03001515 ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
Corentin Wallez91c8de82017-10-12 16:32:44 -04001516 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1517 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
1518 ASSERT_NE(-1, posLocation);
1519 ASSERT_NE(-1, wLocation);
1520 glUseProgram(program.get());
1521
1522 GLBuffer buffer;
1523 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1524 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1525
1526 glEnableVertexAttribArray(posLocation);
1527 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1528 glVertexAttribDivisorANGLE(posLocation, 0);
1529
1530 glEnableVertexAttribArray(wLocation);
1531 glVertexAttribDivisorANGLE(wLocation, 1);
1532
1533 const uint8_t* zeroOffset = nullptr;
1534
1535 // Test touching the last element is valid.
1536 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1537 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1538 ASSERT_GL_NO_ERROR();
1539
1540 // Test touching the last element + 1 is invalid.
1541 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1542 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1543 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1544
1545 // Test touching the last element is valid, using a stride.
1546 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1547 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1548 ASSERT_GL_NO_ERROR();
1549
1550 // Test touching the last element + 1 is invalid, using a stride.
1551 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1552 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
1553 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1554
1555 // Test any offset is valid if no vertices are drawn.
1556 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1557 glDrawArraysInstancedANGLE(GL_POINTS, 0, 0, 1);
1558 ASSERT_GL_NO_ERROR();
1559
1560 // Test any offset is valid if no primitives are drawn.
1561 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1562 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 0);
1563 ASSERT_GL_NO_ERROR();
Corentin Wallezfd456442016-12-21 17:57:00 -05001564}
1565
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001566// Test the checks for OOB reads in the index buffer
1567TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
Geoff Lang5f319a42017-01-09 16:49:19 -05001568{
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001569 const std::string &vert =
1570 "attribute float a_pos;\n"
1571 "void main()\n"
1572 "{\n"
1573 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1574 "}\n";
Geoff Lang5f319a42017-01-09 16:49:19 -05001575
Olli Etuaho5804dc82018-04-13 14:11:46 +03001576 ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001577 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1578 ASSERT_NE(-1, posLocation);
1579 glUseProgram(program.get());
1580
1581 GLBuffer vertexBuffer;
1582 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1583 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1584
1585 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001586 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001587
1588 const uint8_t *zeroOffset = nullptr;
1589 const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
1590
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001591 GLBuffer indexBuffer;
1592 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1593 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
Geoff Lang5f319a42017-01-09 16:49:19 -05001594 ASSERT_GL_NO_ERROR();
1595
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001596 // Test touching the last index is valid
1597 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1598 ASSERT_GL_NO_ERROR();
Geoff Lang5f319a42017-01-09 16:49:19 -05001599
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001600 // Test touching the last + 1 element is invalid
1601 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
1602 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang5f319a42017-01-09 16:49:19 -05001603
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001604 // Test any offset if valid if count is zero
1605 glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
1606 ASSERT_GL_NO_ERROR();
Corentin Wallezfe9306a2017-02-01 17:41:05 -05001607
1608 // Test touching the first index is valid
1609 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1610 ASSERT_GL_NO_ERROR();
1611
1612 // Test touching the first - 1 index is invalid
1613 // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was
1614 // the historic behavior of WebGL implementations
1615 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1);
1616 EXPECT_GL_ERROR(GL_INVALID_VALUE);
Geoff Lang5f319a42017-01-09 16:49:19 -05001617}
1618
Corentin Wallez91c8de82017-10-12 16:32:44 -04001619// Test the checks for OOB in vertex buffers caused by indices, non-instanced version
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001620TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInVertexBuffer)
1621{
1622 const std::string &vert =
1623 "attribute float a_pos;\n"
1624 "void main()\n"
1625 "{\n"
1626 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1627 "}\n";
1628
Olli Etuaho5804dc82018-04-13 14:11:46 +03001629 ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001630 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1631 ASSERT_NE(-1, posLocation);
1632 glUseProgram(program.get());
1633
1634 GLBuffer vertexBuffer;
1635 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1636 glBufferData(GL_ARRAY_BUFFER, 8, nullptr, GL_STATIC_DRAW);
1637
1638 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001639 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001640
1641 const uint8_t *zeroOffset = nullptr;
1642 const uint8_t testIndices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 255};
1643
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001644 GLBuffer indexBuffer;
1645 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1646 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(testIndices), testIndices, GL_STATIC_DRAW);
1647 ASSERT_GL_NO_ERROR();
1648
1649 // Test touching the end of the vertex buffer is valid
1650 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 7);
1651 ASSERT_GL_NO_ERROR();
1652
1653 // Test touching just after the end of the vertex buffer is invalid
1654 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 8);
1655 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1656
1657 // Test touching the whole vertex buffer is valid
1658 glDrawElements(GL_POINTS, 8, GL_UNSIGNED_BYTE, zeroOffset + 0);
1659 ASSERT_GL_NO_ERROR();
1660
1661 // Test an index that would be negative
1662 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 9);
1663 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1664}
1665
Frank Henigman6137ddc2017-02-10 18:55:07 -05001666// Test depth range with 'near' more or less than 'far.'
1667TEST_P(WebGLCompatibilityTest, DepthRange)
1668{
1669 glDepthRangef(0, 1);
1670 ASSERT_GL_NO_ERROR();
1671
1672 glDepthRangef(.5, .5);
1673 ASSERT_GL_NO_ERROR();
1674
1675 glDepthRangef(1, 0);
1676 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1677}
1678
Frank Henigman146e8a12017-03-02 23:22:37 -05001679// Test all blend function combinations.
1680// In WebGL it is invalid to combine constant color with constant alpha.
1681TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
1682{
1683 constexpr GLenum srcFunc[] = {
1684 GL_ZERO,
1685 GL_ONE,
1686 GL_SRC_COLOR,
1687 GL_ONE_MINUS_SRC_COLOR,
1688 GL_DST_COLOR,
1689 GL_ONE_MINUS_DST_COLOR,
1690 GL_SRC_ALPHA,
1691 GL_ONE_MINUS_SRC_ALPHA,
1692 GL_DST_ALPHA,
1693 GL_ONE_MINUS_DST_ALPHA,
1694 GL_CONSTANT_COLOR,
1695 GL_ONE_MINUS_CONSTANT_COLOR,
1696 GL_CONSTANT_ALPHA,
1697 GL_ONE_MINUS_CONSTANT_ALPHA,
1698 GL_SRC_ALPHA_SATURATE,
1699 };
1700
1701 constexpr GLenum dstFunc[] = {
1702 GL_ZERO, GL_ONE,
1703 GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
1704 GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
1705 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1706 GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
1707 GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
1708 GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
1709 };
1710
1711 for (GLenum src : srcFunc)
1712 {
1713 for (GLenum dst : dstFunc)
1714 {
1715 glBlendFunc(src, dst);
1716 CheckBlendFunctions(src, dst);
1717 glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE);
1718 CheckBlendFunctions(src, dst);
1719 }
1720 }
1721}
1722
Geoff Langfc32e8b2017-05-31 14:16:59 -04001723// Test that binding/querying uniforms and attributes with invalid names generates errors
1724TEST_P(WebGLCompatibilityTest, InvalidAttributeAndUniformNames)
1725{
1726 const std::string validAttribName =
1727 "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1728 const std::string validUniformName =
1729 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
Geoff Langa71a98e2017-06-19 15:15:00 -04001730 std::vector<char> invalidSet = {'"', '$', '`', '@', '\''};
1731 if (getClientMajorVersion() < 3)
1732 {
1733 invalidSet.push_back('\\');
1734 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04001735
1736 std::string vert = "attribute float ";
1737 vert += validAttribName;
1738 vert +=
1739 ";\n"
1740 "void main()\n"
1741 "{\n"
1742 " gl_Position = vec4(1.0);\n"
1743 "}\n";
1744
1745 std::string frag =
1746 "precision highp float;\n"
1747 "uniform vec4 ";
1748 frag += validUniformName;
Geoff Langcab92ee2017-07-19 17:32:07 -04001749 // Insert illegal characters into comments
Geoff Langfc32e8b2017-05-31 14:16:59 -04001750 frag +=
1751 ";\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001752 " // $ \" @ /*\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001753 "void main()\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001754 "{/*\n"
1755 " ` @ $\n"
1756 " */gl_FragColor = vec4(1.0);\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001757 "}\n";
1758
1759 ANGLE_GL_PROGRAM(program, vert, frag);
1760 EXPECT_GL_NO_ERROR();
1761
1762 for (char invalidChar : invalidSet)
1763 {
1764 std::string invalidName = validAttribName + invalidChar;
1765 glGetAttribLocation(program, invalidName.c_str());
1766 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1767 << "glGetAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1768
1769 glBindAttribLocation(program, 0, invalidName.c_str());
1770 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1771 << "glBindAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1772 }
1773
1774 for (char invalidChar : invalidSet)
1775 {
1776 std::string invalidName = validUniformName + invalidChar;
1777 glGetUniformLocation(program, invalidName.c_str());
1778 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1779 << "glGetUniformLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1780 }
1781
1782 for (char invalidChar : invalidSet)
1783 {
1784 std::string invalidAttribName = validAttribName + invalidChar;
1785 const char *invalidVert[] = {
1786 "attribute float ",
1787 invalidAttribName.c_str(),
1788 ";\n",
1789 "void main()\n",
1790 "{\n",
1791 " gl_Position = vec4(1.0);\n",
1792 "}\n",
1793 };
1794
1795 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1796 glShaderSource(shader, static_cast<GLsizei>(ArraySize(invalidVert)), invalidVert, nullptr);
1797 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1798 glDeleteShader(shader);
1799 }
1800}
1801
Geoff Langcab92ee2017-07-19 17:32:07 -04001802// Test that line continuation is handled correctly when valdiating shader source
Bryan Bernhart (Intel Americas Inc)335d8bf2017-10-23 15:41:43 -07001803TEST_P(WebGLCompatibilityTest, ShaderSourceLineContinuation)
1804{
1805 // Verify that a line continuation character (i.e. backslash) cannot be used
1806 // within a preprocessor directive in a ES2 context.
1807 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1808
1809 const char *validVert =
1810 "#define foo this is a test\n"
1811 "precision mediump float;\n"
1812 "void main()\n"
1813 "{\n"
1814 " gl_Position = vec4(1.0);\n"
1815 "}\n";
1816
1817 const char *invalidVert =
1818 "#define foo this \\n"
1819 " is a test\n"
1820 "precision mediump float;\n"
1821 "void main()\n"
1822 "{\n"
1823 " gl_Position = vec4(1.0);\n"
1824 "}\n";
1825
1826 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1827 glShaderSource(shader, 1, &validVert, nullptr);
1828 EXPECT_GL_NO_ERROR();
1829
1830 glShaderSource(shader, 1, &invalidVert, nullptr);
1831 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1832 glDeleteShader(shader);
1833}
1834
1835// Test that line continuation is handled correctly when valdiating shader source
Geoff Langcab92ee2017-07-19 17:32:07 -04001836TEST_P(WebGL2CompatibilityTest, ShaderSourceLineContinuation)
1837{
1838 const char *validVert =
1839 "#version 300 es\n"
1840 "precision mediump float;\n"
1841 "\n"
1842 "void main ()\n"
1843 "{\n"
1844 " float f\\\n"
1845 "oo = 1.0;\n"
1846 " gl_Position = vec4(foo);\n"
1847 "}\n";
1848
1849 const char *invalidVert =
1850 "#version 300 es\n"
1851 "precision mediump float;\n"
1852 "\n"
1853 "void main ()\n"
1854 "{\n"
1855 " float f\\$\n"
1856 "oo = 1.0;\n"
1857 " gl_Position = vec4(foo);\n"
1858 "}\n";
1859
1860 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1861 glShaderSource(shader, 1, &validVert, nullptr);
1862 EXPECT_GL_NO_ERROR();
1863 glShaderSource(shader, 1, &invalidVert, nullptr);
1864 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1865 glDeleteShader(shader);
1866}
1867
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001868// Tests bindAttribLocations for reserved prefixes and length limits
1869TEST_P(WebGLCompatibilityTest, BindAttribLocationLimitation)
1870{
1871 constexpr int maxLocStringLength = 256;
1872 const std::string tooLongString(maxLocStringLength + 1, '_');
1873
1874 glBindAttribLocation(0, 0, "_webgl_var");
1875
1876 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1877
1878 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
1879
1880 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1881}
1882
Corentin Wallez0dc97812017-06-22 14:38:44 -04001883// Test that having no attributes with a zero divisor is valid in WebGL2
Geoff Lang407d4e72017-04-12 14:54:11 -04001884TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor)
1885{
1886 const std::string &vert =
1887 "attribute float a_pos;\n"
1888 "void main()\n"
1889 "{\n"
1890 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1891 "}\n";
1892
Olli Etuaho5804dc82018-04-13 14:11:46 +03001893 ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
Geoff Lang407d4e72017-04-12 14:54:11 -04001894
1895 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1896 ASSERT_NE(-1, posLocation);
1897
1898 glUseProgram(program.get());
1899
1900 GLBuffer buffer;
1901 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1902 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1903
1904 glEnableVertexAttribArray(posLocation);
1905 glVertexAttribDivisor(posLocation, 1);
1906
Geoff Lang407d4e72017-04-12 14:54:11 -04001907 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
1908 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
Geoff Lang407d4e72017-04-12 14:54:11 -04001909 ASSERT_GL_NO_ERROR();
1910}
1911
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001912// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
1913TEST_P(WebGLCompatibilityTest, NPOT)
1914{
1915 EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
1916
1917 // Create a texture and set an NPOT mip 0, should always be acceptable.
1918 GLTexture texture;
1919 glBindTexture(GL_TEXTURE_2D, texture.get());
1920 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1921 ASSERT_GL_NO_ERROR();
1922
1923 // Try setting an NPOT mip 1 and verify the error if WebGL 1
1924 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1925 if (getClientMajorVersion() < 3)
1926 {
1927 ASSERT_GL_ERROR(GL_INVALID_VALUE);
1928 }
1929 else
1930 {
1931 ASSERT_GL_NO_ERROR();
1932 }
1933
1934 if (extensionRequestable("GL_OES_texture_npot"))
1935 {
1936 glRequestExtensionANGLE("GL_OES_texture_npot");
1937 ASSERT_GL_NO_ERROR();
1938
1939 // Try again to set NPOT mip 1
1940 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1941 ASSERT_GL_NO_ERROR();
1942 }
1943}
1944
Jamie Madillcad97ee2017-02-02 18:52:44 -05001945template <typename T>
1946void FillTexture2D(GLuint texture,
1947 GLsizei width,
1948 GLsizei height,
1949 const T &onePixelData,
1950 GLint level,
1951 GLint internalFormat,
1952 GLenum format,
1953 GLenum type)
1954{
1955 std::vector<T> allPixelsData(width * height, onePixelData);
1956
1957 glBindTexture(GL_TEXTURE_2D, texture);
1958 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
1959 allPixelsData.data());
1960 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1962 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1963 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1964}
1965
Frank Henigman875bbba2017-02-08 16:38:17 -05001966// Test that unset gl_Position defaults to (0,0,0,0).
1967TEST_P(WebGLCompatibilityTest, DefaultPosition)
1968{
1969 // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set,
1970 // and green otherwise. The center of each quadrant will be red if and only if all
1971 // four corners are red.
1972 const std::string vertexShader =
1973 "attribute vec3 pos;\n"
1974 "varying vec4 color;\n"
1975 "void main() {\n"
1976 " if (gl_Position == vec4(0,0,0,0)) {\n"
1977 " color = vec4(1,0,0,1);\n"
1978 " } else {\n"
1979 " color = vec4(0,1,0,1);\n"
1980 " }\n"
1981 " gl_Position = vec4(pos,1);\n"
1982 "}\n";
1983
1984 const std::string fragmentShader =
1985 "precision mediump float;\n"
1986 "varying vec4 color;\n"
1987 "void main() {\n"
1988 " gl_FragColor = color;\n"
1989 "}\n";
1990
1991 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1992 drawQuad(program.get(), "pos", 0.0f, 1.0f, true);
1993 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1994 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1995 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red);
1996 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red);
1997}
1998
Jamie Madilla4595b82017-01-11 17:36:34 -05001999// Tests that a rendering feedback loop triggers a GL error under WebGL.
2000// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
2001TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
2002{
2003 const std::string vertexShader =
2004 "attribute vec4 a_position;\n"
2005 "varying vec2 v_texCoord;\n"
2006 "void main() {\n"
2007 " gl_Position = a_position;\n"
2008 " v_texCoord = (a_position.xy * 0.5) + 0.5;\n"
2009 "}\n";
2010
2011 const std::string fragmentShader =
2012 "precision mediump float;\n"
2013 "varying vec2 v_texCoord;\n"
2014 "uniform sampler2D u_texture;\n"
2015 "void main() {\n"
2016 " // Shader swizzles color channels so we can tell if the draw succeeded.\n"
2017 " gl_FragColor = texture2D(u_texture, v_texCoord).gbra;\n"
2018 "}\n";
2019
2020 GLTexture texture;
Jamie Madillcad97ee2017-02-02 18:52:44 -05002021 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05002022
2023 ASSERT_GL_NO_ERROR();
2024
2025 GLFramebuffer framebuffer;
2026 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2027 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2028
2029 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2030
2031 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2032
2033 GLint uniformLoc = glGetUniformLocation(program.get(), "u_texture");
2034 ASSERT_NE(-1, uniformLoc);
2035
2036 glUseProgram(program.get());
2037 glUniform1i(uniformLoc, 0);
2038 glDisable(GL_BLEND);
2039 glDisable(GL_DEPTH_TEST);
2040 ASSERT_GL_NO_ERROR();
2041
2042 // Drawing with a texture that is also bound to the current framebuffer should fail
2043 glBindTexture(GL_TEXTURE_2D, texture.get());
2044 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
2045 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2046
2047 // Ensure that the texture contents did not change after the previous render
2048 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2049 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
2050 ASSERT_GL_NO_ERROR();
2051 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2052
2053 // Drawing when texture is bound to an inactive uniform should succeed
2054 GLTexture texture2;
Jamie Madillcad97ee2017-02-02 18:52:44 -05002055 FillTexture2D(texture2.get(), 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05002056
2057 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2058 glActiveTexture(GL_TEXTURE1);
2059 glBindTexture(GL_TEXTURE_2D, texture.get());
2060 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
2061 ASSERT_GL_NO_ERROR();
2062 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2063}
2064
Bryan Bernhart58806562017-01-05 13:09:31 -08002065// Test for the max draw buffers and color attachments.
2066TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
2067{
2068 // This test only applies to ES2.
2069 if (getClientMajorVersion() != 2)
2070 {
2071 return;
2072 }
2073
2074 GLFramebuffer fbo[2];
2075 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0].get());
2076
2077 // Test that is valid when we bind with a single attachment point.
2078 GLTexture texture;
2079 glBindTexture(GL_TEXTURE_2D, texture.get());
2080 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2081 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2082 ASSERT_GL_NO_ERROR();
2083
2084 // Test that enabling the draw buffers extension will allow us to bind with a non-zero
2085 // attachment point.
2086 if (extensionRequestable("GL_EXT_draw_buffers"))
2087 {
2088 glRequestExtensionANGLE("GL_EXT_draw_buffers");
2089 EXPECT_GL_NO_ERROR();
2090 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
2091
2092 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1].get());
2093
2094 GLTexture texture2;
2095 glBindTexture(GL_TEXTURE_2D, texture2.get());
2096 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2097 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2.get(),
2098 0);
2099 ASSERT_GL_NO_ERROR();
2100 }
2101}
2102
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002103// Test that the offset in the index buffer is forced to be a multiple of the element size
2104TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction)
2105{
2106 const std::string &vert =
2107 "attribute vec3 a_pos;\n"
2108 "void main()\n"
2109 "{\n"
2110 " gl_Position = vec4(a_pos, 1.0);\n"
2111 "}\n";
2112
Olli Etuaho5804dc82018-04-13 14:11:46 +03002113 ANGLE_GL_PROGRAM(program, vert, essl1_shaders::fs::Red());
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002114
2115 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
2116 ASSERT_NE(-1, posLocation);
2117 glUseProgram(program.get());
2118
2119 const auto &vertices = GetQuadVertices();
2120
2121 GLBuffer vertexBuffer;
2122 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
2123 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2124 GL_STATIC_DRAW);
2125
2126 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2127 glEnableVertexAttribArray(posLocation);
2128
2129 GLBuffer indexBuffer;
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002130 const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0, 0};
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002131 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
2132 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
2133
2134 ASSERT_GL_NO_ERROR();
2135
2136 const char *zeroIndices = nullptr;
2137
2138 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices);
2139 ASSERT_GL_NO_ERROR();
2140
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002141 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002142 ASSERT_GL_NO_ERROR();
2143
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002144 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices + 1);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002145 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2146}
2147
2148// Test that the offset and stride in the vertex buffer is forced to be a multiple of the element
2149// size
2150TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction)
2151{
2152 const char *zeroOffset = nullptr;
2153
2154 // Base case, vector of two floats
2155 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset);
2156 ASSERT_GL_NO_ERROR();
2157
2158 // Test setting a non-multiple offset
2159 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1);
2160 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2161 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2);
2162 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2163 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3);
2164 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2165
2166 // Test setting a non-multiple stride
2167 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset);
2168 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2169 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset);
2170 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2171 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset);
2172 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2173}
2174
Jamie Madillcad97ee2017-02-02 18:52:44 -05002175void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program,
2176 const std::array<GLenum, 2> &drawBuffers,
2177 GLenum expectedError)
2178{
2179 glDrawBuffersEXT(2, drawBuffers.data());
2180
2181 // Make sure framebuffer is complete before feedback loop detection
2182 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2183
2184 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2185
2186 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2187 // it should be NO_ERROR"
2188 EXPECT_GL_ERROR(expectedError);
2189}
2190
2191// This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers.
2192// Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html
2193TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT)
2194{
2195 const std::string vertexShader =
2196 "attribute vec4 aPosition;\n"
2197 "varying vec2 texCoord;\n"
2198 "void main() {\n"
2199 " gl_Position = aPosition;\n"
2200 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2201 "}\n";
2202
2203 const std::string fragmentShader =
2204 "#extension GL_EXT_draw_buffers : require\n"
2205 "precision mediump float;\n"
2206 "uniform sampler2D tex;\n"
2207 "varying vec2 texCoord;\n"
2208 "void main() {\n"
2209 " gl_FragData[0] = texture2D(tex, texCoord);\n"
2210 " gl_FragData[1] = texture2D(tex, texCoord);\n"
2211 "}\n";
2212
2213 GLsizei width = 8;
2214 GLsizei height = 8;
2215
2216 // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers
2217 // extension and gl_FragData semantics are changed to enforce indexing by zero always.
2218 // TODO(jmadill): This extension should be disabled in WebGL 2 contexts.
2219 if (/*!extensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2)
2220 {
2221 // No WEBGL_draw_buffers support -- this is legal.
2222 return;
2223 }
2224
2225 GLint maxDrawBuffers = 0;
2226 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2227
Yunchao He9550c602018-02-13 14:47:05 +08002228 // Test skipped because MAX_DRAW_BUFFERS is too small.
2229 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 2);
Jamie Madillcad97ee2017-02-02 18:52:44 -05002230
2231 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2232 glUseProgram(program.get());
2233 glViewport(0, 0, width, height);
2234
2235 GLTexture tex0;
2236 GLTexture tex1;
2237 GLFramebuffer fbo;
2238 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2239 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2240 ASSERT_GL_NO_ERROR();
2241
2242 glBindTexture(GL_TEXTURE_2D, tex1.get());
2243 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2244 ASSERT_NE(-1, texLoc);
2245 glUniform1i(texLoc, 0);
2246 ASSERT_GL_NO_ERROR();
2247
2248 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
2249 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2250 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2251 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
2252
2253 drawBuffersEXTFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}},
2254 GL_INVALID_OPERATION);
2255 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
2256 GL_INVALID_OPERATION);
2257 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
2258}
2259
Jamie Madill07be8bf2017-02-02 19:59:57 -05002260// Test tests that texture copying feedback loops are properly rejected in WebGL.
2261// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
2262TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
2263{
2264 GLTexture texture;
2265 glBindTexture(GL_TEXTURE_2D, texture.get());
2266 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2268 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2271
2272 GLTexture texture2;
2273 glBindTexture(GL_TEXTURE_2D, texture2.get());
2274 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2279
2280 GLFramebuffer framebuffer;
2281 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2282 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2283
2284 // framebuffer should be FRAMEBUFFER_COMPLETE.
2285 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2286 ASSERT_GL_NO_ERROR();
2287
2288 // testing copyTexImage2D
2289
2290 // copyTexImage2D to same texture but different level
2291 glBindTexture(GL_TEXTURE_2D, texture.get());
2292 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
2293 EXPECT_GL_NO_ERROR();
2294
2295 // copyTexImage2D to same texture same level, invalid feedback loop
2296 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2297 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2298
2299 // copyTexImage2D to different texture
2300 glBindTexture(GL_TEXTURE_2D, texture2.get());
2301 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2302 EXPECT_GL_NO_ERROR();
2303
2304 // testing copyTexSubImage2D
2305
2306 // copyTexSubImage2D to same texture but different level
2307 glBindTexture(GL_TEXTURE_2D, texture.get());
2308 glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
2309 EXPECT_GL_NO_ERROR();
2310
2311 // copyTexSubImage2D to same texture same level, invalid feedback loop
2312 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2313 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2314
2315 // copyTexSubImage2D to different texture
2316 glBindTexture(GL_TEXTURE_2D, texture2.get());
2317 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2318 EXPECT_GL_NO_ERROR();
2319}
2320
2321void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program,
2322 const std::array<GLenum, 2> &drawBuffers,
2323 GLenum expectedError)
2324{
2325 glDrawBuffers(2, drawBuffers.data());
2326
2327 // Make sure framebuffer is complete before feedback loop detection
2328 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2329
2330 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2331
2332 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2333 // it should be NO_ERROR"
2334 EXPECT_GL_ERROR(expectedError);
2335}
2336
Yuly Novikov817232e2017-02-22 18:36:10 -05002337// Tests invariance matching rules between built in varyings.
2338// Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html.
2339TEST_P(WebGLCompatibilityTest, BuiltInInvariant)
2340{
2341 const std::string vertexShaderVariant =
2342 "varying vec4 v_varying;\n"
2343 "void main()\n"
2344 "{\n"
2345 " gl_PointSize = 1.0;\n"
2346 " gl_Position = v_varying;\n"
2347 "}";
2348 const std::string fragmentShaderInvariantGlFragCoord =
2349 "invariant gl_FragCoord;\n"
2350 "void main()\n"
2351 "{\n"
2352 " gl_FragColor = gl_FragCoord;\n"
2353 "}";
2354 const std::string fragmentShaderInvariantGlPointCoord =
2355 "invariant gl_PointCoord;\n"
2356 "void main()\n"
2357 "{\n"
2358 " gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);\n"
2359 "}";
2360
2361 GLuint program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlFragCoord);
2362 EXPECT_EQ(0u, program);
2363
2364 program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlPointCoord);
2365 EXPECT_EQ(0u, program);
2366}
2367
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04002368// Tests global namespace conflicts between uniforms and attributes.
2369// Based on WebGL test conformance/glsl/misc/shaders-with-name-conflicts.html.
2370TEST_P(WebGLCompatibilityTest, GlobalNamesConflict)
2371{
2372 const std::string vertexShader =
2373 "attribute vec4 foo;\n"
2374 "void main()\n"
2375 "{\n"
2376 " gl_Position = foo;\n"
2377 "}";
2378 const std::string fragmentShader =
2379 "precision mediump float;\n"
2380 "uniform vec4 foo;\n"
2381 "void main()\n"
2382 "{\n"
2383 " gl_FragColor = foo;\n"
2384 "}";
2385
2386 GLuint program = CompileProgram(vertexShader, fragmentShader);
2387 EXPECT_EQ(0u, program);
2388}
2389
Geoff Lang966c9402017-04-18 12:38:27 -04002390// Test dimension and image size validation of compressed textures
2391TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
2392{
2393 if (extensionRequestable("GL_EXT_texture_compression_dxt1"))
2394 {
2395 glRequestExtensionANGLE("GL_EXT_texture_compression_dxt1");
2396 }
2397
Yunchao He9550c602018-02-13 14:47:05 +08002398 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_compression_dxt1"));
Geoff Lang966c9402017-04-18 12:38:27 -04002399
2400 constexpr uint8_t CompressedImageDXT1[] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
2401
2402 GLTexture texture;
2403 glBindTexture(GL_TEXTURE_2D, texture);
2404
2405 // Regular case, verify that it works
2406 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2407 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2408 ASSERT_GL_NO_ERROR();
2409
2410 // Test various dimensions that are not valid
2411 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3, 4, 0,
2412 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2413 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2414
2415 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 3, 0,
2416 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2417 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2418
2419 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2420 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2421 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2422
2423 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2424 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2425 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2426
2427 // Test various image sizes that are not valid
2428 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2429 sizeof(CompressedImageDXT1) - 1, CompressedImageDXT1);
2430 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2431
2432 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2433 sizeof(CompressedImageDXT1) + 1, CompressedImageDXT1);
2434 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2435
2436 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 0,
2437 CompressedImageDXT1);
2438 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2439
2440 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0, 0,
2441 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2442 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2443
2444 // Fill a full mip chain and verify that it works
2445 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2446 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2447 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2448 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2449 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2450 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2451 ASSERT_GL_NO_ERROR();
2452
2453 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2454 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2455 ASSERT_GL_NO_ERROR();
2456
2457 // Test that non-block size sub-uploads are not valid for the 0 mip
2458 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2459 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2460 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2461
2462 // Test that non-block size sub-uploads are valid for if they fill the whole mip
2463 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2464 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2465 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, 1, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2466 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2467 ASSERT_GL_NO_ERROR();
2468
2469 // Test that if the format miss-matches the texture, an error is generated
2470 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
2471 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2472 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2473}
2474
Geoff Lang677bb6f2017-04-05 12:40:40 -04002475TEST_P(WebGLCompatibilityTest, L32FTextures)
2476{
2477 constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f};
2478 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 1.0f};
2479
2480 for (auto extension : FloatingPointTextureExtensions)
2481 {
2482 if (strlen(extension) > 0 && extensionRequestable(extension))
2483 {
2484 glRequestExtensionANGLE(extension);
2485 ASSERT_GL_NO_ERROR();
2486 }
2487
2488 // Unsized L 32F
2489 {
2490 bool texture = extensionEnabled("GL_OES_texture_float");
2491 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2492 bool render = false;
2493 TestFloatTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, texture, filter, render,
2494 textureData, readPixelData);
2495 }
2496
2497 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2498 {
2499 // Sized L 32F
2500 bool texture = extensionEnabled("GL_OES_texture_float") &&
2501 extensionEnabled("GL_EXT_texture_storage");
2502 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2503 bool render = false;
2504 TestFloatTextureFormat(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT, texture, filter,
2505 render, textureData, readPixelData);
2506 }
2507 }
2508}
2509
2510TEST_P(WebGLCompatibilityTest, A32FTextures)
2511{
2512 constexpr float textureData[] = {33.33f, 0.0f, 0.0f, 0.0f};
2513 constexpr float readPixelData[] = {0.0f, 0.0f, 0.0f, textureData[0]};
2514
2515 for (auto extension : FloatingPointTextureExtensions)
2516 {
2517 if (strlen(extension) > 0 && extensionRequestable(extension))
2518 {
2519 glRequestExtensionANGLE(extension);
2520 ASSERT_GL_NO_ERROR();
2521 }
2522
2523 // Unsized A 32F
2524 {
2525 bool texture = extensionEnabled("GL_OES_texture_float");
2526 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2527 bool render = false;
2528 TestFloatTextureFormat(GL_ALPHA, GL_ALPHA, GL_FLOAT, texture, filter, render,
2529 textureData, readPixelData);
2530 }
2531
2532 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2533 {
2534 // Sized A 32F
2535 bool texture = extensionEnabled("GL_OES_texture_float") &&
2536 extensionEnabled("GL_EXT_texture_storage");
2537 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2538 bool render = false;
2539 TestFloatTextureFormat(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT, texture, filter, render,
2540 textureData, readPixelData);
2541 }
2542 }
2543}
2544
2545TEST_P(WebGLCompatibilityTest, LA32FTextures)
2546{
2547 constexpr float textureData[] = {-0.21f, 15.1f, 0.0f, 0.0f};
2548 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0],
2549 textureData[1]};
2550
2551 for (auto extension : FloatingPointTextureExtensions)
2552 {
2553 if (strlen(extension) > 0 && extensionRequestable(extension))
2554 {
2555 glRequestExtensionANGLE(extension);
2556 ASSERT_GL_NO_ERROR();
2557 }
2558
2559 // Unsized LA 32F
2560 {
2561 bool texture = extensionEnabled("GL_OES_texture_float");
2562 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2563 bool render = false;
2564 TestFloatTextureFormat(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2565 filter, render, textureData, readPixelData);
2566 }
2567
2568 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2569 {
2570 // Sized LA 32F
2571 bool texture = extensionEnabled("GL_OES_texture_float") &&
2572 extensionEnabled("GL_EXT_texture_storage");
2573 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2574 bool render = false;
2575 TestFloatTextureFormat(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2576 filter, render, textureData, readPixelData);
2577 }
2578 }
2579}
2580
2581TEST_P(WebGLCompatibilityTest, R32FTextures)
2582{
2583 constexpr float data[] = {1000.0f, 0.0f, 0.0f, 1.0f};
2584
2585 for (auto extension : FloatingPointTextureExtensions)
2586 {
2587 if (strlen(extension) > 0 && extensionRequestable(extension))
2588 {
2589 glRequestExtensionANGLE(extension);
2590 ASSERT_GL_NO_ERROR();
2591 }
2592
2593 // Unsized R 32F
2594 {
2595 bool texture =
2596 extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg");
2597 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2598 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2599 TestFloatTextureFormat(GL_RED, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2600 }
2601
2602 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2603 {
2604 // Sized R 32F
2605 bool texture =
2606 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2607 extensionEnabled("GL_EXT_texture_rg") &&
2608 extensionEnabled("GL_EXT_texture_storage"));
2609 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2610 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2611 TestFloatTextureFormat(GL_R32F, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2612 }
2613 }
2614}
2615
2616TEST_P(WebGLCompatibilityTest, RG32FTextures)
2617{
2618 constexpr float data[] = {1000.0f, -0.001f, 0.0f, 1.0f};
2619
2620 for (auto extension : FloatingPointTextureExtensions)
2621 {
2622 if (strlen(extension) > 0 && extensionRequestable(extension))
2623 {
2624 glRequestExtensionANGLE(extension);
2625 ASSERT_GL_NO_ERROR();
2626 }
2627
2628 // Unsized RG 32F
2629 {
2630 bool texture =
2631 (extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg"));
2632 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2633 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2634 TestFloatTextureFormat(GL_RG, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2635 }
2636
2637 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2638 {
2639 // Sized RG 32F
2640 bool texture =
2641 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2642 extensionEnabled("GL_EXT_texture_rg") &&
2643 extensionEnabled("GL_EXT_texture_storage"));
2644 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2645 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2646 TestFloatTextureFormat(GL_RG32F, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2647 }
2648 }
2649}
2650
2651TEST_P(WebGLCompatibilityTest, RGB32FTextures)
2652{
Yunchao He9550c602018-02-13 14:47:05 +08002653 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002654
Geoff Lang677bb6f2017-04-05 12:40:40 -04002655 constexpr float data[] = {1000.0f, -500.0f, 10.0f, 1.0f};
2656
2657 for (auto extension : FloatingPointTextureExtensions)
2658 {
2659 if (strlen(extension) > 0 && extensionRequestable(extension))
2660 {
2661 glRequestExtensionANGLE(extension);
2662 ASSERT_GL_NO_ERROR();
2663 }
2664
2665 // Unsized RGB 32F
2666 {
2667 bool texture = extensionEnabled("GL_OES_texture_float");
2668 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2669 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2670 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_FLOAT, texture, filter, render, data, data);
2671 }
2672
2673 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2674 {
2675 // Sized RGBA 32F
2676 bool texture =
2677 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2678 extensionEnabled("GL_EXT_texture_storage"));
2679 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2680 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2681 TestFloatTextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT, texture, filter, render, data,
2682 data);
2683 }
2684 }
2685}
2686
2687TEST_P(WebGLCompatibilityTest, RGBA32FTextures)
2688{
2689 constexpr float data[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2690
2691 for (auto extension : FloatingPointTextureExtensions)
2692 {
2693 if (strlen(extension) > 0 && extensionRequestable(extension))
2694 {
2695 glRequestExtensionANGLE(extension);
2696 ASSERT_GL_NO_ERROR();
2697 }
2698
2699 // Unsized RGBA 32F
2700 {
2701 bool texture = extensionEnabled("GL_OES_texture_float");
2702 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2703 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2704 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2705 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_FLOAT, texture, filter, render, data, data);
2706 }
2707
2708 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2709 {
2710 // Sized RGBA 32F
2711 bool texture =
2712 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2713 extensionEnabled("GL_EXT_texture_storage"));
2714 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2715 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2716 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2717 TestFloatTextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT, texture, filter, render, data,
2718 data);
2719 }
2720 }
2721}
2722
2723TEST_P(WebGLCompatibilityTest, R16FTextures)
2724{
2725 constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
2726 const GLushort textureData[] = {
2727 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2728 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2729
2730 for (auto extension : FloatingPointTextureExtensions)
2731 {
2732 if (strlen(extension) > 0 && extensionRequestable(extension))
2733 {
2734 glRequestExtensionANGLE(extension);
2735 ASSERT_GL_NO_ERROR();
2736 }
2737
2738 // Unsized R 16F (OES)
2739 {
2740 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2741 extensionEnabled("GL_EXT_texture_rg");
2742 bool filter = getClientMajorVersion() >= 3 ||
2743 extensionEnabled("GL_OES_texture_half_float_linear");
2744 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2745 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render,
2746 textureData, readPixelsData);
2747 }
2748
2749 // Unsized R 16F
2750 {
2751 bool texture = false;
2752 bool filter = false;
2753 bool render = false;
2754 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2755 textureData, readPixelsData);
2756 }
2757
2758 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2759 {
2760 // Sized R 16F
2761 bool texture = getClientMajorVersion() >= 3;
2762 bool filter = getClientMajorVersion() >= 3 ||
2763 extensionEnabled("GL_OES_texture_half_float_linear");
2764 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2765 extensionEnabled("GL_EXT_color_buffer_float");
2766 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2767 textureData, readPixelsData);
2768 }
2769 }
2770}
2771
2772TEST_P(WebGLCompatibilityTest, RG16FTextures)
2773{
2774 constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f};
2775 const GLushort textureData[] = {
2776 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2777 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2778
2779 for (auto extension : FloatingPointTextureExtensions)
2780 {
2781 if (strlen(extension) > 0 && extensionRequestable(extension))
2782 {
2783 glRequestExtensionANGLE(extension);
2784 ASSERT_GL_NO_ERROR();
2785 }
2786
2787 // Unsized RG 16F (OES)
2788 {
2789 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2790 extensionEnabled("GL_EXT_texture_rg");
2791 bool filter = getClientMajorVersion() >= 3 ||
2792 extensionEnabled("GL_OES_texture_half_float_linear");
2793 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") &&
2794 extensionEnabled("GL_EXT_texture_rg");
2795 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render,
2796 textureData, readPixelsData);
2797 }
2798
2799 // Unsized RG 16F
2800 {
2801 bool texture = false;
2802 bool filter = false;
2803 bool render = false;
2804 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2805 textureData, readPixelsData);
2806 }
2807
2808 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2809 {
2810 // Sized RG 16F
2811 bool texture = getClientMajorVersion() >= 3;
2812 bool filter = getClientMajorVersion() >= 3 ||
2813 extensionEnabled("GL_OES_texture_half_float_linear");
2814 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2815 extensionEnabled("GL_EXT_color_buffer_float");
2816 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2817 textureData, readPixelsData);
2818 }
2819 }
2820}
2821
2822TEST_P(WebGLCompatibilityTest, RGB16FTextures)
2823{
Yunchao He9550c602018-02-13 14:47:05 +08002824 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002825
Geoff Lang677bb6f2017-04-05 12:40:40 -04002826 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f};
2827 const GLushort textureData[] = {
2828 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2829 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2830
2831 for (auto extension : FloatingPointTextureExtensions)
2832 {
2833 if (strlen(extension) > 0 && extensionRequestable(extension))
2834 {
2835 glRequestExtensionANGLE(extension);
2836 ASSERT_GL_NO_ERROR();
2837 }
2838
2839 // Unsized RGB 16F (OES)
2840 {
2841 bool texture = extensionEnabled("GL_OES_texture_half_float");
2842 bool filter = getClientMajorVersion() >= 3 ||
2843 extensionEnabled("GL_OES_texture_half_float_linear");
2844 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2845 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render,
2846 textureData, readPixelsData);
2847 }
2848
2849 // Unsized RGB 16F
2850 {
2851 bool texture = false;
2852 bool filter = false;
2853 bool render = false;
2854 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2855 textureData, readPixelsData);
2856 }
2857
2858 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2859 {
2860 // Sized RGB 16F
2861 bool texture = getClientMajorVersion() >= 3;
2862 bool filter = getClientMajorVersion() >= 3 ||
2863 extensionEnabled("GL_OES_texture_half_float_linear");
2864 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2865 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2866 textureData, readPixelsData);
2867 }
2868 }
2869}
2870
2871TEST_P(WebGLCompatibilityTest, RGBA16FTextures)
2872{
Yunchao He9550c602018-02-13 14:47:05 +08002873 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002874
Geoff Lang677bb6f2017-04-05 12:40:40 -04002875 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2876 const GLushort textureData[] = {
2877 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2878 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2879
2880 for (auto extension : FloatingPointTextureExtensions)
2881 {
2882 if (strlen(extension) > 0 && extensionRequestable(extension))
2883 {
2884 glRequestExtensionANGLE(extension);
2885 ASSERT_GL_NO_ERROR();
2886 }
2887
2888 // Unsized RGBA 16F (OES)
2889 {
2890 bool texture = extensionEnabled("GL_OES_texture_half_float");
2891 bool filter = getClientMajorVersion() >= 3 ||
2892 extensionEnabled("GL_OES_texture_half_float_linear");
2893 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2894 extensionEnabled("GL_EXT_color_buffer_float");
2895 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render,
2896 textureData, readPixelsData);
2897 }
2898
2899 // Unsized RGBA 16F
2900 {
2901 bool texture = false;
2902 bool filter = false;
2903 bool render = false;
2904 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2905 textureData, readPixelsData);
2906 }
2907
2908 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2909 {
2910 // Sized RGBA 16F
2911 bool texture = getClientMajorVersion() >= 3;
2912 bool filter = getClientMajorVersion() >= 3 ||
2913 extensionEnabled("GL_OES_texture_half_float_linear");
2914 bool render = extensionEnabled("GL_EXT_color_buffer_half_float") ||
2915 extensionEnabled("GL_EXT_color_buffer_float");
2916 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
2917 textureData, readPixelsData);
2918 }
2919 }
2920}
2921
Geoff Lang6e898aa2017-06-02 11:17:26 -04002922// Test that when GL_CHROMIUM_color_buffer_float_rgb[a] is enabled, sized GL_RGB[A]_32F formats are
2923// accepted by glTexImage2D
2924TEST_P(WebGLCompatibilityTest, SizedRGBA32FFormats)
2925{
Yunchao He9550c602018-02-13 14:47:05 +08002926 // Test skipped because it is only valid for WebGL1 contexts.
2927 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
Geoff Lang6e898aa2017-06-02 11:17:26 -04002928
Yunchao He9550c602018-02-13 14:47:05 +08002929 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_OES_texture_float"));
2930
Geoff Lang6e898aa2017-06-02 11:17:26 -04002931 glRequestExtensionANGLE("GL_OES_texture_float");
2932 ASSERT_GL_NO_ERROR();
2933
2934 GLTexture texture;
2935 glBindTexture(GL_TEXTURE_2D, texture);
2936
2937 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2938 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2939
2940 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2941 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2942
2943 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgba"))
2944 {
2945 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgba");
2946 ASSERT_GL_NO_ERROR();
2947
2948 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
2949 EXPECT_GL_NO_ERROR();
2950 }
2951
2952 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgb"))
2953 {
2954 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgb");
2955 ASSERT_GL_NO_ERROR();
2956
2957 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
2958 EXPECT_GL_NO_ERROR();
2959 }
2960}
2961
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002962// Verify GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point.
2963TEST_P(WebGLCompatibilityTest, DepthStencilAttachment)
2964{
2965 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
2966
2967 // Test that attaching a bound texture succeeds.
2968 GLTexture texture;
2969 glBindTexture(GL_TEXTURE_2D, texture);
2970
2971 GLFramebuffer fbo;
2972 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2973
2974 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
2975
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002976 GLint attachmentType = 0;
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002977 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002978 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002979 EXPECT_GL_NO_ERROR();
2980 EXPECT_GLENUM_EQ(GL_TEXTURE, attachmentType);
2981
2982 // Test when if no attach object at the named attachment point and pname is not OBJECT_TYPE.
2983 GLFramebuffer fbo2;
2984 glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
2985
2986 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002987 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attachmentType);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08002988 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2989}
2990
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08002991// Verify framebuffer attachments return expected types when in an inconsistant state.
2992TEST_P(WebGLCompatibilityTest, FramebufferAttachmentConsistancy)
2993{
2994 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
2995
2996 GLFramebuffer fbo;
2997 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2998
2999 GLRenderbuffer rb1;
3000 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
3001
3002 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb1);
3003
3004 GLint attachmentType = 0;
3005 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
3006 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3007
3008 EXPECT_GL_NO_ERROR();
3009 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
3010
3011 GLRenderbuffer rb2;
3012 glBindRenderbuffer(GL_RENDERBUFFER, rb2);
3013
3014 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2);
3015
3016 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
3017 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3018
3019 EXPECT_GL_NO_ERROR();
3020 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -08003021
3022 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb2);
3023
3024 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
3025 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3026
3027 EXPECT_GL_NO_ERROR();
3028 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
3029
3030 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2);
3031
3032 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
3033 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3034
3035 EXPECT_GL_NO_ERROR();
3036 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003037}
3038
Jamie Madill07be8bf2017-02-02 19:59:57 -05003039// This tests that rendering feedback loops works as expected with WebGL 2.
3040// Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html
3041TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers)
3042{
3043 const std::string vertexShader =
3044 "#version 300 es\n"
3045 "in vec4 aPosition;\n"
3046 "out vec2 texCoord;\n"
3047 "void main() {\n"
3048 " gl_Position = aPosition;\n"
3049 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
3050 "}\n";
3051
3052 const std::string fragmentShader =
3053 "#version 300 es\n"
3054 "precision mediump float;\n"
3055 "uniform sampler2D tex;\n"
3056 "in vec2 texCoord;\n"
3057 "out vec4 oColor;\n"
3058 "void main() {\n"
3059 " oColor = texture(tex, texCoord);\n"
3060 "}\n";
3061
3062 GLsizei width = 8;
3063 GLsizei height = 8;
3064
3065 GLint maxDrawBuffers = 0;
3066 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3067 // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS.
3068 ASSERT_GE(maxDrawBuffers, 2);
3069
3070 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3071 glUseProgram(program.get());
3072 glViewport(0, 0, width, height);
3073
3074 GLTexture tex0;
3075 GLTexture tex1;
3076 GLFramebuffer fbo;
3077 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3078 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3079 ASSERT_GL_NO_ERROR();
3080
3081 glBindTexture(GL_TEXTURE_2D, tex1.get());
3082 GLint texLoc = glGetUniformLocation(program.get(), "tex");
3083 ASSERT_NE(-1, texLoc);
3084 glUniform1i(texLoc, 0);
3085
3086 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
3087 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
3088 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
3089 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
3090 ASSERT_GL_NO_ERROR();
3091
3092 drawBuffersFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION);
3093 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
3094 GL_INVALID_OPERATION);
3095 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
3096}
3097
Jamie Madill1d37bc52017-02-02 19:59:58 -05003098// This test covers detection of rendering feedback loops between the FBO and a depth Texture.
3099// Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html
3100TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil)
3101{
3102 const std::string vertexShader =
3103 "#version 300 es\n"
3104 "in vec4 aPosition;\n"
3105 "out vec2 texCoord;\n"
3106 "void main() {\n"
3107 " gl_Position = aPosition;\n"
3108 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
3109 "}\n";
3110
3111 const std::string fragmentShader =
3112 "#version 300 es\n"
3113 "precision mediump float;\n"
3114 "uniform sampler2D tex;\n"
3115 "in vec2 texCoord;\n"
3116 "out vec4 oColor;\n"
3117 "void main() {\n"
3118 " oColor = texture(tex, texCoord);\n"
3119 "}\n";
3120
3121 GLsizei width = 8;
3122 GLsizei height = 8;
3123
3124 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3125 glUseProgram(program.get());
3126
3127 glViewport(0, 0, width, height);
3128
3129 GLint texLoc = glGetUniformLocation(program.get(), "tex");
3130 glUniform1i(texLoc, 0);
3131
3132 // Create textures and allocate storage
3133 GLTexture tex0;
3134 GLTexture tex1;
3135 GLRenderbuffer rb;
3136 FillTexture2D(tex0.get(), width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3137 FillTexture2D(tex1.get(), width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
3138 GL_UNSIGNED_INT);
3139 glBindRenderbuffer(GL_RENDERBUFFER, rb.get());
3140 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
3141 ASSERT_GL_NO_ERROR();
3142
3143 GLFramebuffer fbo;
3144 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
3145 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
3146
3147 // Test rendering and sampling feedback loop for depth buffer
3148 glBindTexture(GL_TEXTURE_2D, tex1.get());
3149 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1.get(), 0);
3150 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3151
3152 // The same image is used as depth buffer during rendering.
3153 glEnable(GL_DEPTH_TEST);
3154 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3155 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3156
3157 // The same image is used as depth buffer. But depth mask is false.
3158 glDepthMask(GL_FALSE);
3159 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3160 EXPECT_GL_NO_ERROR();
3161
3162 // The same image is used as depth buffer. But depth test is not enabled during rendering.
3163 glDepthMask(GL_TRUE);
3164 glDisable(GL_DEPTH_TEST);
3165 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3166 EXPECT_GL_NO_ERROR();
3167
3168 // Test rendering and sampling feedback loop for stencil buffer
3169 glBindTexture(GL_RENDERBUFFER, rb.get());
3170 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
3171 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb.get());
3172 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3173 constexpr GLint stencilClearValue = 0x40;
3174 glClearBufferiv(GL_STENCIL, 0, &stencilClearValue);
3175
3176 // The same image is used as stencil buffer during rendering.
3177 glEnable(GL_STENCIL_TEST);
3178 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3179 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3180
3181 // The same image is used as stencil buffer. But stencil mask is zero.
3182 glStencilMask(0x0);
3183 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3184 EXPECT_GL_NO_ERROR();
3185
3186 // The same image is used as stencil buffer. But stencil test is not enabled during rendering.
3187 glStencilMask(0xffff);
3188 glDisable(GL_STENCIL_TEST);
3189 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
3190 EXPECT_GL_NO_ERROR();
3191}
3192
Jamie Madillfd3dd432017-02-02 19:59:59 -05003193// The source and the target for CopyTexSubImage3D are the same 3D texture.
3194// But the level of the 3D texture != the level of the read attachment.
3195TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels)
3196{
3197 GLTexture texture;
3198 GLFramebuffer framebuffer;
3199
3200 glBindTexture(GL_TEXTURE_3D, texture.get());
3201 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3202
3203 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3204 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3205 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
3206 ASSERT_GL_NO_ERROR();
3207
3208 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3209 EXPECT_GL_NO_ERROR();
3210}
3211
3212// The source and the target for CopyTexSubImage3D are the same 3D texture.
3213// But the zoffset of the 3D texture != the layer of the read attachment.
3214TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers)
3215{
3216 GLTexture texture;
3217 GLFramebuffer framebuffer;
3218
3219 glBindTexture(GL_TEXTURE_3D, texture.get());
3220 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3221
3222 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3223 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 1);
3224 ASSERT_GL_NO_ERROR();
3225
3226 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2);
3227 EXPECT_GL_NO_ERROR();
3228}
3229
3230// The source and the target for CopyTexSubImage3D are the same 3D texture.
3231// And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment.
3232TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D)
3233{
3234 GLTexture texture;
3235 GLFramebuffer framebuffer;
3236
3237 glBindTexture(GL_TEXTURE_3D, texture.get());
3238 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3239
3240 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3241 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3242 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3243 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 1, 0);
3244 ASSERT_GL_NO_ERROR();
3245
3246 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3247 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3248}
3249
Corentin Wallez59c41592017-07-11 13:19:54 -04003250// Verify that errors are generated when there isn't a defined conversion between the clear type and
3251// the buffer type.
Geoff Lang76e65652017-03-27 14:58:02 -04003252TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity)
3253{
Yunchao He9550c602018-02-13 14:47:05 +08003254 // Test skipped for D3D11 because it generates D3D11 runtime warnings.
3255 ANGLE_SKIP_TEST_IF(IsD3D11());
Geoff Lang76e65652017-03-27 14:58:02 -04003256
3257 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3258 constexpr int clearInt[] = {0, 0, 0, 0};
3259 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3260
3261 GLTexture texture;
3262 GLFramebuffer framebuffer;
3263
3264 glBindTexture(GL_TEXTURE_2D, texture.get());
3265 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3266
3267 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
3268 ASSERT_GL_NO_ERROR();
3269
3270 // Unsigned integer buffer
3271 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr);
3272 ASSERT_GL_NO_ERROR();
3273
3274 glClearBufferfv(GL_COLOR, 0, clearFloat);
3275 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3276
3277 glClearBufferiv(GL_COLOR, 0, clearInt);
3278 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3279
3280 glClearBufferuiv(GL_COLOR, 0, clearUint);
3281 EXPECT_GL_NO_ERROR();
3282
3283 glClear(GL_COLOR_BUFFER_BIT);
3284 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3285
3286 // Integer buffer
3287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr);
3288 ASSERT_GL_NO_ERROR();
3289
3290 glClearBufferfv(GL_COLOR, 0, clearFloat);
3291 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3292
3293 glClearBufferiv(GL_COLOR, 0, clearInt);
3294 EXPECT_GL_NO_ERROR();
3295
3296 glClearBufferuiv(GL_COLOR, 0, clearUint);
3297 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3298
3299 glClear(GL_COLOR_BUFFER_BIT);
3300 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3301
3302 // Float buffer
Geoff Lang677bb6f2017-04-05 12:40:40 -04003303 if (extensionRequestable("GL_EXT_color_buffer_float"))
3304 {
3305 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3306 }
Geoff Lang76e65652017-03-27 14:58:02 -04003307
Geoff Lang677bb6f2017-04-05 12:40:40 -04003308 if (extensionEnabled("GL_EXT_color_buffer_float"))
3309 {
3310 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
3311 ASSERT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003312
Geoff Lang677bb6f2017-04-05 12:40:40 -04003313 glClearBufferfv(GL_COLOR, 0, clearFloat);
3314 EXPECT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003315
Geoff Lang677bb6f2017-04-05 12:40:40 -04003316 glClearBufferiv(GL_COLOR, 0, clearInt);
3317 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang76e65652017-03-27 14:58:02 -04003318
Geoff Lang677bb6f2017-04-05 12:40:40 -04003319 glClearBufferuiv(GL_COLOR, 0, clearUint);
3320 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3321
3322 glClear(GL_COLOR_BUFFER_BIT);
3323 EXPECT_GL_NO_ERROR();
3324 }
Geoff Lang76e65652017-03-27 14:58:02 -04003325
3326 // Normalized uint buffer
3327 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3328 ASSERT_GL_NO_ERROR();
3329
3330 glClearBufferfv(GL_COLOR, 0, clearFloat);
3331 EXPECT_GL_NO_ERROR();
3332
3333 glClearBufferiv(GL_COLOR, 0, clearInt);
3334 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3335
3336 glClearBufferuiv(GL_COLOR, 0, clearUint);
3337 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3338
3339 glClear(GL_COLOR_BUFFER_BIT);
3340 EXPECT_GL_NO_ERROR();
3341}
3342
Corentin Wallez59c41592017-07-11 13:19:54 -04003343// Test the interaction of WebGL compatibility clears with default framebuffers
3344TEST_P(WebGL2CompatibilityTest, ClearBufferDefaultFramebuffer)
3345{
3346 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3347 constexpr int clearInt[] = {0, 0, 0, 0};
3348 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3349
3350 // glClear works as usual, this is also a regression test for a bug where we
3351 // iterated on maxDrawBuffers for default framebuffers, triggering an assert
3352 glClear(GL_COLOR_BUFFER_BIT);
3353 EXPECT_GL_NO_ERROR();
3354
3355 // Default framebuffers are normalized uints, so only glClearBufferfv works.
3356 glClearBufferfv(GL_COLOR, 0, clearFloat);
3357 EXPECT_GL_NO_ERROR();
3358
3359 glClearBufferiv(GL_COLOR, 0, clearInt);
3360 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3361
3362 glClearBufferuiv(GL_COLOR, 0, clearUint);
3363 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3364}
3365
Geoff Lange4915782017-04-12 15:19:07 -04003366// Verify that errors are generate when trying to blit from an image to itself
3367TEST_P(WebGL2CompatibilityTest, BlitFramebufferSameImage)
3368{
3369 GLTexture textures[2];
3370 glBindTexture(GL_TEXTURE_2D, textures[0]);
3371 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3372 glBindTexture(GL_TEXTURE_2D, textures[1]);
3373 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3374
3375 GLRenderbuffer renderbuffers[2];
3376 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
3377 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3378 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
3379 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3380
3381 GLFramebuffer framebuffers[2];
3382 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]);
3383 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]);
3384
3385 ASSERT_GL_NO_ERROR();
3386
3387 // Same texture
3388 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3389 0);
3390 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3391 0);
3392 ASSERT_GL_NO_ERROR();
3393 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3394 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3395
3396 // Same textures but different renderbuffers
3397 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3398 renderbuffers[0]);
3399 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3400 renderbuffers[1]);
3401 ASSERT_GL_NO_ERROR();
3402 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3403 ASSERT_GL_NO_ERROR();
3404 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3405 GL_NEAREST);
3406 ASSERT_GL_NO_ERROR();
3407 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3408 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3409 GL_NEAREST);
3410 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3411
3412 // Same renderbuffers but different textures
3413 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3414 0);
3415 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1],
3416 0);
3417 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3418 renderbuffers[0]);
3419 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3420 renderbuffers[0]);
3421 ASSERT_GL_NO_ERROR();
3422 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3423 ASSERT_GL_NO_ERROR();
3424 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3425 GL_NEAREST);
3426 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3427 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3428 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3429 GL_NEAREST);
3430 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3431}
3432
Geoff Lange0cff192017-05-30 13:04:56 -04003433// Verify that errors are generated when the fragment shader output doesn't match the bound color
3434// buffer types
3435TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch)
3436{
3437 const std::string vertexShader =
3438 "#version 300 es\n"
3439 "void main() {\n"
3440 " gl_Position = vec4(0, 0, 0, 1);\n"
3441 "}\n";
3442
3443 const std::string fragmentShader =
3444 "#version 300 es\n"
3445 "precision mediump float;\n"
3446 "layout(location = 0) out vec4 floatOutput;\n"
3447 "layout(location = 1) out uvec4 uintOutput;\n"
3448 "layout(location = 2) out ivec4 intOutput;\n"
3449 "void main() {\n"
3450 " floatOutput = vec4(0, 0, 0, 1);\n"
3451 " uintOutput = uvec4(0, 0, 0, 1);\n"
3452 " intOutput = ivec4(0, 0, 0, 1);\n"
3453 "}\n";
3454
3455 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3456 glUseProgram(program.get());
3457
3458 GLuint floatLocation = glGetFragDataLocation(program, "floatOutput");
3459 GLuint uintLocation = glGetFragDataLocation(program, "uintOutput");
3460 GLuint intLocation = glGetFragDataLocation(program, "intOutput");
3461
3462 GLFramebuffer fbo;
3463 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3464
3465 GLRenderbuffer floatRenderbuffer;
3466 glBindRenderbuffer(GL_RENDERBUFFER, floatRenderbuffer);
3467 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
3468 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3469 floatRenderbuffer);
3470
3471 GLRenderbuffer uintRenderbuffer;
3472 glBindRenderbuffer(GL_RENDERBUFFER, uintRenderbuffer);
3473 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 1, 1);
3474 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3475 uintRenderbuffer);
3476
3477 GLRenderbuffer intRenderbuffer;
3478 glBindRenderbuffer(GL_RENDERBUFFER, intRenderbuffer);
3479 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 1, 1);
3480 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3481 intRenderbuffer);
3482
3483 ASSERT_GL_NO_ERROR();
3484
3485 GLint maxDrawBuffers = 0;
3486 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3487 std::vector<GLenum> drawBuffers(static_cast<size_t>(maxDrawBuffers), GL_NONE);
3488 drawBuffers[floatLocation] = GL_COLOR_ATTACHMENT0 + floatLocation;
3489 drawBuffers[uintLocation] = GL_COLOR_ATTACHMENT0 + uintLocation;
3490 drawBuffers[intLocation] = GL_COLOR_ATTACHMENT0 + intLocation;
3491
3492 glDrawBuffers(maxDrawBuffers, drawBuffers.data());
3493
3494 // Check that the correct case generates no errors
3495 glDrawArrays(GL_TRIANGLES, 0, 6);
3496 EXPECT_GL_NO_ERROR();
3497
3498 // Unbind some buffers and verify that there are still no errors
3499 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3500 0);
3501 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3502 0);
3503 glDrawArrays(GL_TRIANGLES, 0, 6);
3504 EXPECT_GL_NO_ERROR();
3505
3506 // Swap the int and uint buffers to and verify that an error is generated
3507 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3508 intRenderbuffer);
3509 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3510 uintRenderbuffer);
3511 glDrawArrays(GL_TRIANGLES, 0, 6);
3512 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3513
3514 // Swap the float and uint buffers to and verify that an error is generated
3515 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3516 floatRenderbuffer);
3517 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3518 uintRenderbuffer);
3519 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3520 intRenderbuffer);
3521 glDrawArrays(GL_TRIANGLES, 0, 6);
3522 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3523}
3524
Geoff Lang9ab5b822017-05-30 16:19:23 -04003525// Verify that errors are generated when the vertex shader intput doesn't match the bound attribute
3526// types
Corentin Wallezc3bc9842017-10-11 15:15:59 -04003527TEST_P(WebGL2CompatibilityTest, VertexShaderAttributeTypeMismatch)
Geoff Lang9ab5b822017-05-30 16:19:23 -04003528{
3529 const std::string vertexShader =
3530 "#version 300 es\n"
3531 "in vec4 floatInput;\n"
3532 "in uvec4 uintInput;\n"
3533 "in ivec4 intInput;\n"
3534 "void main() {\n"
3535 " gl_Position = vec4(floatInput.x, uintInput.x, intInput.x, 1);\n"
3536 "}\n";
3537
3538 const std::string fragmentShader =
3539 "#version 300 es\n"
3540 "precision mediump float;\n"
3541 "out vec4 outputColor;\n"
3542 "void main() {\n"
3543 " outputColor = vec4(0, 0, 0, 1);"
3544 "}\n";
3545
3546 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3547 glUseProgram(program.get());
3548
3549 GLint floatLocation = glGetAttribLocation(program, "floatInput");
3550 GLint uintLocation = glGetAttribLocation(program, "uintInput");
3551 GLint intLocation = glGetAttribLocation(program, "intInput");
3552
3553 // Default attributes are of float types
3554 glDrawArrays(GL_TRIANGLES, 0, 6);
3555 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3556
3557 // Set the default attributes to the correct types, should succeed
3558 glVertexAttribI4ui(uintLocation, 0, 0, 0, 1);
3559 glVertexAttribI4i(intLocation, 0, 0, 0, 1);
3560 glDrawArrays(GL_TRIANGLES, 0, 6);
3561 EXPECT_GL_NO_ERROR();
3562
3563 // Change the default float attribute to an integer, should fail
3564 glVertexAttribI4ui(floatLocation, 0, 0, 0, 1);
3565 glDrawArrays(GL_TRIANGLES, 0, 6);
3566 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3567
3568 // Use a buffer for some attributes
3569 GLBuffer buffer;
3570 glBindBuffer(GL_ARRAY_BUFFER, buffer);
3571 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
3572 glEnableVertexAttribArray(floatLocation);
3573 glVertexAttribPointer(floatLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3574 glDrawArrays(GL_TRIANGLES, 0, 6);
3575 EXPECT_GL_NO_ERROR();
3576
3577 // Use a float pointer attrib for a uint input
3578 glEnableVertexAttribArray(uintLocation);
3579 glVertexAttribPointer(uintLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3580 glDrawArrays(GL_TRIANGLES, 0, 6);
3581 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3582
3583 // Use a uint pointer for the uint input
3584 glVertexAttribIPointer(uintLocation, 4, GL_UNSIGNED_INT, 0, nullptr);
3585 glDrawArrays(GL_TRIANGLES, 0, 6);
3586 EXPECT_GL_NO_ERROR();
3587}
3588
Geoff Langfa125c92017-10-24 13:01:46 -04003589// Test that it's not possible to query the non-zero color attachments without the drawbuffers
3590// extension in WebGL1
3591TEST_P(WebGLCompatibilityTest, FramebufferAttachmentQuery)
3592{
3593 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
3594 ANGLE_SKIP_TEST_IF(extensionEnabled("GL_EXT_draw_buffers"));
3595
3596 GLFramebuffer fbo;
3597 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3598 EXPECT_GL_NO_ERROR();
3599
3600 GLint result;
3601 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
3602 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &result);
3603 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3604
3605 GLRenderbuffer renderbuffer;
3606 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3607 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
3608 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderbuffer);
3609 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3610}
3611
Corentin Walleze7557742017-06-01 13:09:57 -04003612// Tests the WebGL removal of undefined behavior when attachments aren't written to.
3613TEST_P(WebGLCompatibilityTest, DrawBuffers)
3614{
Corentin Walleze7557742017-06-01 13:09:57 -04003615 // Make sure we can use at least 4 attachments for the tests.
3616 bool useEXT = false;
3617 if (getClientMajorVersion() < 3)
3618 {
Yunchao He9550c602018-02-13 14:47:05 +08003619 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_EXT_draw_buffers"));
Corentin Walleze7557742017-06-01 13:09:57 -04003620
3621 glRequestExtensionANGLE("GL_EXT_draw_buffers");
3622 useEXT = true;
3623 EXPECT_GL_NO_ERROR();
3624 }
3625
3626 GLint maxDrawBuffers = 0;
3627 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
Yunchao He9550c602018-02-13 14:47:05 +08003628 // Test skipped because MAX_DRAW_BUFFERS is too small.
3629 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4);
Corentin Walleze7557742017-06-01 13:09:57 -04003630
3631 // Clears all the renderbuffers to red.
3632 auto ClearEverythingToRed = [](GLRenderbuffer *renderbuffers) {
3633 GLFramebuffer clearFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003634 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003635
3636 glClearColor(1, 0, 0, 1);
3637 for (int i = 0; i < 4; ++i)
3638 {
Geoff Lange8afa902017-09-27 15:00:43 -04003639 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
Corentin Walleze7557742017-06-01 13:09:57 -04003640 renderbuffers[i]);
3641 glClear(GL_COLOR_BUFFER_BIT);
3642 }
3643 ASSERT_GL_NO_ERROR();
3644 };
3645
3646 // Checks that the renderbuffers specified by mask have the correct color
3647 auto CheckColors = [](GLRenderbuffer *renderbuffers, int mask, GLColor color) {
3648 GLFramebuffer readFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003649 glBindFramebuffer(GL_FRAMEBUFFER, readFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003650
3651 for (int i = 0; i < 4; ++i)
3652 {
3653 if (mask & (1 << i))
3654 {
Geoff Lange8afa902017-09-27 15:00:43 -04003655 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
3656 renderbuffers[i]);
Corentin Walleze7557742017-06-01 13:09:57 -04003657 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
3658 }
3659 }
3660 ASSERT_GL_NO_ERROR();
3661 };
3662
3663 // Depending on whether we are using the extension or ES3, a different entrypoint must be called
3664 auto DrawBuffers = [](bool useEXT, int numBuffers, GLenum *buffers) {
3665 if (useEXT)
3666 {
3667 glDrawBuffersEXT(numBuffers, buffers);
3668 }
3669 else
3670 {
3671 glDrawBuffers(numBuffers, buffers);
3672 }
3673 };
3674
3675 // Initialized the test framebuffer
3676 GLFramebuffer drawFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003677 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003678
3679 GLRenderbuffer renderbuffers[4];
3680 for (int i = 0; i < 4; ++i)
3681 {
3682 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
Geoff Langd84a00b2017-10-27 17:27:26 -04003683 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
Geoff Lange8afa902017-09-27 15:00:43 -04003684 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER,
Corentin Walleze7557742017-06-01 13:09:57 -04003685 renderbuffers[i]);
3686 }
3687
3688 ASSERT_GL_NO_ERROR();
3689
Corentin Walleze7557742017-06-01 13:09:57 -04003690 GLenum allDrawBuffers[] = {
3691 GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3692 };
3693
3694 GLenum halfDrawBuffers[] = {
3695 GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3,
3696 };
3697
3698 // Test that when using gl_FragColor, only the first attachment is written to.
3699 const char *fragESSL1 =
3700 "precision highp float;\n"
3701 "void main()\n"
3702 "{\n"
3703 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3704 "}\n";
Olli Etuaho5804dc82018-04-13 14:11:46 +03003705 ANGLE_GL_PROGRAM(programESSL1, essl1_shaders::vs::Simple(), fragESSL1);
Corentin Walleze7557742017-06-01 13:09:57 -04003706
3707 {
3708 ClearEverythingToRed(renderbuffers);
3709
Geoff Lange8afa902017-09-27 15:00:43 -04003710 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003711 DrawBuffers(useEXT, 4, allDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003712 drawQuad(programESSL1, essl1_shaders::PositionAttrib(), 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003713 ASSERT_GL_NO_ERROR();
3714
3715 CheckColors(renderbuffers, 0b0001, GLColor::green);
3716 CheckColors(renderbuffers, 0b1110, GLColor::red);
3717 }
3718
3719 // Test that when using gl_FragColor, but the first draw buffer is 0, then no attachment is
3720 // written to.
3721 {
3722 ClearEverythingToRed(renderbuffers);
3723
Geoff Lange8afa902017-09-27 15:00:43 -04003724 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003725 DrawBuffers(useEXT, 4, halfDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003726 drawQuad(programESSL1, essl1_shaders::PositionAttrib(), 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003727 ASSERT_GL_NO_ERROR();
3728
3729 CheckColors(renderbuffers, 0b1111, GLColor::red);
3730 }
3731
3732 // Test what happens when rendering to a subset of the outputs. There is a behavior difference
3733 // between the extension and ES3. In the extension gl_FragData is implicitly declared as an
3734 // array of size MAX_DRAW_BUFFERS, so the WebGL spec stipulates that elements not written to
3735 // should default to 0. On the contrary, in ES3 outputs are specified one by one, so
3736 // attachments not declared in the shader should not be written to.
Olli Etuaho5804dc82018-04-13 14:11:46 +03003737 const char *positionAttrib;
Corentin Walleze7557742017-06-01 13:09:57 -04003738 const char *writeOddOutputsVert;
3739 const char *writeOddOutputsFrag;
3740 GLColor unwrittenColor;
3741 if (useEXT)
3742 {
3743 // In the extension, when an attachment isn't written to, it should get 0's
3744 unwrittenColor = GLColor(0, 0, 0, 0);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003745 positionAttrib = essl1_shaders::PositionAttrib();
3746 writeOddOutputsVert = essl1_shaders::vs::Simple();
Corentin Walleze7557742017-06-01 13:09:57 -04003747 writeOddOutputsFrag =
3748 "#extension GL_EXT_draw_buffers : require\n"
3749 "precision highp float;\n"
3750 "void main()\n"
3751 "{\n"
3752 " gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3753 " gl_FragData[3] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3754 "}\n";
3755 }
3756 else
3757 {
3758 // In ES3 if an attachment isn't declared, it shouldn't get written and should be red
3759 // because of the preceding clears.
3760 unwrittenColor = GLColor::red;
Olli Etuaho5804dc82018-04-13 14:11:46 +03003761 positionAttrib = essl3_shaders::PositionAttrib();
3762 writeOddOutputsVert = essl3_shaders::vs::Simple();
Corentin Walleze7557742017-06-01 13:09:57 -04003763 writeOddOutputsFrag =
3764 "#version 300 es\n"
3765 "precision highp float;\n"
3766 "layout(location = 1) out vec4 output1;"
3767 "layout(location = 3) out vec4 output2;"
3768 "void main()\n"
3769 "{\n"
3770 " output1 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3771 " output2 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3772 "}\n";
3773 }
3774 ANGLE_GL_PROGRAM(writeOddOutputsProgram, writeOddOutputsVert, writeOddOutputsFrag);
3775
3776 // Test that attachments not written to get the "unwritten" color
3777 {
3778 ClearEverythingToRed(renderbuffers);
3779
Geoff Lange8afa902017-09-27 15:00:43 -04003780 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003781 DrawBuffers(useEXT, 4, allDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003782 drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003783 ASSERT_GL_NO_ERROR();
3784
3785 CheckColors(renderbuffers, 0b1010, GLColor::green);
3786 CheckColors(renderbuffers, 0b0101, unwrittenColor);
3787 }
3788
3789 // Test that attachments not written to get the "unwritten" color but that even when the
3790 // extension is used, disabled attachments are not written at all and stay red.
3791 {
3792 ClearEverythingToRed(renderbuffers);
3793
Geoff Lange8afa902017-09-27 15:00:43 -04003794 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003795 DrawBuffers(useEXT, 4, halfDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003796 drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003797 ASSERT_GL_NO_ERROR();
3798
3799 CheckColors(renderbuffers, 0b1000, GLColor::green);
3800 CheckColors(renderbuffers, 0b0100, unwrittenColor);
3801 CheckColors(renderbuffers, 0b0011, GLColor::red);
3802 }
3803}
3804
Geoff Lang536eca12017-09-13 11:23:35 -04003805// Test that it's possible to generate mipmaps on unsized floating point textures once the
3806// extensions have been enabled
3807TEST_P(WebGLCompatibilityTest, GenerateMipmapUnsizedFloatingPointTexture)
3808{
3809 if (extensionRequestable("GL_OES_texture_float"))
3810 {
3811 glRequestExtensionANGLE("GL_OES_texture_float");
3812 }
3813 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3814
3815 GLTexture texture;
3816 glBindTexture(GL_TEXTURE_2D, texture);
3817
3818 constexpr GLColor32F data[4] = {
3819 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3820 };
3821 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_FLOAT, data);
3822 ASSERT_GL_NO_ERROR();
3823
3824 glGenerateMipmap(GL_TEXTURE_2D);
3825 EXPECT_GL_NO_ERROR();
3826}
3827// Test that it's possible to generate mipmaps on unsized floating point textures once the
3828// extensions have been enabled
3829TEST_P(WebGLCompatibilityTest, GenerateMipmapSizedFloatingPointTexture)
3830{
3831 if (extensionRequestable("GL_OES_texture_float"))
3832 {
3833 glRequestExtensionANGLE("GL_OES_texture_float");
3834 }
3835 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3836
3837 if (extensionRequestable("GL_EXT_texture_storage"))
3838 {
3839 glRequestExtensionANGLE("GL_EXT_texture_storage");
3840 }
3841 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_storage"));
3842
3843 GLTexture texture;
3844 glBindTexture(GL_TEXTURE_2D, texture);
3845
3846 constexpr GLColor32F data[4] = {
3847 kFloatRed, kFloatRed, kFloatGreen, kFloatBlue,
3848 };
3849 glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA32F, 2, 2);
3850 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, data);
3851 ASSERT_GL_NO_ERROR();
3852
3853 glGenerateMipmap(GL_TEXTURE_2D);
3854 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3855
3856 if (extensionRequestable("GL_EXT_color_buffer_float"))
3857 {
3858 // Format is renderable but not filterable
3859 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3860 glGenerateMipmap(GL_TEXTURE_2D);
3861 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3862 }
3863
3864 if (extensionRequestable("GL_EXT_color_buffer_float_linear"))
3865 {
3866 // Format is renderable but not filterable
3867 glRequestExtensionANGLE("GL_EXT_color_buffer_float_linear");
3868
3869 if (extensionEnabled("GL_EXT_color_buffer_float"))
3870 {
3871 // Format is filterable and renderable
3872 glGenerateMipmap(GL_TEXTURE_2D);
3873 EXPECT_GL_NO_ERROR();
3874 }
3875 else
3876 {
3877 // Format is filterable but not renderable
3878 glGenerateMipmap(GL_TEXTURE_2D);
3879 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3880 }
3881 }
3882}
3883
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003884// Verify that a texture format is only allowed with extension enabled.
3885void WebGLCompatibilityTest::validateTexImageExtensionFormat(GLenum format,
3886 const std::string &extName)
3887{
3888 // Verify texture format fails by default.
3889 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
3890 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3891
3892 if (extensionRequestable(extName))
3893 {
3894 // Verify texture format is allowed once extension is enabled.
3895 glRequestExtensionANGLE(extName.c_str());
3896 EXPECT_TRUE(extensionEnabled(extName));
3897
3898 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
3899 ASSERT_GL_NO_ERROR();
3900 }
3901}
3902
Geoff Lang86f81162017-10-30 15:10:45 -04003903// Test enabling various non-compressed texture format extensions
3904TEST_P(WebGLCompatibilityTest, EnableTextureFormatExtensions)
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003905{
Geoff Lang2c5c41f2017-10-31 10:58:09 -04003906 ANGLE_SKIP_TEST_IF(IsOzone());
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003907 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
3908
3909 GLTexture texture;
3910 glBindTexture(GL_TEXTURE_2D, texture.get());
3911
3912 // Verify valid format is allowed.
3913 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3914 ASSERT_GL_NO_ERROR();
3915
3916 // Verify invalid format fails.
3917 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA32F, GL_UNSIGNED_BYTE, nullptr);
3918 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3919
3920 // Verify formats from enableable extensions.
Geoff Lang660b28c2017-10-30 12:58:56 -04003921 if (!IsOpenGLES())
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07003922 {
3923 validateTexImageExtensionFormat(GL_RED_EXT, "GL_EXT_texture_rg");
3924 }
3925
3926 validateTexImageExtensionFormat(GL_SRGB_EXT, "GL_EXT_texture_sRGB");
3927 validateTexImageExtensionFormat(GL_BGRA_EXT, "GL_EXT_texture_format_BGRA8888");
3928}
3929
Geoff Lang86f81162017-10-30 15:10:45 -04003930void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum format,
3931 GLsizei width,
3932 GLsizei height,
3933 GLsizei blockSize,
3934 const std::string &extName,
3935 bool subImageAllowed)
3936{
3937 std::vector<GLubyte> data(blockSize, 0u);
3938
3939 GLTexture texture;
3940 glBindTexture(GL_TEXTURE_2D, texture.get());
3941
3942 // Verify texture format fails by default.
3943 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
3944 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3945
3946 if (extensionRequestable(extName))
3947 {
3948 // Verify texture format is allowed once extension is enabled.
3949 glRequestExtensionANGLE(extName.c_str());
3950 EXPECT_TRUE(extensionEnabled(extName));
3951
3952 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
3953 EXPECT_GL_NO_ERROR();
3954
3955 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, blockSize,
3956 data.data());
3957 if (subImageAllowed)
3958 {
3959 EXPECT_GL_NO_ERROR();
3960 }
3961 else
3962 {
3963 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3964 }
3965 }
3966}
3967
3968// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT
3969TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB)
3970{
3971 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8,
3972 "GL_EXT_texture_compression_dxt1", true);
3973}
3974
3975// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
3976TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGBA)
3977{
3978 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8,
3979 "GL_EXT_texture_compression_dxt1", true);
3980}
3981
3982// Test enabling GL_ANGLE_texture_compression_dxt3
3983TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3)
3984{
3985 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 16,
3986 "GL_ANGLE_texture_compression_dxt3", true);
3987}
3988
3989// Test enabling GL_ANGLE_texture_compression_dxt5
3990TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5)
3991{
3992 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 16,
3993 "GL_ANGLE_texture_compression_dxt5", true);
3994}
3995
3996// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
3997TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGB)
3998{
3999 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8,
4000 "GL_EXT_texture_compression_s3tc_srgb", true);
4001}
4002
4003// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
4004TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGBA)
4005{
4006 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8,
4007 "GL_EXT_texture_compression_s3tc_srgb", true);
4008}
4009
4010// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
4011TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3SRGBA)
4012{
4013 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16,
4014 "GL_EXT_texture_compression_s3tc_srgb", true);
4015}
4016
4017// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
4018TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5SRGBA)
4019{
4020 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16,
4021 "GL_EXT_texture_compression_s3tc_srgb", true);
4022}
4023
4024// Test enabling GL_OES_compressed_ETC1_RGB8_texture
4025TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionETC1)
4026{
4027 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_OES, 4, 4, 8,
4028 "GL_OES_compressed_ETC1_RGB8_texture", false);
4029}
4030
4031// Test enabling GL_ANGLE_lossy_etc_decode
4032TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionLossyDecode)
4033{
4034 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 8,
4035 "GL_ANGLE_lossy_etc_decode", true);
4036}
4037
Frank Henigmanfccbac22017-05-28 17:29:26 -04004038// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
4039// qualifiers.
4040TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch)
4041{
4042 const std::string vertexShader =
4043 "#version 300 es\n"
4044 "uniform Block { mediump vec4 val; };\n"
4045 "void main() { gl_Position = val; }\n";
4046 const std::string fragmentShader =
4047 "#version 300 es\n"
4048 "uniform Block { highp vec4 val; };\n"
4049 "out highp vec4 out_FragColor;\n"
4050 "void main() { out_FragColor = val; }\n";
4051
4052 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
4053 ASSERT_NE(0u, vs);
4054 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
4055 ASSERT_NE(0u, fs);
4056
4057 GLuint program = glCreateProgram();
4058
4059 glAttachShader(program, vs);
4060 glDeleteShader(vs);
4061 glAttachShader(program, fs);
4062 glDeleteShader(fs);
4063
4064 glLinkProgram(program);
4065 GLint linkStatus;
4066 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
4067 ASSERT_EQ(0, linkStatus);
4068
4069 glDeleteProgram(program);
4070}
4071
Geoff Lang69df2422017-07-05 12:42:31 -04004072// Test no attribute vertex shaders
4073TEST_P(WebGL2CompatibilityTest, NoAttributeVertexShader)
4074{
4075 const std::string vertexShader =
4076 "#version 300 es\n"
4077 "void main()\n"
4078 "{\n"
4079 "\n"
4080 " ivec2 xy = ivec2(gl_VertexID % 2, (gl_VertexID / 2 + gl_VertexID / 3) % 2);\n"
4081 " gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1);\n"
4082 "}";
Geoff Lang69df2422017-07-05 12:42:31 -04004083
Olli Etuaho5804dc82018-04-13 14:11:46 +03004084 ANGLE_GL_PROGRAM(program, vertexShader, essl3_shaders::fs::Red());
Geoff Lang69df2422017-07-05 12:42:31 -04004085 glUseProgram(program);
4086
4087 glDrawArrays(GL_TRIANGLES, 0, 6);
4088 ASSERT_GL_NO_ERROR();
Olli Etuaho5804dc82018-04-13 14:11:46 +03004089 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
Geoff Lang69df2422017-07-05 12:42:31 -04004090}
4091
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004092// Tests bindAttribLocations for length limit
4093TEST_P(WebGL2CompatibilityTest, BindAttribLocationLimitation)
4094{
4095 constexpr int maxLocStringLength = 1024;
4096 const std::string tooLongString(maxLocStringLength + 1, '_');
4097
4098 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
4099
4100 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4101}
4102
Geoff Langc287ea62016-09-16 14:46:51 -04004103// Use this to select which configurations (e.g. which renderer, which GLES major version) these
4104// tests should be run against.
4105ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
4106 ES2_D3D9(),
4107 ES2_D3D11(),
4108 ES3_D3D11(),
Geoff Langc287ea62016-09-16 14:46:51 -04004109 ES2_OPENGL(),
4110 ES3_OPENGL(),
4111 ES2_OPENGLES(),
4112 ES3_OPENGLES());
4113
Jamie Madill07be8bf2017-02-02 19:59:57 -05004114ANGLE_INSTANTIATE_TEST(WebGL2CompatibilityTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Geoff Langc287ea62016-09-16 14:46:51 -04004115} // namespace