blob: 4db6c0dc79485207d49a4e4ad653f5294ff4e087 [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
Jamie Madill35cd7332018-12-02 12:03:33 -050088 constexpr char kVS[] =
Geoff Lang677bb6f2017-04-05 12:40:40 -040089 "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
Jamie Madill35cd7332018-12-02 12:03:33 -050097 constexpr char kFS[] =
Geoff Lang677bb6f2017-04-05 12:40:40 -040098 "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
Jamie Madill35cd7332018-12-02 12:03:33 -0500118 ANGLE_GL_PROGRAM(samplingProgram, kVS, kFS);
Geoff Lang677bb6f2017-04-05 12:40:40 -0400119 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
Jamie Madillb980c562018-11-27 11:34:27 -0500241{};
Corentin Wallezfd456442016-12-21 17:57:00 -0500242
Geoff Langc287ea62016-09-16 14:46:51 -0400243// Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so
244// the GL extension should always be present
245TEST_P(WebGLCompatibilityTest, ExtensionStringExposed)
246{
247 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
248}
249
250// Verify that all extension entry points are available
251TEST_P(WebGLCompatibilityTest, EntryPoints)
252{
Geoff Langc339c4e2016-11-29 10:37:36 -0500253 if (extensionEnabled("GL_ANGLE_request_extension"))
Geoff Langc287ea62016-09-16 14:46:51 -0400254 {
Geoff Langc339c4e2016-11-29 10:37:36 -0500255 EXPECT_NE(nullptr, eglGetProcAddress("glRequestExtensionANGLE"));
Geoff Langc287ea62016-09-16 14:46:51 -0400256 }
257}
258
259// WebGL 1 allows GL_DEPTH_STENCIL_ATTACHMENT as a valid binding point. Make sure it is usable,
260// even in ES2 contexts.
261TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint)
262{
263 GLRenderbuffer renderbuffer;
264 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
265 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
266
267 GLFramebuffer framebuffer;
268 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
269 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
270 renderbuffer.get());
271
272 EXPECT_GL_NO_ERROR();
273}
274
275// Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION
276TEST_P(WebGLCompatibilityTest, EnableExtensionValidation)
277{
Geoff Langc339c4e2016-11-29 10:37:36 -0500278 glRequestExtensionANGLE("invalid_extension_string");
Geoff Langc287ea62016-09-16 14:46:51 -0400279 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
280}
281
282// Test enabling the GL_OES_element_index_uint extension
283TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices)
284{
285 if (getClientMajorVersion() != 2)
286 {
287 // This test only works on ES2 where uint indices are not available by default
288 return;
289 }
290
291 EXPECT_FALSE(extensionEnabled("GL_OES_element_index_uint"));
292
293 GLBuffer indexBuffer;
294 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
295
296 GLuint data[] = {0, 1, 2, 1, 3, 2};
297 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
298
299 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
Jamie Madillc09ae152019-02-01 14:16:32 -0500300 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }");
Geoff Langc287ea62016-09-16 14:46:51 -0400301 glUseProgram(program.get());
302
Jamie Madille7b96342017-06-23 15:06:08 -0400303 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
Geoff Langc287ea62016-09-16 14:46:51 -0400304 EXPECT_GL_ERROR(GL_INVALID_ENUM);
305
Geoff Langc339c4e2016-11-29 10:37:36 -0500306 if (extensionRequestable("GL_OES_element_index_uint"))
Geoff Langc287ea62016-09-16 14:46:51 -0400307 {
Geoff Langc339c4e2016-11-29 10:37:36 -0500308 glRequestExtensionANGLE("GL_OES_element_index_uint");
Geoff Langc287ea62016-09-16 14:46:51 -0400309 EXPECT_GL_NO_ERROR();
310 EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint"));
311
Jamie Madille7b96342017-06-23 15:06:08 -0400312 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
Geoff Langc287ea62016-09-16 14:46:51 -0400313 EXPECT_GL_NO_ERROR();
314 }
315}
316
Geoff Langff5c63e2017-04-12 15:26:54 -0400317// Test enabling the GL_OES_standard_derivatives extension
318TEST_P(WebGLCompatibilityTest, EnableExtensionStandardDerivitives)
319{
320 EXPECT_FALSE(extensionEnabled("GL_OES_standard_derivatives"));
321
Jamie Madill35cd7332018-12-02 12:03:33 -0500322 constexpr char kFS[] =
Geoff Langff5c63e2017-04-12 15:26:54 -0400323 "#extension GL_OES_standard_derivatives : require\n"
324 "void main() { gl_FragColor = vec4(dFdx(vec2(1.0, 1.0)).x, 1, 0, 1); }\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500325 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFS));
Geoff Langff5c63e2017-04-12 15:26:54 -0400326
327 if (extensionRequestable("GL_OES_standard_derivatives"))
328 {
329 glRequestExtensionANGLE("GL_OES_standard_derivatives");
330 EXPECT_GL_NO_ERROR();
331 EXPECT_TRUE(extensionEnabled("GL_OES_standard_derivatives"));
332
Jamie Madill35cd7332018-12-02 12:03:33 -0500333 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
Geoff Langff5c63e2017-04-12 15:26:54 -0400334 ASSERT_NE(0u, shader);
335 glDeleteShader(shader);
336 }
337}
338
339// Test enabling the GL_EXT_shader_texture_lod extension
340TEST_P(WebGLCompatibilityTest, EnableExtensionTextureLOD)
341{
342 EXPECT_FALSE(extensionEnabled("GL_EXT_shader_texture_lod"));
343
Jamie Madill35cd7332018-12-02 12:03:33 -0500344 constexpr char kFS[] =
Geoff Langff5c63e2017-04-12 15:26:54 -0400345 "#extension GL_EXT_shader_texture_lod : require\n"
346 "uniform sampler2D u_texture;\n"
347 "void main() {\n"
348 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
349 "0.0));\n"
350 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500351 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFS));
Geoff Langff5c63e2017-04-12 15:26:54 -0400352
353 if (extensionRequestable("GL_EXT_shader_texture_lod"))
354 {
355 glRequestExtensionANGLE("GL_EXT_shader_texture_lod");
356 EXPECT_GL_NO_ERROR();
357 EXPECT_TRUE(extensionEnabled("GL_EXT_shader_texture_lod"));
358
Jamie Madill35cd7332018-12-02 12:03:33 -0500359 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
Geoff Langff5c63e2017-04-12 15:26:54 -0400360 ASSERT_NE(0u, shader);
361 glDeleteShader(shader);
362 }
363}
364
365// Test enabling the GL_EXT_frag_depth extension
366TEST_P(WebGLCompatibilityTest, EnableExtensionFragDepth)
367{
368 EXPECT_FALSE(extensionEnabled("GL_EXT_frag_depth"));
369
Jamie Madill35cd7332018-12-02 12:03:33 -0500370 constexpr char kFS[] =
Geoff Langff5c63e2017-04-12 15:26:54 -0400371 "#extension GL_EXT_frag_depth : require\n"
372 "void main() {\n"
373 " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
374 " gl_FragDepthEXT = 1.0;\n"
375 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500376 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFS));
Geoff Langff5c63e2017-04-12 15:26:54 -0400377
378 if (extensionRequestable("GL_EXT_frag_depth"))
379 {
380 glRequestExtensionANGLE("GL_EXT_frag_depth");
381 EXPECT_GL_NO_ERROR();
382 EXPECT_TRUE(extensionEnabled("GL_EXT_frag_depth"));
383
Jamie Madill35cd7332018-12-02 12:03:33 -0500384 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
Geoff Langff5c63e2017-04-12 15:26:54 -0400385 ASSERT_NE(0u, shader);
386 glDeleteShader(shader);
387 }
388}
389
Geoff Langd7d526a2017-02-21 16:48:43 -0500390// Test enabling the GL_EXT_texture_filter_anisotropic extension
391TEST_P(WebGLCompatibilityTest, EnableExtensionTextureFilterAnisotropic)
392{
393 EXPECT_FALSE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
394
395 GLfloat maxAnisotropy = 0.0f;
396 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
397 EXPECT_GL_ERROR(GL_INVALID_ENUM);
398
399 GLTexture texture;
400 glBindTexture(GL_TEXTURE_2D, texture.get());
401 ASSERT_GL_NO_ERROR();
402
403 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
404 EXPECT_GL_ERROR(GL_INVALID_ENUM);
405
406 GLfloat currentAnisotropy = 0.0f;
407 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
408 EXPECT_GL_ERROR(GL_INVALID_ENUM);
409
410 if (extensionRequestable("GL_EXT_texture_filter_anisotropic"))
411 {
412 glRequestExtensionANGLE("GL_EXT_texture_filter_anisotropic");
413 EXPECT_GL_NO_ERROR();
414 EXPECT_TRUE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
415
416 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
417 ASSERT_GL_NO_ERROR();
418 EXPECT_GE(maxAnisotropy, 2.0f);
419
420 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
421 ASSERT_GL_NO_ERROR();
422 EXPECT_EQ(1.0f, currentAnisotropy);
423
424 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
425 ASSERT_GL_NO_ERROR();
426 }
427}
428
Geoff Lang025aafd2017-10-30 15:16:37 -0400429// Test enabling the EGL image extensions
430TEST_P(WebGLCompatibilityTest, EnableExtensionEGLImage)
431{
432 EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image"));
433 EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external"));
434 EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external_essl3"));
435 EXPECT_FALSE(extensionEnabled("NV_EGL_stream_consumer_external"));
436
Jamie Madill35cd7332018-12-02 12:03:33 -0500437 constexpr char kFSES2[] =
Geoff Lang025aafd2017-10-30 15:16:37 -0400438 "#extension GL_OES_EGL_image_external : require\n"
439 "precision highp float;\n"
440 "uniform samplerExternalOES sampler;\n"
441 "void main()\n"
442 "{\n"
443 " gl_FragColor = texture2D(sampler, vec2(0, 0));\n"
444 "}";
Jamie Madill35cd7332018-12-02 12:03:33 -0500445 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES2));
Geoff Lang025aafd2017-10-30 15:16:37 -0400446
Jamie Madill35cd7332018-12-02 12:03:33 -0500447 constexpr char kFSES3[] =
Geoff Lang025aafd2017-10-30 15:16:37 -0400448 "#version 300 es\n"
449 "#extension GL_OES_EGL_image_external : require\n"
450 "precision highp float;\n"
451 "uniform samplerExternalOES sampler;\n"
452 "void main()\n"
453 "{\n"
454 " gl_FragColor = texture(sampler, vec2(0, 0));\n"
455 "}";
456 if (getClientMajorVersion() > 3)
457 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500458 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES3));
Geoff Lang025aafd2017-10-30 15:16:37 -0400459 }
460
461 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
462 EXPECT_GL_ERROR(GL_INVALID_ENUM);
463
464 GLint result;
465 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result);
466 EXPECT_GL_ERROR(GL_INVALID_ENUM);
467
468 if (extensionRequestable("GL_OES_EGL_image_external"))
469 {
470 glRequestExtensionANGLE("GL_OES_EGL_image_external");
471 EXPECT_GL_NO_ERROR();
472 EXPECT_TRUE(extensionEnabled("GL_OES_EGL_image_external"));
473
Jamie Madill35cd7332018-12-02 12:03:33 -0500474 EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES2));
Geoff Lang025aafd2017-10-30 15:16:37 -0400475
476 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
477 EXPECT_GL_NO_ERROR();
478
479 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result);
480 EXPECT_GL_NO_ERROR();
481
482 if (getClientMajorVersion() > 3 && extensionRequestable("GL_OES_EGL_image_external_essl3"))
483 {
484 glRequestExtensionANGLE("GL_OES_EGL_image_external_essl3");
485 EXPECT_GL_NO_ERROR();
486 EXPECT_TRUE(extensionEnabled("GL_OES_EGL_image_external_essl3"));
487
Jamie Madill35cd7332018-12-02 12:03:33 -0500488 EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES3));
Geoff Lang025aafd2017-10-30 15:16:37 -0400489 }
490 else
491 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500492 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES3));
Geoff Lang025aafd2017-10-30 15:16:37 -0400493 }
494 }
495}
496
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700497// Verify that shaders are of a compatible spec when the extension is enabled.
498TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec)
499{
500 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
501
502 // Use of reserved _webgl prefix should fail when the shader specification is for WebGL.
Jamie Madill35cd7332018-12-02 12:03:33 -0500503 constexpr char kVS[] =
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700504 "struct Foo {\n"
505 " int _webgl_bar;\n"
506 "};\n"
507 "void main()\n"
508 "{\n"
509 " Foo foo = Foo(1);\n"
510 "}";
511
512 // Default fragement shader.
Jamie Madill35cd7332018-12-02 12:03:33 -0500513 constexpr char kFS[] =
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700514 "void main()\n"
515 "{\n"
516 " gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n"
517 "}";
518
Jamie Madill35cd7332018-12-02 12:03:33 -0500519 GLuint program = CompileProgram(kVS, kFS);
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700520 EXPECT_EQ(0u, program);
521 glDeleteProgram(program);
522}
523
Geoff Lang3fab7632017-09-26 15:45:54 -0400524// Test enabling the GL_NV_pixel_buffer_object extension
525TEST_P(WebGLCompatibilityTest, EnablePixelBufferObjectExtensions)
526{
527 EXPECT_FALSE(extensionEnabled("GL_NV_pixel_buffer_object"));
528 EXPECT_FALSE(extensionEnabled("GL_OES_mapbuffer"));
529 EXPECT_FALSE(extensionEnabled("GL_EXT_map_buffer_range"));
530
531 // These extensions become core in in ES3/WebGL2.
532 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
533
534 GLBuffer buffer;
535 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
536 EXPECT_GL_ERROR(GL_INVALID_ENUM);
537
538 if (extensionRequestable("GL_NV_pixel_buffer_object"))
539 {
540 glRequestExtensionANGLE("GL_NV_pixel_buffer_object");
541 EXPECT_GL_NO_ERROR();
542
543 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
544 EXPECT_GL_NO_ERROR();
545
546 glBufferData(GL_PIXEL_PACK_BUFFER, 4, nullptr, GL_STATIC_DRAW);
547 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
548 EXPECT_GL_NO_ERROR();
549 }
550}
551
Geoff Langd54d3042017-11-07 14:56:07 -0500552// Test enabling the GL_EXT_texture_storage extension
553TEST_P(WebGLCompatibilityTest, EnableTextureStorage)
554{
555 EXPECT_FALSE(extensionEnabled("GL_EXT_texture_storage"));
556
557 GLTexture texture;
558 glBindTexture(GL_TEXTURE_2D, texture);
559
560 GLint result;
561 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result);
562 if (getClientMajorVersion() >= 3)
563 {
564 EXPECT_GL_NO_ERROR();
565 }
566 else
567 {
568 EXPECT_GL_ERROR(GL_INVALID_ENUM);
569 }
570
571 if (extensionRequestable("GL_EXT_texture_storage"))
572 {
573 glRequestExtensionANGLE("GL_EXT_texture_storage");
574 EXPECT_GL_NO_ERROR();
575 EXPECT_TRUE(extensionEnabled("GL_EXT_texture_storage"));
576
577 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result);
578 EXPECT_GL_NO_ERROR();
579
580 const GLenum alwaysAcceptableFormats[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500581 GL_ALPHA8_EXT,
582 GL_LUMINANCE8_EXT,
583 GL_LUMINANCE8_ALPHA8_EXT,
Geoff Langd54d3042017-11-07 14:56:07 -0500584 };
585 for (const auto &acceptableFormat : alwaysAcceptableFormats)
586 {
587 GLTexture localTexture;
588 glBindTexture(GL_TEXTURE_2D, localTexture);
589 glTexStorage2DEXT(GL_TEXTURE_2D, 1, acceptableFormat, 1, 1);
590 EXPECT_GL_NO_ERROR();
591 }
592 }
593}
594
Geoff Lang3fab7632017-09-26 15:45:54 -0400595// Test enabling the GL_OES_mapbuffer and GL_EXT_map_buffer_range extensions
596TEST_P(WebGLCompatibilityTest, EnableMapBufferExtensions)
597{
598 EXPECT_FALSE(extensionEnabled("GL_OES_mapbuffer"));
599 EXPECT_FALSE(extensionEnabled("GL_EXT_map_buffer_range"));
600
601 // These extensions become core in in ES3/WebGL2.
602 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
603
604 GLBuffer buffer;
605 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
606 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4, nullptr, GL_STATIC_DRAW);
607
608 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
609 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
610
611 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
612 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
613
614 GLint access = 0;
615 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
616 EXPECT_GL_ERROR(GL_INVALID_ENUM);
617
618 if (extensionRequestable("GL_OES_mapbuffer"))
619 {
620 glRequestExtensionANGLE("GL_OES_mapbuffer");
621 EXPECT_GL_NO_ERROR();
622
623 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
624 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
625 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
626 EXPECT_GL_NO_ERROR();
627 }
628
629 if (extensionRequestable("GL_EXT_map_buffer_range"))
630 {
631 glRequestExtensionANGLE("GL_EXT_map_buffer_range");
632 EXPECT_GL_NO_ERROR();
633
634 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT);
635 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
636 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access);
637 EXPECT_GL_NO_ERROR();
638 }
639}
640
Geoff Lang8c7133c2017-09-26 17:31:10 -0400641// Test enabling the GL_OES_fbo_render_mipmap extension
642TEST_P(WebGLCompatibilityTest, EnableRenderMipmapExtension)
643{
644 EXPECT_FALSE(extensionEnabled("GL_OES_fbo_render_mipmap"));
645
646 // This extensions become core in in ES3/WebGL2.
647 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
648
649 GLTexture texture;
650 glBindTexture(GL_TEXTURE_2D, texture);
651 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
652 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
653
654 GLFramebuffer fbo;
655 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
656 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
657 EXPECT_GL_NO_ERROR();
658
659 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
660 EXPECT_GL_ERROR(GL_INVALID_VALUE);
661
662 if (extensionRequestable("GL_OES_fbo_render_mipmap"))
663 {
664 glRequestExtensionANGLE("GL_OES_fbo_render_mipmap");
665 EXPECT_GL_NO_ERROR();
666
667 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
668 EXPECT_GL_NO_ERROR();
669 }
670}
671
Geoff Lang50cac572017-09-26 17:37:43 -0400672// Test enabling the GL_EXT_blend_minmax extension
673TEST_P(WebGLCompatibilityTest, EnableBlendMinMaxExtension)
674{
675 EXPECT_FALSE(extensionEnabled("GL_EXT_blend_minmax"));
676
677 // This extensions become core in in ES3/WebGL2.
678 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
679
680 glBlendEquation(GL_MIN);
681 EXPECT_GL_ERROR(GL_INVALID_ENUM);
682
683 glBlendEquation(GL_MAX);
684 EXPECT_GL_ERROR(GL_INVALID_ENUM);
685
686 if (extensionRequestable("GL_EXT_blend_minmax"))
687 {
688 glRequestExtensionANGLE("GL_EXT_blend_minmax");
689 EXPECT_GL_NO_ERROR();
690
691 glBlendEquation(GL_MIN);
692 glBlendEquation(GL_MAX);
693 EXPECT_GL_NO_ERROR();
694 }
695}
696
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400697// Test enabling the query extensions
698TEST_P(WebGLCompatibilityTest, EnableQueryExtensions)
699{
Jamie Madill8b92c532018-03-22 01:05:02 -0400700 // Seems to be causing a device lost. http://anglebug.com/2423
701 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
702
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400703 EXPECT_FALSE(extensionEnabled("GL_EXT_occlusion_query_boolean"));
704 EXPECT_FALSE(extensionEnabled("GL_EXT_disjoint_timer_query"));
705 EXPECT_FALSE(extensionEnabled("GL_CHROMIUM_sync_query"));
706
707 // This extensions become core in in ES3/WebGL2.
708 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
709
710 GLQueryEXT badQuery;
711
712 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, badQuery);
713 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
714
715 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, badQuery);
716 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
717
718 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, badQuery);
719 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
720
721 glQueryCounterEXT(GL_TIMESTAMP_EXT, badQuery);
722 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
723
724 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, badQuery);
725 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
726
727 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
728 {
729 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
730 EXPECT_GL_NO_ERROR();
731
732 GLQueryEXT query;
733 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
734 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
735 EXPECT_GL_NO_ERROR();
736 }
737
738 if (extensionRequestable("GL_EXT_disjoint_timer_query"))
739 {
740 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
741 EXPECT_GL_NO_ERROR();
742
743 GLQueryEXT query1;
744 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
745 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
746 EXPECT_GL_NO_ERROR();
747
748 GLQueryEXT query2;
749 glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
750 EXPECT_GL_NO_ERROR();
751 }
752
753 if (extensionRequestable("GL_CHROMIUM_sync_query"))
754 {
755 glRequestExtensionANGLE("GL_CHROMIUM_sync_query");
756 EXPECT_GL_NO_ERROR();
757
758 GLQueryEXT query;
759 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query);
760 glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
761 EXPECT_GL_NO_ERROR();
762 }
763}
764
Geoff Lang488130e2017-09-27 13:53:11 -0400765// Test enabling the GL_ANGLE_framebuffer_multisample extension
766TEST_P(WebGLCompatibilityTest, EnableFramebufferMultisampleExtension)
767{
768 EXPECT_FALSE(extensionEnabled("GL_ANGLE_framebuffer_multisample"));
769
770 // This extensions become core in in ES3/WebGL2.
771 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
772
773 GLint maxSamples = 0;
774 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
775 EXPECT_GL_ERROR(GL_INVALID_ENUM);
776
777 GLRenderbuffer renderbuffer;
778 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
779 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA4, 1, 1);
780 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
781
782 if (extensionRequestable("GL_ANGLE_framebuffer_multisample"))
783 {
784 glRequestExtensionANGLE("GL_ANGLE_framebuffer_multisample");
785 EXPECT_GL_NO_ERROR();
786
787 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
788 EXPECT_GL_NO_ERROR();
789
790 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, maxSamples, GL_RGBA4, 1, 1);
791 EXPECT_GL_NO_ERROR();
792 }
793}
794
Geoff Lang63c5a592017-09-27 14:08:16 -0400795// Test enabling the GL_ANGLE_instanced_arrays extension
796TEST_P(WebGLCompatibilityTest, EnableInstancedArraysExtension)
797{
798 EXPECT_FALSE(extensionEnabled("GL_ANGLE_instanced_arrays"));
799
800 // This extensions become core in in ES3/WebGL2.
801 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
802
803 GLint divisor = 0;
804 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
805 EXPECT_GL_ERROR(GL_INVALID_ENUM);
806
807 glVertexAttribDivisorANGLE(0, 1);
808 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
809
810 if (extensionRequestable("GL_ANGLE_instanced_arrays"))
811 {
812 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
813 EXPECT_GL_NO_ERROR();
814
815 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
816 glVertexAttribDivisorANGLE(0, 1);
817 EXPECT_GL_NO_ERROR();
818 }
819}
820
Geoff Lang000dab82017-09-27 14:27:07 -0400821// Test enabling the GL_ANGLE_pack_reverse_row_order extension
822TEST_P(WebGLCompatibilityTest, EnablePackReverseRowOrderExtension)
823{
824 EXPECT_FALSE(extensionEnabled("GL_ANGLE_pack_reverse_row_order"));
825
826 GLint result = 0;
827 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result);
828 EXPECT_GL_ERROR(GL_INVALID_ENUM);
829
830 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE);
831 EXPECT_GL_ERROR(GL_INVALID_ENUM);
832
833 if (extensionRequestable("GL_ANGLE_pack_reverse_row_order"))
834 {
835 glRequestExtensionANGLE("GL_ANGLE_pack_reverse_row_order");
836 EXPECT_GL_NO_ERROR();
837
838 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result);
839 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE);
840 EXPECT_GL_NO_ERROR();
841 }
842}
843
844// Test enabling the GL_EXT_unpack_subimage extension
845TEST_P(WebGLCompatibilityTest, EnablePackUnpackSubImageExtension)
846{
847 EXPECT_FALSE(extensionEnabled("GL_EXT_unpack_subimage"));
848
849 // This extensions become core in in ES3/WebGL2.
850 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
851
852 constexpr GLenum parameters[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500853 GL_UNPACK_ROW_LENGTH_EXT,
854 GL_UNPACK_SKIP_ROWS_EXT,
855 GL_UNPACK_SKIP_PIXELS_EXT,
Geoff Lang000dab82017-09-27 14:27:07 -0400856 };
857
858 for (GLenum param : parameters)
859 {
860 GLint resultI = 0;
861 glGetIntegerv(param, &resultI);
862 EXPECT_GL_ERROR(GL_INVALID_ENUM);
863
864 GLfloat resultF = 0.0f;
865 glGetFloatv(param, &resultF);
866 EXPECT_GL_ERROR(GL_INVALID_ENUM);
867
868 glPixelStorei(param, 0);
869 EXPECT_GL_ERROR(GL_INVALID_ENUM);
870 }
871
872 if (extensionRequestable("GL_EXT_unpack_subimage"))
873 {
874 glRequestExtensionANGLE("GL_EXT_unpack_subimage");
875 EXPECT_GL_NO_ERROR();
876
877 for (GLenum param : parameters)
878 {
879 GLint resultI = 0;
880 glGetIntegerv(param, &resultI);
881
882 GLfloat resultF = 0.0f;
883 glGetFloatv(param, &resultF);
884
885 glPixelStorei(param, 0);
886
887 EXPECT_GL_NO_ERROR();
888 }
889 }
890}
891
Geoff Lang4751aab2017-10-30 15:14:52 -0400892TEST_P(WebGLCompatibilityTest, EnableTextureRectangle)
893{
894 EXPECT_FALSE(extensionEnabled("GL_ANGLE_texture_rectangle"));
895
896 GLTexture texture;
897 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture);
898 EXPECT_GL_ERROR(GL_INVALID_ENUM);
899
900 GLint minFilter = 0;
901 glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, &minFilter);
902 EXPECT_GL_ERROR(GL_INVALID_ENUM);
903
904 if (extensionRequestable("GL_ANGLE_texture_rectangle"))
905 {
906 glRequestExtensionANGLE("GL_ANGLE_texture_rectangle");
907 EXPECT_GL_NO_ERROR();
908
909 EXPECT_TRUE(extensionEnabled("GL_ANGLE_texture_rectangle"));
910
911 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture);
912 EXPECT_GL_NO_ERROR();
913
914 glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
915 nullptr);
916 EXPECT_GL_NO_ERROR();
917 }
918}
919
Geoff Lang000dab82017-09-27 14:27:07 -0400920// Test enabling the GL_NV_pack_subimage extension
921TEST_P(WebGLCompatibilityTest, EnablePackPackSubImageExtension)
922{
923 EXPECT_FALSE(extensionEnabled("GL_NV_pack_subimage"));
924
925 // This extensions become core in in ES3/WebGL2.
926 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
927
928 constexpr GLenum parameters[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500929 GL_PACK_ROW_LENGTH,
930 GL_PACK_SKIP_ROWS,
931 GL_PACK_SKIP_PIXELS,
Geoff Lang000dab82017-09-27 14:27:07 -0400932 };
933
934 for (GLenum param : parameters)
935 {
936 GLint resultI = 0;
937 glGetIntegerv(param, &resultI);
938 EXPECT_GL_ERROR(GL_INVALID_ENUM);
939
940 GLfloat resultF = 0.0f;
941 glGetFloatv(param, &resultF);
942 EXPECT_GL_ERROR(GL_INVALID_ENUM);
943
944 glPixelStorei(param, 0);
945 EXPECT_GL_ERROR(GL_INVALID_ENUM);
946 }
947
948 if (extensionRequestable("GL_NV_pack_subimage"))
949 {
950 glRequestExtensionANGLE("GL_NV_pack_subimage");
951 EXPECT_GL_NO_ERROR();
952
953 for (GLenum param : parameters)
954 {
955 GLint resultI = 0;
956 glGetIntegerv(param, &resultI);
957
958 GLfloat resultF = 0.0f;
959 glGetFloatv(param, &resultF);
960
961 glPixelStorei(param, 0);
962
963 EXPECT_GL_NO_ERROR();
964 }
965 }
966}
967
Geoff Langd84a00b2017-10-27 17:27:26 -0400968TEST_P(WebGLCompatibilityTest, EnableRGB8RGBA8Extension)
969{
970 EXPECT_FALSE(extensionEnabled("GL_OES_rgb8_rgba8"));
971
972 // This extensions become core in in ES3/WebGL2.
973 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
974
975 GLRenderbuffer renderbuffer;
976 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
977 EXPECT_GL_NO_ERROR();
978
979 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1);
980 EXPECT_GL_ERROR(GL_INVALID_ENUM);
981
982 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
983 EXPECT_GL_ERROR(GL_INVALID_ENUM);
984
985 if (extensionRequestable("GL_OES_rgb8_rgba8"))
986 {
987 glRequestExtensionANGLE("GL_OES_rgb8_rgba8");
988 EXPECT_GL_NO_ERROR();
989
990 EXPECT_TRUE(extensionEnabled("GL_OES_rgb8_rgba8"));
991
992 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1);
993 EXPECT_GL_NO_ERROR();
994
995 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
996 EXPECT_GL_NO_ERROR();
997 }
998}
999
Geoff Lange8afa902017-09-27 15:00:43 -04001000// Test enabling the GL_ANGLE_framebuffer_blit extension
1001TEST_P(WebGLCompatibilityTest, EnableFramebufferBlitExtension)
1002{
1003 EXPECT_FALSE(extensionEnabled("GL_ANGLE_framebuffer_blit"));
1004
1005 // This extensions become core in in ES3/WebGL2.
1006 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1007
1008 GLFramebuffer fbo;
1009
1010 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
1011 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1012
1013 GLint result;
1014 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result);
1015 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1016
1017 glBlitFramebufferANGLE(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1018 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1019
1020 if (extensionRequestable("GL_ANGLE_framebuffer_blit"))
1021 {
1022 glRequestExtensionANGLE("GL_ANGLE_framebuffer_blit");
1023 EXPECT_GL_NO_ERROR();
1024
1025 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
1026 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result);
1027 EXPECT_GL_NO_ERROR();
1028 }
1029}
1030
Geoff Lang2348e212017-09-27 17:46:25 -04001031// Test enabling the GL_OES_get_program_binary extension
1032TEST_P(WebGLCompatibilityTest, EnableProgramBinaryExtension)
1033{
1034 EXPECT_FALSE(extensionEnabled("GL_OES_get_program_binary"));
1035
1036 // This extensions become core in in ES3/WebGL2.
1037 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1038
1039 GLint result = 0;
1040 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
1041 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1042
1043 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
1044 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1045
Jamie Madill35cd7332018-12-02 12:03:33 -05001046 constexpr char kVS[] =
Geoff Lang2348e212017-09-27 17:46:25 -04001047 "void main()\n"
1048 "{\n"
1049 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1050 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001051 constexpr char kFS[] =
Geoff Lang2348e212017-09-27 17:46:25 -04001052 "precision highp float;\n"
1053 "void main()\n"
1054 "{\n"
1055 " gl_FragColor = vec4(1.0);\n"
1056 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001057 ANGLE_GL_PROGRAM(program, kVS, kFS);
Geoff Lang2348e212017-09-27 17:46:25 -04001058
1059 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &result);
1060 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1061
1062 uint8_t tempArray[512];
1063 GLenum tempFormat = 0;
1064 GLsizei tempLength = 0;
1065 glGetProgramBinaryOES(program, static_cast<GLsizei>(ArraySize(tempArray)), &tempLength,
1066 &tempFormat, tempArray);
1067 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1068
1069 if (extensionRequestable("GL_OES_get_program_binary"))
1070 {
1071 glRequestExtensionANGLE("GL_OES_get_program_binary");
1072 EXPECT_GL_NO_ERROR();
1073
1074 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &result);
1075 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result);
1076 EXPECT_GL_NO_ERROR();
1077
1078 GLint binaryLength = 0;
1079 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
1080 EXPECT_GL_NO_ERROR();
1081
1082 GLenum binaryFormat;
1083 GLsizei writeLength = 0;
1084 std::vector<uint8_t> binary(binaryLength);
1085 glGetProgramBinaryOES(program, binaryLength, &writeLength, &binaryFormat, binary.data());
1086 EXPECT_GL_NO_ERROR();
1087
1088 glProgramBinaryOES(program, binaryFormat, binary.data(), binaryLength);
1089 EXPECT_GL_NO_ERROR();
1090 }
1091}
1092
Geoff Langb0f917f2017-12-05 13:41:54 -05001093// Test enabling the GL_OES_vertex_array_object extension
1094TEST_P(WebGLCompatibilityTest, EnableVertexArrayExtension)
1095{
1096 EXPECT_FALSE(extensionEnabled("GL_OES_vertex_array_object"));
1097
1098 // This extensions become core in in ES3/WebGL2.
1099 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1100
1101 GLint result = 0;
1102 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result);
1103 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1104
1105 // Expect that GL_OES_vertex_array_object is always available. It is implemented in the GL
1106 // frontend.
1107 EXPECT_TRUE(extensionRequestable("GL_OES_vertex_array_object"));
1108
1109 glRequestExtensionANGLE("GL_OES_vertex_array_object");
1110 EXPECT_GL_NO_ERROR();
1111
1112 EXPECT_TRUE(extensionEnabled("GL_OES_vertex_array_object"));
1113
1114 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result);
1115 EXPECT_GL_NO_ERROR();
1116
1117 GLuint vao = 0;
1118 glGenVertexArraysOES(0, &vao);
1119 EXPECT_GL_NO_ERROR();
1120
1121 glBindVertexArrayOES(vao);
1122 EXPECT_GL_NO_ERROR();
1123
1124 glDeleteVertexArraysOES(1, &vao);
1125 EXPECT_GL_NO_ERROR();
1126}
1127
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001128// Verify that the context generates the correct error when the framebuffer attachments are
1129// different sizes
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001130TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch)
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001131{
1132 GLFramebuffer fbo;
1133 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1134
1135 GLTexture textures[2];
1136 glBindTexture(GL_TEXTURE_2D, textures[0]);
1137 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1138 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
1139
1140 ASSERT_GL_NO_ERROR();
1141 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1142
1143 GLRenderbuffer renderbuffer;
1144 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1145 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3);
1146 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
1147
1148 ASSERT_GL_NO_ERROR();
1149 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1150 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1151
1152 if (extensionRequestable("GL_EXT_draw_buffers"))
1153 {
1154 glRequestExtensionANGLE("GL_EXT_draw_buffers");
1155 EXPECT_GL_NO_ERROR();
1156 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
1157
1158 glBindTexture(GL_TEXTURE_2D, textures[1]);
1159 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1160 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
1161 ASSERT_GL_NO_ERROR();
1162
1163 ASSERT_GL_NO_ERROR();
1164 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1165 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1166
1167 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
1168
1169 ASSERT_GL_NO_ERROR();
1170 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1171
1172 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1173
1174 ASSERT_GL_NO_ERROR();
1175 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1176 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1177 }
1178}
1179
Corentin Wallez327411e2016-12-09 11:09:17 -05001180// Test that client-side array buffers are forbidden in WebGL mode
1181TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer)
1182{
Jamie Madill35cd7332018-12-02 12:03:33 -05001183 constexpr char kVS[] =
Corentin Wallez327411e2016-12-09 11:09:17 -05001184 "attribute vec3 a_pos;\n"
1185 "void main()\n"
1186 "{\n"
1187 " gl_Position = vec4(a_pos, 1.0);\n"
1188 "}\n";
1189
Jamie Madill35cd7332018-12-02 12:03:33 -05001190 constexpr char kFS[] =
Corentin Wallez327411e2016-12-09 11:09:17 -05001191 "precision highp float;\n"
1192 "void main()\n"
1193 "{\n"
1194 " gl_FragColor = vec4(1.0);\n"
1195 "}\n";
1196
Jamie Madill35cd7332018-12-02 12:03:33 -05001197 ANGLE_GL_PROGRAM(program, kVS, kFS);
Corentin Wallez327411e2016-12-09 11:09:17 -05001198
1199 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1200 ASSERT_NE(-1, posLocation);
1201 glUseProgram(program.get());
1202
1203 const auto &vertices = GetQuadVertices();
Corentin Wallezfd456442016-12-21 17:57:00 -05001204 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
Corentin Wallez327411e2016-12-09 11:09:17 -05001205 glEnableVertexAttribArray(posLocation);
1206
1207 ASSERT_GL_NO_ERROR();
1208 glDrawArrays(GL_TRIANGLES, 0, 6);
1209 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1210}
1211
1212// Test that client-side element array buffers are forbidden in WebGL mode
1213TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
1214{
Jamie Madill35cd7332018-12-02 12:03:33 -05001215 constexpr char kVS[] =
Corentin Wallez327411e2016-12-09 11:09:17 -05001216 "attribute vec3 a_pos;\n"
1217 "void main()\n"
1218 "{\n"
1219 " gl_Position = vec4(a_pos, 1.0);\n"
1220 "}\n";
1221
Jamie Madill35cd7332018-12-02 12:03:33 -05001222 constexpr char kFS[] =
Corentin Wallez327411e2016-12-09 11:09:17 -05001223 "precision highp float;\n"
1224 "void main()\n"
1225 "{\n"
1226 " gl_FragColor = vec4(1.0);\n"
1227 "}\n";
1228
Jamie Madill35cd7332018-12-02 12:03:33 -05001229 ANGLE_GL_PROGRAM(program, kVS, kFS);
Corentin Wallez327411e2016-12-09 11:09:17 -05001230
1231 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1232 ASSERT_NE(-1, posLocation);
1233 glUseProgram(program.get());
1234
1235 const auto &vertices = GetQuadVertices();
1236
1237 GLBuffer vertexBuffer;
1238 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1239 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1240 GL_STATIC_DRAW);
1241
1242 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1243 glEnableVertexAttribArray(posLocation);
1244
Corentin Wallez327411e2016-12-09 11:09:17 -05001245 ASSERT_GL_NO_ERROR();
Corentin Wallezded1b5a2017-03-09 18:58:48 -05001246
1247 // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also
1248 // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate
1249 // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check.
Jamie Madillb980c562018-11-27 11:34:27 -05001250 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(intptr_t(1)));
Corentin Wallez327411e2016-12-09 11:09:17 -05001251 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1252}
1253
Corentin Wallez672f7f32017-06-15 17:42:17 -04001254// Test that client-side array buffers are forbidden even if the program doesn't use the attribute
1255TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBufferEvenNotUsedOnes)
1256{
Jamie Madill35cd7332018-12-02 12:03:33 -05001257 constexpr char kVS[] =
Corentin Wallez672f7f32017-06-15 17:42:17 -04001258 "void main()\n"
1259 "{\n"
1260 " gl_Position = vec4(1.0);\n"
1261 "}\n";
1262
Jamie Madill35cd7332018-12-02 12:03:33 -05001263 constexpr char kFS[] =
Corentin Wallez672f7f32017-06-15 17:42:17 -04001264 "precision highp float;\n"
1265 "void main()\n"
1266 "{\n"
1267 " gl_FragColor = vec4(1.0);\n"
1268 "}\n";
1269
Jamie Madill35cd7332018-12-02 12:03:33 -05001270 ANGLE_GL_PROGRAM(program, kVS, kFS);
Corentin Wallez672f7f32017-06-15 17:42:17 -04001271
1272 glUseProgram(program.get());
1273
1274 const auto &vertices = GetQuadVertices();
1275 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
1276 glEnableVertexAttribArray(0);
1277
1278 ASSERT_GL_NO_ERROR();
1279 glDrawArrays(GL_TRIANGLES, 0, 6);
1280 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1281}
1282
Geoff Langfb052642017-10-24 13:42:09 -04001283// Test that passing a null pixel data pointer to TexSubImage calls generates an INVALID_VALUE error
1284TEST_P(WebGLCompatibilityTest, NullPixelDataForSubImage)
1285{
1286 // glTexSubImage2D
1287 {
1288 GLTexture texture;
1289 glBindTexture(GL_TEXTURE_2D, texture);
1290
1291 // TexImage with null data - OK
1292 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1293 EXPECT_GL_NO_ERROR();
1294
1295 // TexSubImage with zero size and null data - OK
1296 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1297 EXPECT_GL_NO_ERROR();
1298
1299 // TexSubImage with non-zero size and null data - Invalid value
1300 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1301 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1302 }
1303
1304 // glTexSubImage3D
1305 if (getClientMajorVersion() >= 3)
1306 {
1307 GLTexture texture;
1308 glBindTexture(GL_TEXTURE_3D, texture);
1309
1310 // TexImage with null data - OK
1311 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1312 EXPECT_GL_NO_ERROR();
1313
1314 // TexSubImage with zero size and null data - OK
1315 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1316 EXPECT_GL_NO_ERROR();
1317
1318 // TexSubImage with non-zero size and null data - Invalid value
1319 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1320 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1321 }
1322}
1323
Ken Russellb9f92502018-01-27 19:00:26 -08001324// Tests the WebGL requirement of having the same stencil mask, writemask and ref for front and back
1325// (when stencil testing is enabled)
1326void WebGLCompatibilityTest::TestDifferentStencilMaskAndRef(GLenum errIfMismatch)
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001327{
1328 // Run the test in an FBO to make sure we have some stencil bits.
1329 GLRenderbuffer renderbuffer;
1330 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
1331 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
1332
1333 GLFramebuffer framebuffer;
1334 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1335 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1336 renderbuffer.get());
1337
1338 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
Jamie Madillc09ae152019-02-01 14:16:32 -05001339 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }");
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001340 glUseProgram(program.get());
1341 ASSERT_GL_NO_ERROR();
1342
1343 // Having ref and mask the same for front and back is valid.
1344 glStencilMask(255);
1345 glStencilFunc(GL_ALWAYS, 0, 255);
1346 glDrawArrays(GL_TRIANGLES, 0, 6);
1347 ASSERT_GL_NO_ERROR();
1348
1349 // Having a different front - back write mask generates an error.
1350 glStencilMaskSeparate(GL_FRONT, 1);
1351 glDrawArrays(GL_TRIANGLES, 0, 6);
Ken Russellb9f92502018-01-27 19:00:26 -08001352 EXPECT_GL_ERROR(errIfMismatch);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001353
1354 // Setting both write masks separately to the same value is valid.
1355 glStencilMaskSeparate(GL_BACK, 1);
1356 glDrawArrays(GL_TRIANGLES, 0, 6);
1357 ASSERT_GL_NO_ERROR();
1358
1359 // Having a different stencil front - back mask generates an error
1360 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
1361 glDrawArrays(GL_TRIANGLES, 0, 6);
Ken Russellb9f92502018-01-27 19:00:26 -08001362 EXPECT_GL_ERROR(errIfMismatch);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001363
1364 // Setting both masks separately to the same value is valid.
1365 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
1366 glDrawArrays(GL_TRIANGLES, 0, 6);
1367 ASSERT_GL_NO_ERROR();
1368
1369 // Having a different stencil front - back reference generates an error
1370 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
1371 glDrawArrays(GL_TRIANGLES, 0, 6);
Ken Russellb9f92502018-01-27 19:00:26 -08001372 EXPECT_GL_ERROR(errIfMismatch);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001373
1374 // Setting both references separately to the same value is valid.
1375 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
1376 glDrawArrays(GL_TRIANGLES, 0, 6);
1377 ASSERT_GL_NO_ERROR();
1378
1379 // Using different stencil funcs, everything being equal is valid.
1380 glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
1381 glDrawArrays(GL_TRIANGLES, 0, 6);
1382 ASSERT_GL_NO_ERROR();
1383}
Ken Russellb9f92502018-01-27 19:00:26 -08001384TEST_P(WebGLCompatibilityTest, StencilTestEnabledDisallowsDifferentStencilMaskAndRef)
1385{
1386 glEnable(GL_STENCIL_TEST);
1387 TestDifferentStencilMaskAndRef(GL_INVALID_OPERATION);
1388}
1389TEST_P(WebGLCompatibilityTest, StencilTestDisabledAllowsDifferentStencilMaskAndRef)
1390{
1391 glDisable(GL_STENCIL_TEST);
1392 TestDifferentStencilMaskAndRef(GL_NO_ERROR);
1393}
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05001394
Corentin Wallez506fc9c2016-12-21 16:53:33 -05001395// Test that GL_FIXED is forbidden
1396TEST_P(WebGLCompatibilityTest, ForbidsGLFixed)
1397{
1398 GLBuffer buffer;
1399 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1400 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1401
1402 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1403 ASSERT_GL_NO_ERROR();
1404
1405 glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr);
1406 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1407}
1408
1409// Test the WebGL limit of 255 for the attribute stride
1410TEST_P(WebGLCompatibilityTest, MaxStride)
1411{
1412 GLBuffer buffer;
1413 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1414 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
1415
1416 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr);
1417 ASSERT_GL_NO_ERROR();
1418
1419 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr);
1420 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1421}
1422
Corentin Wallezfd456442016-12-21 17:57:00 -05001423// Test the checks for OOB reads in the vertex buffers, non-instanced version
1424TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
1425{
Jamie Madill35cd7332018-12-02 12:03:33 -05001426 constexpr char kVS[] =
Corentin Wallezfd456442016-12-21 17:57:00 -05001427 "attribute float a_pos;\n"
1428 "void main()\n"
1429 "{\n"
1430 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1431 "}\n";
1432
Jamie Madill35cd7332018-12-02 12:03:33 -05001433 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Corentin Wallezfd456442016-12-21 17:57:00 -05001434 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1435 ASSERT_NE(-1, posLocation);
1436 glUseProgram(program.get());
1437
1438 GLBuffer buffer;
1439 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1440 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1441
1442 glEnableVertexAttribArray(posLocation);
1443
Jamie Madillb980c562018-11-27 11:34:27 -05001444 const uint8_t *zeroOffset = nullptr;
Corentin Wallezfd456442016-12-21 17:57:00 -05001445
1446 // Test touching the last element is valid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001447 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
Corentin Wallezfd456442016-12-21 17:57:00 -05001448 glDrawArrays(GL_POINTS, 0, 4);
1449 ASSERT_GL_NO_ERROR();
1450
1451 // Test touching the last element + 1 is invalid.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001452 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
Corentin Wallezfd456442016-12-21 17:57:00 -05001453 glDrawArrays(GL_POINTS, 0, 4);
1454 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1455
1456 // Test touching the last element is valid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001457 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
Corentin Wallezfd456442016-12-21 17:57:00 -05001458 glDrawArrays(GL_POINTS, 0, 4);
1459 ASSERT_GL_NO_ERROR();
1460
1461 // Test touching the last element + 1 is invalid, using a stride.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001462 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
Corentin Wallezfd456442016-12-21 17:57:00 -05001463 glDrawArrays(GL_POINTS, 0, 4);
1464 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1465
1466 // Test any offset is valid if no vertices are drawn.
Corentin Wallez91c8de82017-10-12 16:32:44 -04001467 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
Corentin Wallezfd456442016-12-21 17:57:00 -05001468 glDrawArrays(GL_POINTS, 0, 0);
1469 ASSERT_GL_NO_ERROR();
Corentin Wallez91c8de82017-10-12 16:32:44 -04001470
1471 // Test a case of overflow that could give a max vertex that's negative
1472 constexpr GLint kIntMax = std::numeric_limits<GLint>::max();
1473 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 0);
1474 glDrawArrays(GL_POINTS, kIntMax, kIntMax);
1475 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1476}
1477
Geoff Lang23633562018-07-17 15:02:36 -04001478// Test that index values outside of the 32-bit integer range do not read out of bounds
1479TEST_P(WebGLCompatibilityTest, LargeIndexRange)
1480{
1481 ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_OES_element_index_uint"));
1482
Jamie Madill35cd7332018-12-02 12:03:33 -05001483 constexpr char kVS[] =
Geoff Lang23633562018-07-17 15:02:36 -04001484 "attribute vec4 a_Position;\n"
1485 "void main()\n"
1486 "{\n"
1487 " gl_Position = a_Position;\n"
1488 "}\n";
1489
Jamie Madill35cd7332018-12-02 12:03:33 -05001490 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Geoff Lang23633562018-07-17 15:02:36 -04001491 glUseProgram(program.get());
1492
1493 glEnableVertexAttribArray(glGetAttribLocation(program, "a_Position"));
1494
1495 constexpr float kVertexData[] = {
1496 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1497 };
1498
1499 GLBuffer vertexBuffer;
1500 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1501 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData, GL_STREAM_DRAW);
1502
1503 constexpr GLuint kMaxIntAsGLuint = static_cast<GLuint>(std::numeric_limits<GLint>::max());
1504 constexpr GLuint kIndexData[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05001505 kMaxIntAsGLuint,
1506 kMaxIntAsGLuint + 1,
1507 kMaxIntAsGLuint + 2,
1508 kMaxIntAsGLuint + 3,
Geoff Lang23633562018-07-17 15:02:36 -04001509 };
1510
1511 GLBuffer indexBuffer;
1512 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBuffer);
1513 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData, GL_DYNAMIC_DRAW);
1514
1515 EXPECT_GL_NO_ERROR();
1516
1517 // First index is representable as 32-bit int but second is not
1518 glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);
1519 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1520
1521 // Neither index is representable as 32-bit int
1522 glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, reinterpret_cast<void *>(sizeof(GLuint) * 2));
1523 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1524}
1525
Brandon Jones2a018152018-06-08 15:59:26 -07001526// Test for drawing with a null index buffer
1527TEST_P(WebGLCompatibilityTest, NullIndexBuffer)
1528{
Jamie Madill35cd7332018-12-02 12:03:33 -05001529 constexpr char kVS[] =
Brandon Jones2a018152018-06-08 15:59:26 -07001530 "attribute float a_pos;\n"
1531 "void main()\n"
1532 "{\n"
1533 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1534 "}\n";
1535
Jamie Madill35cd7332018-12-02 12:03:33 -05001536 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Brandon Jones2a018152018-06-08 15:59:26 -07001537 glUseProgram(program.get());
1538
1539 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1540 glEnableVertexAttribArray(0);
1541
1542 glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_BYTE, 0);
1543 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1544}
1545
Corentin Wallez91c8de82017-10-12 16:32:44 -04001546// Test the checks for OOB reads in the vertex buffers, instanced version
1547TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
1548{
Jamie Madill35cd7332018-12-02 12:03:33 -05001549 constexpr char kVS[] =
Corentin Wallez91c8de82017-10-12 16:32:44 -04001550 "attribute float a_pos;\n"
1551 "attribute float a_w;\n"
1552 "void main()\n"
1553 "{\n"
1554 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1555 "}\n";
1556
Jamie Madill35cd7332018-12-02 12:03:33 -05001557 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Corentin Wallez91c8de82017-10-12 16:32:44 -04001558 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
Jamie Madillb980c562018-11-27 11:34:27 -05001559 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
Corentin Wallez91c8de82017-10-12 16:32:44 -04001560 ASSERT_NE(-1, posLocation);
1561 ASSERT_NE(-1, wLocation);
1562 glUseProgram(program.get());
1563
1564 GLBuffer buffer;
1565 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1566 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1567
1568 glEnableVertexAttribArray(posLocation);
1569 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1570 glVertexAttribDivisor(posLocation, 0);
1571
1572 glEnableVertexAttribArray(wLocation);
1573 glVertexAttribDivisor(wLocation, 1);
1574
Jamie Madillb980c562018-11-27 11:34:27 -05001575 const uint8_t *zeroOffset = nullptr;
Corentin Wallez91c8de82017-10-12 16:32:44 -04001576
1577 // Test touching the last element is valid.
1578 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1579 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1580 ASSERT_GL_NO_ERROR();
1581
1582 // Test touching the last element + 1 is invalid.
1583 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1584 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1585 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1586
1587 // Test touching the last element is valid, using a stride.
1588 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1589 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1590 ASSERT_GL_NO_ERROR();
1591
1592 // Test touching the last element + 1 is invalid, using a stride.
1593 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1594 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
1595 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1596
1597 // Test any offset is valid if no vertices are drawn.
1598 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1599 glDrawArraysInstanced(GL_POINTS, 0, 0, 1);
1600 ASSERT_GL_NO_ERROR();
1601
1602 // Test any offset is valid if no primitives are drawn.
1603 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1604 glDrawArraysInstanced(GL_POINTS, 0, 1, 0);
1605 ASSERT_GL_NO_ERROR();
1606}
1607
1608// Test the checks for OOB reads in the vertex buffers, ANGLE_instanced_arrays version
1609TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsInstancedANGLE)
1610{
1611 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_ANGLE_instanced_arrays"));
1612 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
1613 EXPECT_GL_NO_ERROR();
1614
Jamie Madill35cd7332018-12-02 12:03:33 -05001615 constexpr char kVS[] =
Corentin Wallez91c8de82017-10-12 16:32:44 -04001616 "attribute float a_pos;\n"
1617 "attribute float a_w;\n"
1618 "void main()\n"
1619 "{\n"
1620 " gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
1621 "}\n";
1622
Jamie Madill35cd7332018-12-02 12:03:33 -05001623 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Corentin Wallez91c8de82017-10-12 16:32:44 -04001624 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
Jamie Madillb980c562018-11-27 11:34:27 -05001625 GLint wLocation = glGetAttribLocation(program.get(), "a_w");
Corentin Wallez91c8de82017-10-12 16:32:44 -04001626 ASSERT_NE(-1, posLocation);
1627 ASSERT_NE(-1, wLocation);
1628 glUseProgram(program.get());
1629
1630 GLBuffer buffer;
1631 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
1632 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1633
1634 glEnableVertexAttribArray(posLocation);
1635 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1636 glVertexAttribDivisorANGLE(posLocation, 0);
1637
1638 glEnableVertexAttribArray(wLocation);
1639 glVertexAttribDivisorANGLE(wLocation, 1);
1640
Jamie Madillb980c562018-11-27 11:34:27 -05001641 const uint8_t *zeroOffset = nullptr;
Corentin Wallez91c8de82017-10-12 16:32:44 -04001642
1643 // Test touching the last element is valid.
1644 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
1645 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -04001646 ASSERT_GL_NO_ERROR() << "touching the last element.";
Corentin Wallez91c8de82017-10-12 16:32:44 -04001647
1648 // Test touching the last element + 1 is invalid.
1649 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
1650 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -04001651 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "touching the last element + 1.";
Corentin Wallez91c8de82017-10-12 16:32:44 -04001652
1653 // Test touching the last element is valid, using a stride.
1654 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
1655 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -04001656 ASSERT_GL_NO_ERROR() << "touching the last element using a stride.";
Corentin Wallez91c8de82017-10-12 16:32:44 -04001657
1658 // Test touching the last element + 1 is invalid, using a stride.
1659 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
1660 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -04001661 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "touching the last element + 1 using a stride.";
Corentin Wallez91c8de82017-10-12 16:32:44 -04001662
1663 // Test any offset is valid if no vertices are drawn.
1664 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1665 glDrawArraysInstancedANGLE(GL_POINTS, 0, 0, 1);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -04001666 ASSERT_GL_NO_ERROR() << "any offset with no vertices.";
Corentin Wallez91c8de82017-10-12 16:32:44 -04001667
1668 // Test any offset is valid if no primitives are drawn.
1669 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
1670 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 0);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -04001671 ASSERT_GL_NO_ERROR() << "any offset with primitives.";
Corentin Wallezfd456442016-12-21 17:57:00 -05001672}
1673
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001674// Test the checks for OOB reads in the index buffer
1675TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
Geoff Lang5f319a42017-01-09 16:49:19 -05001676{
Jamie Madill35cd7332018-12-02 12:03:33 -05001677 constexpr char kVS[] =
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001678 "attribute float a_pos;\n"
1679 "void main()\n"
1680 "{\n"
1681 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1682 "}\n";
Geoff Lang5f319a42017-01-09 16:49:19 -05001683
Jamie Madill35cd7332018-12-02 12:03:33 -05001684 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001685 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1686 ASSERT_NE(-1, posLocation);
1687 glUseProgram(program.get());
1688
1689 GLBuffer vertexBuffer;
1690 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1691 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
1692
1693 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001694 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001695
1696 const uint8_t *zeroOffset = nullptr;
1697 const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
1698
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001699 GLBuffer indexBuffer;
1700 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1701 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
Geoff Lang5f319a42017-01-09 16:49:19 -05001702 ASSERT_GL_NO_ERROR();
1703
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001704 // Test touching the last index is valid
1705 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1706 ASSERT_GL_NO_ERROR();
Geoff Lang5f319a42017-01-09 16:49:19 -05001707
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001708 // Test touching the last + 1 element is invalid
1709 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
1710 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang5f319a42017-01-09 16:49:19 -05001711
Corentin Wallez0844f2d2017-01-31 17:02:59 -05001712 // Test any offset if valid if count is zero
1713 glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
1714 ASSERT_GL_NO_ERROR();
Corentin Wallezfe9306a2017-02-01 17:41:05 -05001715
1716 // Test touching the first index is valid
1717 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
1718 ASSERT_GL_NO_ERROR();
1719
1720 // Test touching the first - 1 index is invalid
1721 // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was
1722 // the historic behavior of WebGL implementations
1723 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1);
1724 EXPECT_GL_ERROR(GL_INVALID_VALUE);
Geoff Lang5f319a42017-01-09 16:49:19 -05001725}
1726
Corentin Wallez91c8de82017-10-12 16:32:44 -04001727// Test the checks for OOB in vertex buffers caused by indices, non-instanced version
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001728TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInVertexBuffer)
1729{
Jamie Madill35cd7332018-12-02 12:03:33 -05001730 constexpr char kVS[] =
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001731 "attribute float a_pos;\n"
1732 "void main()\n"
1733 "{\n"
1734 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1735 "}\n";
1736
Jamie Madill35cd7332018-12-02 12:03:33 -05001737 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001738 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
1739 ASSERT_NE(-1, posLocation);
1740 glUseProgram(program.get());
1741
1742 GLBuffer vertexBuffer;
1743 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
1744 glBufferData(GL_ARRAY_BUFFER, 8, nullptr, GL_STATIC_DRAW);
1745
1746 glEnableVertexAttribArray(posLocation);
Corentin Wallez91c8de82017-10-12 16:32:44 -04001747 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001748
1749 const uint8_t *zeroOffset = nullptr;
1750 const uint8_t testIndices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 255};
1751
Corentin Wallezc3bc9842017-10-11 15:15:59 -04001752 GLBuffer indexBuffer;
1753 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
1754 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(testIndices), testIndices, GL_STATIC_DRAW);
1755 ASSERT_GL_NO_ERROR();
1756
1757 // Test touching the end of the vertex buffer is valid
1758 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 7);
1759 ASSERT_GL_NO_ERROR();
1760
1761 // Test touching just after the end of the vertex buffer is invalid
1762 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 8);
1763 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1764
1765 // Test touching the whole vertex buffer is valid
1766 glDrawElements(GL_POINTS, 8, GL_UNSIGNED_BYTE, zeroOffset + 0);
1767 ASSERT_GL_NO_ERROR();
1768
1769 // Test an index that would be negative
1770 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 9);
1771 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1772}
1773
Frank Henigman6137ddc2017-02-10 18:55:07 -05001774// Test depth range with 'near' more or less than 'far.'
1775TEST_P(WebGLCompatibilityTest, DepthRange)
1776{
1777 glDepthRangef(0, 1);
1778 ASSERT_GL_NO_ERROR();
1779
1780 glDepthRangef(.5, .5);
1781 ASSERT_GL_NO_ERROR();
1782
1783 glDepthRangef(1, 0);
1784 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1785}
1786
Frank Henigman146e8a12017-03-02 23:22:37 -05001787// Test all blend function combinations.
1788// In WebGL it is invalid to combine constant color with constant alpha.
1789TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
1790{
1791 constexpr GLenum srcFunc[] = {
1792 GL_ZERO,
1793 GL_ONE,
1794 GL_SRC_COLOR,
1795 GL_ONE_MINUS_SRC_COLOR,
1796 GL_DST_COLOR,
1797 GL_ONE_MINUS_DST_COLOR,
1798 GL_SRC_ALPHA,
1799 GL_ONE_MINUS_SRC_ALPHA,
1800 GL_DST_ALPHA,
1801 GL_ONE_MINUS_DST_ALPHA,
1802 GL_CONSTANT_COLOR,
1803 GL_ONE_MINUS_CONSTANT_COLOR,
1804 GL_CONSTANT_ALPHA,
1805 GL_ONE_MINUS_CONSTANT_ALPHA,
1806 GL_SRC_ALPHA_SATURATE,
1807 };
1808
1809 constexpr GLenum dstFunc[] = {
1810 GL_ZERO, GL_ONE,
1811 GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
1812 GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
1813 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1814 GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
1815 GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
1816 GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
1817 };
1818
1819 for (GLenum src : srcFunc)
1820 {
1821 for (GLenum dst : dstFunc)
1822 {
1823 glBlendFunc(src, dst);
1824 CheckBlendFunctions(src, dst);
1825 glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE);
1826 CheckBlendFunctions(src, dst);
1827 }
1828 }
1829}
1830
Geoff Langfc32e8b2017-05-31 14:16:59 -04001831// Test that binding/querying uniforms and attributes with invalid names generates errors
1832TEST_P(WebGLCompatibilityTest, InvalidAttributeAndUniformNames)
1833{
1834 const std::string validAttribName =
1835 "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1836 const std::string validUniformName =
1837 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
Geoff Langa71a98e2017-06-19 15:15:00 -04001838 std::vector<char> invalidSet = {'"', '$', '`', '@', '\''};
1839 if (getClientMajorVersion() < 3)
1840 {
1841 invalidSet.push_back('\\');
1842 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04001843
1844 std::string vert = "attribute float ";
1845 vert += validAttribName;
1846 vert +=
1847 ";\n"
1848 "void main()\n"
1849 "{\n"
1850 " gl_Position = vec4(1.0);\n"
1851 "}\n";
1852
1853 std::string frag =
1854 "precision highp float;\n"
1855 "uniform vec4 ";
1856 frag += validUniformName;
Geoff Langcab92ee2017-07-19 17:32:07 -04001857 // Insert illegal characters into comments
Geoff Langfc32e8b2017-05-31 14:16:59 -04001858 frag +=
1859 ";\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001860 " // $ \" @ /*\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001861 "void main()\n"
Geoff Langcab92ee2017-07-19 17:32:07 -04001862 "{/*\n"
1863 " ` @ $\n"
1864 " */gl_FragColor = vec4(1.0);\n"
Geoff Langfc32e8b2017-05-31 14:16:59 -04001865 "}\n";
1866
Jamie Madill35cd7332018-12-02 12:03:33 -05001867 ANGLE_GL_PROGRAM(program, vert.c_str(), frag.c_str());
Geoff Langfc32e8b2017-05-31 14:16:59 -04001868 EXPECT_GL_NO_ERROR();
1869
1870 for (char invalidChar : invalidSet)
1871 {
1872 std::string invalidName = validAttribName + invalidChar;
1873 glGetAttribLocation(program, invalidName.c_str());
1874 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1875 << "glGetAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1876
1877 glBindAttribLocation(program, 0, invalidName.c_str());
1878 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1879 << "glBindAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1880 }
1881
1882 for (char invalidChar : invalidSet)
1883 {
1884 std::string invalidName = validUniformName + invalidChar;
1885 glGetUniformLocation(program, invalidName.c_str());
1886 EXPECT_GL_ERROR(GL_INVALID_VALUE)
1887 << "glGetUniformLocation unexpectedly succeeded for name \"" << invalidName << "\".";
1888 }
1889
1890 for (char invalidChar : invalidSet)
1891 {
1892 std::string invalidAttribName = validAttribName + invalidChar;
Jamie Madillb980c562018-11-27 11:34:27 -05001893 const char *invalidVert[] = {
Geoff Langfc32e8b2017-05-31 14:16:59 -04001894 "attribute float ",
1895 invalidAttribName.c_str(),
1896 ";\n",
1897 "void main()\n",
1898 "{\n",
1899 " gl_Position = vec4(1.0);\n",
1900 "}\n",
1901 };
1902
1903 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1904 glShaderSource(shader, static_cast<GLsizei>(ArraySize(invalidVert)), invalidVert, nullptr);
1905 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1906 glDeleteShader(shader);
1907 }
1908}
1909
Geoff Langcab92ee2017-07-19 17:32:07 -04001910// Test that line continuation is handled correctly when valdiating shader source
Bryan Bernhart (Intel Americas Inc)335d8bf2017-10-23 15:41:43 -07001911TEST_P(WebGLCompatibilityTest, ShaderSourceLineContinuation)
1912{
1913 // Verify that a line continuation character (i.e. backslash) cannot be used
1914 // within a preprocessor directive in a ES2 context.
1915 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
1916
1917 const char *validVert =
1918 "#define foo this is a test\n"
1919 "precision mediump float;\n"
1920 "void main()\n"
1921 "{\n"
1922 " gl_Position = vec4(1.0);\n"
1923 "}\n";
1924
1925 const char *invalidVert =
1926 "#define foo this \\n"
1927 " is a test\n"
1928 "precision mediump float;\n"
1929 "void main()\n"
1930 "{\n"
1931 " gl_Position = vec4(1.0);\n"
1932 "}\n";
1933
1934 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1935 glShaderSource(shader, 1, &validVert, nullptr);
1936 EXPECT_GL_NO_ERROR();
1937
1938 glShaderSource(shader, 1, &invalidVert, nullptr);
1939 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1940 glDeleteShader(shader);
1941}
1942
1943// Test that line continuation is handled correctly when valdiating shader source
Geoff Langcab92ee2017-07-19 17:32:07 -04001944TEST_P(WebGL2CompatibilityTest, ShaderSourceLineContinuation)
1945{
1946 const char *validVert =
1947 "#version 300 es\n"
1948 "precision mediump float;\n"
1949 "\n"
1950 "void main ()\n"
1951 "{\n"
1952 " float f\\\n"
1953 "oo = 1.0;\n"
1954 " gl_Position = vec4(foo);\n"
1955 "}\n";
1956
1957 const char *invalidVert =
1958 "#version 300 es\n"
1959 "precision mediump float;\n"
1960 "\n"
1961 "void main ()\n"
1962 "{\n"
1963 " float f\\$\n"
1964 "oo = 1.0;\n"
1965 " gl_Position = vec4(foo);\n"
1966 "}\n";
1967
1968 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1969 glShaderSource(shader, 1, &validVert, nullptr);
1970 EXPECT_GL_NO_ERROR();
1971 glShaderSource(shader, 1, &invalidVert, nullptr);
1972 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1973 glDeleteShader(shader);
1974}
1975
Brandon Jonesed5b46f2017-07-21 08:39:17 -07001976// Tests bindAttribLocations for reserved prefixes and length limits
1977TEST_P(WebGLCompatibilityTest, BindAttribLocationLimitation)
1978{
1979 constexpr int maxLocStringLength = 256;
1980 const std::string tooLongString(maxLocStringLength + 1, '_');
1981
1982 glBindAttribLocation(0, 0, "_webgl_var");
1983
1984 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1985
1986 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
1987
1988 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1989}
1990
Corentin Wallez0dc97812017-06-22 14:38:44 -04001991// Test that having no attributes with a zero divisor is valid in WebGL2
Geoff Lang407d4e72017-04-12 14:54:11 -04001992TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor)
1993{
Jamie Madill35cd7332018-12-02 12:03:33 -05001994 constexpr char kVS[] =
Geoff Lang407d4e72017-04-12 14:54:11 -04001995 "attribute float a_pos;\n"
1996 "void main()\n"
1997 "{\n"
1998 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
1999 "}\n";
2000
Jamie Madill35cd7332018-12-02 12:03:33 -05002001 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Geoff Lang407d4e72017-04-12 14:54:11 -04002002
2003 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
2004 ASSERT_NE(-1, posLocation);
2005
2006 glUseProgram(program.get());
2007
2008 GLBuffer buffer;
2009 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
2010 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
2011
2012 glEnableVertexAttribArray(posLocation);
2013 glVertexAttribDivisor(posLocation, 1);
2014
Geoff Lang407d4e72017-04-12 14:54:11 -04002015 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
2016 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
Geoff Lang407d4e72017-04-12 14:54:11 -04002017 ASSERT_GL_NO_ERROR();
2018}
2019
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002020// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
2021TEST_P(WebGLCompatibilityTest, NPOT)
2022{
2023 EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
2024
2025 // Create a texture and set an NPOT mip 0, should always be acceptable.
2026 GLTexture texture;
2027 glBindTexture(GL_TEXTURE_2D, texture.get());
2028 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2029 ASSERT_GL_NO_ERROR();
2030
2031 // Try setting an NPOT mip 1 and verify the error if WebGL 1
2032 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2033 if (getClientMajorVersion() < 3)
2034 {
2035 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2036 }
2037 else
2038 {
2039 ASSERT_GL_NO_ERROR();
2040 }
2041
2042 if (extensionRequestable("GL_OES_texture_npot"))
2043 {
2044 glRequestExtensionANGLE("GL_OES_texture_npot");
2045 ASSERT_GL_NO_ERROR();
2046
2047 // Try again to set NPOT mip 1
2048 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2049 ASSERT_GL_NO_ERROR();
2050 }
2051}
2052
Jamie Madillcad97ee2017-02-02 18:52:44 -05002053template <typename T>
2054void FillTexture2D(GLuint texture,
2055 GLsizei width,
2056 GLsizei height,
2057 const T &onePixelData,
2058 GLint level,
2059 GLint internalFormat,
2060 GLenum format,
2061 GLenum type)
2062{
2063 std::vector<T> allPixelsData(width * height, onePixelData);
2064
2065 glBindTexture(GL_TEXTURE_2D, texture);
2066 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
2067 allPixelsData.data());
2068 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2069 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2070 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2071 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2072}
2073
Frank Henigman875bbba2017-02-08 16:38:17 -05002074// Test that unset gl_Position defaults to (0,0,0,0).
2075TEST_P(WebGLCompatibilityTest, DefaultPosition)
2076{
2077 // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set,
2078 // and green otherwise. The center of each quadrant will be red if and only if all
2079 // four corners are red.
Jamie Madill35cd7332018-12-02 12:03:33 -05002080 constexpr char kVS[] =
Frank Henigman875bbba2017-02-08 16:38:17 -05002081 "attribute vec3 pos;\n"
2082 "varying vec4 color;\n"
2083 "void main() {\n"
2084 " if (gl_Position == vec4(0,0,0,0)) {\n"
2085 " color = vec4(1,0,0,1);\n"
2086 " } else {\n"
2087 " color = vec4(0,1,0,1);\n"
2088 " }\n"
2089 " gl_Position = vec4(pos,1);\n"
2090 "}\n";
2091
Jamie Madill35cd7332018-12-02 12:03:33 -05002092 constexpr char kFS[] =
Frank Henigman875bbba2017-02-08 16:38:17 -05002093 "precision mediump float;\n"
2094 "varying vec4 color;\n"
2095 "void main() {\n"
2096 " gl_FragColor = color;\n"
2097 "}\n";
2098
Jamie Madill35cd7332018-12-02 12:03:33 -05002099 ANGLE_GL_PROGRAM(program, kVS, kFS);
Frank Henigman875bbba2017-02-08 16:38:17 -05002100 drawQuad(program.get(), "pos", 0.0f, 1.0f, true);
2101 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red);
2102 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red);
2103 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red);
2104 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red);
2105}
2106
Jamie Madilla4595b82017-01-11 17:36:34 -05002107// Tests that a rendering feedback loop triggers a GL error under WebGL.
2108// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
2109TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
2110{
Jamie Madill35cd7332018-12-02 12:03:33 -05002111 constexpr char kVS[] =
Jamie Madilla4595b82017-01-11 17:36:34 -05002112 "attribute vec4 a_position;\n"
2113 "varying vec2 v_texCoord;\n"
2114 "void main() {\n"
2115 " gl_Position = a_position;\n"
2116 " v_texCoord = (a_position.xy * 0.5) + 0.5;\n"
2117 "}\n";
2118
Jamie Madill35cd7332018-12-02 12:03:33 -05002119 constexpr char kFS[] =
Jamie Madilla4595b82017-01-11 17:36:34 -05002120 "precision mediump float;\n"
2121 "varying vec2 v_texCoord;\n"
2122 "uniform sampler2D u_texture;\n"
2123 "void main() {\n"
2124 " // Shader swizzles color channels so we can tell if the draw succeeded.\n"
2125 " gl_FragColor = texture2D(u_texture, v_texCoord).gbra;\n"
2126 "}\n";
2127
2128 GLTexture texture;
Jamie Madillcad97ee2017-02-02 18:52:44 -05002129 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05002130
2131 ASSERT_GL_NO_ERROR();
2132
2133 GLFramebuffer framebuffer;
2134 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2135 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2136
2137 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2138
Jamie Madill35cd7332018-12-02 12:03:33 -05002139 ANGLE_GL_PROGRAM(program, kVS, kFS);
Jamie Madilla4595b82017-01-11 17:36:34 -05002140
2141 GLint uniformLoc = glGetUniformLocation(program.get(), "u_texture");
2142 ASSERT_NE(-1, uniformLoc);
2143
2144 glUseProgram(program.get());
2145 glUniform1i(uniformLoc, 0);
2146 glDisable(GL_BLEND);
2147 glDisable(GL_DEPTH_TEST);
2148 ASSERT_GL_NO_ERROR();
2149
2150 // Drawing with a texture that is also bound to the current framebuffer should fail
2151 glBindTexture(GL_TEXTURE_2D, texture.get());
2152 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
2153 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2154
2155 // Ensure that the texture contents did not change after the previous render
2156 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2157 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
2158 ASSERT_GL_NO_ERROR();
2159 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2160
2161 // Drawing when texture is bound to an inactive uniform should succeed
2162 GLTexture texture2;
Jamie Madillcad97ee2017-02-02 18:52:44 -05002163 FillTexture2D(texture2.get(), 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -05002164
2165 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2166 glActiveTexture(GL_TEXTURE1);
2167 glBindTexture(GL_TEXTURE_2D, texture.get());
2168 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
2169 ASSERT_GL_NO_ERROR();
2170 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2171}
2172
Bryan Bernhart58806562017-01-05 13:09:31 -08002173// Test for the max draw buffers and color attachments.
2174TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
2175{
2176 // This test only applies to ES2.
2177 if (getClientMajorVersion() != 2)
2178 {
2179 return;
2180 }
2181
2182 GLFramebuffer fbo[2];
2183 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0].get());
2184
2185 // Test that is valid when we bind with a single attachment point.
2186 GLTexture texture;
2187 glBindTexture(GL_TEXTURE_2D, texture.get());
2188 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2189 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2190 ASSERT_GL_NO_ERROR();
2191
2192 // Test that enabling the draw buffers extension will allow us to bind with a non-zero
2193 // attachment point.
2194 if (extensionRequestable("GL_EXT_draw_buffers"))
2195 {
2196 glRequestExtensionANGLE("GL_EXT_draw_buffers");
2197 EXPECT_GL_NO_ERROR();
2198 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
2199
2200 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1].get());
2201
2202 GLTexture texture2;
2203 glBindTexture(GL_TEXTURE_2D, texture2.get());
2204 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2205 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2.get(),
2206 0);
2207 ASSERT_GL_NO_ERROR();
2208 }
2209}
2210
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002211// Test that the offset in the index buffer is forced to be a multiple of the element size
2212TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction)
2213{
Jamie Madill35cd7332018-12-02 12:03:33 -05002214 constexpr char kVS[] =
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002215 "attribute vec3 a_pos;\n"
2216 "void main()\n"
2217 "{\n"
2218 " gl_Position = vec4(a_pos, 1.0);\n"
2219 "}\n";
2220
Jamie Madill35cd7332018-12-02 12:03:33 -05002221 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002222
2223 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
2224 ASSERT_NE(-1, posLocation);
2225 glUseProgram(program.get());
2226
2227 const auto &vertices = GetQuadVertices();
2228
2229 GLBuffer vertexBuffer;
2230 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
2231 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2232 GL_STATIC_DRAW);
2233
2234 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2235 glEnableVertexAttribArray(posLocation);
2236
2237 GLBuffer indexBuffer;
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002238 const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0, 0};
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002239 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
2240 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
2241
2242 ASSERT_GL_NO_ERROR();
2243
2244 const char *zeroIndices = nullptr;
2245
2246 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices);
2247 ASSERT_GL_NO_ERROR();
2248
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002249 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002250 ASSERT_GL_NO_ERROR();
2251
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002252 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices + 1);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002253 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2254}
2255
2256// Test that the offset and stride in the vertex buffer is forced to be a multiple of the element
2257// size
2258TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction)
2259{
2260 const char *zeroOffset = nullptr;
2261
2262 // Base case, vector of two floats
2263 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset);
2264 ASSERT_GL_NO_ERROR();
2265
2266 // Test setting a non-multiple offset
2267 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1);
2268 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2269 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2);
2270 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2271 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3);
2272 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2273
2274 // Test setting a non-multiple stride
2275 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset);
2276 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2277 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset);
2278 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2279 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset);
2280 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2281}
2282
Jamie Madillcad97ee2017-02-02 18:52:44 -05002283void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program,
2284 const std::array<GLenum, 2> &drawBuffers,
2285 GLenum expectedError)
2286{
2287 glDrawBuffersEXT(2, drawBuffers.data());
2288
2289 // Make sure framebuffer is complete before feedback loop detection
2290 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2291
2292 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2293
2294 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2295 // it should be NO_ERROR"
2296 EXPECT_GL_ERROR(expectedError);
2297}
2298
2299// This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers.
2300// Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html
2301TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT)
2302{
Jamie Madill35cd7332018-12-02 12:03:33 -05002303 constexpr char kVS[] =
Jamie Madillcad97ee2017-02-02 18:52:44 -05002304 "attribute vec4 aPosition;\n"
2305 "varying vec2 texCoord;\n"
2306 "void main() {\n"
2307 " gl_Position = aPosition;\n"
2308 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
2309 "}\n";
2310
Jamie Madill35cd7332018-12-02 12:03:33 -05002311 constexpr char kFS[] =
Jamie Madillcad97ee2017-02-02 18:52:44 -05002312 "#extension GL_EXT_draw_buffers : require\n"
2313 "precision mediump float;\n"
2314 "uniform sampler2D tex;\n"
2315 "varying vec2 texCoord;\n"
2316 "void main() {\n"
2317 " gl_FragData[0] = texture2D(tex, texCoord);\n"
2318 " gl_FragData[1] = texture2D(tex, texCoord);\n"
2319 "}\n";
2320
2321 GLsizei width = 8;
2322 GLsizei height = 8;
2323
2324 // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers
2325 // extension and gl_FragData semantics are changed to enforce indexing by zero always.
2326 // TODO(jmadill): This extension should be disabled in WebGL 2 contexts.
2327 if (/*!extensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2)
2328 {
2329 // No WEBGL_draw_buffers support -- this is legal.
2330 return;
2331 }
2332
2333 GLint maxDrawBuffers = 0;
2334 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
2335
Yunchao He9550c602018-02-13 14:47:05 +08002336 // Test skipped because MAX_DRAW_BUFFERS is too small.
2337 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 2);
Jamie Madillcad97ee2017-02-02 18:52:44 -05002338
Jamie Madill35cd7332018-12-02 12:03:33 -05002339 ANGLE_GL_PROGRAM(program, kVS, kFS);
Jamie Madillcad97ee2017-02-02 18:52:44 -05002340 glUseProgram(program.get());
2341 glViewport(0, 0, width, height);
2342
2343 GLTexture tex0;
2344 GLTexture tex1;
2345 GLFramebuffer fbo;
2346 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2347 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2348 ASSERT_GL_NO_ERROR();
2349
2350 glBindTexture(GL_TEXTURE_2D, tex1.get());
2351 GLint texLoc = glGetUniformLocation(program.get(), "tex");
2352 ASSERT_NE(-1, texLoc);
2353 glUniform1i(texLoc, 0);
2354 ASSERT_GL_NO_ERROR();
2355
2356 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
2357 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
2358 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
2359 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
2360
2361 drawBuffersEXTFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}},
2362 GL_INVALID_OPERATION);
2363 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
2364 GL_INVALID_OPERATION);
2365 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
2366}
2367
Jamie Madill07be8bf2017-02-02 19:59:57 -05002368// Test tests that texture copying feedback loops are properly rejected in WebGL.
2369// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
2370TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
2371{
2372 GLTexture texture;
2373 glBindTexture(GL_TEXTURE_2D, texture.get());
2374 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2378 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2379
2380 GLTexture texture2;
2381 glBindTexture(GL_TEXTURE_2D, texture2.get());
2382 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2387
2388 GLFramebuffer framebuffer;
2389 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2390 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
2391
2392 // framebuffer should be FRAMEBUFFER_COMPLETE.
2393 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2394 ASSERT_GL_NO_ERROR();
2395
2396 // testing copyTexImage2D
2397
2398 // copyTexImage2D to same texture but different level
2399 glBindTexture(GL_TEXTURE_2D, texture.get());
2400 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
2401 EXPECT_GL_NO_ERROR();
2402
2403 // copyTexImage2D to same texture same level, invalid feedback loop
2404 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2405 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2406
2407 // copyTexImage2D to different texture
2408 glBindTexture(GL_TEXTURE_2D, texture2.get());
2409 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
2410 EXPECT_GL_NO_ERROR();
2411
2412 // testing copyTexSubImage2D
2413
2414 // copyTexSubImage2D to same texture but different level
2415 glBindTexture(GL_TEXTURE_2D, texture.get());
2416 glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
2417 EXPECT_GL_NO_ERROR();
2418
2419 // copyTexSubImage2D to same texture same level, invalid feedback loop
2420 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2421 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2422
2423 // copyTexSubImage2D to different texture
2424 glBindTexture(GL_TEXTURE_2D, texture2.get());
2425 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2426 EXPECT_GL_NO_ERROR();
2427}
2428
2429void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program,
2430 const std::array<GLenum, 2> &drawBuffers,
2431 GLenum expectedError)
2432{
2433 glDrawBuffers(2, drawBuffers.data());
2434
2435 // Make sure framebuffer is complete before feedback loop detection
2436 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2437
2438 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
2439
2440 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
2441 // it should be NO_ERROR"
2442 EXPECT_GL_ERROR(expectedError);
2443}
2444
Yuly Novikov817232e2017-02-22 18:36:10 -05002445// Tests invariance matching rules between built in varyings.
2446// Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html.
2447TEST_P(WebGLCompatibilityTest, BuiltInInvariant)
2448{
Jamie Madill35cd7332018-12-02 12:03:33 -05002449 constexpr char kVS[] =
Yuly Novikov817232e2017-02-22 18:36:10 -05002450 "varying vec4 v_varying;\n"
2451 "void main()\n"
2452 "{\n"
2453 " gl_PointSize = 1.0;\n"
2454 " gl_Position = v_varying;\n"
2455 "}";
Jamie Madill35cd7332018-12-02 12:03:33 -05002456 constexpr char kFSInvariantGlFragCoord[] =
Yuly Novikov817232e2017-02-22 18:36:10 -05002457 "invariant gl_FragCoord;\n"
2458 "void main()\n"
2459 "{\n"
2460 " gl_FragColor = gl_FragCoord;\n"
2461 "}";
Jamie Madill35cd7332018-12-02 12:03:33 -05002462 constexpr char kFSInvariantGlPointCoord[] =
Yuly Novikov817232e2017-02-22 18:36:10 -05002463 "invariant gl_PointCoord;\n"
2464 "void main()\n"
2465 "{\n"
2466 " gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);\n"
2467 "}";
2468
Jamie Madill35cd7332018-12-02 12:03:33 -05002469 GLuint program = CompileProgram(kVS, kFSInvariantGlFragCoord);
Yuly Novikov817232e2017-02-22 18:36:10 -05002470 EXPECT_EQ(0u, program);
2471
Jamie Madill35cd7332018-12-02 12:03:33 -05002472 program = CompileProgram(kVS, kFSInvariantGlPointCoord);
Yuly Novikov817232e2017-02-22 18:36:10 -05002473 EXPECT_EQ(0u, program);
2474}
2475
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04002476// Tests global namespace conflicts between uniforms and attributes.
2477// Based on WebGL test conformance/glsl/misc/shaders-with-name-conflicts.html.
2478TEST_P(WebGLCompatibilityTest, GlobalNamesConflict)
2479{
Jamie Madill35cd7332018-12-02 12:03:33 -05002480 constexpr char kVS[] =
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04002481 "attribute vec4 foo;\n"
2482 "void main()\n"
2483 "{\n"
2484 " gl_Position = foo;\n"
2485 "}";
Jamie Madill35cd7332018-12-02 12:03:33 -05002486 constexpr char kFS[] =
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04002487 "precision mediump float;\n"
2488 "uniform vec4 foo;\n"
2489 "void main()\n"
2490 "{\n"
2491 " gl_FragColor = foo;\n"
2492 "}";
2493
Jamie Madill35cd7332018-12-02 12:03:33 -05002494 GLuint program = CompileProgram(kVS, kFS);
Yuly Novikovcaa5cda2017-06-15 21:14:03 -04002495 EXPECT_EQ(0u, program);
2496}
2497
Geoff Lang966c9402017-04-18 12:38:27 -04002498// Test dimension and image size validation of compressed textures
2499TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
2500{
2501 if (extensionRequestable("GL_EXT_texture_compression_dxt1"))
2502 {
2503 glRequestExtensionANGLE("GL_EXT_texture_compression_dxt1");
2504 }
2505
Yunchao He9550c602018-02-13 14:47:05 +08002506 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_compression_dxt1"));
Geoff Lang966c9402017-04-18 12:38:27 -04002507
2508 constexpr uint8_t CompressedImageDXT1[] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
2509
2510 GLTexture texture;
2511 glBindTexture(GL_TEXTURE_2D, texture);
2512
2513 // Regular case, verify that it works
2514 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2515 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2516 ASSERT_GL_NO_ERROR();
2517
2518 // Test various dimensions that are not valid
2519 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3, 4, 0,
2520 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2521 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2522
2523 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 3, 0,
2524 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2525 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2526
2527 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2528 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2529 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2530
2531 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2532 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2533 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2534
2535 // Test various image sizes that are not valid
2536 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2537 sizeof(CompressedImageDXT1) - 1, CompressedImageDXT1);
2538 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2539
2540 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2541 sizeof(CompressedImageDXT1) + 1, CompressedImageDXT1);
2542 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2543
2544 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 0,
2545 CompressedImageDXT1);
2546 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2547
2548 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0, 0,
2549 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2550 ASSERT_GL_ERROR(GL_INVALID_VALUE);
2551
2552 // Fill a full mip chain and verify that it works
2553 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
2554 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2555 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0,
2556 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2557 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0,
2558 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2559 ASSERT_GL_NO_ERROR();
2560
2561 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2562 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2563 ASSERT_GL_NO_ERROR();
2564
2565 // Test that non-block size sub-uploads are not valid for the 0 mip
2566 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2567 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2568 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2569
2570 // Test that non-block size sub-uploads are valid for if they fill the whole mip
2571 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2572 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2573 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, 1, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
2574 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2575 ASSERT_GL_NO_ERROR();
2576
2577 // Test that if the format miss-matches the texture, an error is generated
2578 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
2579 sizeof(CompressedImageDXT1), CompressedImageDXT1);
2580 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
2581}
2582
Geoff Lang677bb6f2017-04-05 12:40:40 -04002583TEST_P(WebGLCompatibilityTest, L32FTextures)
2584{
2585 constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f};
2586 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 1.0f};
2587
2588 for (auto extension : FloatingPointTextureExtensions)
2589 {
2590 if (strlen(extension) > 0 && extensionRequestable(extension))
2591 {
2592 glRequestExtensionANGLE(extension);
2593 ASSERT_GL_NO_ERROR();
2594 }
2595
2596 // Unsized L 32F
2597 {
2598 bool texture = extensionEnabled("GL_OES_texture_float");
2599 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2600 bool render = false;
2601 TestFloatTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, texture, filter, render,
2602 textureData, readPixelData);
2603 }
2604
2605 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2606 {
2607 // Sized L 32F
2608 bool texture = extensionEnabled("GL_OES_texture_float") &&
2609 extensionEnabled("GL_EXT_texture_storage");
2610 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2611 bool render = false;
2612 TestFloatTextureFormat(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT, texture, filter,
2613 render, textureData, readPixelData);
2614 }
2615 }
2616}
2617
2618TEST_P(WebGLCompatibilityTest, A32FTextures)
2619{
2620 constexpr float textureData[] = {33.33f, 0.0f, 0.0f, 0.0f};
2621 constexpr float readPixelData[] = {0.0f, 0.0f, 0.0f, textureData[0]};
2622
2623 for (auto extension : FloatingPointTextureExtensions)
2624 {
2625 if (strlen(extension) > 0 && extensionRequestable(extension))
2626 {
2627 glRequestExtensionANGLE(extension);
2628 ASSERT_GL_NO_ERROR();
2629 }
2630
2631 // Unsized A 32F
2632 {
2633 bool texture = extensionEnabled("GL_OES_texture_float");
2634 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2635 bool render = false;
2636 TestFloatTextureFormat(GL_ALPHA, GL_ALPHA, GL_FLOAT, texture, filter, render,
2637 textureData, readPixelData);
2638 }
2639
2640 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2641 {
2642 // Sized A 32F
2643 bool texture = extensionEnabled("GL_OES_texture_float") &&
2644 extensionEnabled("GL_EXT_texture_storage");
2645 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2646 bool render = false;
2647 TestFloatTextureFormat(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT, texture, filter, render,
2648 textureData, readPixelData);
2649 }
2650 }
2651}
2652
2653TEST_P(WebGLCompatibilityTest, LA32FTextures)
2654{
2655 constexpr float textureData[] = {-0.21f, 15.1f, 0.0f, 0.0f};
2656 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0],
2657 textureData[1]};
2658
2659 for (auto extension : FloatingPointTextureExtensions)
2660 {
2661 if (strlen(extension) > 0 && extensionRequestable(extension))
2662 {
2663 glRequestExtensionANGLE(extension);
2664 ASSERT_GL_NO_ERROR();
2665 }
2666
2667 // Unsized LA 32F
2668 {
2669 bool texture = extensionEnabled("GL_OES_texture_float");
2670 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2671 bool render = false;
2672 TestFloatTextureFormat(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2673 filter, render, textureData, readPixelData);
2674 }
2675
2676 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2677 {
2678 // Sized LA 32F
2679 bool texture = extensionEnabled("GL_OES_texture_float") &&
2680 extensionEnabled("GL_EXT_texture_storage");
2681 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2682 bool render = false;
2683 TestFloatTextureFormat(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT, texture,
2684 filter, render, textureData, readPixelData);
2685 }
2686 }
2687}
2688
2689TEST_P(WebGLCompatibilityTest, R32FTextures)
2690{
2691 constexpr float data[] = {1000.0f, 0.0f, 0.0f, 1.0f};
2692
2693 for (auto extension : FloatingPointTextureExtensions)
2694 {
2695 if (strlen(extension) > 0 && extensionRequestable(extension))
2696 {
2697 glRequestExtensionANGLE(extension);
2698 ASSERT_GL_NO_ERROR();
2699 }
2700
2701 // Unsized R 32F
2702 {
2703 bool texture =
2704 extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg");
2705 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2706 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2707 TestFloatTextureFormat(GL_RED, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2708 }
2709
2710 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2711 {
2712 // Sized R 32F
2713 bool texture =
2714 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2715 extensionEnabled("GL_EXT_texture_rg") &&
2716 extensionEnabled("GL_EXT_texture_storage"));
2717 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2718 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2719 TestFloatTextureFormat(GL_R32F, GL_RED, GL_FLOAT, texture, filter, render, data, data);
2720 }
2721 }
2722}
2723
2724TEST_P(WebGLCompatibilityTest, RG32FTextures)
2725{
2726 constexpr float data[] = {1000.0f, -0.001f, 0.0f, 1.0f};
2727
2728 for (auto extension : FloatingPointTextureExtensions)
2729 {
2730 if (strlen(extension) > 0 && extensionRequestable(extension))
2731 {
2732 glRequestExtensionANGLE(extension);
2733 ASSERT_GL_NO_ERROR();
2734 }
2735
2736 // Unsized RG 32F
2737 {
2738 bool texture =
2739 (extensionEnabled("GL_OES_texture_float") && extensionEnabled("GL_EXT_texture_rg"));
2740 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2741 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2742 TestFloatTextureFormat(GL_RG, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2743 }
2744
2745 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2746 {
2747 // Sized RG 32F
2748 bool texture =
2749 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2750 extensionEnabled("GL_EXT_texture_rg") &&
2751 extensionEnabled("GL_EXT_texture_storage"));
2752 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2753 bool render = extensionEnabled("GL_EXT_color_buffer_float");
2754 TestFloatTextureFormat(GL_RG32F, GL_RG, GL_FLOAT, texture, filter, render, data, data);
2755 }
2756 }
2757}
2758
2759TEST_P(WebGLCompatibilityTest, RGB32FTextures)
2760{
Yunchao He9550c602018-02-13 14:47:05 +08002761 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002762
Geoff Lang677bb6f2017-04-05 12:40:40 -04002763 constexpr float data[] = {1000.0f, -500.0f, 10.0f, 1.0f};
2764
2765 for (auto extension : FloatingPointTextureExtensions)
2766 {
2767 if (strlen(extension) > 0 && extensionRequestable(extension))
2768 {
2769 glRequestExtensionANGLE(extension);
2770 ASSERT_GL_NO_ERROR();
2771 }
2772
2773 // Unsized RGB 32F
2774 {
2775 bool texture = extensionEnabled("GL_OES_texture_float");
2776 bool filter = extensionEnabled("GL_OES_texture_float_linear");
Yuly Novikovd0828192018-06-15 15:51:07 -04002777 bool render = false;
Geoff Lang677bb6f2017-04-05 12:40:40 -04002778 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_FLOAT, texture, filter, render, data, data);
2779 }
2780
2781 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2782 {
Yuly Novikovd0828192018-06-15 15:51:07 -04002783 // Sized RGB 32F
Geoff Lang677bb6f2017-04-05 12:40:40 -04002784 bool texture =
2785 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2786 extensionEnabled("GL_EXT_texture_storage"));
2787 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2788 bool render = extensionEnabled("GL_CHROMIUM_color_buffer_float_rgb");
2789 TestFloatTextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT, texture, filter, render, data,
2790 data);
2791 }
2792 }
2793}
2794
2795TEST_P(WebGLCompatibilityTest, RGBA32FTextures)
2796{
2797 constexpr float data[] = {7000.0f, 100.0f, 33.0f, -1.0f};
2798
2799 for (auto extension : FloatingPointTextureExtensions)
2800 {
2801 if (strlen(extension) > 0 && extensionRequestable(extension))
2802 {
2803 glRequestExtensionANGLE(extension);
2804 ASSERT_GL_NO_ERROR();
2805 }
2806
2807 // Unsized RGBA 32F
2808 {
2809 bool texture = extensionEnabled("GL_OES_texture_float");
2810 bool filter = extensionEnabled("GL_OES_texture_float_linear");
Yuly Novikovd0828192018-06-15 15:51:07 -04002811 bool render = false;
Geoff Lang677bb6f2017-04-05 12:40:40 -04002812 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_FLOAT, texture, filter, render, data, data);
2813 }
2814
2815 if (getClientMajorVersion() >= 3 || extensionEnabled("GL_EXT_texture_storage"))
2816 {
2817 // Sized RGBA 32F
2818 bool texture =
2819 (getClientMajorVersion() >= 3) || (extensionEnabled("GL_OES_texture_float") &&
2820 extensionEnabled("GL_EXT_texture_storage"));
2821 bool filter = extensionEnabled("GL_OES_texture_float_linear");
2822 bool render = extensionEnabled("GL_EXT_color_buffer_float") ||
2823 extensionEnabled("GL_CHROMIUM_color_buffer_float_rgba");
2824 TestFloatTextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT, texture, filter, render, data,
2825 data);
2826 }
2827 }
2828}
2829
2830TEST_P(WebGLCompatibilityTest, R16FTextures)
2831{
2832 constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
2833 const GLushort textureData[] = {
2834 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2835 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2836
2837 for (auto extension : FloatingPointTextureExtensions)
2838 {
2839 if (strlen(extension) > 0 && extensionRequestable(extension))
2840 {
2841 glRequestExtensionANGLE(extension);
2842 ASSERT_GL_NO_ERROR();
2843 }
2844
2845 // Unsized R 16F (OES)
2846 {
2847 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2848 extensionEnabled("GL_EXT_texture_rg");
Yuly Novikovd0828192018-06-15 15:51:07 -04002849 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
2850 bool render = false;
Geoff Lang677bb6f2017-04-05 12:40:40 -04002851 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render,
2852 textureData, readPixelsData);
2853 }
2854
2855 // Unsized R 16F
2856 {
2857 bool texture = false;
2858 bool filter = false;
2859 bool render = false;
2860 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2861 textureData, readPixelsData);
2862 }
2863
Yuly Novikovd0828192018-06-15 15:51:07 -04002864 if (getClientMajorVersion() >= 3)
Geoff Lang677bb6f2017-04-05 12:40:40 -04002865 {
2866 // Sized R 16F
Yuly Novikovd0828192018-06-15 15:51:07 -04002867 bool texture = true;
2868 bool filter = true;
2869 bool render = extensionEnabled("GL_EXT_color_buffer_float");
Geoff Lang677bb6f2017-04-05 12:40:40 -04002870 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT, texture, filter, render,
2871 textureData, readPixelsData);
2872 }
Yuly Novikovd0828192018-06-15 15:51:07 -04002873 else if (extensionEnabled("GL_EXT_texture_storage"))
2874 {
2875 // Sized R 16F (OES)
2876 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2877 extensionEnabled("GL_EXT_texture_rg");
2878 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
2879 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2880 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render,
2881 textureData, readPixelsData);
2882 }
Geoff Lang677bb6f2017-04-05 12:40:40 -04002883 }
2884}
2885
2886TEST_P(WebGLCompatibilityTest, RG16FTextures)
2887{
2888 constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f};
2889 const GLushort textureData[] = {
2890 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2891 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2892
2893 for (auto extension : FloatingPointTextureExtensions)
2894 {
2895 if (strlen(extension) > 0 && extensionRequestable(extension))
2896 {
2897 glRequestExtensionANGLE(extension);
2898 ASSERT_GL_NO_ERROR();
2899 }
2900
2901 // Unsized RG 16F (OES)
2902 {
2903 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2904 extensionEnabled("GL_EXT_texture_rg");
Yuly Novikovd0828192018-06-15 15:51:07 -04002905 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
2906 bool render = false;
Geoff Lang677bb6f2017-04-05 12:40:40 -04002907 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render,
2908 textureData, readPixelsData);
2909 }
2910
2911 // Unsized RG 16F
2912 {
2913 bool texture = false;
2914 bool filter = false;
2915 bool render = false;
2916 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2917 textureData, readPixelsData);
2918 }
2919
Yuly Novikovd0828192018-06-15 15:51:07 -04002920 if (getClientMajorVersion() >= 3)
Geoff Lang677bb6f2017-04-05 12:40:40 -04002921 {
2922 // Sized RG 16F
Yuly Novikovd0828192018-06-15 15:51:07 -04002923 bool texture = true;
2924 bool filter = true;
2925 bool render = extensionEnabled("GL_EXT_color_buffer_float");
Geoff Lang677bb6f2017-04-05 12:40:40 -04002926 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT, texture, filter, render,
2927 textureData, readPixelsData);
2928 }
Yuly Novikovd0828192018-06-15 15:51:07 -04002929 else if (extensionEnabled("GL_EXT_texture_storage"))
2930 {
2931 // Sized RG 16F (OES)
2932 bool texture = extensionEnabled("GL_OES_texture_half_float") &&
2933 extensionEnabled("GL_EXT_texture_rg");
2934 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
2935 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2936 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render,
2937 textureData, readPixelsData);
2938 }
Geoff Lang677bb6f2017-04-05 12:40:40 -04002939 }
2940}
2941
2942TEST_P(WebGLCompatibilityTest, RGB16FTextures)
2943{
Yunchao He9550c602018-02-13 14:47:05 +08002944 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04002945
Geoff Lang677bb6f2017-04-05 12:40:40 -04002946 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f};
2947 const GLushort textureData[] = {
2948 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
2949 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
2950
2951 for (auto extension : FloatingPointTextureExtensions)
2952 {
2953 if (strlen(extension) > 0 && extensionRequestable(extension))
2954 {
2955 glRequestExtensionANGLE(extension);
2956 ASSERT_GL_NO_ERROR();
2957 }
2958
2959 // Unsized RGB 16F (OES)
2960 {
2961 bool texture = extensionEnabled("GL_OES_texture_half_float");
Yuly Novikovd0828192018-06-15 15:51:07 -04002962 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
2963 bool render = false;
Geoff Lang677bb6f2017-04-05 12:40:40 -04002964 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render,
2965 textureData, readPixelsData);
2966 }
2967
2968 // Unsized RGB 16F
2969 {
2970 bool texture = false;
2971 bool filter = false;
2972 bool render = false;
2973 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2974 textureData, readPixelsData);
2975 }
2976
Yuly Novikovd0828192018-06-15 15:51:07 -04002977 if (getClientMajorVersion() >= 3)
Geoff Lang677bb6f2017-04-05 12:40:40 -04002978 {
2979 // Sized RGB 16F
Yuly Novikovd0828192018-06-15 15:51:07 -04002980 bool texture = true;
2981 bool filter = true;
2982 // It is unclear how EXT_color_buffer_half_float applies to ES3.0 and above, however,
2983 // dEQP GLES3 es3fFboColorbufferTests.cpp verifies that texture attachment of GL_RGB16F
2984 // is possible, so assume that all GLES implementations support it.
Geoff Lang677bb6f2017-04-05 12:40:40 -04002985 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2986 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT, texture, filter, render,
2987 textureData, readPixelsData);
2988 }
Yuly Novikovd0828192018-06-15 15:51:07 -04002989 else if (extensionEnabled("GL_EXT_texture_storage"))
2990 {
2991 // Sized RGB 16F (OES)
2992 bool texture = extensionEnabled("GL_OES_texture_half_float");
2993 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
2994 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
2995 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render,
2996 textureData, readPixelsData);
2997 }
Geoff Lang677bb6f2017-04-05 12:40:40 -04002998 }
2999}
3000
3001TEST_P(WebGLCompatibilityTest, RGBA16FTextures)
3002{
Yunchao He9550c602018-02-13 14:47:05 +08003003 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
Geoff Lang40762ef2017-05-08 13:47:03 -04003004
Geoff Lang677bb6f2017-04-05 12:40:40 -04003005 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f};
3006 const GLushort textureData[] = {
3007 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
3008 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
3009
3010 for (auto extension : FloatingPointTextureExtensions)
3011 {
3012 if (strlen(extension) > 0 && extensionRequestable(extension))
3013 {
3014 glRequestExtensionANGLE(extension);
3015 ASSERT_GL_NO_ERROR();
3016 }
3017
3018 // Unsized RGBA 16F (OES)
3019 {
3020 bool texture = extensionEnabled("GL_OES_texture_half_float");
Yuly Novikovd0828192018-06-15 15:51:07 -04003021 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
3022 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
Geoff Lang677bb6f2017-04-05 12:40:40 -04003023 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render,
3024 textureData, readPixelsData);
3025 }
3026
3027 // Unsized RGBA 16F
3028 {
3029 bool texture = false;
3030 bool filter = false;
3031 bool render = false;
3032 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
3033 textureData, readPixelsData);
3034 }
3035
Yuly Novikovd0828192018-06-15 15:51:07 -04003036 if (getClientMajorVersion() >= 3)
Geoff Lang677bb6f2017-04-05 12:40:40 -04003037 {
3038 // Sized RGBA 16F
Yuly Novikovd0828192018-06-15 15:51:07 -04003039 bool texture = true;
3040 bool filter = true;
3041 bool render = extensionEnabled("GL_EXT_color_buffer_float");
Geoff Lang677bb6f2017-04-05 12:40:40 -04003042 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, texture, filter, render,
3043 textureData, readPixelsData);
3044 }
Yuly Novikovd0828192018-06-15 15:51:07 -04003045 else if (extensionEnabled("GL_EXT_texture_storage"))
3046 {
3047 // Sized RGBA 16F (OES)
3048 bool texture = extensionEnabled("GL_OES_texture_half_float");
3049 bool filter = extensionEnabled("GL_OES_texture_half_float_linear");
3050 bool render = extensionEnabled("GL_EXT_color_buffer_half_float");
3051 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render,
3052 textureData, readPixelsData);
3053 }
Geoff Lang677bb6f2017-04-05 12:40:40 -04003054 }
3055}
3056
Geoff Lang6e898aa2017-06-02 11:17:26 -04003057// Test that when GL_CHROMIUM_color_buffer_float_rgb[a] is enabled, sized GL_RGB[A]_32F formats are
3058// accepted by glTexImage2D
3059TEST_P(WebGLCompatibilityTest, SizedRGBA32FFormats)
3060{
Yunchao He9550c602018-02-13 14:47:05 +08003061 // Test skipped because it is only valid for WebGL1 contexts.
3062 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
Geoff Lang6e898aa2017-06-02 11:17:26 -04003063
Yunchao He9550c602018-02-13 14:47:05 +08003064 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_OES_texture_float"));
3065
Geoff Lang6e898aa2017-06-02 11:17:26 -04003066 glRequestExtensionANGLE("GL_OES_texture_float");
3067 ASSERT_GL_NO_ERROR();
3068
3069 GLTexture texture;
3070 glBindTexture(GL_TEXTURE_2D, texture);
3071
3072 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
3073 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3074
3075 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
3076 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3077
3078 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgba"))
3079 {
3080 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgba");
3081 ASSERT_GL_NO_ERROR();
3082
3083 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
3084 EXPECT_GL_NO_ERROR();
3085 }
3086
3087 if (extensionRequestable("GL_CHROMIUM_color_buffer_float_rgb"))
3088 {
3089 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgb");
3090 ASSERT_GL_NO_ERROR();
3091
3092 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr);
3093 EXPECT_GL_NO_ERROR();
3094 }
3095}
3096
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003097// Verify GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point.
3098TEST_P(WebGLCompatibilityTest, DepthStencilAttachment)
3099{
3100 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
3101
3102 // Test that attaching a bound texture succeeds.
3103 GLTexture texture;
3104 glBindTexture(GL_TEXTURE_2D, texture);
3105
3106 GLFramebuffer fbo;
3107 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3108
3109 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
3110
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003111 GLint attachmentType = 0;
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003112 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003113 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003114 EXPECT_GL_NO_ERROR();
3115 EXPECT_GLENUM_EQ(GL_TEXTURE, attachmentType);
3116
3117 // Test when if no attach object at the named attachment point and pname is not OBJECT_TYPE.
3118 GLFramebuffer fbo2;
3119 glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
3120
3121 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003122 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attachmentType);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003123 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3124}
3125
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003126// Verify framebuffer attachments return expected types when in an inconsistant state.
3127TEST_P(WebGLCompatibilityTest, FramebufferAttachmentConsistancy)
3128{
3129 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
3130
3131 GLFramebuffer fbo;
3132 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3133
3134 GLRenderbuffer rb1;
3135 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
3136
3137 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb1);
3138
3139 GLint attachmentType = 0;
3140 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
3141 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3142
3143 EXPECT_GL_NO_ERROR();
3144 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
3145
3146 GLRenderbuffer rb2;
3147 glBindRenderbuffer(GL_RENDERBUFFER, rb2);
3148
3149 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2);
3150
3151 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
3152 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3153
3154 EXPECT_GL_NO_ERROR();
3155 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -08003156
3157 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb2);
3158
3159 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
3160 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3161
3162 EXPECT_GL_NO_ERROR();
3163 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
3164
3165 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2);
3166
3167 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
3168 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
3169
3170 EXPECT_GL_NO_ERROR();
3171 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType);
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003172}
3173
Jamie Madill07be8bf2017-02-02 19:59:57 -05003174// This tests that rendering feedback loops works as expected with WebGL 2.
3175// Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html
3176TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers)
3177{
Jamie Madill35cd7332018-12-02 12:03:33 -05003178 constexpr char kVS[] =
Jamie Madill07be8bf2017-02-02 19:59:57 -05003179 "#version 300 es\n"
3180 "in vec4 aPosition;\n"
3181 "out vec2 texCoord;\n"
3182 "void main() {\n"
3183 " gl_Position = aPosition;\n"
3184 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
3185 "}\n";
3186
Jamie Madill35cd7332018-12-02 12:03:33 -05003187 constexpr char kFS[] =
Jamie Madill07be8bf2017-02-02 19:59:57 -05003188 "#version 300 es\n"
3189 "precision mediump float;\n"
3190 "uniform sampler2D tex;\n"
3191 "in vec2 texCoord;\n"
3192 "out vec4 oColor;\n"
3193 "void main() {\n"
3194 " oColor = texture(tex, texCoord);\n"
3195 "}\n";
3196
3197 GLsizei width = 8;
3198 GLsizei height = 8;
3199
3200 GLint maxDrawBuffers = 0;
3201 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3202 // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS.
3203 ASSERT_GE(maxDrawBuffers, 2);
3204
Jamie Madill35cd7332018-12-02 12:03:33 -05003205 ANGLE_GL_PROGRAM(program, kVS, kFS);
Jamie Madill07be8bf2017-02-02 19:59:57 -05003206 glUseProgram(program.get());
3207 glViewport(0, 0, width, height);
3208
3209 GLTexture tex0;
3210 GLTexture tex1;
3211 GLFramebuffer fbo;
3212 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3213 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3214 ASSERT_GL_NO_ERROR();
3215
3216 glBindTexture(GL_TEXTURE_2D, tex1.get());
3217 GLint texLoc = glGetUniformLocation(program.get(), "tex");
3218 ASSERT_NE(-1, texLoc);
3219 glUniform1i(texLoc, 0);
3220
3221 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
3222 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
3223 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
3224 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
3225 ASSERT_GL_NO_ERROR();
3226
3227 drawBuffersFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION);
3228 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
3229 GL_INVALID_OPERATION);
3230 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
3231}
3232
Jamie Madill1d37bc52017-02-02 19:59:58 -05003233// This test covers detection of rendering feedback loops between the FBO and a depth Texture.
3234// Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html
3235TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil)
3236{
Jamie Madill35cd7332018-12-02 12:03:33 -05003237 constexpr char kVS[] =
Jamie Madill1d37bc52017-02-02 19:59:58 -05003238 "#version 300 es\n"
3239 "in vec4 aPosition;\n"
3240 "out vec2 texCoord;\n"
3241 "void main() {\n"
3242 " gl_Position = aPosition;\n"
3243 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
3244 "}\n";
3245
Jamie Madill35cd7332018-12-02 12:03:33 -05003246 constexpr char kFS[] =
Jamie Madill1d37bc52017-02-02 19:59:58 -05003247 "#version 300 es\n"
3248 "precision mediump float;\n"
3249 "uniform sampler2D tex;\n"
3250 "in vec2 texCoord;\n"
3251 "out vec4 oColor;\n"
3252 "void main() {\n"
3253 " oColor = texture(tex, texCoord);\n"
3254 "}\n";
3255
3256 GLsizei width = 8;
3257 GLsizei height = 8;
3258
Jamie Madill35cd7332018-12-02 12:03:33 -05003259 ANGLE_GL_PROGRAM(program, kVS, kFS);
Jamie Madill1d37bc52017-02-02 19:59:58 -05003260 glUseProgram(program.get());
3261
3262 glViewport(0, 0, width, height);
3263
3264 GLint texLoc = glGetUniformLocation(program.get(), "tex");
3265 glUniform1i(texLoc, 0);
3266
3267 // Create textures and allocate storage
3268 GLTexture tex0;
3269 GLTexture tex1;
Jamie Madill0fdb9562018-09-17 17:18:43 -04003270 GLTexture tex2;
Jamie Madill1d37bc52017-02-02 19:59:58 -05003271 FillTexture2D(tex0.get(), width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3272 FillTexture2D(tex1.get(), width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
3273 GL_UNSIGNED_INT);
Jamie Madill0fdb9562018-09-17 17:18:43 -04003274 FillTexture2D(tex2.get(), width, height, 0x40, 0, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL,
3275 GL_UNSIGNED_INT_24_8);
Jamie Madill1d37bc52017-02-02 19:59:58 -05003276 ASSERT_GL_NO_ERROR();
3277
3278 GLFramebuffer fbo;
3279 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
3280 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
3281
3282 // Test rendering and sampling feedback loop for depth buffer
3283 glBindTexture(GL_TEXTURE_2D, tex1.get());
3284 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1.get(), 0);
3285 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3286
3287 // The same image is used as depth buffer during rendering.
3288 glEnable(GL_DEPTH_TEST);
3289 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
Jamie Madill0fdb9562018-09-17 17:18:43 -04003290 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Same image as depth buffer should fail";
Jamie Madill1d37bc52017-02-02 19:59:58 -05003291
3292 // The same image is used as depth buffer. But depth mask is false.
Jamie Madill38fe6842018-09-19 07:20:00 -04003293 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695
Jamie Madill1d37bc52017-02-02 19:59:58 -05003294 glDepthMask(GL_FALSE);
3295 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
Jamie Madill38fe6842018-09-19 07:20:00 -04003296 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth writes disabled should still fail";
Jamie Madill1d37bc52017-02-02 19:59:58 -05003297
3298 // The same image is used as depth buffer. But depth test is not enabled during rendering.
Jamie Madill38fe6842018-09-19 07:20:00 -04003299 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695
Jamie Madill1d37bc52017-02-02 19:59:58 -05003300 glDepthMask(GL_TRUE);
3301 glDisable(GL_DEPTH_TEST);
3302 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
Jamie Madill38fe6842018-09-19 07:20:00 -04003303 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth read disabled should still fail";
Jamie Madill1d37bc52017-02-02 19:59:58 -05003304
3305 // Test rendering and sampling feedback loop for stencil buffer
Jamie Madill0fdb9562018-09-17 17:18:43 -04003306 glBindTexture(GL_TEXTURE_2D, tex2.get());
Jamie Madill1d37bc52017-02-02 19:59:58 -05003307 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
Jamie Madill0fdb9562018-09-17 17:18:43 -04003308 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex2.get(), 0);
Jamie Madill1d37bc52017-02-02 19:59:58 -05003309 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3310 constexpr GLint stencilClearValue = 0x40;
3311 glClearBufferiv(GL_STENCIL, 0, &stencilClearValue);
3312
3313 // The same image is used as stencil buffer during rendering.
3314 glEnable(GL_STENCIL_TEST);
3315 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
Jamie Madill0fdb9562018-09-17 17:18:43 -04003316 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Same image as stencil buffer should fail";
Jamie Madill1d37bc52017-02-02 19:59:58 -05003317
3318 // The same image is used as stencil buffer. But stencil mask is zero.
Jamie Madill38fe6842018-09-19 07:20:00 -04003319 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695
Jamie Madill1d37bc52017-02-02 19:59:58 -05003320 glStencilMask(0x0);
3321 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
Jamie Madill38fe6842018-09-19 07:20:00 -04003322 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Stencil mask zero should still fail";
Jamie Madill1d37bc52017-02-02 19:59:58 -05003323
3324 // The same image is used as stencil buffer. But stencil test is not enabled during rendering.
Jamie Madill38fe6842018-09-19 07:20:00 -04003325 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695
Jamie Madill1d37bc52017-02-02 19:59:58 -05003326 glStencilMask(0xffff);
3327 glDisable(GL_STENCIL_TEST);
3328 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
Jamie Madill38fe6842018-09-19 07:20:00 -04003329 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Stencil test disabled should still fail";
Jamie Madill1d37bc52017-02-02 19:59:58 -05003330}
3331
Jamie Madillfd3dd432017-02-02 19:59:59 -05003332// The source and the target for CopyTexSubImage3D are the same 3D texture.
3333// But the level of the 3D texture != the level of the read attachment.
3334TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels)
3335{
3336 GLTexture texture;
3337 GLFramebuffer framebuffer;
3338
3339 glBindTexture(GL_TEXTURE_3D, texture.get());
3340 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3341
3342 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3343 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3344 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
3345 ASSERT_GL_NO_ERROR();
3346
3347 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3348 EXPECT_GL_NO_ERROR();
3349}
3350
3351// The source and the target for CopyTexSubImage3D are the same 3D texture.
3352// But the zoffset of the 3D texture != the layer of the read attachment.
3353TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers)
3354{
3355 GLTexture texture;
3356 GLFramebuffer framebuffer;
3357
3358 glBindTexture(GL_TEXTURE_3D, texture.get());
3359 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3360
3361 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3362 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 1);
3363 ASSERT_GL_NO_ERROR();
3364
3365 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2);
3366 EXPECT_GL_NO_ERROR();
3367}
3368
3369// The source and the target for CopyTexSubImage3D are the same 3D texture.
3370// And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment.
3371TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D)
3372{
3373 GLTexture texture;
3374 GLFramebuffer framebuffer;
3375
3376 glBindTexture(GL_TEXTURE_3D, texture.get());
3377 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3378
3379 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3380 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3381 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3382 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 1, 0);
3383 ASSERT_GL_NO_ERROR();
3384
3385 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
3386 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3387}
3388
Corentin Wallez59c41592017-07-11 13:19:54 -04003389// Verify that errors are generated when there isn't a defined conversion between the clear type and
3390// the buffer type.
Geoff Lang76e65652017-03-27 14:58:02 -04003391TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity)
3392{
Yunchao He9550c602018-02-13 14:47:05 +08003393 // Test skipped for D3D11 because it generates D3D11 runtime warnings.
3394 ANGLE_SKIP_TEST_IF(IsD3D11());
Geoff Lang76e65652017-03-27 14:58:02 -04003395
3396 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3397 constexpr int clearInt[] = {0, 0, 0, 0};
3398 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3399
3400 GLTexture texture;
3401 GLFramebuffer framebuffer;
3402
3403 glBindTexture(GL_TEXTURE_2D, texture.get());
3404 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3405
3406 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
3407 ASSERT_GL_NO_ERROR();
3408
3409 // Unsigned integer buffer
3410 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr);
3411 ASSERT_GL_NO_ERROR();
3412
3413 glClearBufferfv(GL_COLOR, 0, clearFloat);
3414 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3415
3416 glClearBufferiv(GL_COLOR, 0, clearInt);
3417 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3418
3419 glClearBufferuiv(GL_COLOR, 0, clearUint);
3420 EXPECT_GL_NO_ERROR();
3421
3422 glClear(GL_COLOR_BUFFER_BIT);
3423 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3424
3425 // Integer buffer
3426 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr);
3427 ASSERT_GL_NO_ERROR();
3428
3429 glClearBufferfv(GL_COLOR, 0, clearFloat);
3430 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3431
3432 glClearBufferiv(GL_COLOR, 0, clearInt);
3433 EXPECT_GL_NO_ERROR();
3434
3435 glClearBufferuiv(GL_COLOR, 0, clearUint);
3436 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3437
3438 glClear(GL_COLOR_BUFFER_BIT);
3439 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3440
3441 // Float buffer
Geoff Lang677bb6f2017-04-05 12:40:40 -04003442 if (extensionRequestable("GL_EXT_color_buffer_float"))
3443 {
3444 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
3445 }
Geoff Lang76e65652017-03-27 14:58:02 -04003446
Geoff Lang677bb6f2017-04-05 12:40:40 -04003447 if (extensionEnabled("GL_EXT_color_buffer_float"))
3448 {
3449 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
3450 ASSERT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003451
Geoff Lang677bb6f2017-04-05 12:40:40 -04003452 glClearBufferfv(GL_COLOR, 0, clearFloat);
3453 EXPECT_GL_NO_ERROR();
Geoff Lang76e65652017-03-27 14:58:02 -04003454
Geoff Lang677bb6f2017-04-05 12:40:40 -04003455 glClearBufferiv(GL_COLOR, 0, clearInt);
3456 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang76e65652017-03-27 14:58:02 -04003457
Geoff Lang677bb6f2017-04-05 12:40:40 -04003458 glClearBufferuiv(GL_COLOR, 0, clearUint);
3459 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3460
3461 glClear(GL_COLOR_BUFFER_BIT);
3462 EXPECT_GL_NO_ERROR();
3463 }
Geoff Lang76e65652017-03-27 14:58:02 -04003464
3465 // Normalized uint buffer
3466 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3467 ASSERT_GL_NO_ERROR();
3468
3469 glClearBufferfv(GL_COLOR, 0, clearFloat);
3470 EXPECT_GL_NO_ERROR();
3471
3472 glClearBufferiv(GL_COLOR, 0, clearInt);
3473 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3474
3475 glClearBufferuiv(GL_COLOR, 0, clearUint);
3476 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3477
3478 glClear(GL_COLOR_BUFFER_BIT);
3479 EXPECT_GL_NO_ERROR();
3480}
3481
Corentin Wallez59c41592017-07-11 13:19:54 -04003482// Test the interaction of WebGL compatibility clears with default framebuffers
3483TEST_P(WebGL2CompatibilityTest, ClearBufferDefaultFramebuffer)
3484{
3485 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
3486 constexpr int clearInt[] = {0, 0, 0, 0};
3487 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
3488
3489 // glClear works as usual, this is also a regression test for a bug where we
3490 // iterated on maxDrawBuffers for default framebuffers, triggering an assert
3491 glClear(GL_COLOR_BUFFER_BIT);
3492 EXPECT_GL_NO_ERROR();
3493
3494 // Default framebuffers are normalized uints, so only glClearBufferfv works.
3495 glClearBufferfv(GL_COLOR, 0, clearFloat);
3496 EXPECT_GL_NO_ERROR();
3497
3498 glClearBufferiv(GL_COLOR, 0, clearInt);
3499 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3500
3501 glClearBufferuiv(GL_COLOR, 0, clearUint);
3502 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3503}
3504
Geoff Lange4915782017-04-12 15:19:07 -04003505// Verify that errors are generate when trying to blit from an image to itself
3506TEST_P(WebGL2CompatibilityTest, BlitFramebufferSameImage)
3507{
3508 GLTexture textures[2];
3509 glBindTexture(GL_TEXTURE_2D, textures[0]);
3510 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3511 glBindTexture(GL_TEXTURE_2D, textures[1]);
3512 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4);
3513
3514 GLRenderbuffer renderbuffers[2];
3515 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
3516 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3517 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
3518 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4);
3519
3520 GLFramebuffer framebuffers[2];
3521 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]);
3522 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]);
3523
3524 ASSERT_GL_NO_ERROR();
3525
3526 // Same texture
3527 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3528 0);
3529 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3530 0);
3531 ASSERT_GL_NO_ERROR();
3532 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3533 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3534
3535 // Same textures but different renderbuffers
3536 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3537 renderbuffers[0]);
3538 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3539 renderbuffers[1]);
3540 ASSERT_GL_NO_ERROR();
3541 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3542 ASSERT_GL_NO_ERROR();
3543 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3544 GL_NEAREST);
3545 ASSERT_GL_NO_ERROR();
3546 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3547 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3548 GL_NEAREST);
3549 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3550
3551 // Same renderbuffers but different textures
3552 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0],
3553 0);
3554 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1],
3555 0);
3556 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3557 renderbuffers[0]);
3558 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3559 renderbuffers[0]);
3560 ASSERT_GL_NO_ERROR();
3561 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3562 ASSERT_GL_NO_ERROR();
3563 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3564 GL_NEAREST);
3565 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3566 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4,
3567 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
3568 GL_NEAREST);
3569 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
3570}
3571
Geoff Lange0cff192017-05-30 13:04:56 -04003572// Verify that errors are generated when the fragment shader output doesn't match the bound color
3573// buffer types
3574TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch)
3575{
Jamie Madill35cd7332018-12-02 12:03:33 -05003576 constexpr char kVS[] =
Geoff Lange0cff192017-05-30 13:04:56 -04003577 "#version 300 es\n"
3578 "void main() {\n"
3579 " gl_Position = vec4(0, 0, 0, 1);\n"
3580 "}\n";
3581
Jamie Madill35cd7332018-12-02 12:03:33 -05003582 constexpr char kFS[] =
Geoff Lange0cff192017-05-30 13:04:56 -04003583 "#version 300 es\n"
3584 "precision mediump float;\n"
3585 "layout(location = 0) out vec4 floatOutput;\n"
3586 "layout(location = 1) out uvec4 uintOutput;\n"
3587 "layout(location = 2) out ivec4 intOutput;\n"
3588 "void main() {\n"
3589 " floatOutput = vec4(0, 0, 0, 1);\n"
3590 " uintOutput = uvec4(0, 0, 0, 1);\n"
3591 " intOutput = ivec4(0, 0, 0, 1);\n"
3592 "}\n";
3593
Jamie Madill35cd7332018-12-02 12:03:33 -05003594 ANGLE_GL_PROGRAM(program, kVS, kFS);
Geoff Lange0cff192017-05-30 13:04:56 -04003595 glUseProgram(program.get());
3596
3597 GLuint floatLocation = glGetFragDataLocation(program, "floatOutput");
3598 GLuint uintLocation = glGetFragDataLocation(program, "uintOutput");
3599 GLuint intLocation = glGetFragDataLocation(program, "intOutput");
3600
3601 GLFramebuffer fbo;
3602 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3603
3604 GLRenderbuffer floatRenderbuffer;
3605 glBindRenderbuffer(GL_RENDERBUFFER, floatRenderbuffer);
3606 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
3607 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3608 floatRenderbuffer);
3609
3610 GLRenderbuffer uintRenderbuffer;
3611 glBindRenderbuffer(GL_RENDERBUFFER, uintRenderbuffer);
3612 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 1, 1);
3613 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3614 uintRenderbuffer);
3615
3616 GLRenderbuffer intRenderbuffer;
3617 glBindRenderbuffer(GL_RENDERBUFFER, intRenderbuffer);
3618 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 1, 1);
3619 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3620 intRenderbuffer);
3621
3622 ASSERT_GL_NO_ERROR();
3623
3624 GLint maxDrawBuffers = 0;
3625 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
3626 std::vector<GLenum> drawBuffers(static_cast<size_t>(maxDrawBuffers), GL_NONE);
3627 drawBuffers[floatLocation] = GL_COLOR_ATTACHMENT0 + floatLocation;
3628 drawBuffers[uintLocation] = GL_COLOR_ATTACHMENT0 + uintLocation;
3629 drawBuffers[intLocation] = GL_COLOR_ATTACHMENT0 + intLocation;
3630
3631 glDrawBuffers(maxDrawBuffers, drawBuffers.data());
3632
3633 // Check that the correct case generates no errors
3634 glDrawArrays(GL_TRIANGLES, 0, 6);
3635 EXPECT_GL_NO_ERROR();
3636
3637 // Unbind some buffers and verify that there are still no errors
3638 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3639 0);
3640 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3641 0);
3642 glDrawArrays(GL_TRIANGLES, 0, 6);
3643 EXPECT_GL_NO_ERROR();
3644
3645 // Swap the int and uint buffers to and verify that an error is generated
3646 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3647 intRenderbuffer);
3648 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3649 uintRenderbuffer);
3650 glDrawArrays(GL_TRIANGLES, 0, 6);
3651 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3652
3653 // Swap the float and uint buffers to and verify that an error is generated
3654 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER,
3655 floatRenderbuffer);
3656 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER,
3657 uintRenderbuffer);
3658 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER,
3659 intRenderbuffer);
3660 glDrawArrays(GL_TRIANGLES, 0, 6);
3661 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3662}
3663
Geoff Lang9ab5b822017-05-30 16:19:23 -04003664// Verify that errors are generated when the vertex shader intput doesn't match the bound attribute
3665// types
Corentin Wallezc3bc9842017-10-11 15:15:59 -04003666TEST_P(WebGL2CompatibilityTest, VertexShaderAttributeTypeMismatch)
Geoff Lang9ab5b822017-05-30 16:19:23 -04003667{
Jamie Madill35cd7332018-12-02 12:03:33 -05003668 constexpr char kVS[] =
Geoff Lang9ab5b822017-05-30 16:19:23 -04003669 "#version 300 es\n"
3670 "in vec4 floatInput;\n"
3671 "in uvec4 uintInput;\n"
3672 "in ivec4 intInput;\n"
3673 "void main() {\n"
3674 " gl_Position = vec4(floatInput.x, uintInput.x, intInput.x, 1);\n"
3675 "}\n";
3676
Jamie Madill35cd7332018-12-02 12:03:33 -05003677 constexpr char kFS[] =
Geoff Lang9ab5b822017-05-30 16:19:23 -04003678 "#version 300 es\n"
3679 "precision mediump float;\n"
3680 "out vec4 outputColor;\n"
3681 "void main() {\n"
3682 " outputColor = vec4(0, 0, 0, 1);"
3683 "}\n";
3684
Jamie Madill35cd7332018-12-02 12:03:33 -05003685 ANGLE_GL_PROGRAM(program, kVS, kFS);
Geoff Lang9ab5b822017-05-30 16:19:23 -04003686 glUseProgram(program.get());
3687
3688 GLint floatLocation = glGetAttribLocation(program, "floatInput");
3689 GLint uintLocation = glGetAttribLocation(program, "uintInput");
3690 GLint intLocation = glGetAttribLocation(program, "intInput");
3691
3692 // Default attributes are of float types
3693 glDrawArrays(GL_TRIANGLES, 0, 6);
3694 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3695
3696 // Set the default attributes to the correct types, should succeed
3697 glVertexAttribI4ui(uintLocation, 0, 0, 0, 1);
3698 glVertexAttribI4i(intLocation, 0, 0, 0, 1);
3699 glDrawArrays(GL_TRIANGLES, 0, 6);
3700 EXPECT_GL_NO_ERROR();
3701
3702 // Change the default float attribute to an integer, should fail
3703 glVertexAttribI4ui(floatLocation, 0, 0, 0, 1);
3704 glDrawArrays(GL_TRIANGLES, 0, 6);
3705 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3706
3707 // Use a buffer for some attributes
3708 GLBuffer buffer;
3709 glBindBuffer(GL_ARRAY_BUFFER, buffer);
3710 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
3711 glEnableVertexAttribArray(floatLocation);
3712 glVertexAttribPointer(floatLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3713 glDrawArrays(GL_TRIANGLES, 0, 6);
3714 EXPECT_GL_NO_ERROR();
3715
3716 // Use a float pointer attrib for a uint input
3717 glEnableVertexAttribArray(uintLocation);
3718 glVertexAttribPointer(uintLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
3719 glDrawArrays(GL_TRIANGLES, 0, 6);
3720 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3721
3722 // Use a uint pointer for the uint input
3723 glVertexAttribIPointer(uintLocation, 4, GL_UNSIGNED_INT, 0, nullptr);
3724 glDrawArrays(GL_TRIANGLES, 0, 6);
3725 EXPECT_GL_NO_ERROR();
3726}
3727
Geoff Langfa125c92017-10-24 13:01:46 -04003728// Test that it's not possible to query the non-zero color attachments without the drawbuffers
3729// extension in WebGL1
3730TEST_P(WebGLCompatibilityTest, FramebufferAttachmentQuery)
3731{
3732 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2);
3733 ANGLE_SKIP_TEST_IF(extensionEnabled("GL_EXT_draw_buffers"));
3734
3735 GLFramebuffer fbo;
3736 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3737 EXPECT_GL_NO_ERROR();
3738
3739 GLint result;
3740 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
3741 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &result);
3742 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3743
3744 GLRenderbuffer renderbuffer;
3745 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3746 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
3747 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderbuffer);
3748 EXPECT_GL_ERROR(GL_INVALID_ENUM);
3749}
3750
Corentin Walleze7557742017-06-01 13:09:57 -04003751// Tests the WebGL removal of undefined behavior when attachments aren't written to.
3752TEST_P(WebGLCompatibilityTest, DrawBuffers)
3753{
Corentin Walleze7557742017-06-01 13:09:57 -04003754 // Make sure we can use at least 4 attachments for the tests.
3755 bool useEXT = false;
3756 if (getClientMajorVersion() < 3)
3757 {
Yunchao He9550c602018-02-13 14:47:05 +08003758 ANGLE_SKIP_TEST_IF(!extensionRequestable("GL_EXT_draw_buffers"));
Corentin Walleze7557742017-06-01 13:09:57 -04003759
3760 glRequestExtensionANGLE("GL_EXT_draw_buffers");
3761 useEXT = true;
3762 EXPECT_GL_NO_ERROR();
3763 }
3764
3765 GLint maxDrawBuffers = 0;
3766 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
Yunchao He9550c602018-02-13 14:47:05 +08003767 // Test skipped because MAX_DRAW_BUFFERS is too small.
3768 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4);
Corentin Walleze7557742017-06-01 13:09:57 -04003769
3770 // Clears all the renderbuffers to red.
3771 auto ClearEverythingToRed = [](GLRenderbuffer *renderbuffers) {
3772 GLFramebuffer clearFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003773 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003774
3775 glClearColor(1, 0, 0, 1);
3776 for (int i = 0; i < 4; ++i)
3777 {
Geoff Lange8afa902017-09-27 15:00:43 -04003778 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
Corentin Walleze7557742017-06-01 13:09:57 -04003779 renderbuffers[i]);
3780 glClear(GL_COLOR_BUFFER_BIT);
3781 }
3782 ASSERT_GL_NO_ERROR();
3783 };
3784
3785 // Checks that the renderbuffers specified by mask have the correct color
3786 auto CheckColors = [](GLRenderbuffer *renderbuffers, int mask, GLColor color) {
3787 GLFramebuffer readFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003788 glBindFramebuffer(GL_FRAMEBUFFER, readFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003789
3790 for (int i = 0; i < 4; ++i)
3791 {
3792 if (mask & (1 << i))
3793 {
Geoff Lange8afa902017-09-27 15:00:43 -04003794 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
3795 renderbuffers[i]);
Corentin Walleze7557742017-06-01 13:09:57 -04003796 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
3797 }
3798 }
3799 ASSERT_GL_NO_ERROR();
3800 };
3801
3802 // Depending on whether we are using the extension or ES3, a different entrypoint must be called
3803 auto DrawBuffers = [](bool useEXT, int numBuffers, GLenum *buffers) {
3804 if (useEXT)
3805 {
3806 glDrawBuffersEXT(numBuffers, buffers);
3807 }
3808 else
3809 {
3810 glDrawBuffers(numBuffers, buffers);
3811 }
3812 };
3813
3814 // Initialized the test framebuffer
3815 GLFramebuffer drawFBO;
Geoff Lange8afa902017-09-27 15:00:43 -04003816 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003817
3818 GLRenderbuffer renderbuffers[4];
3819 for (int i = 0; i < 4; ++i)
3820 {
3821 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
Geoff Langd84a00b2017-10-27 17:27:26 -04003822 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
Geoff Lange8afa902017-09-27 15:00:43 -04003823 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER,
Corentin Walleze7557742017-06-01 13:09:57 -04003824 renderbuffers[i]);
3825 }
3826
3827 ASSERT_GL_NO_ERROR();
3828
Corentin Walleze7557742017-06-01 13:09:57 -04003829 GLenum allDrawBuffers[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05003830 GL_COLOR_ATTACHMENT0,
3831 GL_COLOR_ATTACHMENT1,
3832 GL_COLOR_ATTACHMENT2,
3833 GL_COLOR_ATTACHMENT3,
Corentin Walleze7557742017-06-01 13:09:57 -04003834 };
3835
3836 GLenum halfDrawBuffers[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05003837 GL_NONE,
3838 GL_NONE,
3839 GL_COLOR_ATTACHMENT2,
3840 GL_COLOR_ATTACHMENT3,
Corentin Walleze7557742017-06-01 13:09:57 -04003841 };
3842
3843 // Test that when using gl_FragColor, only the first attachment is written to.
3844 const char *fragESSL1 =
3845 "precision highp float;\n"
3846 "void main()\n"
3847 "{\n"
3848 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
3849 "}\n";
Olli Etuaho5804dc82018-04-13 14:11:46 +03003850 ANGLE_GL_PROGRAM(programESSL1, essl1_shaders::vs::Simple(), fragESSL1);
Corentin Walleze7557742017-06-01 13:09:57 -04003851
3852 {
3853 ClearEverythingToRed(renderbuffers);
3854
Geoff Lange8afa902017-09-27 15:00:43 -04003855 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003856 DrawBuffers(useEXT, 4, allDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003857 drawQuad(programESSL1, essl1_shaders::PositionAttrib(), 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003858 ASSERT_GL_NO_ERROR();
3859
3860 CheckColors(renderbuffers, 0b0001, GLColor::green);
3861 CheckColors(renderbuffers, 0b1110, GLColor::red);
3862 }
3863
3864 // Test that when using gl_FragColor, but the first draw buffer is 0, then no attachment is
3865 // written to.
3866 {
3867 ClearEverythingToRed(renderbuffers);
3868
Geoff Lange8afa902017-09-27 15:00:43 -04003869 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003870 DrawBuffers(useEXT, 4, halfDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003871 drawQuad(programESSL1, essl1_shaders::PositionAttrib(), 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003872 ASSERT_GL_NO_ERROR();
3873
3874 CheckColors(renderbuffers, 0b1111, GLColor::red);
3875 }
3876
3877 // Test what happens when rendering to a subset of the outputs. There is a behavior difference
3878 // between the extension and ES3. In the extension gl_FragData is implicitly declared as an
3879 // array of size MAX_DRAW_BUFFERS, so the WebGL spec stipulates that elements not written to
3880 // should default to 0. On the contrary, in ES3 outputs are specified one by one, so
3881 // attachments not declared in the shader should not be written to.
Olli Etuaho5804dc82018-04-13 14:11:46 +03003882 const char *positionAttrib;
Corentin Walleze7557742017-06-01 13:09:57 -04003883 const char *writeOddOutputsVert;
3884 const char *writeOddOutputsFrag;
3885 GLColor unwrittenColor;
3886 if (useEXT)
3887 {
3888 // In the extension, when an attachment isn't written to, it should get 0's
3889 unwrittenColor = GLColor(0, 0, 0, 0);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003890 positionAttrib = essl1_shaders::PositionAttrib();
3891 writeOddOutputsVert = essl1_shaders::vs::Simple();
Corentin Walleze7557742017-06-01 13:09:57 -04003892 writeOddOutputsFrag =
3893 "#extension GL_EXT_draw_buffers : require\n"
3894 "precision highp float;\n"
3895 "void main()\n"
3896 "{\n"
3897 " gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3898 " gl_FragData[3] = vec4(0.0, 1.0, 0.0, 1.0);\n"
3899 "}\n";
3900 }
3901 else
3902 {
3903 // In ES3 if an attachment isn't declared, it shouldn't get written and should be red
3904 // because of the preceding clears.
3905 unwrittenColor = GLColor::red;
Olli Etuaho5804dc82018-04-13 14:11:46 +03003906 positionAttrib = essl3_shaders::PositionAttrib();
3907 writeOddOutputsVert = essl3_shaders::vs::Simple();
Corentin Walleze7557742017-06-01 13:09:57 -04003908 writeOddOutputsFrag =
3909 "#version 300 es\n"
3910 "precision highp float;\n"
3911 "layout(location = 1) out vec4 output1;"
3912 "layout(location = 3) out vec4 output2;"
3913 "void main()\n"
3914 "{\n"
3915 " output1 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3916 " output2 = vec4(0.0, 1.0, 0.0, 1.0);\n"
3917 "}\n";
3918 }
3919 ANGLE_GL_PROGRAM(writeOddOutputsProgram, writeOddOutputsVert, writeOddOutputsFrag);
3920
3921 // Test that attachments not written to get the "unwritten" color
3922 {
3923 ClearEverythingToRed(renderbuffers);
3924
Geoff Lange8afa902017-09-27 15:00:43 -04003925 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003926 DrawBuffers(useEXT, 4, allDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003927 drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003928 ASSERT_GL_NO_ERROR();
3929
3930 CheckColors(renderbuffers, 0b1010, GLColor::green);
3931 CheckColors(renderbuffers, 0b0101, unwrittenColor);
3932 }
3933
3934 // Test that attachments not written to get the "unwritten" color but that even when the
3935 // extension is used, disabled attachments are not written at all and stay red.
3936 {
3937 ClearEverythingToRed(renderbuffers);
3938
Geoff Lange8afa902017-09-27 15:00:43 -04003939 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
Corentin Walleze7557742017-06-01 13:09:57 -04003940 DrawBuffers(useEXT, 4, halfDrawBuffers);
Olli Etuaho5804dc82018-04-13 14:11:46 +03003941 drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true);
Corentin Walleze7557742017-06-01 13:09:57 -04003942 ASSERT_GL_NO_ERROR();
3943
3944 CheckColors(renderbuffers, 0b1000, GLColor::green);
3945 CheckColors(renderbuffers, 0b0100, unwrittenColor);
3946 CheckColors(renderbuffers, 0b0011, GLColor::red);
3947 }
3948}
3949
Geoff Lang536eca12017-09-13 11:23:35 -04003950// Test that it's possible to generate mipmaps on unsized floating point textures once the
3951// extensions have been enabled
3952TEST_P(WebGLCompatibilityTest, GenerateMipmapUnsizedFloatingPointTexture)
3953{
3954 if (extensionRequestable("GL_OES_texture_float"))
3955 {
3956 glRequestExtensionANGLE("GL_OES_texture_float");
3957 }
3958 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3959
3960 GLTexture texture;
3961 glBindTexture(GL_TEXTURE_2D, texture);
3962
3963 constexpr GLColor32F data[4] = {
Jamie Madillb980c562018-11-27 11:34:27 -05003964 kFloatRed,
3965 kFloatRed,
3966 kFloatGreen,
3967 kFloatBlue,
Geoff Lang536eca12017-09-13 11:23:35 -04003968 };
3969 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_FLOAT, data);
3970 ASSERT_GL_NO_ERROR();
3971
3972 glGenerateMipmap(GL_TEXTURE_2D);
3973 EXPECT_GL_NO_ERROR();
3974}
3975// Test that it's possible to generate mipmaps on unsized floating point textures once the
3976// extensions have been enabled
3977TEST_P(WebGLCompatibilityTest, GenerateMipmapSizedFloatingPointTexture)
3978{
3979 if (extensionRequestable("GL_OES_texture_float"))
3980 {
3981 glRequestExtensionANGLE("GL_OES_texture_float");
3982 }
3983 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_texture_float"));
3984
3985 if (extensionRequestable("GL_EXT_texture_storage"))
3986 {
3987 glRequestExtensionANGLE("GL_EXT_texture_storage");
3988 }
3989 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_storage"));
3990
3991 GLTexture texture;
3992 glBindTexture(GL_TEXTURE_2D, texture);
3993
3994 constexpr GLColor32F data[4] = {
Jamie Madillb980c562018-11-27 11:34:27 -05003995 kFloatRed,
3996 kFloatRed,
3997 kFloatGreen,
3998 kFloatBlue,
Geoff Lang536eca12017-09-13 11:23:35 -04003999 };
4000 glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA32F, 2, 2);
4001 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, data);
4002 ASSERT_GL_NO_ERROR();
4003
4004 glGenerateMipmap(GL_TEXTURE_2D);
4005 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4006
4007 if (extensionRequestable("GL_EXT_color_buffer_float"))
4008 {
4009 // Format is renderable but not filterable
4010 glRequestExtensionANGLE("GL_EXT_color_buffer_float");
4011 glGenerateMipmap(GL_TEXTURE_2D);
4012 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4013 }
4014
4015 if (extensionRequestable("GL_EXT_color_buffer_float_linear"))
4016 {
4017 // Format is renderable but not filterable
4018 glRequestExtensionANGLE("GL_EXT_color_buffer_float_linear");
4019
4020 if (extensionEnabled("GL_EXT_color_buffer_float"))
4021 {
4022 // Format is filterable and renderable
4023 glGenerateMipmap(GL_TEXTURE_2D);
4024 EXPECT_GL_NO_ERROR();
4025 }
4026 else
4027 {
4028 // Format is filterable but not renderable
4029 glGenerateMipmap(GL_TEXTURE_2D);
4030 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4031 }
4032 }
4033}
4034
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07004035// Verify that a texture format is only allowed with extension enabled.
4036void WebGLCompatibilityTest::validateTexImageExtensionFormat(GLenum format,
4037 const std::string &extName)
4038{
4039 // Verify texture format fails by default.
4040 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
4041 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4042
4043 if (extensionRequestable(extName))
4044 {
4045 // Verify texture format is allowed once extension is enabled.
4046 glRequestExtensionANGLE(extName.c_str());
4047 EXPECT_TRUE(extensionEnabled(extName));
4048
4049 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr);
4050 ASSERT_GL_NO_ERROR();
4051 }
4052}
4053
Geoff Lang86f81162017-10-30 15:10:45 -04004054// Test enabling various non-compressed texture format extensions
4055TEST_P(WebGLCompatibilityTest, EnableTextureFormatExtensions)
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07004056{
Geoff Lang2c5c41f2017-10-31 10:58:09 -04004057 ANGLE_SKIP_TEST_IF(IsOzone());
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07004058 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
4059
4060 GLTexture texture;
4061 glBindTexture(GL_TEXTURE_2D, texture.get());
4062
4063 // Verify valid format is allowed.
4064 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4065 ASSERT_GL_NO_ERROR();
4066
4067 // Verify invalid format fails.
4068 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA32F, GL_UNSIGNED_BYTE, nullptr);
4069 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4070
4071 // Verify formats from enableable extensions.
Geoff Lang660b28c2017-10-30 12:58:56 -04004072 if (!IsOpenGLES())
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07004073 {
4074 validateTexImageExtensionFormat(GL_RED_EXT, "GL_EXT_texture_rg");
4075 }
4076
4077 validateTexImageExtensionFormat(GL_SRGB_EXT, "GL_EXT_texture_sRGB");
4078 validateTexImageExtensionFormat(GL_BGRA_EXT, "GL_EXT_texture_format_BGRA8888");
4079}
4080
Geoff Lang86f81162017-10-30 15:10:45 -04004081void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum format,
4082 GLsizei width,
4083 GLsizei height,
4084 GLsizei blockSize,
4085 const std::string &extName,
4086 bool subImageAllowed)
4087{
4088 std::vector<GLubyte> data(blockSize, 0u);
4089
4090 GLTexture texture;
4091 glBindTexture(GL_TEXTURE_2D, texture.get());
4092
4093 // Verify texture format fails by default.
4094 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
4095 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4096
4097 if (extensionRequestable(extName))
4098 {
4099 // Verify texture format is allowed once extension is enabled.
4100 glRequestExtensionANGLE(extName.c_str());
4101 EXPECT_TRUE(extensionEnabled(extName));
4102
4103 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data());
4104 EXPECT_GL_NO_ERROR();
4105
4106 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, blockSize,
4107 data.data());
4108 if (subImageAllowed)
4109 {
4110 EXPECT_GL_NO_ERROR();
4111 }
4112 else
4113 {
4114 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4115 }
4116 }
4117}
4118
4119// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT
4120TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB)
4121{
4122 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8,
4123 "GL_EXT_texture_compression_dxt1", true);
4124}
4125
4126// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
4127TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGBA)
4128{
4129 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8,
4130 "GL_EXT_texture_compression_dxt1", true);
4131}
4132
4133// Test enabling GL_ANGLE_texture_compression_dxt3
4134TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3)
4135{
4136 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 16,
4137 "GL_ANGLE_texture_compression_dxt3", true);
4138}
4139
4140// Test enabling GL_ANGLE_texture_compression_dxt5
4141TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5)
4142{
4143 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 16,
4144 "GL_ANGLE_texture_compression_dxt5", true);
4145}
4146
4147// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
4148TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGB)
4149{
4150 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8,
4151 "GL_EXT_texture_compression_s3tc_srgb", true);
4152}
4153
4154// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
4155TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGBA)
4156{
4157 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8,
4158 "GL_EXT_texture_compression_s3tc_srgb", true);
4159}
4160
4161// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
4162TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3SRGBA)
4163{
4164 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16,
4165 "GL_EXT_texture_compression_s3tc_srgb", true);
4166}
4167
4168// Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
4169TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5SRGBA)
4170{
4171 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16,
4172 "GL_EXT_texture_compression_s3tc_srgb", true);
4173}
4174
4175// Test enabling GL_OES_compressed_ETC1_RGB8_texture
4176TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionETC1)
4177{
4178 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_OES, 4, 4, 8,
4179 "GL_OES_compressed_ETC1_RGB8_texture", false);
4180}
4181
4182// Test enabling GL_ANGLE_lossy_etc_decode
4183TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionLossyDecode)
4184{
4185 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 8,
4186 "GL_ANGLE_lossy_etc_decode", true);
4187}
4188
Frank Henigmanfccbac22017-05-28 17:29:26 -04004189// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
4190// qualifiers.
4191TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch)
4192{
Jamie Madill35cd7332018-12-02 12:03:33 -05004193 constexpr char kVS[] =
Frank Henigmanfccbac22017-05-28 17:29:26 -04004194 "#version 300 es\n"
4195 "uniform Block { mediump vec4 val; };\n"
4196 "void main() { gl_Position = val; }\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05004197 constexpr char kFS[] =
Frank Henigmanfccbac22017-05-28 17:29:26 -04004198 "#version 300 es\n"
4199 "uniform Block { highp vec4 val; };\n"
4200 "out highp vec4 out_FragColor;\n"
4201 "void main() { out_FragColor = val; }\n";
4202
Jamie Madill35cd7332018-12-02 12:03:33 -05004203 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
Frank Henigmanfccbac22017-05-28 17:29:26 -04004204 ASSERT_NE(0u, vs);
Jamie Madill35cd7332018-12-02 12:03:33 -05004205 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
Frank Henigmanfccbac22017-05-28 17:29:26 -04004206 ASSERT_NE(0u, fs);
4207
4208 GLuint program = glCreateProgram();
4209
4210 glAttachShader(program, vs);
4211 glDeleteShader(vs);
4212 glAttachShader(program, fs);
4213 glDeleteShader(fs);
4214
4215 glLinkProgram(program);
4216 GLint linkStatus;
4217 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
4218 ASSERT_EQ(0, linkStatus);
4219
4220 glDeleteProgram(program);
4221}
4222
Geoff Lang69df2422017-07-05 12:42:31 -04004223// Test no attribute vertex shaders
4224TEST_P(WebGL2CompatibilityTest, NoAttributeVertexShader)
4225{
Jamie Madill35cd7332018-12-02 12:03:33 -05004226 constexpr char kVS[] =
Geoff Lang69df2422017-07-05 12:42:31 -04004227 "#version 300 es\n"
4228 "void main()\n"
4229 "{\n"
4230 "\n"
4231 " ivec2 xy = ivec2(gl_VertexID % 2, (gl_VertexID / 2 + gl_VertexID / 3) % 2);\n"
4232 " gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1);\n"
4233 "}";
Geoff Lang69df2422017-07-05 12:42:31 -04004234
Jamie Madill35cd7332018-12-02 12:03:33 -05004235 ANGLE_GL_PROGRAM(program, kVS, essl3_shaders::fs::Red());
Geoff Lang69df2422017-07-05 12:42:31 -04004236 glUseProgram(program);
4237
4238 glDrawArrays(GL_TRIANGLES, 0, 6);
4239 ASSERT_GL_NO_ERROR();
Olli Etuaho5804dc82018-04-13 14:11:46 +03004240 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
Geoff Lang69df2422017-07-05 12:42:31 -04004241}
4242
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004243// Tests bindAttribLocations for length limit
4244TEST_P(WebGL2CompatibilityTest, BindAttribLocationLimitation)
4245{
4246 constexpr int maxLocStringLength = 1024;
4247 const std::string tooLongString(maxLocStringLength + 1, '_');
4248
4249 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str()));
4250
4251 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4252}
4253
Jamie Madill629bb252018-04-20 11:01:33 -04004254// Covers a bug in transform feedback loop detection.
4255TEST_P(WebGL2CompatibilityTest, TransformFeedbackCheckNullDeref)
4256{
4257 constexpr char kVS[] = R"(attribute vec4 color; void main() { color.r; })";
4258 constexpr char kFS[] = R"(void main(){})";
4259 ANGLE_GL_PROGRAM(program, kVS, kFS);
4260 glUseProgram(program);
4261
Jamie Madill629bb252018-04-20 11:01:33 -04004262 glEnableVertexAttribArray(0);
4263 glDrawArrays(GL_POINTS, 0, 1);
4264
Jamie Madilldc358af2018-07-31 11:22:13 -04004265 // This should fail because it is trying to pull a vertex with no buffer.
4266 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4267
4268 GLBuffer buffer;
4269 glBindBuffer(GL_ARRAY_BUFFER, buffer);
4270 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
4271
4272 // This should fail because it is trying to pull a vertex from an empty buffer.
4273 glDrawArrays(GL_POINTS, 0, 1);
Jamie Madill629bb252018-04-20 11:01:33 -04004274 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4275}
4276
James Darpinian471b8d42018-11-21 15:37:47 -08004277// We should forbid two transform feedback outputs going to the same buffer.
4278TEST_P(WebGL2CompatibilityTest, TransformFeedbackDoubleBinding)
4279{
4280 constexpr char kVS[] =
4281 R"(attribute float a; varying float b; varying float c; void main() { b = a; c = a; })";
4282 constexpr char kFS[] = R"(void main(){})";
4283 ANGLE_GL_PROGRAM(program, kVS, kFS);
4284 static const char *varyings[] = {"b", "c"};
4285 glTransformFeedbackVaryings(program, 2, varyings, GL_SEPARATE_ATTRIBS);
4286 glLinkProgram(program);
4287 glUseProgram(program);
4288 ASSERT_GL_NO_ERROR();
4289
4290 // Bind the transform feedback varyings to non-overlapping regions of the same buffer.
4291 GLBuffer buffer;
4292 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, 4);
4293 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 1, buffer, 4, 4);
4294 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 8, nullptr, GL_STATIC_DRAW);
4295 ASSERT_GL_NO_ERROR();
4296 // Two varyings bound to the same buffer should be an error.
4297 glBeginTransformFeedback(GL_POINTS);
4298 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4299}
4300
Bryan Bernhart22f7aaf2018-08-23 14:13:51 -07004301// Check the return type of a given parameter upon getting the active uniforms.
4302TEST_P(WebGL2CompatibilityTest, UniformVariablesReturnTypes)
4303{
4304 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4305
4306 std::vector<GLuint> validUniformIndices = {0};
4307 std::vector<GLint> uniformNameLengthBuf(validUniformIndices.size());
4308
4309 // This should fail because GL_UNIFORM_NAME_LENGTH cannot be used in WebGL2.
4310 glGetActiveUniformsiv(program, static_cast<GLsizei>(validUniformIndices.size()),
4311 &validUniformIndices[0], GL_UNIFORM_NAME_LENGTH,
4312 &uniformNameLengthBuf[0]);
4313 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4314}
4315
Geoff Langc287ea62016-09-16 14:46:51 -04004316// Use this to select which configurations (e.g. which renderer, which GLES major version) these
4317// tests should be run against.
4318ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
4319 ES2_D3D9(),
4320 ES2_D3D11(),
4321 ES3_D3D11(),
Geoff Langc287ea62016-09-16 14:46:51 -04004322 ES2_OPENGL(),
4323 ES3_OPENGL(),
4324 ES2_OPENGLES(),
4325 ES3_OPENGLES());
4326
Jamie Madill07be8bf2017-02-02 19:59:57 -05004327ANGLE_INSTANTIATE_TEST(WebGL2CompatibilityTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madillb980c562018-11-27 11:34:27 -05004328} // namespace angle