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