blob: 7da5b9d8e93d567d8ee326035b8509240024131e [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
11#include "test_utils/gl_raii.h"
12
Frank Henigman146e8a12017-03-02 23:22:37 -050013namespace
14{
15
16bool ConstantColorAndAlphaBlendFunctions(GLenum first, GLenum second)
17{
18 return (first == GL_CONSTANT_COLOR || first == GL_ONE_MINUS_CONSTANT_COLOR) &&
19 (second == GL_CONSTANT_ALPHA || second == GL_ONE_MINUS_CONSTANT_ALPHA);
20}
21
22void CheckBlendFunctions(GLenum src, GLenum dst)
23{
24 if (ConstantColorAndAlphaBlendFunctions(src, dst) ||
25 ConstantColorAndAlphaBlendFunctions(dst, src))
26 {
27 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
28 }
29 else
30 {
31 ASSERT_GL_NO_ERROR();
32 }
33}
34
35} // namespace
36
Geoff Langc287ea62016-09-16 14:46:51 -040037namespace angle
38{
39
40class WebGLCompatibilityTest : public ANGLETest
41{
42 protected:
43 WebGLCompatibilityTest()
44 {
45 setWindowWidth(128);
46 setWindowHeight(128);
47 setConfigRedBits(8);
48 setConfigGreenBits(8);
49 setConfigBlueBits(8);
50 setConfigAlphaBits(8);
51 setWebGLCompatibilityEnabled(true);
52 }
53
54 void SetUp() override
55 {
56 ANGLETest::SetUp();
Geoff Langc339c4e2016-11-29 10:37:36 -050057 glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
58 eglGetProcAddress("glRequestExtensionANGLE"));
Geoff Langc287ea62016-09-16 14:46:51 -040059 }
60
Jamie Madillcad97ee2017-02-02 18:52:44 -050061 // Called from RenderingFeedbackLoopWithDrawBuffersEXT.
62 void drawBuffersEXTFeedbackLoop(GLuint program,
63 const std::array<GLenum, 2> &drawBuffers,
64 GLenum expectedError);
65
Jamie Madill07be8bf2017-02-02 19:59:57 -050066 // Called from RenderingFeedbackLoopWithDrawBuffers.
67 void drawBuffersFeedbackLoop(GLuint program,
68 const std::array<GLenum, 2> &drawBuffers,
69 GLenum expectedError);
70
Geoff Langc339c4e2016-11-29 10:37:36 -050071 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
Geoff Langc287ea62016-09-16 14:46:51 -040072};
73
Corentin Wallezfd456442016-12-21 17:57:00 -050074class WebGL2CompatibilityTest : public WebGLCompatibilityTest
75{
76};
77
Geoff Langc287ea62016-09-16 14:46:51 -040078// Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so
79// the GL extension should always be present
80TEST_P(WebGLCompatibilityTest, ExtensionStringExposed)
81{
82 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
83}
84
85// Verify that all extension entry points are available
86TEST_P(WebGLCompatibilityTest, EntryPoints)
87{
Geoff Langc339c4e2016-11-29 10:37:36 -050088 if (extensionEnabled("GL_ANGLE_request_extension"))
Geoff Langc287ea62016-09-16 14:46:51 -040089 {
Geoff Langc339c4e2016-11-29 10:37:36 -050090 EXPECT_NE(nullptr, eglGetProcAddress("glRequestExtensionANGLE"));
Geoff Langc287ea62016-09-16 14:46:51 -040091 }
92}
93
94// WebGL 1 allows GL_DEPTH_STENCIL_ATTACHMENT as a valid binding point. Make sure it is usable,
95// even in ES2 contexts.
96TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint)
97{
98 GLRenderbuffer renderbuffer;
99 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
100 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
101
102 GLFramebuffer framebuffer;
103 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
104 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
105 renderbuffer.get());
106
107 EXPECT_GL_NO_ERROR();
108}
109
110// Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION
111TEST_P(WebGLCompatibilityTest, EnableExtensionValidation)
112{
Geoff Langc339c4e2016-11-29 10:37:36 -0500113 glRequestExtensionANGLE("invalid_extension_string");
Geoff Langc287ea62016-09-16 14:46:51 -0400114 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
115}
116
117// Test enabling the GL_OES_element_index_uint extension
118TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices)
119{
120 if (getClientMajorVersion() != 2)
121 {
122 // This test only works on ES2 where uint indices are not available by default
123 return;
124 }
125
126 EXPECT_FALSE(extensionEnabled("GL_OES_element_index_uint"));
127
128 GLBuffer indexBuffer;
129 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
130
131 GLuint data[] = {0, 1, 2, 1, 3, 2};
132 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
133
134 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
135 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
136 glUseProgram(program.get());
137
138 glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr);
139 EXPECT_GL_ERROR(GL_INVALID_ENUM);
140
Geoff Langc339c4e2016-11-29 10:37:36 -0500141 if (extensionRequestable("GL_OES_element_index_uint"))
Geoff Langc287ea62016-09-16 14:46:51 -0400142 {
Geoff Langc339c4e2016-11-29 10:37:36 -0500143 glRequestExtensionANGLE("GL_OES_element_index_uint");
Geoff Langc287ea62016-09-16 14:46:51 -0400144 EXPECT_GL_NO_ERROR();
145 EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint"));
146
147 glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr);
148 EXPECT_GL_NO_ERROR();
149 }
150}
151
Geoff Langd7d526a2017-02-21 16:48:43 -0500152// Test enabling the GL_EXT_texture_filter_anisotropic extension
153TEST_P(WebGLCompatibilityTest, EnableExtensionTextureFilterAnisotropic)
154{
155 EXPECT_FALSE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
156
157 GLfloat maxAnisotropy = 0.0f;
158 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
159 EXPECT_GL_ERROR(GL_INVALID_ENUM);
160
161 GLTexture texture;
162 glBindTexture(GL_TEXTURE_2D, texture.get());
163 ASSERT_GL_NO_ERROR();
164
165 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
166 EXPECT_GL_ERROR(GL_INVALID_ENUM);
167
168 GLfloat currentAnisotropy = 0.0f;
169 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
170 EXPECT_GL_ERROR(GL_INVALID_ENUM);
171
172 if (extensionRequestable("GL_EXT_texture_filter_anisotropic"))
173 {
174 glRequestExtensionANGLE("GL_EXT_texture_filter_anisotropic");
175 EXPECT_GL_NO_ERROR();
176 EXPECT_TRUE(extensionEnabled("GL_EXT_texture_filter_anisotropic"));
177
178 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
179 ASSERT_GL_NO_ERROR();
180 EXPECT_GE(maxAnisotropy, 2.0f);
181
182 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &currentAnisotropy);
183 ASSERT_GL_NO_ERROR();
184 EXPECT_EQ(1.0f, currentAnisotropy);
185
186 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
187 ASSERT_GL_NO_ERROR();
188 }
189}
190
Bryan Bernhart87c182e2016-11-02 11:23:22 -0700191// Verify that shaders are of a compatible spec when the extension is enabled.
192TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec)
193{
194 EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
195
196 // Use of reserved _webgl prefix should fail when the shader specification is for WebGL.
197 const std::string &vert =
198 "struct Foo {\n"
199 " int _webgl_bar;\n"
200 "};\n"
201 "void main()\n"
202 "{\n"
203 " Foo foo = Foo(1);\n"
204 "}";
205
206 // Default fragement shader.
207 const std::string &frag =
208 "void main()\n"
209 "{\n"
210 " gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n"
211 "}";
212
213 GLuint program = CompileProgram(vert, frag);
214 EXPECT_EQ(0u, program);
215 glDeleteProgram(program);
216}
217
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400218// Verify that the context generates the correct error when the framebuffer attachments are
219// different sizes
220TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMissmatch)
221{
222 GLFramebuffer fbo;
223 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
224
225 GLTexture textures[2];
226 glBindTexture(GL_TEXTURE_2D, textures[0]);
227 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
228 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
229
230 ASSERT_GL_NO_ERROR();
231 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
232
233 GLRenderbuffer renderbuffer;
234 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
235 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3);
236 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
237
238 ASSERT_GL_NO_ERROR();
239 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
240 glCheckFramebufferStatus(GL_FRAMEBUFFER));
241
242 if (extensionRequestable("GL_EXT_draw_buffers"))
243 {
244 glRequestExtensionANGLE("GL_EXT_draw_buffers");
245 EXPECT_GL_NO_ERROR();
246 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
247
248 glBindTexture(GL_TEXTURE_2D, textures[1]);
249 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
250 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
251 ASSERT_GL_NO_ERROR();
252
253 ASSERT_GL_NO_ERROR();
254 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
255 glCheckFramebufferStatus(GL_FRAMEBUFFER));
256
257 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
258
259 ASSERT_GL_NO_ERROR();
260 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
261
262 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
263
264 ASSERT_GL_NO_ERROR();
265 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
266 glCheckFramebufferStatus(GL_FRAMEBUFFER));
267 }
268}
269
Corentin Wallez327411e2016-12-09 11:09:17 -0500270// Test that client-side array buffers are forbidden in WebGL mode
271TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer)
272{
273 const std::string &vert =
274 "attribute vec3 a_pos;\n"
275 "void main()\n"
276 "{\n"
277 " gl_Position = vec4(a_pos, 1.0);\n"
278 "}\n";
279
280 const std::string &frag =
281 "precision highp float;\n"
282 "void main()\n"
283 "{\n"
284 " gl_FragColor = vec4(1.0);\n"
285 "}\n";
286
287 ANGLE_GL_PROGRAM(program, vert, frag);
288
289 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
290 ASSERT_NE(-1, posLocation);
291 glUseProgram(program.get());
292
293 const auto &vertices = GetQuadVertices();
Corentin Wallezfd456442016-12-21 17:57:00 -0500294 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
Corentin Wallez327411e2016-12-09 11:09:17 -0500295 glEnableVertexAttribArray(posLocation);
296
297 ASSERT_GL_NO_ERROR();
298 glDrawArrays(GL_TRIANGLES, 0, 6);
299 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
300}
301
302// Test that client-side element array buffers are forbidden in WebGL mode
303TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
304{
305 const std::string &vert =
306 "attribute vec3 a_pos;\n"
307 "void main()\n"
308 "{\n"
309 " gl_Position = vec4(a_pos, 1.0);\n"
310 "}\n";
311
312 const std::string &frag =
313 "precision highp float;\n"
314 "void main()\n"
315 "{\n"
316 " gl_FragColor = vec4(1.0);\n"
317 "}\n";
318
319 ANGLE_GL_PROGRAM(program, vert, frag);
320
321 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
322 ASSERT_NE(-1, posLocation);
323 glUseProgram(program.get());
324
325 const auto &vertices = GetQuadVertices();
326
327 GLBuffer vertexBuffer;
328 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
329 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
330 GL_STATIC_DRAW);
331
332 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
333 glEnableVertexAttribArray(posLocation);
334
Corentin Wallez327411e2016-12-09 11:09:17 -0500335 ASSERT_GL_NO_ERROR();
Corentin Wallezded1b5a2017-03-09 18:58:48 -0500336
337 // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also
338 // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate
339 // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check.
340 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void*>(intptr_t(1)));
Corentin Wallez327411e2016-12-09 11:09:17 -0500341 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
342}
343
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500344// Tests the WebGL requirement of having the same stencil mask, writemask and ref for fron and back
345TEST_P(WebGLCompatibilityTest, RequiresSameStencilMaskAndRef)
346{
347 // Run the test in an FBO to make sure we have some stencil bits.
348 GLRenderbuffer renderbuffer;
349 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
350 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
351
352 GLFramebuffer framebuffer;
353 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
354 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
355 renderbuffer.get());
356
357 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
358 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
359 glUseProgram(program.get());
360 ASSERT_GL_NO_ERROR();
361
362 // Having ref and mask the same for front and back is valid.
363 glStencilMask(255);
364 glStencilFunc(GL_ALWAYS, 0, 255);
365 glDrawArrays(GL_TRIANGLES, 0, 6);
366 ASSERT_GL_NO_ERROR();
367
368 // Having a different front - back write mask generates an error.
369 glStencilMaskSeparate(GL_FRONT, 1);
370 glDrawArrays(GL_TRIANGLES, 0, 6);
371 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
372
373 // Setting both write masks separately to the same value is valid.
374 glStencilMaskSeparate(GL_BACK, 1);
375 glDrawArrays(GL_TRIANGLES, 0, 6);
376 ASSERT_GL_NO_ERROR();
377
378 // Having a different stencil front - back mask generates an error
379 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
380 glDrawArrays(GL_TRIANGLES, 0, 6);
381 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
382
383 // Setting both masks separately to the same value is valid.
384 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
385 glDrawArrays(GL_TRIANGLES, 0, 6);
386 ASSERT_GL_NO_ERROR();
387
388 // Having a different stencil front - back reference generates an error
389 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
390 glDrawArrays(GL_TRIANGLES, 0, 6);
391 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
392
393 // Setting both references separately to the same value is valid.
394 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
395 glDrawArrays(GL_TRIANGLES, 0, 6);
396 ASSERT_GL_NO_ERROR();
397
398 // Using different stencil funcs, everything being equal is valid.
399 glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
400 glDrawArrays(GL_TRIANGLES, 0, 6);
401 ASSERT_GL_NO_ERROR();
402}
403
Corentin Wallez506fc9c2016-12-21 16:53:33 -0500404// Test that GL_FIXED is forbidden
405TEST_P(WebGLCompatibilityTest, ForbidsGLFixed)
406{
407 GLBuffer buffer;
408 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
409 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
410
411 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
412 ASSERT_GL_NO_ERROR();
413
414 glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr);
415 EXPECT_GL_ERROR(GL_INVALID_ENUM);
416}
417
418// Test the WebGL limit of 255 for the attribute stride
419TEST_P(WebGLCompatibilityTest, MaxStride)
420{
421 GLBuffer buffer;
422 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
423 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
424
425 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr);
426 ASSERT_GL_NO_ERROR();
427
428 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr);
429 EXPECT_GL_ERROR(GL_INVALID_VALUE);
430}
431
Corentin Wallezfd456442016-12-21 17:57:00 -0500432// Test the checks for OOB reads in the vertex buffers, non-instanced version
433TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
434{
435 const std::string &vert =
436 "attribute float a_pos;\n"
437 "void main()\n"
438 "{\n"
439 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
440 "}\n";
441
442 const std::string &frag =
443 "precision highp float;\n"
444 "void main()\n"
445 "{\n"
446 " gl_FragColor = vec4(1.0);\n"
447 "}\n";
448
449 ANGLE_GL_PROGRAM(program, vert, frag);
450
451 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
452 ASSERT_NE(-1, posLocation);
453 glUseProgram(program.get());
454
455 GLBuffer buffer;
456 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
457 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
458
459 glEnableVertexAttribArray(posLocation);
460
461 const uint8_t* zeroOffset = nullptr;
462
463 // Test touching the last element is valid.
464 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
465 glDrawArrays(GL_POINTS, 0, 4);
466 ASSERT_GL_NO_ERROR();
467
468 // Test touching the last element + 1 is invalid.
469 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
470 glDrawArrays(GL_POINTS, 0, 4);
471 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
472
473 // Test touching the last element is valid, using a stride.
474 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
475 glDrawArrays(GL_POINTS, 0, 4);
476 ASSERT_GL_NO_ERROR();
477
478 // Test touching the last element + 1 is invalid, using a stride.
479 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
480 glDrawArrays(GL_POINTS, 0, 4);
481 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
482
483 // Test any offset is valid if no vertices are drawn.
484 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
485 glDrawArrays(GL_POINTS, 0, 0);
486 ASSERT_GL_NO_ERROR();
487}
488
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500489// Test the checks for OOB reads in the index buffer
490TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
Geoff Lang5f319a42017-01-09 16:49:19 -0500491{
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500492 const std::string &vert =
493 "attribute float a_pos;\n"
494 "void main()\n"
495 "{\n"
496 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
497 "}\n";
Geoff Lang5f319a42017-01-09 16:49:19 -0500498
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500499 const std::string &frag =
500 "precision highp float;\n"
501 "void main()\n"
502 "{\n"
503 " gl_FragColor = vec4(1.0);\n"
504 "}\n";
505
506 ANGLE_GL_PROGRAM(program, vert, frag);
507
508 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
509 ASSERT_NE(-1, posLocation);
510 glUseProgram(program.get());
511
512 GLBuffer vertexBuffer;
513 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
514 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
515
516 glEnableVertexAttribArray(posLocation);
517
518 const uint8_t *zeroOffset = nullptr;
519 const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
520
521 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset);
522
523 GLBuffer indexBuffer;
524 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
525 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
Geoff Lang5f319a42017-01-09 16:49:19 -0500526 ASSERT_GL_NO_ERROR();
527
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500528 // Test touching the last index is valid
529 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
530 ASSERT_GL_NO_ERROR();
Geoff Lang5f319a42017-01-09 16:49:19 -0500531
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500532 // Test touching the last + 1 element is invalid
533 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
534 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Geoff Lang5f319a42017-01-09 16:49:19 -0500535
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500536 // Test any offset if valid if count is zero
537 glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
538 ASSERT_GL_NO_ERROR();
Corentin Wallezfe9306a2017-02-01 17:41:05 -0500539
540 // Test touching the first index is valid
541 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
542 ASSERT_GL_NO_ERROR();
543
544 // Test touching the first - 1 index is invalid
545 // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was
546 // the historic behavior of WebGL implementations
547 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1);
548 EXPECT_GL_ERROR(GL_INVALID_VALUE);
Geoff Lang5f319a42017-01-09 16:49:19 -0500549}
550
Frank Henigman6137ddc2017-02-10 18:55:07 -0500551// Test depth range with 'near' more or less than 'far.'
552TEST_P(WebGLCompatibilityTest, DepthRange)
553{
554 glDepthRangef(0, 1);
555 ASSERT_GL_NO_ERROR();
556
557 glDepthRangef(.5, .5);
558 ASSERT_GL_NO_ERROR();
559
560 glDepthRangef(1, 0);
561 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
562}
563
Frank Henigman146e8a12017-03-02 23:22:37 -0500564// Test all blend function combinations.
565// In WebGL it is invalid to combine constant color with constant alpha.
566TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
567{
568 constexpr GLenum srcFunc[] = {
569 GL_ZERO,
570 GL_ONE,
571 GL_SRC_COLOR,
572 GL_ONE_MINUS_SRC_COLOR,
573 GL_DST_COLOR,
574 GL_ONE_MINUS_DST_COLOR,
575 GL_SRC_ALPHA,
576 GL_ONE_MINUS_SRC_ALPHA,
577 GL_DST_ALPHA,
578 GL_ONE_MINUS_DST_ALPHA,
579 GL_CONSTANT_COLOR,
580 GL_ONE_MINUS_CONSTANT_COLOR,
581 GL_CONSTANT_ALPHA,
582 GL_ONE_MINUS_CONSTANT_ALPHA,
583 GL_SRC_ALPHA_SATURATE,
584 };
585
586 constexpr GLenum dstFunc[] = {
587 GL_ZERO, GL_ONE,
588 GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
589 GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
590 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
591 GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
592 GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
593 GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
594 };
595
596 for (GLenum src : srcFunc)
597 {
598 for (GLenum dst : dstFunc)
599 {
600 glBlendFunc(src, dst);
601 CheckBlendFunctions(src, dst);
602 glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE);
603 CheckBlendFunctions(src, dst);
604 }
605 }
606}
607
Corentin Wallezfd456442016-12-21 17:57:00 -0500608// Test the checks for OOB reads in the vertex buffers, instanced version
609TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
610{
611 const std::string &vert =
612 "attribute float a_pos;\n"
613 "void main()\n"
614 "{\n"
615 " gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
616 "}\n";
617
618 const std::string &frag =
619 "precision highp float;\n"
620 "void main()\n"
621 "{\n"
622 " gl_FragColor = vec4(1.0);\n"
623 "}\n";
624
625 ANGLE_GL_PROGRAM(program, vert, frag);
626
627 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
628 ASSERT_NE(-1, posLocation);
629 glUseProgram(program.get());
630
631 GLBuffer buffer;
632 glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
633 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
634
635 glEnableVertexAttribArray(posLocation);
636 glVertexAttribDivisor(posLocation, 1);
637
638 const uint8_t* zeroOffset = nullptr;
639
640 // Test touching the last element is valid.
641 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12);
642 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
643 ASSERT_GL_NO_ERROR();
644
645 // Test touching the last element + 1 is invalid.
646 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13);
647 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
648 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
649
650 // Test touching the last element is valid, using a stride.
651 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9);
652 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
653 ASSERT_GL_NO_ERROR();
654
655 // Test touching the last element + 1 is invalid, using a stride.
656 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10);
657 glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
658 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
659
660 // Test any offset is valid if no vertices are drawn.
661 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32);
662 glDrawArraysInstanced(GL_POINTS, 0, 1, 0);
663 ASSERT_GL_NO_ERROR();
664}
665
Corentin Wallez0844f2d2017-01-31 17:02:59 -0500666// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
667TEST_P(WebGLCompatibilityTest, NPOT)
668{
669 EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
670
671 // Create a texture and set an NPOT mip 0, should always be acceptable.
672 GLTexture texture;
673 glBindTexture(GL_TEXTURE_2D, texture.get());
674 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
675 ASSERT_GL_NO_ERROR();
676
677 // Try setting an NPOT mip 1 and verify the error if WebGL 1
678 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
679 if (getClientMajorVersion() < 3)
680 {
681 ASSERT_GL_ERROR(GL_INVALID_VALUE);
682 }
683 else
684 {
685 ASSERT_GL_NO_ERROR();
686 }
687
688 if (extensionRequestable("GL_OES_texture_npot"))
689 {
690 glRequestExtensionANGLE("GL_OES_texture_npot");
691 ASSERT_GL_NO_ERROR();
692
693 // Try again to set NPOT mip 1
694 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
695 ASSERT_GL_NO_ERROR();
696 }
697}
698
Jamie Madillcad97ee2017-02-02 18:52:44 -0500699template <typename T>
700void FillTexture2D(GLuint texture,
701 GLsizei width,
702 GLsizei height,
703 const T &onePixelData,
704 GLint level,
705 GLint internalFormat,
706 GLenum format,
707 GLenum type)
708{
709 std::vector<T> allPixelsData(width * height, onePixelData);
710
711 glBindTexture(GL_TEXTURE_2D, texture);
712 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
713 allPixelsData.data());
714 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
715 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
716 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
717 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
718}
719
Frank Henigman875bbba2017-02-08 16:38:17 -0500720// Test that unset gl_Position defaults to (0,0,0,0).
721TEST_P(WebGLCompatibilityTest, DefaultPosition)
722{
723 // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set,
724 // and green otherwise. The center of each quadrant will be red if and only if all
725 // four corners are red.
726 const std::string vertexShader =
727 "attribute vec3 pos;\n"
728 "varying vec4 color;\n"
729 "void main() {\n"
730 " if (gl_Position == vec4(0,0,0,0)) {\n"
731 " color = vec4(1,0,0,1);\n"
732 " } else {\n"
733 " color = vec4(0,1,0,1);\n"
734 " }\n"
735 " gl_Position = vec4(pos,1);\n"
736 "}\n";
737
738 const std::string fragmentShader =
739 "precision mediump float;\n"
740 "varying vec4 color;\n"
741 "void main() {\n"
742 " gl_FragColor = color;\n"
743 "}\n";
744
745 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
746 drawQuad(program.get(), "pos", 0.0f, 1.0f, true);
747 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red);
748 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red);
749 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red);
750 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red);
751}
752
Jamie Madilla4595b82017-01-11 17:36:34 -0500753// Tests that a rendering feedback loop triggers a GL error under WebGL.
754// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
755TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
756{
757 const std::string vertexShader =
758 "attribute vec4 a_position;\n"
759 "varying vec2 v_texCoord;\n"
760 "void main() {\n"
761 " gl_Position = a_position;\n"
762 " v_texCoord = (a_position.xy * 0.5) + 0.5;\n"
763 "}\n";
764
765 const std::string fragmentShader =
766 "precision mediump float;\n"
767 "varying vec2 v_texCoord;\n"
768 "uniform sampler2D u_texture;\n"
769 "void main() {\n"
770 " // Shader swizzles color channels so we can tell if the draw succeeded.\n"
771 " gl_FragColor = texture2D(u_texture, v_texCoord).gbra;\n"
772 "}\n";
773
774 GLTexture texture;
Jamie Madillcad97ee2017-02-02 18:52:44 -0500775 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -0500776
777 ASSERT_GL_NO_ERROR();
778
779 GLFramebuffer framebuffer;
780 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
781 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
782
783 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
784
785 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
786
787 GLint uniformLoc = glGetUniformLocation(program.get(), "u_texture");
788 ASSERT_NE(-1, uniformLoc);
789
790 glUseProgram(program.get());
791 glUniform1i(uniformLoc, 0);
792 glDisable(GL_BLEND);
793 glDisable(GL_DEPTH_TEST);
794 ASSERT_GL_NO_ERROR();
795
796 // Drawing with a texture that is also bound to the current framebuffer should fail
797 glBindTexture(GL_TEXTURE_2D, texture.get());
798 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
799 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
800
801 // Ensure that the texture contents did not change after the previous render
802 glBindFramebuffer(GL_FRAMEBUFFER, 0);
803 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
804 ASSERT_GL_NO_ERROR();
805 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
806
807 // Drawing when texture is bound to an inactive uniform should succeed
808 GLTexture texture2;
Jamie Madillcad97ee2017-02-02 18:52:44 -0500809 FillTexture2D(texture2.get(), 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
Jamie Madilla4595b82017-01-11 17:36:34 -0500810
811 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
812 glActiveTexture(GL_TEXTURE1);
813 glBindTexture(GL_TEXTURE_2D, texture.get());
814 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
815 ASSERT_GL_NO_ERROR();
816 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
817}
818
Bryan Bernhart58806562017-01-05 13:09:31 -0800819// Test for the max draw buffers and color attachments.
820TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
821{
822 // This test only applies to ES2.
823 if (getClientMajorVersion() != 2)
824 {
825 return;
826 }
827
828 GLFramebuffer fbo[2];
829 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0].get());
830
831 // Test that is valid when we bind with a single attachment point.
832 GLTexture texture;
833 glBindTexture(GL_TEXTURE_2D, texture.get());
834 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
835 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
836 ASSERT_GL_NO_ERROR();
837
838 // Test that enabling the draw buffers extension will allow us to bind with a non-zero
839 // attachment point.
840 if (extensionRequestable("GL_EXT_draw_buffers"))
841 {
842 glRequestExtensionANGLE("GL_EXT_draw_buffers");
843 EXPECT_GL_NO_ERROR();
844 EXPECT_TRUE(extensionEnabled("GL_EXT_draw_buffers"));
845
846 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1].get());
847
848 GLTexture texture2;
849 glBindTexture(GL_TEXTURE_2D, texture2.get());
850 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
851 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2.get(),
852 0);
853 ASSERT_GL_NO_ERROR();
854 }
855}
856
Corentin Wallez3f6d4df2017-01-30 18:04:36 -0500857// Test that the offset in the index buffer is forced to be a multiple of the element size
858TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction)
859{
860 const std::string &vert =
861 "attribute vec3 a_pos;\n"
862 "void main()\n"
863 "{\n"
864 " gl_Position = vec4(a_pos, 1.0);\n"
865 "}\n";
866
867 const std::string &frag =
868 "precision highp float;\n"
869 "void main()\n"
870 "{\n"
871 " gl_FragColor = vec4(1.0);\n"
872 "}\n";
873
874 ANGLE_GL_PROGRAM(program, vert, frag);
875
876 GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
877 ASSERT_NE(-1, posLocation);
878 glUseProgram(program.get());
879
880 const auto &vertices = GetQuadVertices();
881
882 GLBuffer vertexBuffer;
883 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
884 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
885 GL_STATIC_DRAW);
886
887 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
888 glEnableVertexAttribArray(posLocation);
889
890 GLBuffer indexBuffer;
891 const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0};
892 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
893 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
894
895 ASSERT_GL_NO_ERROR();
896
897 const char *zeroIndices = nullptr;
898
899 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices);
900 ASSERT_GL_NO_ERROR();
901
902 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices);
903 ASSERT_GL_NO_ERROR();
904
905 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices + 1);
906 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
907}
908
909// Test that the offset and stride in the vertex buffer is forced to be a multiple of the element
910// size
911TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction)
912{
913 const char *zeroOffset = nullptr;
914
915 // Base case, vector of two floats
916 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset);
917 ASSERT_GL_NO_ERROR();
918
919 // Test setting a non-multiple offset
920 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1);
921 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
922 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2);
923 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
924 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3);
925 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
926
927 // Test setting a non-multiple stride
928 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset);
929 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
930 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset);
931 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
932 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset);
933 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
934}
935
Jamie Madillcad97ee2017-02-02 18:52:44 -0500936void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program,
937 const std::array<GLenum, 2> &drawBuffers,
938 GLenum expectedError)
939{
940 glDrawBuffersEXT(2, drawBuffers.data());
941
942 // Make sure framebuffer is complete before feedback loop detection
943 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
944
945 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
946
947 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
948 // it should be NO_ERROR"
949 EXPECT_GL_ERROR(expectedError);
950}
951
952// This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers.
953// Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html
954TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT)
955{
956 const std::string vertexShader =
957 "attribute vec4 aPosition;\n"
958 "varying vec2 texCoord;\n"
959 "void main() {\n"
960 " gl_Position = aPosition;\n"
961 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
962 "}\n";
963
964 const std::string fragmentShader =
965 "#extension GL_EXT_draw_buffers : require\n"
966 "precision mediump float;\n"
967 "uniform sampler2D tex;\n"
968 "varying vec2 texCoord;\n"
969 "void main() {\n"
970 " gl_FragData[0] = texture2D(tex, texCoord);\n"
971 " gl_FragData[1] = texture2D(tex, texCoord);\n"
972 "}\n";
973
974 GLsizei width = 8;
975 GLsizei height = 8;
976
977 // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers
978 // extension and gl_FragData semantics are changed to enforce indexing by zero always.
979 // TODO(jmadill): This extension should be disabled in WebGL 2 contexts.
980 if (/*!extensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2)
981 {
982 // No WEBGL_draw_buffers support -- this is legal.
983 return;
984 }
985
986 GLint maxDrawBuffers = 0;
987 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
988
989 if (maxDrawBuffers < 2)
990 {
991 std::cout << "Test skipped because MAX_DRAW_BUFFERS is too small." << std::endl;
992 return;
993 }
994
995 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
996 glUseProgram(program.get());
997 glViewport(0, 0, width, height);
998
999 GLTexture tex0;
1000 GLTexture tex1;
1001 GLFramebuffer fbo;
1002 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1003 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1004 ASSERT_GL_NO_ERROR();
1005
1006 glBindTexture(GL_TEXTURE_2D, tex1.get());
1007 GLint texLoc = glGetUniformLocation(program.get(), "tex");
1008 ASSERT_NE(-1, texLoc);
1009 glUniform1i(texLoc, 0);
1010 ASSERT_GL_NO_ERROR();
1011
1012 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
1013 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
1014 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
1015 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
1016
1017 drawBuffersEXTFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}},
1018 GL_INVALID_OPERATION);
1019 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
1020 GL_INVALID_OPERATION);
1021 drawBuffersEXTFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
1022}
1023
Jamie Madill07be8bf2017-02-02 19:59:57 -05001024// Test tests that texture copying feedback loops are properly rejected in WebGL.
1025// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
1026TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
1027{
1028 GLTexture texture;
1029 glBindTexture(GL_TEXTURE_2D, texture.get());
1030 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1031 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1032 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1033 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1034 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1035
1036 GLTexture texture2;
1037 glBindTexture(GL_TEXTURE_2D, texture2.get());
1038 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1040 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1041 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1042 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1043
1044 GLFramebuffer framebuffer;
1045 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1046 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1047
1048 // framebuffer should be FRAMEBUFFER_COMPLETE.
1049 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1050 ASSERT_GL_NO_ERROR();
1051
1052 // testing copyTexImage2D
1053
1054 // copyTexImage2D to same texture but different level
1055 glBindTexture(GL_TEXTURE_2D, texture.get());
1056 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
1057 EXPECT_GL_NO_ERROR();
1058
1059 // copyTexImage2D to same texture same level, invalid feedback loop
1060 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
1061 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1062
1063 // copyTexImage2D to different texture
1064 glBindTexture(GL_TEXTURE_2D, texture2.get());
1065 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0);
1066 EXPECT_GL_NO_ERROR();
1067
1068 // testing copyTexSubImage2D
1069
1070 // copyTexSubImage2D to same texture but different level
1071 glBindTexture(GL_TEXTURE_2D, texture.get());
1072 glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
1073 EXPECT_GL_NO_ERROR();
1074
1075 // copyTexSubImage2D to same texture same level, invalid feedback loop
1076 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
1077 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1078
1079 // copyTexSubImage2D to different texture
1080 glBindTexture(GL_TEXTURE_2D, texture2.get());
1081 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
1082 EXPECT_GL_NO_ERROR();
1083}
1084
1085void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program,
1086 const std::array<GLenum, 2> &drawBuffers,
1087 GLenum expectedError)
1088{
1089 glDrawBuffers(2, drawBuffers.data());
1090
1091 // Make sure framebuffer is complete before feedback loop detection
1092 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1093
1094 drawQuad(program, "aPosition", 0.5f, 1.0f, true);
1095
1096 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise,
1097 // it should be NO_ERROR"
1098 EXPECT_GL_ERROR(expectedError);
1099}
1100
Yuly Novikov817232e2017-02-22 18:36:10 -05001101// Tests invariance matching rules between built in varyings.
1102// Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html.
1103TEST_P(WebGLCompatibilityTest, BuiltInInvariant)
1104{
1105 const std::string vertexShaderVariant =
1106 "varying vec4 v_varying;\n"
1107 "void main()\n"
1108 "{\n"
1109 " gl_PointSize = 1.0;\n"
1110 " gl_Position = v_varying;\n"
1111 "}";
1112 const std::string fragmentShaderInvariantGlFragCoord =
1113 "invariant gl_FragCoord;\n"
1114 "void main()\n"
1115 "{\n"
1116 " gl_FragColor = gl_FragCoord;\n"
1117 "}";
1118 const std::string fragmentShaderInvariantGlPointCoord =
1119 "invariant gl_PointCoord;\n"
1120 "void main()\n"
1121 "{\n"
1122 " gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0);\n"
1123 "}";
1124
1125 GLuint program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlFragCoord);
1126 EXPECT_EQ(0u, program);
1127
1128 program = CompileProgram(vertexShaderVariant, fragmentShaderInvariantGlPointCoord);
1129 EXPECT_EQ(0u, program);
1130}
1131
Jamie Madill07be8bf2017-02-02 19:59:57 -05001132// This tests that rendering feedback loops works as expected with WebGL 2.
1133// Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html
1134TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers)
1135{
1136 const std::string vertexShader =
1137 "#version 300 es\n"
1138 "in vec4 aPosition;\n"
1139 "out vec2 texCoord;\n"
1140 "void main() {\n"
1141 " gl_Position = aPosition;\n"
1142 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
1143 "}\n";
1144
1145 const std::string fragmentShader =
1146 "#version 300 es\n"
1147 "precision mediump float;\n"
1148 "uniform sampler2D tex;\n"
1149 "in vec2 texCoord;\n"
1150 "out vec4 oColor;\n"
1151 "void main() {\n"
1152 " oColor = texture(tex, texCoord);\n"
1153 "}\n";
1154
1155 GLsizei width = 8;
1156 GLsizei height = 8;
1157
1158 GLint maxDrawBuffers = 0;
1159 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1160 // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS.
1161 ASSERT_GE(maxDrawBuffers, 2);
1162
1163 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1164 glUseProgram(program.get());
1165 glViewport(0, 0, width, height);
1166
1167 GLTexture tex0;
1168 GLTexture tex1;
1169 GLFramebuffer fbo;
1170 FillTexture2D(tex0.get(), width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1171 FillTexture2D(tex1.get(), width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1172 ASSERT_GL_NO_ERROR();
1173
1174 glBindTexture(GL_TEXTURE_2D, tex1.get());
1175 GLint texLoc = glGetUniformLocation(program.get(), "tex");
1176 ASSERT_NE(-1, texLoc);
1177 glUniform1i(texLoc, 0);
1178
1179 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
1180 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
1181 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
1182 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1.get(), 0);
1183 ASSERT_GL_NO_ERROR();
1184
1185 drawBuffersFeedbackLoop(program.get(), {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION);
1186 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}},
1187 GL_INVALID_OPERATION);
1188 drawBuffersFeedbackLoop(program.get(), {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_NO_ERROR);
1189}
1190
Jamie Madill1d37bc52017-02-02 19:59:58 -05001191// This test covers detection of rendering feedback loops between the FBO and a depth Texture.
1192// Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html
1193TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil)
1194{
1195 const std::string vertexShader =
1196 "#version 300 es\n"
1197 "in vec4 aPosition;\n"
1198 "out vec2 texCoord;\n"
1199 "void main() {\n"
1200 " gl_Position = aPosition;\n"
1201 " texCoord = (aPosition.xy * 0.5) + 0.5;\n"
1202 "}\n";
1203
1204 const std::string fragmentShader =
1205 "#version 300 es\n"
1206 "precision mediump float;\n"
1207 "uniform sampler2D tex;\n"
1208 "in vec2 texCoord;\n"
1209 "out vec4 oColor;\n"
1210 "void main() {\n"
1211 " oColor = texture(tex, texCoord);\n"
1212 "}\n";
1213
1214 GLsizei width = 8;
1215 GLsizei height = 8;
1216
1217 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
1218 glUseProgram(program.get());
1219
1220 glViewport(0, 0, width, height);
1221
1222 GLint texLoc = glGetUniformLocation(program.get(), "tex");
1223 glUniform1i(texLoc, 0);
1224
1225 // Create textures and allocate storage
1226 GLTexture tex0;
1227 GLTexture tex1;
1228 GLRenderbuffer rb;
1229 FillTexture2D(tex0.get(), width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1230 FillTexture2D(tex1.get(), width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
1231 GL_UNSIGNED_INT);
1232 glBindRenderbuffer(GL_RENDERBUFFER, rb.get());
1233 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
1234 ASSERT_GL_NO_ERROR();
1235
1236 GLFramebuffer fbo;
1237 glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
1238 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0.get(), 0);
1239
1240 // Test rendering and sampling feedback loop for depth buffer
1241 glBindTexture(GL_TEXTURE_2D, tex1.get());
1242 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1.get(), 0);
1243 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1244
1245 // The same image is used as depth buffer during rendering.
1246 glEnable(GL_DEPTH_TEST);
1247 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
1248 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1249
1250 // The same image is used as depth buffer. But depth mask is false.
1251 glDepthMask(GL_FALSE);
1252 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
1253 EXPECT_GL_NO_ERROR();
1254
1255 // The same image is used as depth buffer. But depth test is not enabled during rendering.
1256 glDepthMask(GL_TRUE);
1257 glDisable(GL_DEPTH_TEST);
1258 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
1259 EXPECT_GL_NO_ERROR();
1260
1261 // Test rendering and sampling feedback loop for stencil buffer
1262 glBindTexture(GL_RENDERBUFFER, rb.get());
1263 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
1264 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb.get());
1265 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1266 constexpr GLint stencilClearValue = 0x40;
1267 glClearBufferiv(GL_STENCIL, 0, &stencilClearValue);
1268
1269 // The same image is used as stencil buffer during rendering.
1270 glEnable(GL_STENCIL_TEST);
1271 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
1272 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1273
1274 // The same image is used as stencil buffer. But stencil mask is zero.
1275 glStencilMask(0x0);
1276 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
1277 EXPECT_GL_NO_ERROR();
1278
1279 // The same image is used as stencil buffer. But stencil test is not enabled during rendering.
1280 glStencilMask(0xffff);
1281 glDisable(GL_STENCIL_TEST);
1282 drawQuad(program.get(), "aPosition", 0.5f, 1.0f, true);
1283 EXPECT_GL_NO_ERROR();
1284}
1285
Jamie Madillfd3dd432017-02-02 19:59:59 -05001286// The source and the target for CopyTexSubImage3D are the same 3D texture.
1287// But the level of the 3D texture != the level of the read attachment.
1288TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels)
1289{
1290 GLTexture texture;
1291 GLFramebuffer framebuffer;
1292
1293 glBindTexture(GL_TEXTURE_3D, texture.get());
1294 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1295
1296 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1297 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1298 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 0);
1299 ASSERT_GL_NO_ERROR();
1300
1301 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
1302 EXPECT_GL_NO_ERROR();
1303}
1304
1305// The source and the target for CopyTexSubImage3D are the same 3D texture.
1306// But the zoffset of the 3D texture != the layer of the read attachment.
1307TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers)
1308{
1309 GLTexture texture;
1310 GLFramebuffer framebuffer;
1311
1312 glBindTexture(GL_TEXTURE_3D, texture.get());
1313 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1314
1315 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1316 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 0, 1);
1317 ASSERT_GL_NO_ERROR();
1318
1319 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2);
1320 EXPECT_GL_NO_ERROR();
1321}
1322
1323// The source and the target for CopyTexSubImage3D are the same 3D texture.
1324// And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment.
1325TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D)
1326{
1327 GLTexture texture;
1328 GLFramebuffer framebuffer;
1329
1330 glBindTexture(GL_TEXTURE_3D, texture.get());
1331 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1332
1333 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1334 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1335 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1336 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.get(), 1, 0);
1337 ASSERT_GL_NO_ERROR();
1338
1339 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
1340 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1341}
1342
Geoff Lang76e65652017-03-27 14:58:02 -04001343// Verify that errors are generated when there isn not a defined conversion between the clear type
1344// and the buffer type.
1345TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity)
1346{
1347 if (IsD3D11())
1348 {
1349 std::cout << "Test skipped because it generates D3D11 runtime warnings." << std::endl;
1350 return;
1351 }
1352
1353 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f};
1354 constexpr int clearInt[] = {0, 0, 0, 0};
1355 constexpr unsigned int clearUint[] = {0, 0, 0, 0};
1356
1357 GLTexture texture;
1358 GLFramebuffer framebuffer;
1359
1360 glBindTexture(GL_TEXTURE_2D, texture.get());
1361 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1362
1363 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1364 ASSERT_GL_NO_ERROR();
1365
1366 // Unsigned integer buffer
1367 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr);
1368 ASSERT_GL_NO_ERROR();
1369
1370 glClearBufferfv(GL_COLOR, 0, clearFloat);
1371 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1372
1373 glClearBufferiv(GL_COLOR, 0, clearInt);
1374 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1375
1376 glClearBufferuiv(GL_COLOR, 0, clearUint);
1377 EXPECT_GL_NO_ERROR();
1378
1379 glClear(GL_COLOR_BUFFER_BIT);
1380 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1381
1382 // Integer buffer
1383 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr);
1384 ASSERT_GL_NO_ERROR();
1385
1386 glClearBufferfv(GL_COLOR, 0, clearFloat);
1387 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1388
1389 glClearBufferiv(GL_COLOR, 0, clearInt);
1390 EXPECT_GL_NO_ERROR();
1391
1392 glClearBufferuiv(GL_COLOR, 0, clearUint);
1393 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1394
1395 glClear(GL_COLOR_BUFFER_BIT);
1396 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1397
1398 // Float buffer
1399 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr);
1400 ASSERT_GL_NO_ERROR();
1401
1402 glClearBufferfv(GL_COLOR, 0, clearFloat);
1403 EXPECT_GL_NO_ERROR();
1404
1405 glClearBufferiv(GL_COLOR, 0, clearInt);
1406 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1407
1408 glClearBufferuiv(GL_COLOR, 0, clearUint);
1409 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1410
1411 glClear(GL_COLOR_BUFFER_BIT);
1412 EXPECT_GL_NO_ERROR();
1413
1414 // Normalized uint buffer
1415 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1416 ASSERT_GL_NO_ERROR();
1417
1418 glClearBufferfv(GL_COLOR, 0, clearFloat);
1419 EXPECT_GL_NO_ERROR();
1420
1421 glClearBufferiv(GL_COLOR, 0, clearInt);
1422 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1423
1424 glClearBufferuiv(GL_COLOR, 0, clearUint);
1425 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1426
1427 glClear(GL_COLOR_BUFFER_BIT);
1428 EXPECT_GL_NO_ERROR();
1429}
1430
Geoff Langc287ea62016-09-16 14:46:51 -04001431// Use this to select which configurations (e.g. which renderer, which GLES major version) these
1432// tests should be run against.
1433ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
1434 ES2_D3D9(),
1435 ES2_D3D11(),
1436 ES3_D3D11(),
1437 ES2_D3D11_FL9_3(),
1438 ES2_OPENGL(),
1439 ES3_OPENGL(),
1440 ES2_OPENGLES(),
1441 ES3_OPENGLES());
1442
Jamie Madill07be8bf2017-02-02 19:59:57 -05001443ANGLE_INSTANTIATE_TEST(WebGL2CompatibilityTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Geoff Langc287ea62016-09-16 14:46:51 -04001444} // namespace