1 // 2 // Copyright 2015 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // WebGLCompatibilityTest.cpp : Tests of the GL_ANGLE_webgl_compatibility extension. 8 9 #include "test_utils/ANGLETest.h" 10 11 #include "common/mathutil.h" 12 #include "test_utils/gl_raii.h" 13 14 namespace 15 { 16 ConstantColorAndAlphaBlendFunctions(GLenum first,GLenum second)17 bool 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 CheckBlendFunctions(GLenum src,GLenum dst)23 void 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 36 // Extensions that affect the ability to use floating point textures 37 constexpr const char *FloatingPointTextureExtensions[] = { 38 "", 39 "GL_EXT_texture_storage", 40 "GL_OES_texture_half_float", 41 "GL_OES_texture_half_float_linear", 42 "GL_EXT_color_buffer_half_float", 43 "GL_OES_texture_float", 44 "GL_OES_texture_float_linear", 45 "GL_EXT_color_buffer_float", 46 "GL_EXT_float_blend", 47 "GL_CHROMIUM_color_buffer_float_rgba", 48 "GL_CHROMIUM_color_buffer_float_rgb", 49 }; 50 51 } // namespace 52 53 namespace angle 54 { 55 56 class WebGLCompatibilityTest : public ANGLETest<> 57 { 58 protected: WebGLCompatibilityTest()59 WebGLCompatibilityTest() 60 { 61 setWindowWidth(128); 62 setWindowHeight(128); 63 setConfigRedBits(8); 64 setConfigGreenBits(8); 65 setConfigBlueBits(8); 66 setConfigAlphaBits(8); 67 setWebGLCompatibilityEnabled(true); 68 } 69 70 template <typename T> TestFloatTextureFormat(GLenum internalFormat,GLenum format,GLenum type,bool texturingEnabled,bool linearSamplingEnabled,bool renderingEnabled,const T textureData[4],const float floatData[4])71 void TestFloatTextureFormat(GLenum internalFormat, 72 GLenum format, 73 GLenum type, 74 bool texturingEnabled, 75 bool linearSamplingEnabled, 76 bool renderingEnabled, 77 const T textureData[4], 78 const float floatData[4]) 79 { 80 ASSERT_GL_NO_ERROR(); 81 82 constexpr char kVS[] = 83 R"(attribute vec4 position; 84 varying vec2 texcoord; 85 void main() 86 { 87 gl_Position = vec4(position.xy, 0.0, 1.0); 88 texcoord = (position.xy * 0.5) + 0.5; 89 })"; 90 91 constexpr char kFS[] = 92 R"(precision mediump float; 93 uniform sampler2D tex; 94 uniform vec4 subtractor; 95 varying vec2 texcoord; 96 void main() 97 { 98 vec4 color = texture2D(tex, texcoord); 99 if (abs(color.r - subtractor.r) + 100 abs(color.g - subtractor.g) + 101 abs(color.b - subtractor.b) + 102 abs(color.a - subtractor.a) < 8.0) 103 { 104 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 105 } 106 else 107 { 108 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 109 } 110 })"; 111 112 ANGLE_GL_PROGRAM(samplingProgram, kVS, kFS); 113 glUseProgram(samplingProgram); 114 115 // Need RGBA8 renderbuffers for enough precision on the readback 116 if (IsGLExtensionRequestable("GL_OES_rgb8_rgba8")) 117 { 118 glRequestExtensionANGLE("GL_OES_rgb8_rgba8"); 119 } 120 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") && 121 getClientMajorVersion() < 3); 122 ASSERT_GL_NO_ERROR(); 123 124 GLRenderbuffer rbo; 125 glBindRenderbuffer(GL_RENDERBUFFER, rbo); 126 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1); 127 128 GLFramebuffer fbo; 129 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 130 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); 131 132 GLTexture texture; 133 glBindTexture(GL_TEXTURE_2D, texture); 134 135 if (internalFormat == format) 136 { 137 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, textureData); 138 } 139 else 140 { 141 if (getClientMajorVersion() >= 3) 142 { 143 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1); 144 } 145 else 146 { 147 ASSERT_TRUE(IsGLExtensionEnabled("GL_EXT_texture_storage")); 148 glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1); 149 } 150 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, textureData); 151 } 152 153 if (!texturingEnabled) 154 { 155 // Depending on the entry point and client version, different errors may be generated 156 ASSERT_GLENUM_NE(GL_NO_ERROR, glGetError()); 157 158 // Two errors may be generated in the glTexStorage + glTexSubImage case, clear the 159 // second error 160 glGetError(); 161 162 return; 163 } 164 ASSERT_GL_NO_ERROR(); 165 166 glUniform1i(glGetUniformLocation(samplingProgram, "tex"), 0); 167 glUniform4fv(glGetUniformLocation(samplingProgram, "subtractor"), 1, floatData); 168 169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 171 drawQuad(samplingProgram, "position", 0.5f, 1.0f, true); 172 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 173 174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 175 drawQuad(samplingProgram, "position", 0.5f, 1.0f, true); 176 177 if (linearSamplingEnabled) 178 { 179 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 180 } 181 else 182 { 183 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); 184 } 185 186 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 187 glBindTexture(GL_TEXTURE_2D, 0); 188 if (!renderingEnabled) 189 { 190 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 191 glCheckFramebufferStatus(GL_FRAMEBUFFER)); 192 return; 193 } 194 195 GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); 196 if (framebufferStatus == GL_FRAMEBUFFER_UNSUPPORTED) 197 { 198 std::cout << "Framebuffer returned GL_FRAMEBUFFER_UNSUPPORTED, this is legal." 199 << std::endl; 200 return; 201 } 202 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, framebufferStatus); 203 204 ANGLE_GL_PROGRAM(renderingProgram, essl1_shaders::vs::Simple(), 205 essl1_shaders::fs::UniformColor()); 206 glUseProgram(renderingProgram); 207 208 glUniform4fv(glGetUniformLocation(renderingProgram, essl1_shaders::ColorUniform()), 1, 209 floatData); 210 211 drawQuad(renderingProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 212 213 EXPECT_PIXEL_COLOR32F_NEAR( 214 0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f); 215 } 216 TestExtFloatBlend(GLenum internalFormat,GLenum type,bool shouldBlend)217 void TestExtFloatBlend(GLenum internalFormat, GLenum type, bool shouldBlend) 218 { 219 constexpr char kVS[] = 220 R"(void main() 221 { 222 gl_PointSize = 1.0; 223 gl_Position = vec4(0, 0, 0, 1); 224 })"; 225 226 constexpr char kFS[] = 227 R"(void main() 228 { 229 gl_FragColor = vec4(0.5, 0, 0, 0); 230 })"; 231 232 ANGLE_GL_PROGRAM(program, kVS, kFS); 233 glUseProgram(program); 234 235 GLTexture texture; 236 glBindTexture(GL_TEXTURE_2D, texture); 237 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, GL_RGBA, type, nullptr); 238 EXPECT_GL_NO_ERROR(); 239 240 GLFramebuffer fbo; 241 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 242 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 243 ASSERT_EGLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 244 245 glClearColor(1, 0, 1, 1); 246 glClear(GL_COLOR_BUFFER_BIT); 247 EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(1, 0, 1, 1), 0.001f); 248 249 glDisable(GL_BLEND); 250 glDrawArrays(GL_POINTS, 0, 1); 251 EXPECT_GL_NO_ERROR(); 252 253 glEnable(GL_BLEND); 254 glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO); 255 glBlendColor(10, 1, 1, 1); 256 glViewport(0, 0, 1, 1); 257 glDrawArrays(GL_POINTS, 0, 1); 258 if (!shouldBlend) 259 { 260 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 261 return; 262 } 263 EXPECT_GL_NO_ERROR(); 264 265 // Ensure that the stored value reflect the actual platform behavior. 266 float storedColor[4]; 267 glGetFloatv(GL_BLEND_COLOR, storedColor); 268 if (storedColor[0] == 10) 269 { 270 EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(5, 0, 0, 0), 0.001f); 271 } 272 else 273 { 274 EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(0.5, 0, 0, 0), 0.001f); 275 } 276 277 // Check sure that non-float attachments clamp BLEND_COLOR. 278 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 279 glDrawArrays(GL_POINTS, 0, 1); 280 281 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0x80, 0, 0, 0), 1); 282 } 283 284 void TestDifferentStencilMaskAndRef(GLenum errIfMismatch); 285 286 // Called from RenderingFeedbackLoopWithDrawBuffersEXT. 287 void drawBuffersEXTFeedbackLoop(GLuint program, 288 const std::array<GLenum, 2> &drawBuffers, 289 GLenum expectedError); 290 291 // Called from RenderingFeedbackLoopWithDrawBuffers. 292 void drawBuffersFeedbackLoop(GLuint program, 293 const std::array<GLenum, 2> &drawBuffers, 294 GLenum expectedError); 295 296 // Called from Enable[Compressed]TextureFormatExtensions 297 void validateTexImageExtensionFormat(GLenum format, const std::string &extName); 298 void validateCompressedTexImageExtensionFormat(GLenum format, 299 GLsizei width, 300 GLsizei height, 301 GLsizei blockSize, 302 const std::string &extName, 303 bool subImageAllowed); 304 305 GLint expectedByteLength(GLenum format, GLsizei width, GLsizei height); 306 void testCompressedTexLevelDimension(GLenum format, 307 GLint level, 308 GLsizei width, 309 GLsizei height, 310 GLsizei expectedByteLength, 311 GLenum expectedError, 312 const char *explanation); 313 void testCompressedTexImage(GLenum format); 314 }; 315 316 class WebGL2CompatibilityTest : public WebGLCompatibilityTest 317 {}; 318 319 // Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so 320 // the GL extension should always be present TEST_P(WebGLCompatibilityTest,ExtensionStringExposed)321 TEST_P(WebGLCompatibilityTest, ExtensionStringExposed) 322 { 323 EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_webgl_compatibility")); 324 } 325 326 // Verify that all extension entry points are available TEST_P(WebGLCompatibilityTest,EntryPoints)327 TEST_P(WebGLCompatibilityTest, EntryPoints) 328 { 329 if (IsGLExtensionEnabled("GL_ANGLE_request_extension")) 330 { 331 EXPECT_NE(nullptr, eglGetProcAddress("glRequestExtensionANGLE")); 332 } 333 } 334 335 // WebGL 1 allows GL_DEPTH_STENCIL_ATTACHMENT as a valid binding point. Make sure it is usable, 336 // even in ES2 contexts. TEST_P(WebGLCompatibilityTest,DepthStencilBindingPoint)337 TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint) 338 { 339 GLRenderbuffer renderbuffer; 340 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 341 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32); 342 343 GLFramebuffer framebuffer; 344 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 345 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 346 renderbuffer); 347 348 EXPECT_GL_NO_ERROR(); 349 } 350 351 // Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION TEST_P(WebGLCompatibilityTest,EnableExtensionValidation)352 TEST_P(WebGLCompatibilityTest, EnableExtensionValidation) 353 { 354 glRequestExtensionANGLE("invalid_extension_string"); 355 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 356 } 357 358 // Test enabling the GL_OES_element_index_uint extension TEST_P(WebGLCompatibilityTest,EnableExtensionUintIndices)359 TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices) 360 { 361 if (getClientMajorVersion() != 2) 362 { 363 // This test only works on ES2 where uint indices are not available by default 364 return; 365 } 366 367 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_element_index_uint")); 368 369 GLBuffer indexBuffer; 370 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 371 372 GLuint data[] = {0, 1, 2, 1, 3, 2}; 373 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); 374 375 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }", 376 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }"); 377 glUseProgram(program); 378 379 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); 380 EXPECT_GL_ERROR(GL_INVALID_ENUM); 381 382 if (IsGLExtensionRequestable("GL_OES_element_index_uint")) 383 { 384 glRequestExtensionANGLE("GL_OES_element_index_uint"); 385 EXPECT_GL_NO_ERROR(); 386 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_element_index_uint")); 387 388 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); 389 EXPECT_GL_NO_ERROR(); 390 } 391 } 392 393 // Test enabling the GL_OES_standard_derivatives extension TEST_P(WebGLCompatibilityTest,EnableExtensionStandardDerivitives)394 TEST_P(WebGLCompatibilityTest, EnableExtensionStandardDerivitives) 395 { 396 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_standard_derivatives")); 397 398 constexpr char kFS[] = 399 R"(#extension GL_OES_standard_derivatives : require 400 void main() { gl_FragColor = vec4(dFdx(vec2(1.0, 1.0)).x, 1, 0, 1); })"; 401 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFS)); 402 403 if (IsGLExtensionRequestable("GL_OES_standard_derivatives")) 404 { 405 glRequestExtensionANGLE("GL_OES_standard_derivatives"); 406 EXPECT_GL_NO_ERROR(); 407 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_standard_derivatives")); 408 409 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); 410 ASSERT_NE(0u, shader); 411 glDeleteShader(shader); 412 } 413 } 414 415 // Test enabling the GL_EXT_shader_texture_lod extension TEST_P(WebGLCompatibilityTest,EnableExtensionTextureLOD)416 TEST_P(WebGLCompatibilityTest, EnableExtensionTextureLOD) 417 { 418 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_shader_texture_lod")); 419 420 constexpr char kFS[] = 421 R"(#extension GL_EXT_shader_texture_lod : require 422 uniform sampler2D u_texture; 423 void main() { 424 gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 425 0.0)); 426 })"; 427 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFS)); 428 429 if (IsGLExtensionRequestable("GL_EXT_shader_texture_lod")) 430 { 431 glRequestExtensionANGLE("GL_EXT_shader_texture_lod"); 432 EXPECT_GL_NO_ERROR(); 433 EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_shader_texture_lod")); 434 435 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); 436 ASSERT_NE(0u, shader); 437 glDeleteShader(shader); 438 } 439 } 440 441 // Test enabling the GL_EXT_frag_depth extension TEST_P(WebGLCompatibilityTest,EnableExtensionFragDepth)442 TEST_P(WebGLCompatibilityTest, EnableExtensionFragDepth) 443 { 444 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_frag_depth")); 445 446 constexpr char kFS[] = 447 R"(#extension GL_EXT_frag_depth : require 448 void main() { 449 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); 450 gl_FragDepthEXT = 1.0; 451 })"; 452 ASSERT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFS)); 453 454 if (IsGLExtensionRequestable("GL_EXT_frag_depth")) 455 { 456 glRequestExtensionANGLE("GL_EXT_frag_depth"); 457 EXPECT_GL_NO_ERROR(); 458 EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_frag_depth")); 459 460 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS); 461 ASSERT_NE(0u, shader); 462 glDeleteShader(shader); 463 } 464 } 465 466 // Test enabling the GL_EXT_texture_filter_anisotropic extension TEST_P(WebGLCompatibilityTest,EnableExtensionTextureFilterAnisotropic)467 TEST_P(WebGLCompatibilityTest, EnableExtensionTextureFilterAnisotropic) 468 { 469 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_texture_filter_anisotropic")); 470 471 GLfloat maxAnisotropy = 0.0f; 472 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy); 473 EXPECT_GL_ERROR(GL_INVALID_ENUM); 474 475 GLTexture texture; 476 glBindTexture(GL_TEXTURE_2D, texture); 477 ASSERT_GL_NO_ERROR(); 478 479 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f); 480 EXPECT_GL_ERROR(GL_INVALID_ENUM); 481 482 GLfloat currentAnisotropy = 0.0f; 483 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, ¤tAnisotropy); 484 EXPECT_GL_ERROR(GL_INVALID_ENUM); 485 486 if (IsGLExtensionRequestable("GL_EXT_texture_filter_anisotropic")) 487 { 488 glRequestExtensionANGLE("GL_EXT_texture_filter_anisotropic"); 489 EXPECT_GL_NO_ERROR(); 490 EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_texture_filter_anisotropic")); 491 492 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy); 493 ASSERT_GL_NO_ERROR(); 494 EXPECT_GE(maxAnisotropy, 2.0f); 495 496 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, ¤tAnisotropy); 497 ASSERT_GL_NO_ERROR(); 498 EXPECT_EQ(1.0f, currentAnisotropy); 499 500 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f); 501 ASSERT_GL_NO_ERROR(); 502 } 503 } 504 505 // Test enabling the EGL image extensions TEST_P(WebGLCompatibilityTest,EnableExtensionEGLImage)506 TEST_P(WebGLCompatibilityTest, EnableExtensionEGLImage) 507 { 508 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_EGL_image")); 509 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_EGL_image_external")); 510 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_EGL_image_external_essl3")); 511 EXPECT_FALSE(IsGLExtensionEnabled("NV_EGL_stream_consumer_external")); 512 513 constexpr char kFSES2[] = 514 R"(#extension GL_OES_EGL_image_external : require 515 precision highp float; 516 uniform samplerExternalOES sampler; 517 void main() 518 { 519 gl_FragColor = texture2D(sampler, vec2(0, 0)); 520 })"; 521 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES2)); 522 523 constexpr char kFSES3[] = 524 R"(#version 300 es 525 #extension GL_OES_EGL_image_external_essl3 : require 526 precision highp float; 527 uniform samplerExternalOES sampler; 528 out vec4 my_FragColor; 529 void main() 530 { 531 my_FragColor = texture(sampler, vec2(0, 0)); 532 })"; 533 if (getClientMajorVersion() >= 3) 534 { 535 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES3)); 536 } 537 538 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); 539 EXPECT_GL_ERROR(GL_INVALID_ENUM); 540 541 GLint result; 542 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result); 543 EXPECT_GL_ERROR(GL_INVALID_ENUM); 544 545 if (IsGLExtensionRequestable("GL_OES_EGL_image_external")) 546 { 547 glRequestExtensionANGLE("GL_OES_EGL_image_external"); 548 EXPECT_GL_NO_ERROR(); 549 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_EGL_image_external")); 550 551 EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES2)); 552 553 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); 554 EXPECT_GL_NO_ERROR(); 555 556 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &result); 557 EXPECT_GL_NO_ERROR(); 558 559 if (getClientMajorVersion() >= 3 && 560 IsGLExtensionRequestable("GL_OES_EGL_image_external_essl3")) 561 { 562 glRequestExtensionANGLE("GL_OES_EGL_image_external_essl3"); 563 EXPECT_GL_NO_ERROR(); 564 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_EGL_image_external_essl3")); 565 566 EXPECT_NE(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES3)); 567 } 568 else 569 { 570 EXPECT_EQ(0u, CompileShader(GL_FRAGMENT_SHADER, kFSES3)); 571 } 572 } 573 } 574 575 // Verify that shaders are of a compatible spec when the extension is enabled. TEST_P(WebGLCompatibilityTest,ExtensionCompilerSpec)576 TEST_P(WebGLCompatibilityTest, ExtensionCompilerSpec) 577 { 578 EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_webgl_compatibility")); 579 580 // Use of reserved _webgl prefix should fail when the shader specification is for WebGL. 581 constexpr char kVS[] = 582 R"(struct Foo { 583 int _webgl_bar; 584 }; 585 void main() 586 { 587 Foo foo = Foo(1); 588 })"; 589 590 // Default fragement shader. 591 constexpr char kFS[] = 592 R"(void main() 593 { 594 gl_FragColor = vec4(1.0,0.0,0.0,1.0); 595 })"; 596 597 GLuint program = CompileProgram(kVS, kFS); 598 EXPECT_EQ(0u, program); 599 glDeleteProgram(program); 600 } 601 602 // Test enabling the GL_NV_pixel_buffer_object extension TEST_P(WebGLCompatibilityTest,EnablePixelBufferObjectExtensions)603 TEST_P(WebGLCompatibilityTest, EnablePixelBufferObjectExtensions) 604 { 605 EXPECT_FALSE(IsGLExtensionEnabled("GL_NV_pixel_buffer_object")); 606 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_mapbuffer")); 607 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_map_buffer_range")); 608 609 // These extensions become core in in ES3/WebGL2. 610 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 611 612 // http://anglebug.com/40644771 613 ANGLE_SKIP_TEST_IF(IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL()); 614 615 GLBuffer buffer; 616 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer); 617 EXPECT_GL_ERROR(GL_INVALID_ENUM); 618 619 if (IsGLExtensionRequestable("GL_NV_pixel_buffer_object")) 620 { 621 glRequestExtensionANGLE("GL_NV_pixel_buffer_object"); 622 EXPECT_GL_NO_ERROR(); 623 624 // Create a framebuffer to read from 625 GLRenderbuffer renderbuffer; 626 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 627 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1); 628 629 GLFramebuffer fbo; 630 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 631 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 632 renderbuffer); 633 EXPECT_GL_NO_ERROR(); 634 635 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer); 636 EXPECT_GL_NO_ERROR(); 637 638 glBufferData(GL_PIXEL_PACK_BUFFER, 4, nullptr, GL_STATIC_DRAW); 639 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 640 EXPECT_GL_NO_ERROR(); 641 } 642 } 643 644 // Test enabling the GL_EXT_texture_storage extension TEST_P(WebGLCompatibilityTest,EnableTextureStorage)645 TEST_P(WebGLCompatibilityTest, EnableTextureStorage) 646 { 647 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_texture_storage")); 648 649 GLTexture texture; 650 glBindTexture(GL_TEXTURE_2D, texture); 651 652 GLint result; 653 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result); 654 if (getClientMajorVersion() >= 3) 655 { 656 EXPECT_GL_NO_ERROR(); 657 } 658 else 659 { 660 EXPECT_GL_ERROR(GL_INVALID_ENUM); 661 } 662 663 if (IsGLExtensionRequestable("GL_EXT_texture_storage")) 664 { 665 glRequestExtensionANGLE("GL_EXT_texture_storage"); 666 EXPECT_GL_NO_ERROR(); 667 EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_texture_storage")); 668 669 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &result); 670 EXPECT_GL_NO_ERROR(); 671 672 const GLenum alwaysAcceptableFormats[] = { 673 GL_ALPHA8_EXT, 674 GL_LUMINANCE8_EXT, 675 GL_LUMINANCE8_ALPHA8_EXT, 676 }; 677 for (const auto &acceptableFormat : alwaysAcceptableFormats) 678 { 679 GLTexture localTexture; 680 glBindTexture(GL_TEXTURE_2D, localTexture); 681 glTexStorage2DEXT(GL_TEXTURE_2D, 1, acceptableFormat, 1, 1); 682 EXPECT_GL_NO_ERROR(); 683 } 684 } 685 } 686 687 // Test enabling the GL_OES_mapbuffer and GL_EXT_map_buffer_range extensions TEST_P(WebGLCompatibilityTest,EnableMapBufferExtensions)688 TEST_P(WebGLCompatibilityTest, EnableMapBufferExtensions) 689 { 690 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_mapbuffer")); 691 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_map_buffer_range")); 692 693 // These extensions become core in in ES3/WebGL2. 694 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 695 696 GLBuffer buffer; 697 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); 698 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4, nullptr, GL_STATIC_DRAW); 699 700 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES); 701 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 702 703 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT); 704 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 705 706 GLint access = 0; 707 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access); 708 EXPECT_GL_ERROR(GL_INVALID_ENUM); 709 710 if (IsGLExtensionRequestable("GL_OES_mapbuffer")) 711 { 712 glRequestExtensionANGLE("GL_OES_mapbuffer"); 713 EXPECT_GL_NO_ERROR(); 714 715 glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES); 716 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER); 717 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access); 718 EXPECT_GL_NO_ERROR(); 719 } 720 721 if (IsGLExtensionRequestable("GL_EXT_map_buffer_range")) 722 { 723 glRequestExtensionANGLE("GL_EXT_map_buffer_range"); 724 EXPECT_GL_NO_ERROR(); 725 726 glMapBufferRangeEXT(GL_ELEMENT_ARRAY_BUFFER, 0, 4, GL_MAP_WRITE_BIT); 727 glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER); 728 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_ACCESS_OES, &access); 729 EXPECT_GL_NO_ERROR(); 730 } 731 } 732 733 // Test enabling the GL_OES_fbo_render_mipmap extension TEST_P(WebGLCompatibilityTest,EnableRenderMipmapExtension)734 TEST_P(WebGLCompatibilityTest, EnableRenderMipmapExtension) 735 { 736 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_fbo_render_mipmap")); 737 738 // This extensions become core in in ES3/WebGL2. 739 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 740 741 GLTexture texture; 742 glBindTexture(GL_TEXTURE_2D, texture); 743 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 744 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 745 746 GLFramebuffer fbo; 747 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 748 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 749 EXPECT_GL_NO_ERROR(); 750 751 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); 752 EXPECT_GL_ERROR(GL_INVALID_VALUE); 753 754 if (IsGLExtensionRequestable("GL_OES_fbo_render_mipmap")) 755 { 756 glRequestExtensionANGLE("GL_OES_fbo_render_mipmap"); 757 EXPECT_GL_NO_ERROR(); 758 759 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); 760 EXPECT_GL_NO_ERROR(); 761 } 762 } 763 764 // Test enabling the GL_EXT_blend_minmax extension TEST_P(WebGLCompatibilityTest,EnableBlendMinMaxExtension)765 TEST_P(WebGLCompatibilityTest, EnableBlendMinMaxExtension) 766 { 767 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_blend_minmax")); 768 769 // This extensions become core in in ES3/WebGL2. 770 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 771 772 glBlendEquation(GL_MIN); 773 EXPECT_GL_ERROR(GL_INVALID_ENUM); 774 775 glBlendEquation(GL_MAX); 776 EXPECT_GL_ERROR(GL_INVALID_ENUM); 777 778 if (IsGLExtensionRequestable("GL_EXT_blend_minmax")) 779 { 780 glRequestExtensionANGLE("GL_EXT_blend_minmax"); 781 EXPECT_GL_NO_ERROR(); 782 783 glBlendEquation(GL_MIN); 784 glBlendEquation(GL_MAX); 785 EXPECT_GL_NO_ERROR(); 786 } 787 } 788 789 // Test enabling the query extensions TEST_P(WebGLCompatibilityTest,EnableQueryExtensions)790 TEST_P(WebGLCompatibilityTest, EnableQueryExtensions) 791 { 792 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean")); 793 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_disjoint_timer_query")); 794 EXPECT_FALSE(IsGLExtensionEnabled("GL_CHROMIUM_sync_query")); 795 796 // This extensions become core in in ES3/WebGL2. 797 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 798 799 GLQueryEXT badQuery; 800 801 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, badQuery); 802 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 803 804 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, badQuery); 805 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 806 807 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, badQuery); 808 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 809 810 glQueryCounterEXT(GL_TIMESTAMP_EXT, badQuery); 811 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 812 813 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, badQuery); 814 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 815 816 if (IsGLExtensionRequestable("GL_EXT_occlusion_query_boolean")) 817 { 818 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean"); 819 EXPECT_GL_NO_ERROR(); 820 821 GLQueryEXT query; 822 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query); 823 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 824 EXPECT_GL_NO_ERROR(); 825 } 826 827 if (IsGLExtensionRequestable("GL_EXT_disjoint_timer_query")) 828 { 829 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query"); 830 EXPECT_GL_NO_ERROR(); 831 832 GLQueryEXT query1; 833 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1); 834 glEndQueryEXT(GL_TIME_ELAPSED_EXT); 835 EXPECT_GL_NO_ERROR(); 836 837 GLQueryEXT query2; 838 glQueryCounterEXT(query2, GL_TIMESTAMP_EXT); 839 EXPECT_GL_NO_ERROR(); 840 } 841 842 if (IsGLExtensionRequestable("GL_CHROMIUM_sync_query")) 843 { 844 glRequestExtensionANGLE("GL_CHROMIUM_sync_query"); 845 EXPECT_GL_NO_ERROR(); 846 847 GLQueryEXT query; 848 glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query); 849 glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); 850 EXPECT_GL_NO_ERROR(); 851 } 852 } 853 854 // Test enabling the GL_ANGLE_framebuffer_multisample extension TEST_P(WebGLCompatibilityTest,EnableFramebufferMultisampleExtension)855 TEST_P(WebGLCompatibilityTest, EnableFramebufferMultisampleExtension) 856 { 857 EXPECT_FALSE(IsGLExtensionEnabled("GL_ANGLE_framebuffer_multisample")); 858 859 // This extensions become core in in ES3/WebGL2. 860 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 861 862 GLint maxSamples = 0; 863 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); 864 EXPECT_GL_ERROR(GL_INVALID_ENUM); 865 866 GLRenderbuffer renderbuffer; 867 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 868 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA4, 1, 1); 869 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 870 871 if (IsGLExtensionRequestable("GL_ANGLE_framebuffer_multisample")) 872 { 873 glRequestExtensionANGLE("GL_ANGLE_framebuffer_multisample"); 874 EXPECT_GL_NO_ERROR(); 875 876 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); 877 EXPECT_GL_NO_ERROR(); 878 879 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, maxSamples, GL_RGBA4, 1, 1); 880 EXPECT_GL_NO_ERROR(); 881 } 882 } 883 884 // Test enabling the GL_ANGLE_instanced_arrays extension TEST_P(WebGLCompatibilityTest,EnableInstancedArraysExtensionANGLE)885 TEST_P(WebGLCompatibilityTest, EnableInstancedArraysExtensionANGLE) 886 { 887 EXPECT_FALSE(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays")); 888 889 // This extensions become core in in ES3/WebGL2. 890 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 891 892 GLint divisor = 0; 893 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor); 894 EXPECT_GL_ERROR(GL_INVALID_ENUM); 895 896 glVertexAttribDivisorANGLE(0, 1); 897 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 898 899 if (IsGLExtensionRequestable("GL_ANGLE_instanced_arrays")) 900 { 901 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays"); 902 EXPECT_GL_NO_ERROR(); 903 904 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor); 905 glVertexAttribDivisorANGLE(0, 1); 906 EXPECT_GL_NO_ERROR(); 907 } 908 } 909 910 // Test enabling the GL_EXT_instanced_arrays extension TEST_P(WebGLCompatibilityTest,EnableInstancedArraysExtensionEXT)911 TEST_P(WebGLCompatibilityTest, EnableInstancedArraysExtensionEXT) 912 { 913 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_instanced_arrays")); 914 915 // This extensions become core in in ES3/WebGL2. 916 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 917 918 GLint divisor = 0; 919 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor); 920 EXPECT_GL_ERROR(GL_INVALID_ENUM); 921 922 glVertexAttribDivisorEXT(0, 1); 923 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 924 925 if (IsGLExtensionRequestable("GL_EXT_instanced_arrays")) 926 { 927 glRequestExtensionANGLE("GL_EXT_instanced_arrays"); 928 EXPECT_GL_NO_ERROR(); 929 930 glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor); 931 glVertexAttribDivisorEXT(0, 1); 932 EXPECT_GL_NO_ERROR(); 933 } 934 } 935 936 // Test enabling the GL_ANGLE_pack_reverse_row_order extension TEST_P(WebGLCompatibilityTest,EnablePackReverseRowOrderExtension)937 TEST_P(WebGLCompatibilityTest, EnablePackReverseRowOrderExtension) 938 { 939 EXPECT_FALSE(IsGLExtensionEnabled("GL_ANGLE_pack_reverse_row_order")); 940 941 GLint result = 0; 942 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result); 943 EXPECT_GL_ERROR(GL_INVALID_ENUM); 944 945 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE); 946 EXPECT_GL_ERROR(GL_INVALID_ENUM); 947 948 if (IsGLExtensionRequestable("GL_ANGLE_pack_reverse_row_order")) 949 { 950 glRequestExtensionANGLE("GL_ANGLE_pack_reverse_row_order"); 951 EXPECT_GL_NO_ERROR(); 952 953 glGetIntegerv(GL_PACK_REVERSE_ROW_ORDER_ANGLE, &result); 954 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE); 955 EXPECT_GL_NO_ERROR(); 956 } 957 } 958 959 // Test enabling the GL_EXT_unpack_subimage extension TEST_P(WebGLCompatibilityTest,EnablePackUnpackSubImageExtension)960 TEST_P(WebGLCompatibilityTest, EnablePackUnpackSubImageExtension) 961 { 962 EXPECT_FALSE(IsGLExtensionEnabled("GL_EXT_unpack_subimage")); 963 964 // This extensions become core in in ES3/WebGL2. 965 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 966 967 constexpr GLenum parameters[] = { 968 GL_UNPACK_ROW_LENGTH_EXT, 969 GL_UNPACK_SKIP_ROWS_EXT, 970 GL_UNPACK_SKIP_PIXELS_EXT, 971 }; 972 973 for (GLenum param : parameters) 974 { 975 GLint resultI = 0; 976 glGetIntegerv(param, &resultI); 977 EXPECT_GL_ERROR(GL_INVALID_ENUM); 978 979 GLfloat resultF = 0.0f; 980 glGetFloatv(param, &resultF); 981 EXPECT_GL_ERROR(GL_INVALID_ENUM); 982 983 glPixelStorei(param, 0); 984 EXPECT_GL_ERROR(GL_INVALID_ENUM); 985 } 986 987 if (IsGLExtensionRequestable("GL_EXT_unpack_subimage")) 988 { 989 glRequestExtensionANGLE("GL_EXT_unpack_subimage"); 990 EXPECT_GL_NO_ERROR(); 991 992 for (GLenum param : parameters) 993 { 994 GLint resultI = 0; 995 glGetIntegerv(param, &resultI); 996 997 GLfloat resultF = 0.0f; 998 glGetFloatv(param, &resultF); 999 1000 glPixelStorei(param, 0); 1001 1002 EXPECT_GL_NO_ERROR(); 1003 } 1004 } 1005 } 1006 TEST_P(WebGLCompatibilityTest,EnableTextureRectangle)1007 TEST_P(WebGLCompatibilityTest, EnableTextureRectangle) 1008 { 1009 EXPECT_FALSE(IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")); 1010 1011 GLTexture texture; 1012 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture); 1013 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1014 1015 GLint minFilter = 0; 1016 glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, &minFilter); 1017 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1018 1019 if (IsGLExtensionRequestable("GL_ANGLE_texture_rectangle")) 1020 { 1021 glRequestExtensionANGLE("GL_ANGLE_texture_rectangle"); 1022 EXPECT_GL_NO_ERROR(); 1023 1024 EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")); 1025 1026 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture); 1027 EXPECT_GL_NO_ERROR(); 1028 1029 glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, 1030 nullptr); 1031 EXPECT_GL_NO_ERROR(); 1032 1033 glDisableExtensionANGLE("GL_ANGLE_texture_rectangle"); 1034 EXPECT_GL_NO_ERROR(); 1035 1036 EXPECT_FALSE(IsGLExtensionEnabled("GL_ANGLE_texture_rectangle")); 1037 1038 glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, texture); 1039 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1040 } 1041 } 1042 1043 // Test enabling the GL_NV_pack_subimage extension TEST_P(WebGLCompatibilityTest,EnablePackPackSubImageExtension)1044 TEST_P(WebGLCompatibilityTest, EnablePackPackSubImageExtension) 1045 { 1046 EXPECT_FALSE(IsGLExtensionEnabled("GL_NV_pack_subimage")); 1047 1048 // This extensions become core in in ES3/WebGL2. 1049 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 1050 1051 constexpr GLenum parameters[] = { 1052 GL_PACK_ROW_LENGTH, 1053 GL_PACK_SKIP_ROWS, 1054 GL_PACK_SKIP_PIXELS, 1055 }; 1056 1057 for (GLenum param : parameters) 1058 { 1059 GLint resultI = 0; 1060 glGetIntegerv(param, &resultI); 1061 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1062 1063 GLfloat resultF = 0.0f; 1064 glGetFloatv(param, &resultF); 1065 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1066 1067 glPixelStorei(param, 0); 1068 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1069 } 1070 1071 if (IsGLExtensionRequestable("GL_NV_pack_subimage")) 1072 { 1073 glRequestExtensionANGLE("GL_NV_pack_subimage"); 1074 EXPECT_GL_NO_ERROR(); 1075 1076 for (GLenum param : parameters) 1077 { 1078 GLint resultI = 0; 1079 glGetIntegerv(param, &resultI); 1080 1081 GLfloat resultF = 0.0f; 1082 glGetFloatv(param, &resultF); 1083 1084 glPixelStorei(param, 0); 1085 1086 EXPECT_GL_NO_ERROR(); 1087 } 1088 } 1089 } 1090 TEST_P(WebGLCompatibilityTest,EnableRGB8RGBA8Extension)1091 TEST_P(WebGLCompatibilityTest, EnableRGB8RGBA8Extension) 1092 { 1093 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_rgb8_rgba8")); 1094 1095 // This extensions become core in in ES3/WebGL2. 1096 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 1097 1098 GLRenderbuffer renderbuffer; 1099 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 1100 EXPECT_GL_NO_ERROR(); 1101 1102 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1); 1103 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1104 1105 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1); 1106 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1107 1108 if (IsGLExtensionRequestable("GL_OES_rgb8_rgba8")) 1109 { 1110 glRequestExtensionANGLE("GL_OES_rgb8_rgba8"); 1111 EXPECT_GL_NO_ERROR(); 1112 1113 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_rgb8_rgba8")); 1114 1115 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 1, 1); 1116 EXPECT_GL_NO_ERROR(); 1117 1118 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1); 1119 EXPECT_GL_NO_ERROR(); 1120 } 1121 } 1122 1123 // Test enabling the GL_ANGLE_framebuffer_blit extension TEST_P(WebGLCompatibilityTest,EnableFramebufferBlitExtension)1124 TEST_P(WebGLCompatibilityTest, EnableFramebufferBlitExtension) 1125 { 1126 EXPECT_FALSE(IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit")); 1127 1128 // This extensions become core in in ES3/WebGL2. 1129 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 1130 1131 GLFramebuffer fbo; 1132 1133 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo); 1134 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1135 1136 GLint result; 1137 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result); 1138 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1139 1140 glBlitFramebufferANGLE(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); 1141 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1142 1143 if (IsGLExtensionRequestable("GL_ANGLE_framebuffer_blit")) 1144 { 1145 glRequestExtensionANGLE("GL_ANGLE_framebuffer_blit"); 1146 EXPECT_GL_NO_ERROR(); 1147 1148 glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo); 1149 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_ANGLE, &result); 1150 EXPECT_GL_NO_ERROR(); 1151 } 1152 } 1153 1154 // Test enabling the GL_OES_get_program_binary extension TEST_P(WebGLCompatibilityTest,EnableProgramBinaryExtension)1155 TEST_P(WebGLCompatibilityTest, EnableProgramBinaryExtension) 1156 { 1157 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_get_program_binary")); 1158 1159 // This extensions become core in in ES3/WebGL2. 1160 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 1161 1162 GLint result = 0; 1163 GLint numBinaryFormats = 0; 1164 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats); 1165 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1166 1167 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result); 1168 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1169 1170 constexpr char kVS[] = 1171 R"(void main() 1172 { 1173 gl_Position = vec4(0.0, 0.0, 0.0, 1.0); 1174 })"; 1175 constexpr char kFS[] = 1176 R"(precision highp float; 1177 void main() 1178 { 1179 gl_FragColor = vec4(1.0); 1180 })"; 1181 ANGLE_GL_PROGRAM(program, kVS, kFS); 1182 1183 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &result); 1184 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1185 1186 uint8_t tempArray[512]; 1187 GLenum tempFormat = 0; 1188 GLsizei tempLength = 0; 1189 glGetProgramBinaryOES(program, static_cast<GLsizei>(ArraySize(tempArray)), &tempLength, 1190 &tempFormat, tempArray); 1191 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1192 1193 if (IsGLExtensionRequestable("GL_OES_get_program_binary")) 1194 { 1195 glRequestExtensionANGLE("GL_OES_get_program_binary"); 1196 EXPECT_GL_NO_ERROR(); 1197 1198 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats); 1199 // No use to test further if no binary formats are supported 1200 ANGLE_SKIP_TEST_IF(numBinaryFormats < 1); 1201 1202 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &result); 1203 EXPECT_GL_NO_ERROR(); 1204 1205 GLint binaryLength = 0; 1206 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength); 1207 EXPECT_GL_NO_ERROR(); 1208 1209 GLenum binaryFormat; 1210 GLsizei writeLength = 0; 1211 std::vector<uint8_t> binary(binaryLength); 1212 glGetProgramBinaryOES(program, binaryLength, &writeLength, &binaryFormat, binary.data()); 1213 EXPECT_GL_NO_ERROR(); 1214 1215 glProgramBinaryOES(program, binaryFormat, binary.data(), binaryLength); 1216 EXPECT_GL_NO_ERROR(); 1217 } 1218 } 1219 1220 // Test enabling the GL_OES_vertex_array_object extension TEST_P(WebGLCompatibilityTest,EnableVertexArrayExtension)1221 TEST_P(WebGLCompatibilityTest, EnableVertexArrayExtension) 1222 { 1223 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_vertex_array_object")); 1224 1225 // This extensions become core in in ES3/WebGL2. 1226 ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3); 1227 1228 GLint result = 0; 1229 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result); 1230 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1231 1232 // Expect that GL_OES_vertex_array_object is always available. It is implemented in the GL 1233 // frontend. 1234 EXPECT_TRUE(IsGLExtensionRequestable("GL_OES_vertex_array_object")); 1235 1236 glRequestExtensionANGLE("GL_OES_vertex_array_object"); 1237 EXPECT_GL_NO_ERROR(); 1238 1239 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_vertex_array_object")); 1240 1241 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result); 1242 EXPECT_GL_NO_ERROR(); 1243 1244 GLuint vao = 0; 1245 glGenVertexArraysOES(0, &vao); 1246 EXPECT_GL_NO_ERROR(); 1247 1248 glBindVertexArrayOES(vao); 1249 EXPECT_GL_NO_ERROR(); 1250 1251 glDeleteVertexArraysOES(1, &vao); 1252 EXPECT_GL_NO_ERROR(); 1253 } 1254 1255 // Verify that the context generates the correct error when the framebuffer attachments are 1256 // different sizes TEST_P(WebGLCompatibilityTest,FramebufferAttachmentSizeMismatch)1257 TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch) 1258 { 1259 GLFramebuffer fbo; 1260 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 1261 1262 GLTexture textures[2]; 1263 glBindTexture(GL_TEXTURE_2D, textures[0]); 1264 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1265 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0); 1266 1267 ASSERT_GL_NO_ERROR(); 1268 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 1269 1270 GLRenderbuffer renderbuffer; 1271 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 1272 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 3, 3); 1273 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer); 1274 1275 ASSERT_GL_NO_ERROR(); 1276 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, 1277 glCheckFramebufferStatus(GL_FRAMEBUFFER)); 1278 1279 if (IsGLExtensionRequestable("GL_EXT_draw_buffers")) 1280 { 1281 glRequestExtensionANGLE("GL_EXT_draw_buffers"); 1282 EXPECT_GL_NO_ERROR(); 1283 EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers")); 1284 1285 glBindTexture(GL_TEXTURE_2D, textures[1]); 1286 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1287 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0); 1288 ASSERT_GL_NO_ERROR(); 1289 1290 ASSERT_GL_NO_ERROR(); 1291 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, 1292 glCheckFramebufferStatus(GL_FRAMEBUFFER)); 1293 1294 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); 1295 1296 ASSERT_GL_NO_ERROR(); 1297 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 1298 1299 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1300 1301 ASSERT_GL_NO_ERROR(); 1302 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, 1303 glCheckFramebufferStatus(GL_FRAMEBUFFER)); 1304 } 1305 } 1306 1307 // Test that client-side array buffers are forbidden in WebGL mode TEST_P(WebGLCompatibilityTest,ForbidsClientSideArrayBuffer)1308 TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBuffer) 1309 { 1310 constexpr char kVS[] = 1311 R"(attribute vec3 a_pos; 1312 void main() 1313 { 1314 gl_Position = vec4(a_pos, 1.0); 1315 })"; 1316 1317 constexpr char kFS[] = 1318 R"(precision highp float; 1319 void main() 1320 { 1321 gl_FragColor = vec4(1.0); 1322 })"; 1323 1324 ANGLE_GL_PROGRAM(program, kVS, kFS); 1325 1326 GLint posLocation = glGetAttribLocation(program, "a_pos"); 1327 ASSERT_NE(-1, posLocation); 1328 glUseProgram(program); 1329 1330 const auto &vertices = GetQuadVertices(); 1331 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 4, vertices.data()); 1332 glEnableVertexAttribArray(posLocation); 1333 1334 ASSERT_GL_NO_ERROR(); 1335 glDrawArrays(GL_TRIANGLES, 0, 6); 1336 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1337 } 1338 1339 // Test that client-side element array buffers are forbidden in WebGL mode TEST_P(WebGLCompatibilityTest,ForbidsClientSideElementBuffer)1340 TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer) 1341 { 1342 constexpr char kVS[] = 1343 R"(attribute vec3 a_pos; 1344 void main() 1345 { 1346 gl_Position = vec4(a_pos, 1.0); 1347 })"; 1348 1349 constexpr char kFS[] = 1350 R"(precision highp float; 1351 void main() 1352 { 1353 gl_FragColor = vec4(1.0); 1354 })"; 1355 1356 ANGLE_GL_PROGRAM(program, kVS, kFS); 1357 1358 GLint posLocation = glGetAttribLocation(program, "a_pos"); 1359 ASSERT_NE(-1, posLocation); 1360 glUseProgram(program); 1361 1362 const auto &vertices = GetQuadVertices(); 1363 1364 GLBuffer vertexBuffer; 1365 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 1366 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(), 1367 GL_STATIC_DRAW); 1368 1369 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); 1370 glEnableVertexAttribArray(posLocation); 1371 1372 ASSERT_GL_NO_ERROR(); 1373 1374 // Use the pointer with value of 1 for indices instead of an actual pointer because WebGL also 1375 // enforces that the top bit of indices must be 0 (i.e. offset >= 0) and would generate 1376 // GL_INVALID_VALUE in that case. Using a null pointer gets caught by another check. 1377 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(intptr_t(1))); 1378 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1379 } 1380 1381 // Test that client-side array buffers are forbidden even if the program doesn't use the attribute TEST_P(WebGLCompatibilityTest,ForbidsClientSideArrayBufferEvenNotUsedOnes)1382 TEST_P(WebGLCompatibilityTest, ForbidsClientSideArrayBufferEvenNotUsedOnes) 1383 { 1384 constexpr char kVS[] = 1385 R"(void main() 1386 { 1387 gl_Position = vec4(1.0); 1388 })"; 1389 1390 constexpr char kFS[] = 1391 R"(precision highp float; 1392 void main() 1393 { 1394 gl_FragColor = vec4(1.0); 1395 })"; 1396 1397 ANGLE_GL_PROGRAM(program, kVS, kFS); 1398 1399 glUseProgram(program); 1400 1401 const auto &vertices = GetQuadVertices(); 1402 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data()); 1403 glEnableVertexAttribArray(0); 1404 1405 ASSERT_GL_NO_ERROR(); 1406 glDrawArrays(GL_TRIANGLES, 0, 6); 1407 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1408 } 1409 1410 // Test that passing a null pixel data pointer to TexSubImage calls generates an INVALID_VALUE error TEST_P(WebGLCompatibilityTest,NullPixelDataForSubImage)1411 TEST_P(WebGLCompatibilityTest, NullPixelDataForSubImage) 1412 { 1413 // glTexSubImage2D 1414 { 1415 GLTexture texture; 1416 glBindTexture(GL_TEXTURE_2D, texture); 1417 1418 // TexImage with null data - OK 1419 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1420 EXPECT_GL_NO_ERROR(); 1421 1422 // TexSubImage with zero size and null data - OK 1423 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1424 EXPECT_GL_NO_ERROR(); 1425 1426 // TexSubImage with non-zero size and null data - Invalid value 1427 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1428 EXPECT_GL_ERROR(GL_INVALID_VALUE); 1429 } 1430 1431 // glTexSubImage3D 1432 if (getClientMajorVersion() >= 3) 1433 { 1434 GLTexture texture; 1435 glBindTexture(GL_TEXTURE_3D, texture); 1436 1437 // TexImage with null data - OK 1438 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1439 EXPECT_GL_NO_ERROR(); 1440 1441 // TexSubImage with zero size and null data - OK 1442 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1443 EXPECT_GL_NO_ERROR(); 1444 1445 // TexSubImage with non-zero size and null data - Invalid value 1446 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 1447 EXPECT_GL_ERROR(GL_INVALID_VALUE); 1448 } 1449 } 1450 1451 // Tests the WebGL requirement of having the same stencil mask, writemask and ref for front and back 1452 // (when stencil testing is enabled) TestDifferentStencilMaskAndRef(GLenum errIfMismatch)1453 void WebGLCompatibilityTest::TestDifferentStencilMaskAndRef(GLenum errIfMismatch) 1454 { 1455 // Run the test in an FBO to make sure we have some stencil bits. 1456 GLRenderbuffer renderbuffer; 1457 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 1458 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32); 1459 1460 GLFramebuffer framebuffer; 1461 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 1462 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 1463 renderbuffer); 1464 1465 ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }", 1466 "void main() { gl_FragColor = vec4(0, 1, 0, 1); }"); 1467 glUseProgram(program); 1468 ASSERT_GL_NO_ERROR(); 1469 1470 // Having ref and mask the same for front and back is valid. 1471 glStencilMask(255); 1472 glStencilFunc(GL_ALWAYS, 0, 255); 1473 glDrawArrays(GL_TRIANGLES, 0, 6); 1474 ASSERT_GL_NO_ERROR(); 1475 1476 // Having a different front - back write mask generates an error. 1477 glStencilMaskSeparate(GL_FRONT, 1); 1478 glDrawArrays(GL_TRIANGLES, 0, 6); 1479 EXPECT_GL_ERROR(errIfMismatch); 1480 1481 // Setting both write masks separately to the same value is valid. 1482 glStencilMaskSeparate(GL_BACK, 1); 1483 glDrawArrays(GL_TRIANGLES, 0, 6); 1484 ASSERT_GL_NO_ERROR(); 1485 1486 // Having a different stencil front - back mask generates an error 1487 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1); 1488 glDrawArrays(GL_TRIANGLES, 0, 6); 1489 EXPECT_GL_ERROR(errIfMismatch); 1490 1491 // Setting both masks separately to the same value is valid. 1492 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1); 1493 glDrawArrays(GL_TRIANGLES, 0, 6); 1494 ASSERT_GL_NO_ERROR(); 1495 1496 // Having a different stencil front - back reference generates an error 1497 glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1); 1498 glDrawArrays(GL_TRIANGLES, 0, 6); 1499 EXPECT_GL_ERROR(errIfMismatch); 1500 1501 // Setting both references separately to the same value is valid. 1502 glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1); 1503 glDrawArrays(GL_TRIANGLES, 0, 6); 1504 ASSERT_GL_NO_ERROR(); 1505 1506 // Using different stencil funcs, everything being equal is valid. 1507 glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1); 1508 glDrawArrays(GL_TRIANGLES, 0, 6); 1509 ASSERT_GL_NO_ERROR(); 1510 } 1511 TEST_P(WebGLCompatibilityTest,StencilTestEnabledDisallowsDifferentStencilMaskAndRef)1512 TEST_P(WebGLCompatibilityTest, StencilTestEnabledDisallowsDifferentStencilMaskAndRef) 1513 { 1514 glEnable(GL_STENCIL_TEST); 1515 TestDifferentStencilMaskAndRef(GL_INVALID_OPERATION); 1516 } 1517 TEST_P(WebGLCompatibilityTest,StencilTestDisabledAllowsDifferentStencilMaskAndRef)1518 TEST_P(WebGLCompatibilityTest, StencilTestDisabledAllowsDifferentStencilMaskAndRef) 1519 { 1520 glDisable(GL_STENCIL_TEST); 1521 TestDifferentStencilMaskAndRef(GL_NO_ERROR); 1522 } 1523 1524 // Test that GL_FIXED is forbidden TEST_P(WebGLCompatibilityTest,ForbidsGLFixed)1525 TEST_P(WebGLCompatibilityTest, ForbidsGLFixed) 1526 { 1527 GLBuffer buffer; 1528 glBindBuffer(GL_ARRAY_BUFFER, buffer); 1529 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW); 1530 1531 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr); 1532 ASSERT_GL_NO_ERROR(); 1533 1534 glVertexAttribPointer(0, 1, GL_FIXED, GL_FALSE, 0, nullptr); 1535 EXPECT_GL_ERROR(GL_INVALID_ENUM); 1536 } 1537 1538 // Test the WebGL limit of 255 for the attribute stride TEST_P(WebGLCompatibilityTest,MaxStride)1539 TEST_P(WebGLCompatibilityTest, MaxStride) 1540 { 1541 GLBuffer buffer; 1542 glBindBuffer(GL_ARRAY_BUFFER, buffer); 1543 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW); 1544 1545 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 255, nullptr); 1546 ASSERT_GL_NO_ERROR(); 1547 1548 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 256, nullptr); 1549 EXPECT_GL_ERROR(GL_INVALID_VALUE); 1550 } 1551 1552 // Test the checks for OOB reads in the vertex buffers, non-instanced version TEST_P(WebGLCompatibilityTest,DrawArraysBufferOutOfBoundsNonInstanced)1553 TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced) 1554 { 1555 constexpr char kVS[] = 1556 R"(attribute float a_pos; 1557 void main() 1558 { 1559 gl_Position = vec4(a_pos, a_pos, a_pos, 1.0); 1560 })"; 1561 1562 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 1563 GLint posLocation = glGetAttribLocation(program, "a_pos"); 1564 ASSERT_NE(-1, posLocation); 1565 glUseProgram(program); 1566 1567 GLBuffer buffer; 1568 glBindBuffer(GL_ARRAY_BUFFER, buffer); 1569 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW); 1570 1571 glEnableVertexAttribArray(posLocation); 1572 1573 const uint8_t *zeroOffset = nullptr; 1574 1575 // Test touching the last element is valid. 1576 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12); 1577 glDrawArrays(GL_POINTS, 0, 4); 1578 ASSERT_GL_NO_ERROR(); 1579 1580 // Test touching the last element + 1 is invalid. 1581 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13); 1582 glDrawArrays(GL_POINTS, 0, 4); 1583 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1584 1585 // Test touching the last element is valid, using a stride. 1586 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9); 1587 glDrawArrays(GL_POINTS, 0, 4); 1588 ASSERT_GL_NO_ERROR(); 1589 1590 // Test touching the last element + 1 is invalid, using a stride. 1591 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10); 1592 glDrawArrays(GL_POINTS, 0, 4); 1593 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1594 1595 // Test any offset is valid if no vertices are drawn. 1596 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32); 1597 glDrawArrays(GL_POINTS, 0, 0); 1598 ASSERT_GL_NO_ERROR(); 1599 1600 // Test a case of overflow that could give a max vertex that's negative 1601 constexpr GLint kIntMax = std::numeric_limits<GLint>::max(); 1602 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 0); 1603 glDrawArrays(GL_POINTS, kIntMax, kIntMax); 1604 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1605 } 1606 1607 // Test that index values outside of the 32-bit integer range do not read out of bounds TEST_P(WebGLCompatibilityTest,LargeIndexRange)1608 TEST_P(WebGLCompatibilityTest, LargeIndexRange) 1609 { 1610 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_element_index_uint")); 1611 1612 constexpr char kVS[] = 1613 R"(attribute vec4 a_Position; 1614 void main() 1615 { 1616 gl_Position = a_Position; 1617 })"; 1618 1619 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 1620 glUseProgram(program); 1621 1622 glEnableVertexAttribArray(glGetAttribLocation(program, "a_Position")); 1623 1624 constexpr float kVertexData[] = { 1625 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1626 }; 1627 1628 GLBuffer vertexBuffer; 1629 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 1630 glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData, GL_STREAM_DRAW); 1631 1632 constexpr GLuint kMaxIntAsGLuint = static_cast<GLuint>(std::numeric_limits<GLint>::max()); 1633 constexpr GLuint kIndexData[] = { 1634 kMaxIntAsGLuint, 1635 kMaxIntAsGLuint + 1, 1636 kMaxIntAsGLuint + 2, 1637 kMaxIntAsGLuint + 3, 1638 }; 1639 1640 GLBuffer indexBuffer; 1641 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBuffer); 1642 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData, GL_DYNAMIC_DRAW); 1643 1644 EXPECT_GL_NO_ERROR(); 1645 1646 // First index is representable as 32-bit int but second is not 1647 glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0); 1648 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1649 1650 // Neither index is representable as 32-bit int 1651 glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, reinterpret_cast<void *>(sizeof(GLuint) * 2)); 1652 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1653 } 1654 1655 // Test for drawing with a null index buffer TEST_P(WebGLCompatibilityTest,NullIndexBuffer)1656 TEST_P(WebGLCompatibilityTest, NullIndexBuffer) 1657 { 1658 constexpr char kVS[] = 1659 R"(attribute float a_pos; 1660 void main() 1661 { 1662 gl_Position = vec4(a_pos, a_pos, a_pos, 1.0); 1663 })"; 1664 1665 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 1666 glUseProgram(program); 1667 1668 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1669 glEnableVertexAttribArray(0); 1670 1671 glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_BYTE, 0); 1672 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1673 } 1674 1675 // Test the checks for OOB reads in the vertex buffers, instanced version TEST_P(WebGL2CompatibilityTest,DrawArraysBufferOutOfBoundsInstanced)1676 TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced) 1677 { 1678 constexpr char kVS[] = 1679 R"(attribute float a_pos; 1680 attribute float a_w; 1681 void main() 1682 { 1683 gl_Position = vec4(a_pos, a_pos, a_pos, a_w); 1684 })"; 1685 1686 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 1687 GLint posLocation = glGetAttribLocation(program, "a_pos"); 1688 GLint wLocation = glGetAttribLocation(program, "a_w"); 1689 ASSERT_NE(-1, posLocation); 1690 ASSERT_NE(-1, wLocation); 1691 glUseProgram(program); 1692 1693 GLBuffer buffer; 1694 glBindBuffer(GL_ARRAY_BUFFER, buffer); 1695 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW); 1696 1697 glEnableVertexAttribArray(posLocation); 1698 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0); 1699 glVertexAttribDivisor(posLocation, 0); 1700 1701 glEnableVertexAttribArray(wLocation); 1702 glVertexAttribDivisor(wLocation, 1); 1703 1704 const uint8_t *zeroOffset = nullptr; 1705 1706 // Test touching the last element is valid. 1707 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12); 1708 glDrawArraysInstanced(GL_POINTS, 0, 1, 4); 1709 ASSERT_GL_NO_ERROR(); 1710 1711 // Test touching the last element + 1 is invalid. 1712 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13); 1713 glDrawArraysInstanced(GL_POINTS, 0, 1, 4); 1714 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1715 1716 // Test touching the last element is valid, using a stride. 1717 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9); 1718 glDrawArraysInstanced(GL_POINTS, 0, 1, 4); 1719 ASSERT_GL_NO_ERROR(); 1720 1721 // Test touching the last element + 1 is invalid, using a stride. 1722 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10); 1723 glDrawArraysInstanced(GL_POINTS, 0, 1, 4); 1724 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1725 1726 // Test any offset is valid if no vertices are drawn. 1727 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32); 1728 glDrawArraysInstanced(GL_POINTS, 0, 0, 1); 1729 ASSERT_GL_NO_ERROR(); 1730 1731 // Test any offset is valid if no primitives are drawn. 1732 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32); 1733 glDrawArraysInstanced(GL_POINTS, 0, 1, 0); 1734 ASSERT_GL_NO_ERROR(); 1735 } 1736 1737 // Test the checks for OOB reads in the vertex buffers, ANGLE_instanced_arrays version TEST_P(WebGLCompatibilityTest,DrawArraysBufferOutOfBoundsInstancedANGLE)1738 TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsInstancedANGLE) 1739 { 1740 ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_ANGLE_instanced_arrays")); 1741 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays"); 1742 EXPECT_GL_NO_ERROR(); 1743 1744 constexpr char kVS[] = 1745 R"(attribute float a_pos; 1746 attribute float a_w; 1747 void main() 1748 { 1749 gl_Position = vec4(a_pos, a_pos, a_pos, a_w); 1750 })"; 1751 1752 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 1753 GLint posLocation = glGetAttribLocation(program, "a_pos"); 1754 GLint wLocation = glGetAttribLocation(program, "a_w"); 1755 ASSERT_NE(-1, posLocation); 1756 ASSERT_NE(-1, wLocation); 1757 glUseProgram(program); 1758 1759 GLBuffer buffer; 1760 glBindBuffer(GL_ARRAY_BUFFER, buffer); 1761 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW); 1762 1763 glEnableVertexAttribArray(posLocation); 1764 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0); 1765 glVertexAttribDivisorANGLE(posLocation, 0); 1766 1767 glEnableVertexAttribArray(wLocation); 1768 glVertexAttribDivisorANGLE(wLocation, 1); 1769 1770 const uint8_t *zeroOffset = nullptr; 1771 1772 // Test touching the last element is valid. 1773 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 12); 1774 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4); 1775 ASSERT_GL_NO_ERROR() << "touching the last element."; 1776 1777 // Test touching the last element + 1 is invalid. 1778 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 13); 1779 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4); 1780 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "touching the last element + 1."; 1781 1782 // Test touching the last element is valid, using a stride. 1783 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 9); 1784 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4); 1785 ASSERT_GL_NO_ERROR() << "touching the last element using a stride."; 1786 1787 // Test touching the last element + 1 is invalid, using a stride. 1788 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 2, zeroOffset + 10); 1789 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 4); 1790 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "touching the last element + 1 using a stride."; 1791 1792 // Test any offset is valid if no vertices are drawn. 1793 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32); 1794 glDrawArraysInstancedANGLE(GL_POINTS, 0, 0, 1); 1795 ASSERT_GL_NO_ERROR() << "any offset with no vertices."; 1796 1797 // Test any offset is valid if no primitives are drawn. 1798 glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset + 32); 1799 glDrawArraysInstancedANGLE(GL_POINTS, 0, 1, 0); 1800 ASSERT_GL_NO_ERROR() << "any offset with primitives."; 1801 } 1802 1803 // Test the checks for OOB reads in the index buffer TEST_P(WebGLCompatibilityTest,DrawElementsBufferOutOfBoundsInIndexBuffer)1804 TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer) 1805 { 1806 constexpr char kVS[] = 1807 R"(attribute float a_pos; 1808 void main() 1809 { 1810 gl_Position = vec4(a_pos, a_pos, a_pos, 1.0); 1811 })"; 1812 1813 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 1814 GLint posLocation = glGetAttribLocation(program, "a_pos"); 1815 ASSERT_NE(-1, posLocation); 1816 glUseProgram(program); 1817 1818 GLBuffer vertexBuffer; 1819 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 1820 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW); 1821 1822 glEnableVertexAttribArray(posLocation); 1823 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr); 1824 1825 const uint8_t *zeroOffset = nullptr; 1826 const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0}; 1827 1828 GLBuffer indexBuffer; 1829 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 1830 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW); 1831 ASSERT_GL_NO_ERROR(); 1832 1833 // Test touching the last index is valid 1834 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4); 1835 ASSERT_GL_NO_ERROR(); 1836 1837 // Test touching the last + 1 element is invalid 1838 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5); 1839 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1840 1841 // Test any offset if valid if count is zero 1842 glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42); 1843 ASSERT_GL_NO_ERROR(); 1844 1845 // Test touching the first index is valid 1846 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4); 1847 ASSERT_GL_NO_ERROR(); 1848 1849 // Test touching the first - 1 index is invalid 1850 // The error ha been specified to be INVALID_VALUE instead of INVALID_OPERATION because it was 1851 // the historic behavior of WebGL implementations 1852 glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset - 1); 1853 EXPECT_GL_ERROR(GL_INVALID_VALUE); 1854 } 1855 1856 // Test the checks for OOB in vertex buffers caused by indices, non-instanced version TEST_P(WebGLCompatibilityTest,DrawElementsBufferOutOfBoundsInVertexBuffer)1857 TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInVertexBuffer) 1858 { 1859 constexpr char kVS[] = 1860 R"(attribute float a_pos; 1861 void main() 1862 { 1863 gl_Position = vec4(a_pos, a_pos, a_pos, 1.0); 1864 })"; 1865 1866 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 1867 GLint posLocation = glGetAttribLocation(program, "a_pos"); 1868 ASSERT_NE(-1, posLocation); 1869 glUseProgram(program); 1870 1871 GLBuffer vertexBuffer; 1872 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 1873 glBufferData(GL_ARRAY_BUFFER, 8, nullptr, GL_STATIC_DRAW); 1874 1875 glEnableVertexAttribArray(posLocation); 1876 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr); 1877 1878 const uint8_t *zeroOffset = nullptr; 1879 const uint8_t testIndices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 255}; 1880 1881 GLBuffer indexBuffer; 1882 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 1883 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(testIndices), testIndices, GL_STATIC_DRAW); 1884 ASSERT_GL_NO_ERROR(); 1885 1886 // Test touching the end of the vertex buffer is valid 1887 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 7); 1888 ASSERT_GL_NO_ERROR(); 1889 1890 // Test touching just after the end of the vertex buffer is invalid 1891 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 8); 1892 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1893 1894 // Test touching the whole vertex buffer is valid 1895 glDrawElements(GL_POINTS, 8, GL_UNSIGNED_BYTE, zeroOffset + 0); 1896 ASSERT_GL_NO_ERROR(); 1897 1898 // Test an index that would be negative 1899 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, zeroOffset + 9); 1900 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1901 } 1902 1903 // Test depth range with 'near' more or less than 'far.' TEST_P(WebGLCompatibilityTest,DepthRange)1904 TEST_P(WebGLCompatibilityTest, DepthRange) 1905 { 1906 glDepthRangef(0, 1); 1907 ASSERT_GL_NO_ERROR(); 1908 1909 glDepthRangef(.5, .5); 1910 ASSERT_GL_NO_ERROR(); 1911 1912 glDepthRangef(1, 0); 1913 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 1914 } 1915 1916 // Test all blend function combinations. 1917 // In WebGL it is invalid to combine constant color with constant alpha. TEST_P(WebGLCompatibilityTest,BlendWithConstantColor)1918 TEST_P(WebGLCompatibilityTest, BlendWithConstantColor) 1919 { 1920 constexpr GLenum srcFunc[] = { 1921 GL_ZERO, 1922 GL_ONE, 1923 GL_SRC_COLOR, 1924 GL_ONE_MINUS_SRC_COLOR, 1925 GL_DST_COLOR, 1926 GL_ONE_MINUS_DST_COLOR, 1927 GL_SRC_ALPHA, 1928 GL_ONE_MINUS_SRC_ALPHA, 1929 GL_DST_ALPHA, 1930 GL_ONE_MINUS_DST_ALPHA, 1931 GL_CONSTANT_COLOR, 1932 GL_ONE_MINUS_CONSTANT_COLOR, 1933 GL_CONSTANT_ALPHA, 1934 GL_ONE_MINUS_CONSTANT_ALPHA, 1935 GL_SRC_ALPHA_SATURATE, 1936 }; 1937 1938 constexpr GLenum dstFunc[] = { 1939 GL_ZERO, GL_ONE, 1940 GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, 1941 GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, 1942 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1943 GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, 1944 GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, 1945 GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, 1946 }; 1947 1948 for (GLenum src : srcFunc) 1949 { 1950 for (GLenum dst : dstFunc) 1951 { 1952 glBlendFunc(src, dst); 1953 CheckBlendFunctions(src, dst); 1954 glBlendFuncSeparate(src, dst, GL_ONE, GL_ONE); 1955 CheckBlendFunctions(src, dst); 1956 } 1957 } 1958 1959 // Ensure the same semantics for indexed blendFunc 1960 if (IsGLExtensionRequestable("GL_OES_draw_buffers_indexed")) 1961 { 1962 glRequestExtensionANGLE("GL_OES_draw_buffers_indexed"); 1963 EXPECT_GL_NO_ERROR(); 1964 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")); 1965 1966 for (GLenum src : srcFunc) 1967 { 1968 for (GLenum dst : dstFunc) 1969 { 1970 glBlendFunciOES(0, src, dst); 1971 CheckBlendFunctions(src, dst); 1972 glBlendFuncSeparateiOES(0, src, dst, GL_ONE, GL_ONE); 1973 CheckBlendFunctions(src, dst); 1974 } 1975 } 1976 } 1977 } 1978 1979 // Test draw state validation and invalidation wrt indexed blendFunc. TEST_P(WebGLCompatibilityTest,IndexedBlendWithConstantColorInvalidation)1980 TEST_P(WebGLCompatibilityTest, IndexedBlendWithConstantColorInvalidation) 1981 { 1982 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); 1983 ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_OES_draw_buffers_indexed")); 1984 1985 glRequestExtensionANGLE("GL_OES_draw_buffers_indexed"); 1986 EXPECT_GL_NO_ERROR(); 1987 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")); 1988 1989 constexpr char kVS[] = 1990 R"(#version 300 es 1991 void main() 1992 { 1993 gl_PointSize = 1.0; 1994 gl_Position = vec4(0, 0, 0, 1); 1995 })"; 1996 1997 constexpr char kFS[] = 1998 R"(#version 300 es 1999 precision lowp float; 2000 layout(location = 0) out vec4 o_color0; 2001 layout(location = 1) out vec4 o_color1; 2002 void main() 2003 { 2004 o_color0 = vec4(1, 0, 0, 1); 2005 o_color1 = vec4(0, 1, 0, 1); 2006 })"; 2007 2008 ANGLE_GL_PROGRAM(program, kVS, kFS); 2009 glUseProgram(program); 2010 2011 glDisable(GL_BLEND); 2012 glEnableiOES(GL_BLEND, 0); 2013 glEnableiOES(GL_BLEND, 1); 2014 2015 GLTexture texture1; 2016 glBindTexture(GL_TEXTURE_2D, texture1); 2017 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2018 EXPECT_GL_NO_ERROR(); 2019 2020 GLTexture texture2; 2021 glBindTexture(GL_TEXTURE_2D, texture2); 2022 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2023 EXPECT_GL_NO_ERROR(); 2024 2025 GLFramebuffer fbo; 2026 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 2027 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); 2028 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2, 0); 2029 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 2030 2031 GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; 2032 glDrawBuffers(2, drawbuffers); 2033 2034 glDrawArrays(GL_POINTS, 0, 1); 2035 EXPECT_GL_NO_ERROR(); 2036 2037 // Force-invalidate draw call 2038 glBlendFuncSeparateiOES(0, GL_CONSTANT_COLOR, GL_CONSTANT_COLOR, GL_CONSTANT_ALPHA, 2039 GL_CONSTANT_ALPHA); 2040 EXPECT_GL_NO_ERROR(); 2041 2042 glBlendFuncSeparateiOES(1, GL_CONSTANT_ALPHA, GL_CONSTANT_ALPHA, GL_CONSTANT_COLOR, 2043 GL_CONSTANT_COLOR); 2044 EXPECT_GL_NO_ERROR(); 2045 2046 glDrawArrays(GL_POINTS, 0, 1); 2047 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2048 } 2049 2050 // Test getIndexedParameter wrt GL_OES_draw_buffers_indexed. TEST_P(WebGLCompatibilityTest,DrawBuffersIndexedGetIndexedParameter)2051 TEST_P(WebGLCompatibilityTest, DrawBuffersIndexedGetIndexedParameter) 2052 { 2053 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); 2054 ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_OES_draw_buffers_indexed")); 2055 2056 GLint value; 2057 GLboolean data[4]; 2058 2059 glGetIntegeri_v(GL_BLEND_EQUATION_RGB, 0, &value); 2060 EXPECT_GL_ERROR(GL_INVALID_ENUM); 2061 glGetIntegeri_v(GL_BLEND_EQUATION_ALPHA, 0, &value); 2062 EXPECT_GL_ERROR(GL_INVALID_ENUM); 2063 glGetIntegeri_v(GL_BLEND_SRC_RGB, 0, &value); 2064 EXPECT_GL_ERROR(GL_INVALID_ENUM); 2065 glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 0, &value); 2066 EXPECT_GL_ERROR(GL_INVALID_ENUM); 2067 glGetIntegeri_v(GL_BLEND_DST_RGB, 0, &value); 2068 EXPECT_GL_ERROR(GL_INVALID_ENUM); 2069 glGetIntegeri_v(GL_BLEND_DST_ALPHA, 0, &value); 2070 EXPECT_GL_ERROR(GL_INVALID_ENUM); 2071 glGetBooleani_v(GL_COLOR_WRITEMASK, 0, data); 2072 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2073 2074 glRequestExtensionANGLE("GL_OES_draw_buffers_indexed"); 2075 EXPECT_GL_NO_ERROR(); 2076 EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_draw_buffers_indexed")); 2077 2078 glDisable(GL_BLEND); 2079 glEnableiOES(GL_BLEND, 0); 2080 glBlendEquationSeparateiOES(0, GL_FUNC_ADD, GL_FUNC_SUBTRACT); 2081 glBlendFuncSeparateiOES(0, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ZERO); 2082 glColorMaskiOES(0, true, false, true, false); 2083 EXPECT_GL_NO_ERROR(); 2084 2085 EXPECT_EQ(true, glIsEnablediOES(GL_BLEND, 0)); 2086 EXPECT_GL_NO_ERROR(); 2087 glGetIntegeri_v(GL_BLEND_EQUATION_RGB, 0, &value); 2088 EXPECT_GL_NO_ERROR(); 2089 EXPECT_EQ(GL_FUNC_ADD, value); 2090 glGetIntegeri_v(GL_BLEND_EQUATION_ALPHA, 0, &value); 2091 EXPECT_GL_NO_ERROR(); 2092 EXPECT_EQ(GL_FUNC_SUBTRACT, value); 2093 glGetIntegeri_v(GL_BLEND_SRC_RGB, 0, &value); 2094 EXPECT_GL_NO_ERROR(); 2095 EXPECT_EQ(GL_SRC_ALPHA, value); 2096 glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 0, &value); 2097 EXPECT_GL_NO_ERROR(); 2098 EXPECT_EQ(GL_ZERO, value); 2099 glGetIntegeri_v(GL_BLEND_DST_RGB, 0, &value); 2100 EXPECT_GL_NO_ERROR(); 2101 EXPECT_EQ(GL_ONE_MINUS_SRC_ALPHA, value); 2102 glGetIntegeri_v(GL_BLEND_DST_ALPHA, 0, &value); 2103 EXPECT_GL_NO_ERROR(); 2104 EXPECT_EQ(GL_ZERO, value); 2105 glGetBooleani_v(GL_COLOR_WRITEMASK, 0, data); 2106 EXPECT_GL_NO_ERROR(); 2107 EXPECT_EQ(true, data[0]); 2108 EXPECT_EQ(false, data[1]); 2109 EXPECT_EQ(true, data[2]); 2110 EXPECT_EQ(false, data[3]); 2111 } 2112 2113 // Test that binding/querying uniforms and attributes with invalid names generates errors TEST_P(WebGLCompatibilityTest,InvalidAttributeAndUniformNames)2114 TEST_P(WebGLCompatibilityTest, InvalidAttributeAndUniformNames) 2115 { 2116 const std::string validAttribName = 2117 "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 2118 const std::string validUniformName = 2119 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890"; 2120 std::vector<char> invalidSet = {'"', '$', '`', '@', '\''}; 2121 if (getClientMajorVersion() < 3) 2122 { 2123 invalidSet.push_back('\\'); 2124 } 2125 2126 std::string vert = "attribute float "; 2127 vert += validAttribName; 2128 vert += 2129 R"(; 2130 void main() 2131 { 2132 gl_Position = vec4(1.0); 2133 })"; 2134 2135 std::string frag = 2136 R"(precision highp float; 2137 uniform vec4 )"; 2138 frag += validUniformName; 2139 // Insert illegal characters into comments 2140 frag += 2141 R"(; 2142 // $ \" @ /* 2143 void main() 2144 {/* 2145 ` @ $ 2146 */gl_FragColor = vec4(1.0); 2147 })"; 2148 2149 ANGLE_GL_PROGRAM(program, vert.c_str(), frag.c_str()); 2150 EXPECT_GL_NO_ERROR(); 2151 2152 for (char invalidChar : invalidSet) 2153 { 2154 std::string invalidName = validAttribName + invalidChar; 2155 glGetAttribLocation(program, invalidName.c_str()); 2156 EXPECT_GL_ERROR(GL_INVALID_VALUE) 2157 << "glGetAttribLocation unexpectedly succeeded for name \"" << invalidName << "\"."; 2158 2159 glBindAttribLocation(program, 0, invalidName.c_str()); 2160 EXPECT_GL_ERROR(GL_INVALID_VALUE) 2161 << "glBindAttribLocation unexpectedly succeeded for name \"" << invalidName << "\"."; 2162 } 2163 2164 for (char invalidChar : invalidSet) 2165 { 2166 std::string invalidName = validUniformName + invalidChar; 2167 glGetUniformLocation(program, invalidName.c_str()); 2168 EXPECT_GL_ERROR(GL_INVALID_VALUE) 2169 << "glGetUniformLocation unexpectedly succeeded for name \"" << invalidName << "\"."; 2170 } 2171 2172 for (char invalidChar : invalidSet) 2173 { 2174 std::string invalidAttribName = validAttribName + invalidChar; 2175 std::string invalidVert = "attribute float "; 2176 invalidVert += invalidAttribName; 2177 invalidVert += R"(;, 2178 void main(), 2179 {, 2180 gl_Position = vec4(1.0);, 2181 })"; 2182 GLuint program_number = CompileProgram(invalidVert.c_str(), essl1_shaders::fs::Red()); 2183 EXPECT_EQ(0u, program_number); 2184 } 2185 } 2186 2187 // Test that line continuation is handled correctly when validating shader source TEST_P(WebGLCompatibilityTest,ShaderSourceLineContinuation)2188 TEST_P(WebGLCompatibilityTest, ShaderSourceLineContinuation) 2189 { 2190 // With recent changes to WebGL's shader source validation in 2191 // https://github.com/KhronosGroup/WebGL/pull/3206 and follow-ons, 2192 // the backslash character can be used in both WebGL 1.0 and 2.0 2193 // contexts. 2194 2195 const char *validVert = 2196 R"(#define foo this \ 2197 is a test 2198 precision mediump float; 2199 void main() 2200 { 2201 gl_Position = vec4(1.0); 2202 })"; 2203 2204 GLuint program = CompileProgram(validVert, essl1_shaders::fs::Red()); 2205 EXPECT_NE(0u, program); 2206 glDeleteProgram(program); 2207 } 2208 2209 // Test that line continuation is handled correctly when valdiating shader source TEST_P(WebGL2CompatibilityTest,ShaderSourceLineContinuation)2210 TEST_P(WebGL2CompatibilityTest, ShaderSourceLineContinuation) 2211 { 2212 const char *validVert = 2213 R"(#version 300 es 2214 precision mediump float; 2215 2216 void main () 2217 { 2218 float f\ 2219 oo = 1.0; 2220 gl_Position = vec4(foo); 2221 })"; 2222 2223 const char *invalidVert = 2224 R"(#version 300 es 2225 precision mediump float; 2226 2227 void main () 2228 { 2229 float f\$ 2230 oo = 1.0; 2231 gl_Position = vec4(foo); 2232 })"; 2233 2234 GLuint program = CompileProgram(validVert, essl3_shaders::fs::Red()); 2235 EXPECT_NE(0u, program); 2236 glDeleteProgram(program); 2237 2238 program = CompileProgram(invalidVert, essl3_shaders::fs::Red()); 2239 EXPECT_EQ(0u, program); 2240 } 2241 2242 // Tests bindAttribLocations for reserved prefixes and length limits TEST_P(WebGLCompatibilityTest,BindAttribLocationLimitation)2243 TEST_P(WebGLCompatibilityTest, BindAttribLocationLimitation) 2244 { 2245 constexpr int maxLocStringLength = 256; 2246 const std::string tooLongString(maxLocStringLength + 1, '_'); 2247 2248 glBindAttribLocation(0, 0, "_webgl_var"); 2249 2250 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2251 2252 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str())); 2253 2254 EXPECT_GL_ERROR(GL_INVALID_VALUE); 2255 } 2256 2257 // Tests getAttribLocation for reserved prefixes TEST_P(WebGLCompatibilityTest,GetAttribLocationNameLimitation)2258 TEST_P(WebGLCompatibilityTest, GetAttribLocationNameLimitation) 2259 { 2260 GLint attrLocation; 2261 2262 attrLocation = glGetAttribLocation(0, "gl_attr"); 2263 EXPECT_GL_NO_ERROR(); 2264 EXPECT_EQ(-1, attrLocation); 2265 2266 attrLocation = glGetAttribLocation(0, "webgl_attr"); 2267 EXPECT_GL_NO_ERROR(); 2268 EXPECT_EQ(-1, attrLocation); 2269 2270 attrLocation = glGetAttribLocation(0, "_webgl_attr"); 2271 EXPECT_GL_NO_ERROR(); 2272 EXPECT_EQ(-1, attrLocation); 2273 } 2274 2275 // Tests getAttribLocation for length limits TEST_P(WebGLCompatibilityTest,GetAttribLocationLengthLimitation)2276 TEST_P(WebGLCompatibilityTest, GetAttribLocationLengthLimitation) 2277 { 2278 constexpr int maxLocStringLength = 256; 2279 const std::string tooLongString(maxLocStringLength + 1, '_'); 2280 2281 glGetAttribLocation(0, static_cast<const GLchar *>(tooLongString.c_str())); 2282 2283 EXPECT_GL_ERROR(GL_INVALID_VALUE); 2284 } 2285 2286 // Test that having no attributes with a zero divisor is valid in WebGL2 TEST_P(WebGL2CompatibilityTest,InstancedDrawZeroDivisor)2287 TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor) 2288 { 2289 constexpr char kVS[] = 2290 R"(attribute float a_pos; 2291 void main() 2292 { 2293 gl_Position = vec4(a_pos, a_pos, a_pos, 1.0); 2294 })"; 2295 2296 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 2297 2298 GLint posLocation = glGetAttribLocation(program, "a_pos"); 2299 ASSERT_NE(-1, posLocation); 2300 2301 glUseProgram(program); 2302 2303 GLBuffer buffer; 2304 glBindBuffer(GL_ARRAY_BUFFER, buffer); 2305 glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW); 2306 2307 glEnableVertexAttribArray(posLocation); 2308 glVertexAttribDivisor(posLocation, 1); 2309 2310 glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr); 2311 glDrawArraysInstanced(GL_POINTS, 0, 1, 4); 2312 ASSERT_GL_NO_ERROR(); 2313 } 2314 2315 // Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled TEST_P(WebGLCompatibilityTest,NPOT)2316 TEST_P(WebGLCompatibilityTest, NPOT) 2317 { 2318 EXPECT_FALSE(IsGLExtensionEnabled("GL_OES_texture_npot")); 2319 2320 // Create a texture and set an NPOT mip 0, should always be acceptable. 2321 GLTexture texture; 2322 glBindTexture(GL_TEXTURE_2D, texture); 2323 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2324 ASSERT_GL_NO_ERROR(); 2325 2326 // Try setting an NPOT mip 1 and verify the error if WebGL 1 2327 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2328 if (getClientMajorVersion() < 3) 2329 { 2330 ASSERT_GL_ERROR(GL_INVALID_VALUE); 2331 } 2332 else 2333 { 2334 ASSERT_GL_NO_ERROR(); 2335 } 2336 2337 if (IsGLExtensionRequestable("GL_OES_texture_npot")) 2338 { 2339 glRequestExtensionANGLE("GL_OES_texture_npot"); 2340 ASSERT_GL_NO_ERROR(); 2341 2342 // Try again to set NPOT mip 1 2343 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2344 ASSERT_GL_NO_ERROR(); 2345 } 2346 } 2347 2348 template <typename T> FillTexture2D(GLuint texture,GLsizei width,GLsizei height,const T & onePixelData,GLint level,GLint internalFormat,GLenum format,GLenum type)2349 void FillTexture2D(GLuint texture, 2350 GLsizei width, 2351 GLsizei height, 2352 const T &onePixelData, 2353 GLint level, 2354 GLint internalFormat, 2355 GLenum format, 2356 GLenum type) 2357 { 2358 std::vector<T> allPixelsData(width * height, onePixelData); 2359 2360 glBindTexture(GL_TEXTURE_2D, texture); 2361 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type, 2362 allPixelsData.data()); 2363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2365 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 2366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 2367 } 2368 2369 // Test that unset gl_Position defaults to (0,0,0,0). TEST_P(WebGLCompatibilityTest,DefaultPosition)2370 TEST_P(WebGLCompatibilityTest, DefaultPosition) 2371 { 2372 // Draw a quad where each vertex is red if gl_Position is (0,0,0,0) before it is set, 2373 // and green otherwise. The center of each quadrant will be red if and only if all 2374 // four corners are red. 2375 constexpr char kVS[] = 2376 R"(attribute vec3 pos; 2377 varying vec4 color; 2378 void main() { 2379 if (gl_Position == vec4(0,0,0,0)) { 2380 color = vec4(1,0,0,1); 2381 } else { 2382 color = vec4(0,1,0,1); 2383 } 2384 gl_Position = vec4(pos,1); 2385 })"; 2386 2387 constexpr char kFS[] = 2388 R"(precision mediump float; 2389 varying vec4 color; 2390 void main() { 2391 gl_FragColor = color; 2392 })"; 2393 2394 ANGLE_GL_PROGRAM(program, kVS, kFS); 2395 drawQuad(program, "pos", 0.0f, 1.0f, true); 2396 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 1 / 4, GLColor::red); 2397 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 1 / 4, getWindowHeight() * 3 / 4, GLColor::red); 2398 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 1 / 4, GLColor::red); 2399 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, GLColor::red); 2400 } 2401 2402 // Tests that a rendering feedback loop triggers a GL error under WebGL. 2403 // Based on WebGL test conformance/renderbuffers/feedback-loop.html. TEST_P(WebGLCompatibilityTest,RenderingFeedbackLoop)2404 TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop) 2405 { 2406 constexpr char kVS[] = 2407 R"(attribute vec4 a_position; 2408 varying vec2 v_texCoord; 2409 void main() { 2410 gl_Position = a_position; 2411 v_texCoord = (a_position.xy * 0.5) + 0.5; 2412 })"; 2413 2414 constexpr char kFS[] = 2415 R"(precision mediump float; 2416 varying vec2 v_texCoord; 2417 uniform sampler2D u_texture; 2418 void main() { 2419 // Shader swizzles color channels so we can tell if the draw succeeded. 2420 gl_FragColor = texture2D(u_texture, v_texCoord).gbra; 2421 })"; 2422 2423 GLTexture texture; 2424 FillTexture2D(texture, 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 2425 2426 ASSERT_GL_NO_ERROR(); 2427 2428 GLFramebuffer framebuffer; 2429 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 2430 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 2431 2432 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 2433 2434 ANGLE_GL_PROGRAM(program, kVS, kFS); 2435 2436 GLint uniformLoc = glGetUniformLocation(program, "u_texture"); 2437 ASSERT_NE(-1, uniformLoc); 2438 2439 glUseProgram(program); 2440 glUniform1i(uniformLoc, 0); 2441 glDisable(GL_BLEND); 2442 glDisable(GL_DEPTH_TEST); 2443 ASSERT_GL_NO_ERROR(); 2444 2445 // Drawing with a texture that is also bound to the current framebuffer should fail 2446 glBindTexture(GL_TEXTURE_2D, texture); 2447 drawQuad(program, "a_position", 0.5f, 1.0f, true); 2448 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2449 2450 // Ensure that the texture contents did not change after the previous render 2451 glBindFramebuffer(GL_FRAMEBUFFER, 0); 2452 drawQuad(program, "a_position", 0.5f, 1.0f, true); 2453 ASSERT_GL_NO_ERROR(); 2454 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); 2455 2456 // Drawing when texture is bound to an inactive uniform should succeed 2457 GLTexture texture2; 2458 FillTexture2D(texture2, 1, 1, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 2459 2460 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 2461 glActiveTexture(GL_TEXTURE1); 2462 glBindTexture(GL_TEXTURE_2D, texture); 2463 drawQuad(program, "a_position", 0.5f, 1.0f, true); 2464 ASSERT_GL_NO_ERROR(); 2465 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); 2466 } 2467 2468 // Multi-context uses of textures should not cause rendering feedback loops. TEST_P(WebGLCompatibilityTest,MultiContextNoRenderingFeedbackLoops)2469 TEST_P(WebGLCompatibilityTest, MultiContextNoRenderingFeedbackLoops) 2470 { 2471 constexpr char kUnusedTextureVS[] = 2472 R"(attribute vec4 a_position; 2473 varying vec2 v_texCoord; 2474 void main() { 2475 gl_Position = a_position; 2476 v_texCoord = (a_position.xy * 0.5) + 0.5; 2477 })"; 2478 2479 constexpr char kUnusedTextureFS[] = 2480 R"(precision mediump float; 2481 varying vec2 v_texCoord; 2482 uniform sampler2D u_texture; 2483 void main() { 2484 gl_FragColor = texture2D(u_texture, v_texCoord).rgba; 2485 })"; 2486 2487 ANGLE_GL_PROGRAM(unusedProgram, kUnusedTextureVS, kUnusedTextureFS); 2488 2489 glUseProgram(unusedProgram); 2490 GLint uniformLoc = glGetUniformLocation(unusedProgram, "u_texture"); 2491 ASSERT_NE(-1, uniformLoc); 2492 glUniform1i(uniformLoc, 0); 2493 2494 GLTexture texture; 2495 FillTexture2D(texture, 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 2496 glBindTexture(GL_TEXTURE_2D, texture); 2497 // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point. 2498 2499 EGLWindow *window = getEGLWindow(); 2500 EGLDisplay display = window->getDisplay(); 2501 EGLConfig config = window->getConfig(); 2502 EGLSurface surface = window->getSurface(); 2503 EGLint contextAttributes[] = { 2504 EGL_CONTEXT_MAJOR_VERSION_KHR, 2505 GetParam().majorVersion, 2506 EGL_CONTEXT_MINOR_VERSION_KHR, 2507 GetParam().minorVersion, 2508 EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, 2509 EGL_TRUE, 2510 EGL_NONE, 2511 }; 2512 auto context1 = eglGetCurrentContext(); 2513 // Create context2, sharing resources with context1. 2514 auto context2 = eglCreateContext(display, config, context1, contextAttributes); 2515 ASSERT_NE(context2, EGL_NO_CONTEXT); 2516 eglMakeCurrent(display, surface, surface, context2); 2517 2518 constexpr char kVS[] = 2519 R"(attribute vec4 a_position; 2520 void main() { 2521 gl_Position = a_position; 2522 })"; 2523 2524 constexpr char kFS[] = 2525 R"(precision mediump float; 2526 void main() { 2527 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 2528 })"; 2529 2530 ANGLE_GL_PROGRAM(program, kVS, kFS); 2531 glUseProgram(program); 2532 2533 ASSERT_GL_NO_ERROR(); 2534 2535 // Render to the texture in context2. 2536 GLFramebuffer framebuffer; 2537 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 2538 // Texture is still a valid name in context2. 2539 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 2540 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 2541 // There is no rendering feedback loop at this point. 2542 2543 glDisable(GL_BLEND); 2544 glDisable(GL_DEPTH_TEST); 2545 ASSERT_GL_NO_ERROR(); 2546 2547 drawQuad(program, "a_position", 0.5f, 1.0f, true); 2548 ASSERT_GL_NO_ERROR(); 2549 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 2550 2551 eglMakeCurrent(display, surface, surface, context1); 2552 eglDestroyContext(display, context2); 2553 } 2554 2555 // Test for the max draw buffers and color attachments. TEST_P(WebGLCompatibilityTest,MaxDrawBuffersAttachmentPoints)2556 TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints) 2557 { 2558 // This test only applies to ES2. 2559 if (getClientMajorVersion() != 2) 2560 { 2561 return; 2562 } 2563 2564 GLFramebuffer fbo[2]; 2565 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]); 2566 2567 // Test that is valid when we bind with a single attachment point. 2568 GLTexture texture; 2569 glBindTexture(GL_TEXTURE_2D, texture); 2570 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2571 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 2572 ASSERT_GL_NO_ERROR(); 2573 2574 // Test that enabling the draw buffers extension will allow us to bind with a non-zero 2575 // attachment point. 2576 if (IsGLExtensionRequestable("GL_EXT_draw_buffers")) 2577 { 2578 glRequestExtensionANGLE("GL_EXT_draw_buffers"); 2579 EXPECT_GL_NO_ERROR(); 2580 EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers")); 2581 2582 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]); 2583 2584 GLTexture texture2; 2585 glBindTexture(GL_TEXTURE_2D, texture2); 2586 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2587 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2, 0); 2588 ASSERT_GL_NO_ERROR(); 2589 } 2590 } 2591 2592 // Test that the offset in the index buffer is forced to be a multiple of the element size TEST_P(WebGLCompatibilityTest,DrawElementsOffsetRestriction)2593 TEST_P(WebGLCompatibilityTest, DrawElementsOffsetRestriction) 2594 { 2595 constexpr char kVS[] = 2596 R"(attribute vec3 a_pos; 2597 void main() 2598 { 2599 gl_Position = vec4(a_pos, 1.0); 2600 })"; 2601 2602 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red()); 2603 2604 GLint posLocation = glGetAttribLocation(program, "a_pos"); 2605 ASSERT_NE(-1, posLocation); 2606 glUseProgram(program); 2607 2608 const auto &vertices = GetQuadVertices(); 2609 2610 GLBuffer vertexBuffer; 2611 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 2612 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(), 2613 GL_STATIC_DRAW); 2614 2615 glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); 2616 glEnableVertexAttribArray(posLocation); 2617 2618 GLBuffer indexBuffer; 2619 const GLubyte indices[] = {0, 0, 0, 0, 0, 0, 0, 0}; 2620 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 2621 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 2622 2623 ASSERT_GL_NO_ERROR(); 2624 2625 const char *zeroIndices = nullptr; 2626 2627 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, zeroIndices); 2628 ASSERT_GL_NO_ERROR(); 2629 2630 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices); 2631 ASSERT_GL_NO_ERROR(); 2632 2633 glDrawElements(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, zeroIndices + 1); 2634 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2635 } 2636 2637 // Test that the offset and stride in the vertex buffer is forced to be a multiple of the element 2638 // size TEST_P(WebGLCompatibilityTest,VertexAttribPointerOffsetRestriction)2639 TEST_P(WebGLCompatibilityTest, VertexAttribPointerOffsetRestriction) 2640 { 2641 const char *zeroOffset = nullptr; 2642 2643 // Base case, vector of two floats 2644 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset); 2645 ASSERT_GL_NO_ERROR(); 2646 2647 // Test setting a non-multiple offset 2648 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 1); 2649 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2650 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 2); 2651 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2652 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, zeroOffset + 3); 2653 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2654 2655 // Test setting a non-multiple stride 2656 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 1, zeroOffset); 2657 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2658 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2, zeroOffset); 2659 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2660 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3, zeroOffset); 2661 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2662 } 2663 drawBuffersEXTFeedbackLoop(GLuint program,const std::array<GLenum,2> & drawBuffers,GLenum expectedError)2664 void WebGLCompatibilityTest::drawBuffersEXTFeedbackLoop(GLuint program, 2665 const std::array<GLenum, 2> &drawBuffers, 2666 GLenum expectedError) 2667 { 2668 glDrawBuffersEXT(2, drawBuffers.data()); 2669 2670 // Make sure framebuffer is complete before feedback loop detection 2671 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 2672 2673 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 2674 2675 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise, 2676 // it should be NO_ERROR" 2677 EXPECT_GL_ERROR(expectedError); 2678 } 2679 2680 // This tests that rendering feedback loops works as expected with GL_EXT_draw_buffers. 2681 // Based on WebGL test conformance/extensions/webgl-draw-buffers-feedback-loop.html TEST_P(WebGLCompatibilityTest,RenderingFeedbackLoopWithDrawBuffersEXT)2682 TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoopWithDrawBuffersEXT) 2683 { 2684 constexpr char kVS[] = 2685 R"(attribute vec4 aPosition; 2686 varying vec2 texCoord; 2687 void main() { 2688 gl_Position = aPosition; 2689 texCoord = (aPosition.xy * 0.5) + 0.5; 2690 })"; 2691 2692 constexpr char kFS[] = 2693 R"(#extension GL_EXT_draw_buffers : require 2694 precision mediump float; 2695 uniform sampler2D tex; 2696 varying vec2 texCoord; 2697 void main() { 2698 gl_FragData[0] = texture2D(tex, texCoord); 2699 gl_FragData[1] = texture2D(tex, texCoord); 2700 })"; 2701 2702 GLsizei width = 8; 2703 GLsizei height = 8; 2704 2705 // This shader cannot be run in ES3, because WebGL 2 does not expose the draw buffers 2706 // extension and gl_FragData semantics are changed to enforce indexing by zero always. 2707 // TODO(jmadill): This extension should be disabled in WebGL 2 contexts. 2708 if (/*!IsGLExtensionEnabled("GL_EXT_draw_buffers")*/ getClientMajorVersion() != 2) 2709 { 2710 // No WEBGL_draw_buffers support -- this is legal. 2711 return; 2712 } 2713 2714 GLint maxDrawBuffers = 0; 2715 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); 2716 2717 // Test skipped because MAX_DRAW_BUFFERS is too small. 2718 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 2); 2719 2720 ANGLE_GL_PROGRAM(program, kVS, kFS); 2721 glUseProgram(program); 2722 glViewport(0, 0, width, height); 2723 2724 GLTexture tex0; 2725 GLTexture tex1; 2726 GLFramebuffer fbo; 2727 FillTexture2D(tex0, width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 2728 FillTexture2D(tex1, width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 2729 ASSERT_GL_NO_ERROR(); 2730 2731 glBindTexture(GL_TEXTURE_2D, tex1); 2732 GLint texLoc = glGetUniformLocation(program, "tex"); 2733 ASSERT_NE(-1, texLoc); 2734 glUniform1i(texLoc, 0); 2735 ASSERT_GL_NO_ERROR(); 2736 2737 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation 2738 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 2739 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0, 0); 2740 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1, 0); 2741 2742 drawBuffersEXTFeedbackLoop(program, {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION); 2743 drawBuffersEXTFeedbackLoop(program, {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}}, 2744 GL_INVALID_OPERATION); 2745 // A feedback loop is formed regardless of drawBuffers settings. 2746 drawBuffersEXTFeedbackLoop(program, {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_INVALID_OPERATION); 2747 } 2748 2749 // Test tests that texture copying feedback loops are properly rejected in WebGL. 2750 // Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html TEST_P(WebGLCompatibilityTest,TextureCopyingFeedbackLoops)2751 TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops) 2752 { 2753 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs. 2754 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); 2755 2756 GLTexture texture; 2757 glBindTexture(GL_TEXTURE_2D, texture); 2758 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2759 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2760 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2761 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 2762 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 2763 2764 GLTexture texture2; 2765 glBindTexture(GL_TEXTURE_2D, texture2); 2766 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 2767 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2768 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 2770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 2771 2772 GLFramebuffer framebuffer; 2773 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 2774 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 2775 2776 // framebuffer should be FRAMEBUFFER_COMPLETE. 2777 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 2778 ASSERT_GL_NO_ERROR(); 2779 2780 // testing copyTexImage2D 2781 2782 // copyTexImage2D to same texture but different level 2783 glBindTexture(GL_TEXTURE_2D, texture); 2784 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0); 2785 EXPECT_GL_NO_ERROR(); 2786 2787 // copyTexImage2D to same texture same level, invalid feedback loop 2788 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0); 2789 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2790 2791 // copyTexImage2D to different texture 2792 glBindTexture(GL_TEXTURE_2D, texture2); 2793 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 2, 2, 0); 2794 EXPECT_GL_NO_ERROR(); 2795 2796 // testing copyTexSubImage2D 2797 2798 // copyTexSubImage2D to same texture but different level 2799 glBindTexture(GL_TEXTURE_2D, texture); 2800 glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1); 2801 EXPECT_GL_NO_ERROR(); 2802 2803 // copyTexSubImage2D to same texture same level, invalid feedback loop 2804 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); 2805 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 2806 2807 // copyTexSubImage2D to different texture 2808 glBindTexture(GL_TEXTURE_2D, texture2); 2809 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); 2810 EXPECT_GL_NO_ERROR(); 2811 } 2812 2813 // Test that copying from mip 1 of a texture to mip 0 works. When the framebuffer is attached to 2814 // mip 1 of a mip-complete texture, an image with both mips are created. When copying from the 2815 // framebuffer to mip 0, it is being redefined. TEST_P(WebGL2CompatibilityTest,CopyMip1ToMip0)2816 TEST_P(WebGL2CompatibilityTest, CopyMip1ToMip0) 2817 { 2818 // http://anglebug.com/42263391 2819 ANGLE_SKIP_TEST_IF(IsD3D11()); 2820 2821 // http://anglebug.com/42263392 2822 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && (IsWindows() || IsMac())); 2823 2824 // TODO(anglebug.com/40096747): Failing on ARM64-based Apple DTKs. 2825 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL()); 2826 2827 GLFramebuffer framebuffer; 2828 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 2829 2830 GLTexture texture; 2831 glBindTexture(GL_TEXTURE_2D, texture); 2832 2833 const GLColor mip0[4] = { 2834 GLColor::red, 2835 GLColor::red, 2836 GLColor::red, 2837 GLColor::red, 2838 }; 2839 const GLColor mip1[1] = { 2840 GLColor::green, 2841 }; 2842 2843 // Create a complete mip chain in mips 0 to 2 2844 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0); 2845 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1); 2846 2847 // Framebuffer can bind to mip 1, as the texture is mip-complete. 2848 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); 2849 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 2850 2851 // Copy to mip 0. This shouldn't crash. 2852 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0); 2853 EXPECT_GL_NO_ERROR(); 2854 2855 // The framebuffer is now incomplete. 2856 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 2857 glCheckFramebufferStatus(GL_FRAMEBUFFER)); 2858 2859 // http://anglebug.com/42263389 2860 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA()); 2861 2862 // http://anglebug.com/42263390 2863 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsMac()); 2864 2865 // Bind framebuffer to mip 0 and make sure the copy was done. 2866 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 2867 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 2868 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 2869 2870 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 2871 } 2872 2873 // Test that copying from mip 0 of a texture to mip 1 works. When the framebuffer is attached to 2874 // mip 0 of a mip-complete texture, an image with both mips are created. When copying from the 2875 // framebuffer to mip 1, it is being redefined. TEST_P(WebGL2CompatibilityTest,CopyMip0ToMip1)2876 TEST_P(WebGL2CompatibilityTest, CopyMip0ToMip1) 2877 { 2878 // http://anglebug.com/42263392 2879 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows()); 2880 2881 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsWindows()); 2882 2883 GLFramebuffer framebuffer; 2884 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 2885 2886 GLTexture texture; 2887 glBindTexture(GL_TEXTURE_2D, texture); 2888 2889 const GLColor mip0[4] = { 2890 GLColor::red, 2891 GLColor::red, 2892 GLColor::red, 2893 GLColor::red, 2894 }; 2895 const GLColor mip1[1] = { 2896 GLColor::green, 2897 }; 2898 2899 // Create a complete mip chain in mips 0 to 2 2900 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0); 2901 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1); 2902 2903 // Framebuffer can bind to mip 0, as the texture is mip-complete. 2904 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 2905 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 2906 2907 // Copy to mip 1. This shouldn't crash. 2908 glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0); 2909 EXPECT_GL_NO_ERROR(); 2910 2911 // The framebuffer is still complete. 2912 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 2913 // Make sure mip 0 is untouched. 2914 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); 2915 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); 2916 2917 // Bind framebuffer to mip 1 and make sure the copy was done. 2918 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); 2919 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1); 2920 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 2921 2922 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); 2923 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); 2924 } 2925 drawBuffersFeedbackLoop(GLuint program,const std::array<GLenum,2> & drawBuffers,GLenum expectedError)2926 void WebGLCompatibilityTest::drawBuffersFeedbackLoop(GLuint program, 2927 const std::array<GLenum, 2> &drawBuffers, 2928 GLenum expectedError) 2929 { 2930 glDrawBuffers(2, drawBuffers.data()); 2931 2932 // Make sure framebuffer is complete before feedback loop detection 2933 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 2934 2935 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 2936 2937 // "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise, 2938 // it should be NO_ERROR" 2939 EXPECT_GL_ERROR(expectedError); 2940 } 2941 2942 // Tests invariance matching rules between built in varyings. 2943 // Based on WebGL test conformance/glsl/misc/shaders-with-invariance.html. TEST_P(WebGLCompatibilityTest,BuiltInInvariant)2944 TEST_P(WebGLCompatibilityTest, BuiltInInvariant) 2945 { 2946 constexpr char kVS[] = 2947 R"(varying vec4 v_varying; 2948 void main() 2949 { 2950 gl_PointSize = 1.0; 2951 gl_Position = v_varying; 2952 })"; 2953 constexpr char kFSInvariantGlFragCoord[] = 2954 R"(invariant gl_FragCoord; 2955 void main() 2956 { 2957 gl_FragColor = gl_FragCoord; 2958 })"; 2959 constexpr char kFSInvariantGlPointCoord[] = 2960 R"(invariant gl_PointCoord; 2961 void main() 2962 { 2963 gl_FragColor = vec4(gl_PointCoord, 0.0, 0.0); 2964 })"; 2965 2966 GLuint program = CompileProgram(kVS, kFSInvariantGlFragCoord); 2967 EXPECT_EQ(0u, program); 2968 2969 program = CompileProgram(kVS, kFSInvariantGlPointCoord); 2970 EXPECT_EQ(0u, program); 2971 } 2972 2973 // Tests global namespace conflicts between uniforms and attributes. 2974 // Based on WebGL test conformance/glsl/misc/shaders-with-name-conflicts.html. TEST_P(WebGLCompatibilityTest,GlobalNamesConflict)2975 TEST_P(WebGLCompatibilityTest, GlobalNamesConflict) 2976 { 2977 constexpr char kVS[] = 2978 R"(attribute vec4 foo; 2979 void main() 2980 { 2981 gl_Position = foo; 2982 })"; 2983 constexpr char kFS[] = 2984 R"(precision mediump float; 2985 uniform vec4 foo; 2986 void main() 2987 { 2988 gl_FragColor = foo; 2989 })"; 2990 2991 GLuint program = CompileProgram(kVS, kFS); 2992 EXPECT_NE(0u, program); 2993 } 2994 2995 // Test dimension and image size validation of compressed textures TEST_P(WebGLCompatibilityTest,CompressedTextureS3TC)2996 TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC) 2997 { 2998 if (IsGLExtensionRequestable("GL_EXT_texture_compression_dxt1")) 2999 { 3000 glRequestExtensionANGLE("GL_EXT_texture_compression_dxt1"); 3001 } 3002 3003 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1")); 3004 3005 constexpr uint8_t CompressedImageDXT1[] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa}; 3006 3007 GLTexture texture; 3008 glBindTexture(GL_TEXTURE_2D, texture); 3009 3010 // Regular case, verify that it works 3011 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 3012 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3013 ASSERT_GL_NO_ERROR(); 3014 3015 // Test various dimensions that are not valid 3016 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3, 4, 0, 3017 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3018 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 3019 3020 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 3, 0, 3021 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3022 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 3023 3024 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0, 3025 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3026 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 3027 3028 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0, 3029 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3030 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 3031 3032 // Test various image sizes that are not valid 3033 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 3034 sizeof(CompressedImageDXT1) - 1, CompressedImageDXT1); 3035 ASSERT_GL_ERROR(GL_INVALID_VALUE); 3036 3037 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 3038 sizeof(CompressedImageDXT1) + 1, CompressedImageDXT1); 3039 ASSERT_GL_ERROR(GL_INVALID_VALUE); 3040 3041 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 0, 3042 CompressedImageDXT1); 3043 ASSERT_GL_ERROR(GL_INVALID_VALUE); 3044 3045 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0, 0, 3046 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3047 ASSERT_GL_ERROR(GL_INVALID_VALUE); 3048 3049 // Fill a full mip chain and verify that it works 3050 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, 3051 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3052 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 2, 2, 0, 3053 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3054 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1, 1, 0, 3055 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3056 ASSERT_GL_NO_ERROR(); 3057 3058 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3059 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3060 ASSERT_GL_NO_ERROR(); 3061 3062 // Test that non-block size sub-uploads are not valid for the 0 mip 3063 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3064 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3065 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 3066 3067 // Test that non-block size sub-uploads are valid for if they fill the whole mip 3068 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 2, 2, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3069 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3070 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, 1, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3071 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3072 ASSERT_GL_NO_ERROR(); 3073 3074 // Test that if the format miss-matches the texture, an error is generated 3075 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 3076 sizeof(CompressedImageDXT1), CompressedImageDXT1); 3077 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 3078 } 3079 3080 // Test WebGL-specific constraints on sizes of S3TC textures' mipmap levels. TEST_P(WebGLCompatibilityTest,CompressedTexImageS3TC)3081 TEST_P(WebGLCompatibilityTest, CompressedTexImageS3TC) 3082 { 3083 const char *extensions[] = { 3084 "GL_EXT_texture_compression_dxt1", 3085 "GL_ANGLE_texture_compression_dxt3", 3086 "GL_ANGLE_texture_compression_dxt5", 3087 }; 3088 3089 for (const char *extension : extensions) 3090 { 3091 if (IsGLExtensionRequestable(extension)) 3092 { 3093 glRequestExtensionANGLE(extension); 3094 } 3095 3096 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extension)); 3097 } 3098 3099 // Ported from WebGL conformance suite: 3100 // sdk/tests/conformance/extensions/s3tc-and-srgb.html 3101 constexpr GLenum formats[] = { 3102 GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 3103 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 3104 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 3105 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 3106 }; 3107 3108 for (GLenum format : formats) 3109 { 3110 testCompressedTexImage(format); 3111 } 3112 } 3113 3114 // Test WebGL-specific constraints on sizes of RGTC textures' mipmap levels. TEST_P(WebGLCompatibilityTest,CompressedTexImageRGTC)3115 TEST_P(WebGLCompatibilityTest, CompressedTexImageRGTC) 3116 { 3117 if (IsGLExtensionRequestable("GL_EXT_texture_compression_rgtc")) 3118 { 3119 glRequestExtensionANGLE("GL_EXT_texture_compression_rgtc"); 3120 } 3121 3122 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_rgtc")); 3123 3124 // Ported from WebGL conformance suite: 3125 // sdk/tests/conformance/extensions/ext-texture-compression-rgtc.html 3126 constexpr GLenum formats[] = {GL_COMPRESSED_RED_RGTC1_EXT, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 3127 GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 3128 GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}; 3129 3130 for (GLenum format : formats) 3131 { 3132 testCompressedTexImage(format); 3133 } 3134 } 3135 3136 // Test WebGL-specific constraints on sizes of BPTC textures' mipmap levels. TEST_P(WebGLCompatibilityTest,CompressedTexImageBPTC)3137 TEST_P(WebGLCompatibilityTest, CompressedTexImageBPTC) 3138 { 3139 if (IsGLExtensionRequestable("GL_EXT_texture_compression_bptc")) 3140 { 3141 glRequestExtensionANGLE("GL_EXT_texture_compression_bptc"); 3142 } 3143 3144 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc")); 3145 3146 // Ported from WebGL conformance suite: 3147 // sdk/tests/conformance/extensions/ext-texture-compression-bptc.html 3148 constexpr GLenum formats[] = { 3149 GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 3150 GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}; 3151 3152 for (GLenum format : formats) 3153 { 3154 testCompressedTexImage(format); 3155 } 3156 } 3157 TEST_P(WebGLCompatibilityTest,L32FTextures)3158 TEST_P(WebGLCompatibilityTest, L32FTextures) 3159 { 3160 constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f}; 3161 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 1.0f}; 3162 3163 for (auto extension : FloatingPointTextureExtensions) 3164 { 3165 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3166 { 3167 glRequestExtensionANGLE(extension); 3168 ASSERT_GL_NO_ERROR(); 3169 } 3170 3171 // Unsized L 32F 3172 { 3173 bool texture = IsGLExtensionEnabled("GL_OES_texture_float"); 3174 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3175 bool render = false; 3176 TestFloatTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, texture, filter, render, 3177 textureData, readPixelData); 3178 } 3179 3180 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_EXT_texture_storage")) 3181 { 3182 // Sized L 32F 3183 bool texture = IsGLExtensionEnabled("GL_OES_texture_float") && 3184 IsGLExtensionEnabled("GL_EXT_texture_storage"); 3185 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3186 bool render = false; 3187 TestFloatTextureFormat(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT, texture, filter, 3188 render, textureData, readPixelData); 3189 } 3190 } 3191 } 3192 TEST_P(WebGLCompatibilityTest,A32FTextures)3193 TEST_P(WebGLCompatibilityTest, A32FTextures) 3194 { 3195 constexpr float textureData[] = {33.33f, 0.0f, 0.0f, 0.0f}; 3196 constexpr float readPixelData[] = {0.0f, 0.0f, 0.0f, textureData[0]}; 3197 3198 for (auto extension : FloatingPointTextureExtensions) 3199 { 3200 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3201 { 3202 glRequestExtensionANGLE(extension); 3203 ASSERT_GL_NO_ERROR(); 3204 } 3205 3206 // Unsized A 32F 3207 { 3208 bool texture = IsGLExtensionEnabled("GL_OES_texture_float"); 3209 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3210 bool render = false; 3211 TestFloatTextureFormat(GL_ALPHA, GL_ALPHA, GL_FLOAT, texture, filter, render, 3212 textureData, readPixelData); 3213 } 3214 3215 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_EXT_texture_storage")) 3216 { 3217 // Sized A 32F 3218 bool texture = IsGLExtensionEnabled("GL_OES_texture_float") && 3219 IsGLExtensionEnabled("GL_EXT_texture_storage"); 3220 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3221 bool render = false; 3222 TestFloatTextureFormat(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT, texture, filter, render, 3223 textureData, readPixelData); 3224 } 3225 } 3226 } 3227 TEST_P(WebGLCompatibilityTest,LA32FTextures)3228 TEST_P(WebGLCompatibilityTest, LA32FTextures) 3229 { 3230 constexpr float textureData[] = {-0.21f, 15.1f, 0.0f, 0.0f}; 3231 constexpr float readPixelData[] = {textureData[0], textureData[0], textureData[0], 3232 textureData[1]}; 3233 3234 for (auto extension : FloatingPointTextureExtensions) 3235 { 3236 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3237 { 3238 glRequestExtensionANGLE(extension); 3239 ASSERT_GL_NO_ERROR(); 3240 } 3241 3242 // Unsized LA 32F 3243 { 3244 bool texture = IsGLExtensionEnabled("GL_OES_texture_float"); 3245 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3246 bool render = false; 3247 TestFloatTextureFormat(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, texture, 3248 filter, render, textureData, readPixelData); 3249 } 3250 3251 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_EXT_texture_storage")) 3252 { 3253 // Sized LA 32F 3254 bool texture = IsGLExtensionEnabled("GL_OES_texture_float") && 3255 IsGLExtensionEnabled("GL_EXT_texture_storage"); 3256 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3257 bool render = false; 3258 TestFloatTextureFormat(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT, texture, 3259 filter, render, textureData, readPixelData); 3260 } 3261 } 3262 } 3263 TEST_P(WebGLCompatibilityTest,R32FTextures)3264 TEST_P(WebGLCompatibilityTest, R32FTextures) 3265 { 3266 constexpr float data[] = {1000.0f, 0.0f, 0.0f, 1.0f}; 3267 3268 for (auto extension : FloatingPointTextureExtensions) 3269 { 3270 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3271 { 3272 glRequestExtensionANGLE(extension); 3273 ASSERT_GL_NO_ERROR(); 3274 } 3275 3276 // Unsized R 32F 3277 { 3278 bool texture = IsGLExtensionEnabled("GL_OES_texture_float") && 3279 IsGLExtensionEnabled("GL_EXT_texture_rg"); 3280 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3281 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float"); 3282 TestFloatTextureFormat(GL_RED, GL_RED, GL_FLOAT, texture, filter, render, data, data); 3283 } 3284 3285 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_EXT_texture_storage")) 3286 { 3287 // Sized R 32F 3288 bool texture = 3289 (getClientMajorVersion() >= 3) || (IsGLExtensionEnabled("GL_OES_texture_float") && 3290 IsGLExtensionEnabled("GL_EXT_texture_rg") && 3291 IsGLExtensionEnabled("GL_EXT_texture_storage")); 3292 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3293 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float"); 3294 TestFloatTextureFormat(GL_R32F, GL_RED, GL_FLOAT, texture, filter, render, data, data); 3295 } 3296 } 3297 } 3298 TEST_P(WebGLCompatibilityTest,RG32FTextures)3299 TEST_P(WebGLCompatibilityTest, RG32FTextures) 3300 { 3301 constexpr float data[] = {1000.0f, -0.001f, 0.0f, 1.0f}; 3302 3303 for (auto extension : FloatingPointTextureExtensions) 3304 { 3305 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3306 { 3307 glRequestExtensionANGLE(extension); 3308 ASSERT_GL_NO_ERROR(); 3309 } 3310 3311 // Unsized RG 32F 3312 { 3313 bool texture = (IsGLExtensionEnabled("GL_OES_texture_float") && 3314 IsGLExtensionEnabled("GL_EXT_texture_rg")); 3315 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3316 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float"); 3317 TestFloatTextureFormat(GL_RG, GL_RG, GL_FLOAT, texture, filter, render, data, data); 3318 } 3319 3320 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_EXT_texture_storage")) 3321 { 3322 // Sized RG 32F 3323 bool texture = 3324 (getClientMajorVersion() >= 3) || (IsGLExtensionEnabled("GL_OES_texture_float") && 3325 IsGLExtensionEnabled("GL_EXT_texture_rg") && 3326 IsGLExtensionEnabled("GL_EXT_texture_storage")); 3327 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3328 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float"); 3329 TestFloatTextureFormat(GL_RG32F, GL_RG, GL_FLOAT, texture, filter, render, data, data); 3330 } 3331 } 3332 } 3333 TEST_P(WebGLCompatibilityTest,RGB32FTextures)3334 TEST_P(WebGLCompatibilityTest, RGB32FTextures) 3335 { 3336 constexpr float data[] = {1000.0f, -500.0f, 10.0f, 1.0f}; 3337 3338 for (auto extension : FloatingPointTextureExtensions) 3339 { 3340 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3341 { 3342 glRequestExtensionANGLE(extension); 3343 ASSERT_GL_NO_ERROR(); 3344 } 3345 3346 // Unsized RGB 32F 3347 { 3348 bool texture = IsGLExtensionEnabled("GL_OES_texture_float"); 3349 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3350 bool render = false; 3351 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_FLOAT, texture, filter, render, data, data); 3352 } 3353 3354 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_EXT_texture_storage")) 3355 { 3356 // Sized RGB 32F 3357 bool texture = 3358 (getClientMajorVersion() >= 3) || (IsGLExtensionEnabled("GL_OES_texture_float") && 3359 IsGLExtensionEnabled("GL_EXT_texture_storage")); 3360 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3361 bool render = IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"); 3362 TestFloatTextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT, texture, filter, render, data, 3363 data); 3364 } 3365 } 3366 } 3367 TEST_P(WebGLCompatibilityTest,RGBA32FTextures)3368 TEST_P(WebGLCompatibilityTest, RGBA32FTextures) 3369 { 3370 // http://anglebug.com/42263897 3371 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac()); 3372 3373 constexpr float data[] = {7000.0f, 100.0f, 33.0f, -1.0f}; 3374 3375 for (auto extension : FloatingPointTextureExtensions) 3376 { 3377 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3378 { 3379 glRequestExtensionANGLE(extension); 3380 ASSERT_GL_NO_ERROR(); 3381 } 3382 3383 // Unsized RGBA 32F 3384 { 3385 bool texture = IsGLExtensionEnabled("GL_OES_texture_float"); 3386 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3387 bool render = false; 3388 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_FLOAT, texture, filter, render, data, data); 3389 } 3390 3391 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_EXT_texture_storage")) 3392 { 3393 // Sized RGBA 32F 3394 bool texture = 3395 (getClientMajorVersion() >= 3) || (IsGLExtensionEnabled("GL_OES_texture_float") && 3396 IsGLExtensionEnabled("GL_EXT_texture_storage")); 3397 bool filter = IsGLExtensionEnabled("GL_OES_texture_float_linear"); 3398 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float") || 3399 IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"); 3400 TestFloatTextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT, texture, filter, render, data, 3401 data); 3402 } 3403 } 3404 } 3405 3406 // Test that has float color attachment caching works when color attachments change, by calling draw 3407 // command when blending is enabled TEST_P(WebGLCompatibilityTest,FramebufferFloatColorAttachment)3408 TEST_P(WebGLCompatibilityTest, FramebufferFloatColorAttachment) 3409 { 3410 if (getClientMajorVersion() >= 3) 3411 { 3412 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); 3413 } 3414 else 3415 { 3416 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_float")); 3417 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba")); 3418 } 3419 3420 constexpr char kVS[] = 3421 R"(void main() 3422 { 3423 gl_Position = vec4(0, 0, 0, 1); 3424 })"; 3425 3426 constexpr char kFS[] = 3427 R"(void main() 3428 { 3429 gl_FragColor = vec4(0, 1, 0, 1); 3430 })"; 3431 3432 ANGLE_GL_PROGRAM(program, kVS, kFS); 3433 glUseProgram(program); 3434 3435 glEnable(GL_BLEND); 3436 3437 GLTexture texture1; 3438 glBindTexture(GL_TEXTURE_2D, texture1); 3439 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 3440 EXPECT_GL_NO_ERROR(); 3441 3442 GLTexture texture2; 3443 glBindTexture(GL_TEXTURE_2D, texture2); 3444 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr); 3445 EXPECT_GL_NO_ERROR(); 3446 3447 GLFramebuffer fbo1; 3448 glBindFramebuffer(GL_FRAMEBUFFER, fbo1); 3449 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); 3450 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 3451 3452 GLFramebuffer fbo2; 3453 glBindFramebuffer(GL_FRAMEBUFFER, fbo2); 3454 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); 3455 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 3456 glDrawArrays(GL_POINTS, 0, 1); 3457 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 3458 3459 glDisable(GL_BLEND); 3460 glDrawArrays(GL_POINTS, 0, 1); 3461 EXPECT_GL_NO_ERROR(); 3462 glEnable(GL_BLEND); 3463 3464 glBindFramebuffer(GL_FRAMEBUFFER, fbo1); 3465 glDrawArrays(GL_POINTS, 0, 1); 3466 3467 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 3468 0); // test unbind 3469 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0); 3470 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 3471 3472 glDrawArrays(GL_POINTS, 0, 1); 3473 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 3474 3475 glDisable(GL_BLEND); 3476 glDrawArrays(GL_POINTS, 0, 1); 3477 EXPECT_GL_NO_ERROR(); 3478 glEnable(GL_BLEND); 3479 3480 glBindTexture(GL_TEXTURE_2D, texture2); 3481 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 3482 3483 glDrawArrays(GL_POINTS, 0, 1); 3484 EXPECT_GL_NO_ERROR(); 3485 } 3486 3487 // Test that has float color attachment caching works with multiple color attachments bound to a 3488 // Framebuffer TEST_P(WebGLCompatibilityTest,FramebufferFloatColorAttachmentMRT)3489 TEST_P(WebGLCompatibilityTest, FramebufferFloatColorAttachmentMRT) 3490 { 3491 bool isWebGL2 = getClientMajorVersion() >= 3; 3492 if (isWebGL2) 3493 { 3494 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); 3495 3496 constexpr char kVS[] = 3497 R"(#version 300 es 3498 void main() 3499 { 3500 gl_Position = vec4(0, 0, 0, 1); 3501 })"; 3502 3503 constexpr char kFS[] = 3504 R"(#version 300 es 3505 precision lowp float; 3506 layout(location = 0) out vec4 o_color0; 3507 layout(location = 1) out vec4 o_color1; 3508 void main() 3509 { 3510 o_color0 = vec4(1, 0, 0, 1); 3511 o_color1 = vec4(0, 1, 0, 1); 3512 })"; 3513 3514 ANGLE_GL_PROGRAM(program, kVS, kFS); 3515 glUseProgram(program); 3516 } 3517 else 3518 { 3519 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_float")); 3520 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba")); 3521 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers")); 3522 3523 constexpr char kVS[] = 3524 R"(void main() 3525 { 3526 gl_Position = vec4(0, 0, 0, 1); 3527 })"; 3528 3529 constexpr char kFS[] = 3530 R"(#extension GL_EXT_draw_buffers : require 3531 precision lowp float; 3532 void main() 3533 { 3534 gl_FragData[0] = vec4(1, 0, 0, 1); 3535 gl_FragData[1] = vec4(0, 1, 0, 1); 3536 })"; 3537 3538 ANGLE_GL_PROGRAM(program, kVS, kFS); 3539 glUseProgram(program); 3540 } 3541 3542 glEnable(GL_BLEND); 3543 3544 GLTexture texture1; 3545 glBindTexture(GL_TEXTURE_2D, texture1); 3546 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 3547 EXPECT_GL_NO_ERROR(); 3548 3549 GLTexture texture2; 3550 glBindTexture(GL_TEXTURE_2D, texture2); 3551 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 3552 EXPECT_GL_NO_ERROR(); 3553 3554 GLTexture textureF1; 3555 glBindTexture(GL_TEXTURE_2D, textureF1); 3556 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr); 3557 EXPECT_GL_NO_ERROR(); 3558 3559 GLTexture textureF2; 3560 glBindTexture(GL_TEXTURE_2D, textureF2); 3561 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr); 3562 EXPECT_GL_NO_ERROR(); 3563 3564 GLFramebuffer fbo; 3565 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3566 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); 3567 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2, 0); 3568 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 3569 3570 GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; 3571 if (isWebGL2) 3572 { 3573 glDrawBuffers(2, drawbuffers); 3574 } 3575 else 3576 { 3577 glDrawBuffersEXT(2, drawbuffers); 3578 } 3579 3580 glDrawArrays(GL_POINTS, 0, 1); 3581 EXPECT_GL_NO_ERROR(); 3582 3583 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureF1, 0); 3584 glDrawArrays(GL_POINTS, 0, 1); 3585 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 3586 3587 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textureF2, 0); 3588 glDrawArrays(GL_POINTS, 0, 1); 3589 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 3590 3591 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); 3592 glDrawArrays(GL_POINTS, 0, 1); 3593 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 3594 3595 if (isWebGL2) 3596 { 3597 // WebGL 1 will report a FRAMEBUFFER_UNSUPPORTED for one unsigned_byte and one float 3598 // attachment bound to one FBO at the same time 3599 glDrawBuffers(1, drawbuffers); 3600 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 3601 glDrawArrays(GL_POINTS, 0, 1); 3602 EXPECT_GL_NO_ERROR(); 3603 glDrawBuffers(2, drawbuffers); 3604 } 3605 3606 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texture2, 0); 3607 glDrawArrays(GL_POINTS, 0, 1); 3608 EXPECT_GL_NO_ERROR(); 3609 } 3610 TestBlendColor(const bool shouldClamp)3611 static void TestBlendColor(const bool shouldClamp) 3612 { 3613 auto expected = GLColor32F(5, 0, 0, 0); 3614 glBlendColor(expected.R, expected.G, expected.B, expected.A); 3615 if (shouldClamp) 3616 { 3617 expected.R = 1; 3618 } 3619 3620 float arr[4] = {}; 3621 glGetFloatv(GL_BLEND_COLOR, arr); 3622 const auto actual = GLColor32F(arr[0], arr[1], arr[2], arr[3]); 3623 EXPECT_COLOR_NEAR(expected, actual, 0.001); 3624 } 3625 3626 // Test if blending of float32 color attachment generates GL_INVALID_OPERATION when 3627 // GL_EXT_float_blend is not enabled TEST_P(WebGLCompatibilityTest,FloatBlend)3628 TEST_P(WebGLCompatibilityTest, FloatBlend) 3629 { 3630 if (getClientMajorVersion() >= 3) 3631 { 3632 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); 3633 } 3634 else 3635 { 3636 TestBlendColor(true); 3637 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_float")); 3638 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba")); 3639 } 3640 3641 // - 3642 3643 TestExtFloatBlend(GL_RGBA32F, GL_FLOAT, false); 3644 3645 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_float_blend")); 3646 ASSERT_GL_NO_ERROR(); 3647 3648 TestExtFloatBlend(GL_RGBA32F, GL_FLOAT, true); 3649 } 3650 3651 // Test the blending of float16 color attachments TEST_P(WebGLCompatibilityTest,HalfFloatBlend)3652 TEST_P(WebGLCompatibilityTest, HalfFloatBlend) 3653 { 3654 GLenum internalFormat = GL_RGBA16F; 3655 GLenum type = GL_FLOAT; 3656 if (getClientMajorVersion() >= 3) 3657 { 3658 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); 3659 } 3660 else 3661 { 3662 TestBlendColor(true); 3663 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_half_float")); 3664 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_half_float")); 3665 internalFormat = GL_RGBA; 3666 type = GL_HALF_FLOAT_OES; 3667 } 3668 3669 // - 3670 3671 TestExtFloatBlend(internalFormat, type, true); 3672 } 3673 TEST_P(WebGLCompatibilityTest,R16FTextures)3674 TEST_P(WebGLCompatibilityTest, R16FTextures) 3675 { 3676 // http://anglebug.com/42263897 3677 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac()); 3678 3679 constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f}; 3680 const GLushort textureData[] = { 3681 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]), 3682 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])}; 3683 3684 for (auto extension : FloatingPointTextureExtensions) 3685 { 3686 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3687 { 3688 glRequestExtensionANGLE(extension); 3689 ASSERT_GL_NO_ERROR(); 3690 } 3691 3692 // Unsized R 16F (OES) 3693 if (getClientMajorVersion() < 3) 3694 { 3695 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float") && 3696 IsGLExtensionEnabled("GL_EXT_texture_rg"); 3697 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3698 bool render = false; 3699 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render, 3700 textureData, readPixelsData); 3701 } 3702 3703 // Unsized R 16F 3704 { 3705 bool texture = false; 3706 bool filter = false; 3707 bool render = false; 3708 TestFloatTextureFormat(GL_RED, GL_RED, GL_HALF_FLOAT, texture, filter, render, 3709 textureData, readPixelsData); 3710 } 3711 3712 if (getClientMajorVersion() >= 3) 3713 { 3714 // Sized R 16F 3715 bool texture = true; 3716 bool filter = true; 3717 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float") || 3718 IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3719 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT, texture, filter, render, 3720 textureData, readPixelsData); 3721 } 3722 else if (IsGLExtensionEnabled("GL_EXT_texture_storage")) 3723 { 3724 // Sized R 16F (OES) 3725 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float") && 3726 IsGLExtensionEnabled("GL_EXT_texture_rg"); 3727 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3728 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3729 TestFloatTextureFormat(GL_R16F, GL_RED, GL_HALF_FLOAT_OES, texture, filter, render, 3730 textureData, readPixelsData); 3731 } 3732 } 3733 } 3734 TEST_P(WebGLCompatibilityTest,RG16FTextures)3735 TEST_P(WebGLCompatibilityTest, RG16FTextures) 3736 { 3737 // http://anglebug.com/42263897 3738 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac()); 3739 3740 constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f}; 3741 const GLushort textureData[] = { 3742 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]), 3743 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])}; 3744 3745 for (auto extension : FloatingPointTextureExtensions) 3746 { 3747 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3748 { 3749 glRequestExtensionANGLE(extension); 3750 ASSERT_GL_NO_ERROR(); 3751 } 3752 3753 // Unsized RG 16F (OES) 3754 if (getClientMajorVersion() < 3) 3755 { 3756 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float") && 3757 IsGLExtensionEnabled("GL_EXT_texture_rg"); 3758 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3759 bool render = false; 3760 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render, 3761 textureData, readPixelsData); 3762 } 3763 3764 // Unsized RG 16F 3765 { 3766 bool texture = false; 3767 bool filter = false; 3768 bool render = false; 3769 TestFloatTextureFormat(GL_RG, GL_RG, GL_HALF_FLOAT, texture, filter, render, 3770 textureData, readPixelsData); 3771 } 3772 3773 if (getClientMajorVersion() >= 3) 3774 { 3775 // Sized RG 16F 3776 bool texture = true; 3777 bool filter = true; 3778 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float") || 3779 IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3780 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT, texture, filter, render, 3781 textureData, readPixelsData); 3782 } 3783 else if (IsGLExtensionEnabled("GL_EXT_texture_storage")) 3784 { 3785 // Sized RG 16F (OES) 3786 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float") && 3787 IsGLExtensionEnabled("GL_EXT_texture_rg"); 3788 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3789 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3790 TestFloatTextureFormat(GL_RG16F, GL_RG, GL_HALF_FLOAT_OES, texture, filter, render, 3791 textureData, readPixelsData); 3792 } 3793 } 3794 } 3795 TEST_P(WebGLCompatibilityTest,RGB16FTextures)3796 TEST_P(WebGLCompatibilityTest, RGB16FTextures) 3797 { 3798 // http://anglebug.com/42263897 3799 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac()); 3800 3801 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel()); 3802 3803 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f}; 3804 const GLushort textureData[] = { 3805 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]), 3806 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])}; 3807 3808 for (auto extension : FloatingPointTextureExtensions) 3809 { 3810 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3811 { 3812 glRequestExtensionANGLE(extension); 3813 ASSERT_GL_NO_ERROR(); 3814 } 3815 3816 // Unsized RGB 16F (OES) 3817 if (getClientMajorVersion() < 3) 3818 { 3819 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float"); 3820 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3821 // WebGL says that Unsized RGB 16F (OES) can be renderable with 3822 // GL_EXT_color_buffer_half_float. 3823 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3824 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render, 3825 textureData, readPixelsData); 3826 } 3827 3828 // Unsized RGB 16F 3829 { 3830 bool texture = false; 3831 bool filter = false; 3832 bool render = false; 3833 TestFloatTextureFormat(GL_RGB, GL_RGB, GL_HALF_FLOAT, texture, filter, render, 3834 textureData, readPixelsData); 3835 } 3836 3837 if (getClientMajorVersion() >= 3) 3838 { 3839 // Sized RGB 16F 3840 bool texture = true; 3841 bool filter = true; 3842 // Renderability of RGB is forbidden by GL_EXT_color_buffer_half_float in WebGL 2. 3843 bool render = false; 3844 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT, texture, filter, render, 3845 textureData, readPixelsData); 3846 } 3847 else if (IsGLExtensionEnabled("GL_EXT_texture_storage")) 3848 { 3849 // Sized RGB 16F (OES) 3850 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float"); 3851 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3852 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3853 TestFloatTextureFormat(GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES, texture, filter, render, 3854 textureData, readPixelsData); 3855 } 3856 } 3857 } 3858 TEST_P(WebGLCompatibilityTest,RGBA16FTextures)3859 TEST_P(WebGLCompatibilityTest, RGBA16FTextures) 3860 { 3861 // http://anglebug.com/42263897 3862 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac()); 3863 3864 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel()); 3865 3866 constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f}; 3867 const GLushort textureData[] = { 3868 gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]), 3869 gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])}; 3870 3871 for (auto extension : FloatingPointTextureExtensions) 3872 { 3873 if (strlen(extension) > 0 && IsGLExtensionRequestable(extension)) 3874 { 3875 glRequestExtensionANGLE(extension); 3876 ASSERT_GL_NO_ERROR(); 3877 } 3878 3879 // Unsized RGBA 16F (OES) 3880 if (getClientMajorVersion() < 3) 3881 { 3882 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float"); 3883 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3884 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3885 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render, 3886 textureData, readPixelsData); 3887 } 3888 3889 // Unsized RGBA 16F 3890 { 3891 bool texture = false; 3892 bool filter = false; 3893 bool render = false; 3894 TestFloatTextureFormat(GL_RGBA, GL_RGBA, GL_HALF_FLOAT, texture, filter, render, 3895 textureData, readPixelsData); 3896 } 3897 3898 if (getClientMajorVersion() >= 3) 3899 { 3900 // Sized RGBA 16F 3901 bool texture = true; 3902 bool filter = true; 3903 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_float") || 3904 IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3905 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, texture, filter, render, 3906 textureData, readPixelsData); 3907 } 3908 else if (IsGLExtensionEnabled("GL_EXT_texture_storage")) 3909 { 3910 // Sized RGBA 16F (OES) 3911 bool texture = IsGLExtensionEnabled("GL_OES_texture_half_float"); 3912 bool filter = IsGLExtensionEnabled("GL_OES_texture_half_float_linear"); 3913 bool render = IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"); 3914 TestFloatTextureFormat(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES, texture, filter, render, 3915 textureData, readPixelsData); 3916 } 3917 } 3918 } 3919 3920 // Test that when GL_CHROMIUM_color_buffer_float_rgb[a] is enabled, sized GL_RGB[A]_32F formats are 3921 // accepted by glTexImage2D TEST_P(WebGLCompatibilityTest,SizedRGBA32FFormats)3922 TEST_P(WebGLCompatibilityTest, SizedRGBA32FFormats) 3923 { 3924 // Test skipped because it is only valid for WebGL1 contexts. 3925 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2); 3926 3927 ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_OES_texture_float")); 3928 3929 glRequestExtensionANGLE("GL_OES_texture_float"); 3930 ASSERT_GL_NO_ERROR(); 3931 3932 GLTexture texture; 3933 glBindTexture(GL_TEXTURE_2D, texture); 3934 3935 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr); 3936 // dEQP implicitly defines error code ordering 3937 EXPECT_GL_ERROR(GL_INVALID_ENUM); 3938 3939 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr); 3940 // dEQP implicitly defines error code ordering 3941 EXPECT_GL_ERROR(GL_INVALID_ENUM); 3942 3943 if (IsGLExtensionRequestable("GL_CHROMIUM_color_buffer_float_rgba")) 3944 { 3945 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgba"); 3946 ASSERT_GL_NO_ERROR(); 3947 3948 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr); 3949 EXPECT_GL_NO_ERROR(); 3950 } 3951 3952 if (IsGLExtensionRequestable("GL_CHROMIUM_color_buffer_float_rgb")) 3953 { 3954 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgb"); 3955 ASSERT_GL_NO_ERROR(); 3956 3957 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 1, 1, 0, GL_RGB, GL_FLOAT, nullptr); 3958 EXPECT_GL_NO_ERROR(); 3959 } 3960 } 3961 3962 // Verify GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point. TEST_P(WebGLCompatibilityTest,DepthStencilAttachment)3963 TEST_P(WebGLCompatibilityTest, DepthStencilAttachment) 3964 { 3965 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2); 3966 3967 // Test that attaching a bound texture succeeds. 3968 GLTexture texture; 3969 glBindTexture(GL_TEXTURE_2D, texture); 3970 3971 GLFramebuffer fbo; 3972 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3973 3974 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0); 3975 3976 GLint attachmentType = 0; 3977 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 3978 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType); 3979 EXPECT_GL_NO_ERROR(); 3980 EXPECT_GLENUM_EQ(GL_TEXTURE, attachmentType); 3981 3982 // Test when if no attach object at the named attachment point and pname is not OBJECT_TYPE. 3983 GLFramebuffer fbo2; 3984 glBindFramebuffer(GL_FRAMEBUFFER, fbo2); 3985 3986 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 3987 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attachmentType); 3988 EXPECT_GL_ERROR(GL_INVALID_ENUM); 3989 } 3990 3991 // Verify framebuffer attachments return expected types when in an inconsistant state. TEST_P(WebGLCompatibilityTest,FramebufferAttachmentConsistancy)3992 TEST_P(WebGLCompatibilityTest, FramebufferAttachmentConsistancy) 3993 { 3994 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2); 3995 3996 GLFramebuffer fbo; 3997 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3998 3999 GLRenderbuffer rb1; 4000 glBindRenderbuffer(GL_RENDERBUFFER, rb1); 4001 4002 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb1); 4003 4004 GLint attachmentType = 0; 4005 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, 4006 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType); 4007 4008 EXPECT_GL_NO_ERROR(); 4009 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType); 4010 4011 GLRenderbuffer rb2; 4012 glBindRenderbuffer(GL_RENDERBUFFER, rb2); 4013 4014 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2); 4015 4016 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 4017 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType); 4018 4019 EXPECT_GL_NO_ERROR(); 4020 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType); 4021 4022 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb2); 4023 4024 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 4025 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType); 4026 4027 EXPECT_GL_NO_ERROR(); 4028 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType); 4029 4030 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb2); 4031 4032 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 4033 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType); 4034 4035 EXPECT_GL_NO_ERROR(); 4036 EXPECT_GLENUM_EQ(GL_RENDERBUFFER, attachmentType); 4037 } 4038 4039 // This tests that rendering feedback loops works as expected with WebGL 2. 4040 // Based on WebGL test conformance2/rendering/rendering-sampling-feedback-loop.html TEST_P(WebGL2CompatibilityTest,RenderingFeedbackLoopWithDrawBuffers)4041 TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDrawBuffers) 4042 { 4043 constexpr char kVS[] = 4044 R"(#version 300 es 4045 in vec4 aPosition; 4046 out vec2 texCoord; 4047 void main() { 4048 gl_Position = aPosition; 4049 texCoord = (aPosition.xy * 0.5) + 0.5; 4050 })"; 4051 4052 constexpr char kFS[] = 4053 R"(#version 300 es 4054 precision mediump float; 4055 uniform sampler2D tex; 4056 in vec2 texCoord; 4057 out vec4 oColor; 4058 void main() { 4059 oColor = texture(tex, texCoord); 4060 })"; 4061 4062 GLsizei width = 8; 4063 GLsizei height = 8; 4064 4065 GLint maxDrawBuffers = 0; 4066 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); 4067 // ES3 requires a minimum value of 4 for MAX_DRAW_BUFFERS. 4068 ASSERT_GE(maxDrawBuffers, 2); 4069 4070 ANGLE_GL_PROGRAM(program, kVS, kFS); 4071 glUseProgram(program); 4072 glViewport(0, 0, width, height); 4073 4074 GLTexture tex0; 4075 GLTexture tex1; 4076 GLFramebuffer fbo; 4077 FillTexture2D(tex0, width, height, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 4078 FillTexture2D(tex1, width, height, GLColor::green, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 4079 ASSERT_GL_NO_ERROR(); 4080 4081 glBindTexture(GL_TEXTURE_2D, tex1); 4082 GLint texLoc = glGetUniformLocation(program, "tex"); 4083 ASSERT_NE(-1, texLoc); 4084 glUniform1i(texLoc, 0); 4085 4086 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation 4087 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 4088 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0, 0); 4089 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1, 0); 4090 ASSERT_GL_NO_ERROR(); 4091 4092 drawBuffersFeedbackLoop(program, {{GL_NONE, GL_COLOR_ATTACHMENT1}}, GL_INVALID_OPERATION); 4093 drawBuffersFeedbackLoop(program, {{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}}, 4094 GL_INVALID_OPERATION); 4095 // A feedback loop is formed regardless of drawBuffers settings. 4096 drawBuffersFeedbackLoop(program, {{GL_COLOR_ATTACHMENT0, GL_NONE}}, GL_INVALID_OPERATION); 4097 } 4098 4099 // This tests that texture base level for immutable textures is clamped to the valid range, unlike 4100 // for non-immutable textures, for purposes of validation. Related to WebGL test 4101 // conformance2/textures/misc/immutable-tex-render-feedback.html TEST_P(WebGL2CompatibilityTest,RenderingFeedbackLoopWithImmutableTextureWithOutOfRangeBaseLevel)4102 TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithImmutableTextureWithOutOfRangeBaseLevel) 4103 { 4104 constexpr char kVS[] = 4105 R"(#version 300 es 4106 in vec4 aPosition; 4107 out vec2 texCoord; 4108 void main() { 4109 gl_Position = aPosition; 4110 texCoord = (aPosition.xy * 0.5) + 0.5; 4111 })"; 4112 4113 constexpr char kFS[] = 4114 R"(#version 300 es 4115 precision mediump float; 4116 uniform sampler2D tex; 4117 in vec2 texCoord; 4118 out vec4 oColor; 4119 void main() { 4120 oColor = texture(tex, texCoord); 4121 })"; 4122 4123 GLTexture texture; 4124 glBindTexture(GL_TEXTURE_2D, texture); 4125 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4); 4126 std::vector<GLColor> texData(4 * 4, GLColor::green); 4127 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, texData.data()); 4128 // Set a base level greater than the max level. It should be clamped to the actual max level. 4129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1); 4130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 4131 4132 ASSERT_GL_NO_ERROR(); 4133 4134 GLFramebuffer framebuffer; 4135 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 4136 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 4137 4138 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 4139 4140 ANGLE_GL_PROGRAM(program, kVS, kFS); 4141 4142 GLint uniformLoc = glGetUniformLocation(program, "tex"); 4143 ASSERT_NE(-1, uniformLoc); 4144 4145 glUseProgram(program); 4146 glUniform1i(uniformLoc, 0); 4147 glDisable(GL_BLEND); 4148 glDisable(GL_DEPTH_TEST); 4149 ASSERT_GL_NO_ERROR(); 4150 4151 // Ensure that the texture can be used for rendering. 4152 glBindFramebuffer(GL_FRAMEBUFFER, 0); 4153 glBindTexture(GL_TEXTURE_2D, texture); 4154 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4155 ASSERT_GL_NO_ERROR(); 4156 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 4157 4158 // Ensure that the texture can't be used to create a feedback loop. 4159 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 4160 glBindTexture(GL_TEXTURE_2D, texture); 4161 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4162 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4163 } 4164 4165 // This test covers detection of rendering feedback loops between the FBO and a depth Texture. 4166 // Based on WebGL test conformance2/rendering/depth-stencil-feedback-loop.html TEST_P(WebGL2CompatibilityTest,RenderingFeedbackLoopWithDepthStencil)4167 TEST_P(WebGL2CompatibilityTest, RenderingFeedbackLoopWithDepthStencil) 4168 { 4169 constexpr char kVS[] = 4170 R"(#version 300 es 4171 in vec4 aPosition; 4172 out vec2 texCoord; 4173 void main() { 4174 gl_Position = aPosition; 4175 texCoord = (aPosition.xy * 0.5) + 0.5; 4176 })"; 4177 4178 constexpr char kFS[] = 4179 R"(#version 300 es 4180 precision mediump float; 4181 uniform sampler2D tex; 4182 in vec2 texCoord; 4183 out vec4 oColor; 4184 void main() { 4185 oColor = texture(tex, texCoord); 4186 })"; 4187 4188 GLsizei width = 8; 4189 GLsizei height = 8; 4190 4191 ANGLE_GL_PROGRAM(program, kVS, kFS); 4192 glUseProgram(program); 4193 4194 glViewport(0, 0, width, height); 4195 4196 GLint texLoc = glGetUniformLocation(program, "tex"); 4197 glUniform1i(texLoc, 0); 4198 4199 // Create textures and allocate storage 4200 GLTexture tex0; 4201 GLTexture tex1; 4202 GLTexture tex2; 4203 FillTexture2D(tex0, width, height, GLColor::black, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); 4204 FillTexture2D(tex1, width, height, 0x80, 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, 4205 GL_UNSIGNED_INT); 4206 FillTexture2D(tex2, width, height, 0x40, 0, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, 4207 GL_UNSIGNED_INT_24_8); 4208 ASSERT_GL_NO_ERROR(); 4209 4210 GLFramebuffer fbo; 4211 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 4212 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0, 0); 4213 4214 // Test rendering and sampling feedback loop for depth buffer 4215 glBindTexture(GL_TEXTURE_2D, tex1); 4216 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex1, 0); 4217 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 4218 4219 // The same image is used as depth buffer during rendering. 4220 glEnable(GL_DEPTH_TEST); 4221 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4222 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Same image as depth buffer should fail"; 4223 4224 // The same image is used as depth buffer. But depth mask is false. 4225 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695 4226 glDepthMask(GL_FALSE); 4227 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4228 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth writes disabled should still fail"; 4229 4230 // The same image is used as depth buffer. But depth test is not enabled during rendering. 4231 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695 4232 glDepthMask(GL_TRUE); 4233 glDisable(GL_DEPTH_TEST); 4234 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4235 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth read disabled should still fail"; 4236 4237 // Test rendering and sampling feedback loop for stencil buffer 4238 glBindTexture(GL_TEXTURE_2D, tex2); 4239 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); 4240 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex2, 0); 4241 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); 4242 constexpr GLint stencilClearValue = 0x40; 4243 glClearBufferiv(GL_STENCIL, 0, &stencilClearValue); 4244 4245 // The same image is used as stencil buffer during rendering. 4246 glEnable(GL_STENCIL_TEST); 4247 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4248 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Same image as stencil buffer should fail"; 4249 4250 // The same image is used as stencil buffer. But stencil mask is zero. 4251 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695 4252 glStencilMask(0x0); 4253 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4254 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Stencil mask zero should still fail"; 4255 4256 // The same image is used as stencil buffer. But stencil test is not enabled during rendering. 4257 // This is now considered a feedback loop and should generate an error. http://crbug.com/763695 4258 glStencilMask(0xffff); 4259 glDisable(GL_STENCIL_TEST); 4260 drawQuad(program, "aPosition", 0.5f, 1.0f, true); 4261 EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Stencil test disabled should still fail"; 4262 } 4263 4264 // The source and the target for CopyTexSubImage3D are the same 3D texture. 4265 // But the level of the 3D texture != the level of the read attachment. TEST_P(WebGL2CompatibilityTest,NoTextureCopyingFeedbackLoopBetween3DLevels)4266 TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLevels) 4267 { 4268 GLTexture texture; 4269 GLFramebuffer framebuffer; 4270 4271 glBindTexture(GL_TEXTURE_3D, texture); 4272 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 4273 4274 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4275 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4276 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0); 4277 ASSERT_GL_NO_ERROR(); 4278 4279 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); 4280 EXPECT_GL_NO_ERROR(); 4281 } 4282 4283 // The source and the target for CopyTexSubImage3D are the same 3D texture. 4284 // But the zoffset of the 3D texture != the layer of the read attachment. TEST_P(WebGL2CompatibilityTest,NoTextureCopyingFeedbackLoopBetween3DLayers)4285 TEST_P(WebGL2CompatibilityTest, NoTextureCopyingFeedbackLoopBetween3DLayers) 4286 { 4287 GLTexture texture; 4288 GLFramebuffer framebuffer; 4289 4290 glBindTexture(GL_TEXTURE_3D, texture); 4291 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 4292 4293 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4294 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 1); 4295 ASSERT_GL_NO_ERROR(); 4296 4297 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 2, 2); 4298 EXPECT_GL_NO_ERROR(); 4299 } 4300 4301 // The source and the target for CopyTexSubImage3D are the same 3D texture. 4302 // And the level / zoffset of the 3D texture is equal to the level / layer of the read attachment. TEST_P(WebGL2CompatibilityTest,TextureCopyingFeedbackLoop3D)4303 TEST_P(WebGL2CompatibilityTest, TextureCopyingFeedbackLoop3D) 4304 { 4305 GLTexture texture; 4306 GLFramebuffer framebuffer; 4307 4308 glBindTexture(GL_TEXTURE_3D, texture); 4309 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 4310 4311 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4312 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4313 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4314 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 1, 0); 4315 ASSERT_GL_NO_ERROR(); 4316 4317 glCopyTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2); 4318 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4319 } 4320 4321 // Verify that errors are generated when there isn't a defined conversion between the clear type and 4322 // the buffer type. TEST_P(WebGL2CompatibilityTest,ClearBufferTypeCompatibity)4323 TEST_P(WebGL2CompatibilityTest, ClearBufferTypeCompatibity) 4324 { 4325 // Test skipped for D3D11 because it generates D3D11 runtime warnings. 4326 ANGLE_SKIP_TEST_IF(IsD3D11()); 4327 4328 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f}; 4329 constexpr int clearInt[] = {0, 0, 0, 0}; 4330 constexpr unsigned int clearUint[] = {0, 0, 0, 0}; 4331 4332 GLTexture texture; 4333 GLFramebuffer framebuffer; 4334 4335 glBindTexture(GL_TEXTURE_2D, texture); 4336 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 4337 4338 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 4339 ASSERT_GL_NO_ERROR(); 4340 4341 // Unsigned integer buffer 4342 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, nullptr); 4343 ASSERT_GL_NO_ERROR(); 4344 4345 glClearBufferfv(GL_COLOR, 0, clearFloat); 4346 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4347 4348 glClearBufferiv(GL_COLOR, 0, clearInt); 4349 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4350 4351 glClearBufferuiv(GL_COLOR, 0, clearUint); 4352 EXPECT_GL_NO_ERROR(); 4353 4354 glClear(GL_COLOR_BUFFER_BIT); 4355 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4356 4357 // Integer buffer 4358 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, nullptr); 4359 ASSERT_GL_NO_ERROR(); 4360 4361 glClearBufferfv(GL_COLOR, 0, clearFloat); 4362 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4363 4364 glClearBufferiv(GL_COLOR, 0, clearInt); 4365 EXPECT_GL_NO_ERROR(); 4366 4367 glClearBufferuiv(GL_COLOR, 0, clearUint); 4368 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4369 4370 glClear(GL_COLOR_BUFFER_BIT); 4371 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4372 4373 // Float buffer 4374 if (IsGLExtensionRequestable("GL_EXT_color_buffer_float")) 4375 { 4376 glRequestExtensionANGLE("GL_EXT_color_buffer_float"); 4377 } 4378 4379 if (IsGLExtensionEnabled("GL_EXT_color_buffer_float")) 4380 { 4381 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr); 4382 ASSERT_GL_NO_ERROR(); 4383 4384 glClearBufferfv(GL_COLOR, 0, clearFloat); 4385 EXPECT_GL_NO_ERROR(); 4386 4387 glClearBufferiv(GL_COLOR, 0, clearInt); 4388 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4389 4390 glClearBufferuiv(GL_COLOR, 0, clearUint); 4391 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4392 4393 glClear(GL_COLOR_BUFFER_BIT); 4394 EXPECT_GL_NO_ERROR(); 4395 } 4396 4397 // Normalized uint buffer 4398 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4399 ASSERT_GL_NO_ERROR(); 4400 4401 glClearBufferfv(GL_COLOR, 0, clearFloat); 4402 EXPECT_GL_NO_ERROR(); 4403 4404 glClearBufferiv(GL_COLOR, 0, clearInt); 4405 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4406 4407 glClearBufferuiv(GL_COLOR, 0, clearUint); 4408 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4409 4410 glClear(GL_COLOR_BUFFER_BIT); 4411 EXPECT_GL_NO_ERROR(); 4412 } 4413 4414 // Test the interaction of WebGL compatibility clears with default framebuffers TEST_P(WebGL2CompatibilityTest,ClearBufferDefaultFramebuffer)4415 TEST_P(WebGL2CompatibilityTest, ClearBufferDefaultFramebuffer) 4416 { 4417 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f}; 4418 constexpr int clearInt[] = {0, 0, 0, 0}; 4419 constexpr unsigned int clearUint[] = {0, 0, 0, 0}; 4420 4421 // glClear works as usual, this is also a regression test for a bug where we 4422 // iterated on maxDrawBuffers for default framebuffers, triggering an assert 4423 glClear(GL_COLOR_BUFFER_BIT); 4424 EXPECT_GL_NO_ERROR(); 4425 4426 // Default framebuffers are normalized uints, so only glClearBufferfv works. 4427 glClearBufferfv(GL_COLOR, 0, clearFloat); 4428 EXPECT_GL_NO_ERROR(); 4429 4430 glClearBufferiv(GL_COLOR, 0, clearInt); 4431 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4432 4433 glClearBufferuiv(GL_COLOR, 0, clearUint); 4434 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4435 } 4436 4437 // Test that clearing a non-existent drawbuffer of the default 4438 // framebuffer does not cause an assertion in WebGL validation TEST_P(WebGL2CompatibilityTest,ClearBuffer1OnDefaultFramebufferNoAssert)4439 TEST_P(WebGL2CompatibilityTest, ClearBuffer1OnDefaultFramebufferNoAssert) 4440 { 4441 constexpr float clearFloat[] = {0.0f, 0.0f, 0.0f, 0.0f}; 4442 constexpr int32_t clearInt[] = {0, 0, 0, 0}; 4443 constexpr uint32_t clearUint[] = {0, 0, 0, 0}; 4444 4445 glClearBufferfv(GL_COLOR, 1, clearFloat); 4446 EXPECT_GL_NO_ERROR(); 4447 4448 glClearBufferiv(GL_COLOR, 1, clearInt); 4449 EXPECT_GL_NO_ERROR(); 4450 4451 glClearBufferuiv(GL_COLOR, 1, clearUint); 4452 EXPECT_GL_NO_ERROR(); 4453 } 4454 4455 // Verify that errors are generate when trying to blit from an image to itself TEST_P(WebGL2CompatibilityTest,BlitFramebufferSameImage)4456 TEST_P(WebGL2CompatibilityTest, BlitFramebufferSameImage) 4457 { 4458 GLTexture textures[2]; 4459 glBindTexture(GL_TEXTURE_2D, textures[0]); 4460 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4); 4461 glBindTexture(GL_TEXTURE_2D, textures[1]); 4462 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 4, 4); 4463 4464 GLRenderbuffer renderbuffers[2]; 4465 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]); 4466 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4); 4467 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]); 4468 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4); 4469 4470 GLFramebuffer framebuffers[2]; 4471 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]); 4472 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]); 4473 4474 ASSERT_GL_NO_ERROR(); 4475 4476 // Same texture 4477 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 4478 0); 4479 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 4480 0); 4481 ASSERT_GL_NO_ERROR(); 4482 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST); 4483 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 4484 4485 // Same textures but different renderbuffers 4486 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 4487 renderbuffers[0]); 4488 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 4489 renderbuffers[1]); 4490 ASSERT_GL_NO_ERROR(); 4491 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT, GL_NEAREST); 4492 ASSERT_GL_NO_ERROR(); 4493 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 4494 GL_NEAREST); 4495 ASSERT_GL_NO_ERROR(); 4496 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, 4497 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 4498 GL_NEAREST); 4499 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 4500 4501 // Same renderbuffers but different textures 4502 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 4503 0); 4504 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 4505 0); 4506 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 4507 renderbuffers[0]); 4508 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 4509 renderbuffers[0]); 4510 ASSERT_GL_NO_ERROR(); 4511 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_COLOR_BUFFER_BIT, GL_NEAREST); 4512 ASSERT_GL_NO_ERROR(); 4513 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 4514 GL_NEAREST); 4515 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 4516 glBlitFramebuffer(0, 0, 4, 4, 0, 0, 4, 4, 4517 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 4518 GL_NEAREST); 4519 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 4520 } 4521 4522 // Verify that errors are generated when the fragment shader output doesn't match the bound color 4523 // buffer types TEST_P(WebGL2CompatibilityTest,FragmentShaderColorBufferTypeMissmatch)4524 TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch) 4525 { 4526 constexpr char kVS[] = 4527 R"(#version 300 es 4528 void main() { 4529 gl_Position = vec4(0, 0, 0, 1); 4530 })"; 4531 4532 constexpr char kFS[] = 4533 R"(#version 300 es 4534 precision mediump float; 4535 layout(location = 0) out vec4 floatOutput; 4536 layout(location = 1) out uvec4 uintOutput; 4537 layout(location = 2) out ivec4 intOutput; 4538 void main() { 4539 floatOutput = vec4(0, 0, 0, 1); 4540 uintOutput = uvec4(0, 0, 0, 1); 4541 intOutput = ivec4(0, 0, 0, 1); 4542 })"; 4543 4544 ANGLE_GL_PROGRAM(program, kVS, kFS); 4545 glUseProgram(program); 4546 4547 GLuint floatLocation = glGetFragDataLocation(program, "floatOutput"); 4548 GLuint uintLocation = glGetFragDataLocation(program, "uintOutput"); 4549 GLuint intLocation = glGetFragDataLocation(program, "intOutput"); 4550 4551 GLFramebuffer fbo; 4552 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 4553 4554 GLRenderbuffer floatRenderbuffer; 4555 glBindRenderbuffer(GL_RENDERBUFFER, floatRenderbuffer); 4556 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1); 4557 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER, 4558 floatRenderbuffer); 4559 4560 GLRenderbuffer uintRenderbuffer; 4561 glBindRenderbuffer(GL_RENDERBUFFER, uintRenderbuffer); 4562 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 1, 1); 4563 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER, 4564 uintRenderbuffer); 4565 4566 GLRenderbuffer intRenderbuffer; 4567 glBindRenderbuffer(GL_RENDERBUFFER, intRenderbuffer); 4568 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 1, 1); 4569 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER, 4570 intRenderbuffer); 4571 4572 ASSERT_GL_NO_ERROR(); 4573 4574 GLint maxDrawBuffers = 0; 4575 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); 4576 std::vector<GLenum> drawBuffers(static_cast<size_t>(maxDrawBuffers), GL_NONE); 4577 drawBuffers[floatLocation] = GL_COLOR_ATTACHMENT0 + floatLocation; 4578 drawBuffers[uintLocation] = GL_COLOR_ATTACHMENT0 + uintLocation; 4579 drawBuffers[intLocation] = GL_COLOR_ATTACHMENT0 + intLocation; 4580 4581 glDrawBuffers(maxDrawBuffers, drawBuffers.data()); 4582 4583 // Check that the correct case generates no errors 4584 glDrawArrays(GL_TRIANGLES, 0, 6); 4585 EXPECT_GL_NO_ERROR(); 4586 4587 // Unbind some buffers and verify that there are still no errors 4588 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER, 4589 0); 4590 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER, 4591 0); 4592 glDrawArrays(GL_TRIANGLES, 0, 6); 4593 EXPECT_GL_NO_ERROR(); 4594 4595 // Swap the int and uint buffers to and verify that an error is generated 4596 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER, 4597 intRenderbuffer); 4598 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER, 4599 uintRenderbuffer); 4600 glDrawArrays(GL_TRIANGLES, 0, 6); 4601 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4602 4603 // Swap the float and uint buffers to and verify that an error is generated 4604 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uintLocation, GL_RENDERBUFFER, 4605 floatRenderbuffer); 4606 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + floatLocation, GL_RENDERBUFFER, 4607 uintRenderbuffer); 4608 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + intLocation, GL_RENDERBUFFER, 4609 intRenderbuffer); 4610 glDrawArrays(GL_TRIANGLES, 0, 6); 4611 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4612 } 4613 4614 // Verify that errors are generated when the vertex shader intput doesn't match the bound attribute 4615 // types TEST_P(WebGL2CompatibilityTest,VertexShaderAttributeTypeMismatch)4616 TEST_P(WebGL2CompatibilityTest, VertexShaderAttributeTypeMismatch) 4617 { 4618 constexpr char kVS[] = 4619 R"(#version 300 es 4620 in vec4 floatInput; 4621 in uvec4 uintInput; 4622 in ivec4 intInput; 4623 void main() { 4624 gl_Position = vec4(floatInput.x, uintInput.x, intInput.x, 1); 4625 })"; 4626 4627 constexpr char kFS[] = 4628 R"(#version 300 es 4629 precision mediump float; 4630 out vec4 outputColor; 4631 void main() { 4632 outputColor = vec4(0, 0, 0, 1); 4633 })"; 4634 4635 ANGLE_GL_PROGRAM(program, kVS, kFS); 4636 glUseProgram(program); 4637 4638 GLint floatLocation = glGetAttribLocation(program, "floatInput"); 4639 GLint uintLocation = glGetAttribLocation(program, "uintInput"); 4640 GLint intLocation = glGetAttribLocation(program, "intInput"); 4641 4642 // Default attributes are of float types 4643 glDrawArrays(GL_TRIANGLES, 0, 6); 4644 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4645 4646 // Set the default attributes to the correct types, should succeed 4647 glVertexAttribI4ui(uintLocation, 0, 0, 0, 1); 4648 glVertexAttribI4i(intLocation, 0, 0, 0, 1); 4649 glDrawArrays(GL_TRIANGLES, 0, 6); 4650 EXPECT_GL_NO_ERROR(); 4651 4652 // Change the default float attribute to an integer, should fail 4653 glVertexAttribI4ui(floatLocation, 0, 0, 0, 1); 4654 glDrawArrays(GL_TRIANGLES, 0, 6); 4655 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4656 4657 // Use a buffer for some attributes 4658 GLBuffer buffer; 4659 glBindBuffer(GL_ARRAY_BUFFER, buffer); 4660 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW); 4661 glEnableVertexAttribArray(floatLocation); 4662 glVertexAttribPointer(floatLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); 4663 glDrawArrays(GL_TRIANGLES, 0, 6); 4664 EXPECT_GL_NO_ERROR(); 4665 4666 // Use a float pointer attrib for a uint input 4667 glEnableVertexAttribArray(uintLocation); 4668 glVertexAttribPointer(uintLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); 4669 glDrawArrays(GL_TRIANGLES, 0, 6); 4670 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4671 4672 // Use a uint pointer for the uint input 4673 glVertexAttribIPointer(uintLocation, 4, GL_UNSIGNED_INT, 0, nullptr); 4674 glDrawArrays(GL_TRIANGLES, 0, 6); 4675 EXPECT_GL_NO_ERROR(); 4676 } 4677 4678 // Test that it's not possible to query the non-zero color attachments without the drawbuffers 4679 // extension in WebGL1 TEST_P(WebGLCompatibilityTest,FramebufferAttachmentQuery)4680 TEST_P(WebGLCompatibilityTest, FramebufferAttachmentQuery) 4681 { 4682 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 2); 4683 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_draw_buffers")); 4684 4685 GLFramebuffer fbo; 4686 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 4687 EXPECT_GL_NO_ERROR(); 4688 4689 GLint result; 4690 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 4691 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &result); 4692 EXPECT_GL_ERROR(GL_INVALID_ENUM); 4693 4694 GLRenderbuffer renderbuffer; 4695 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 4696 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1); 4697 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderbuffer); 4698 EXPECT_GL_ERROR(GL_INVALID_ENUM); 4699 } 4700 4701 // Tests WebGL reports INVALID_OPERATION for mismatch of drawbuffers and fragment output TEST_P(WebGLCompatibilityTest,DrawBuffers)4702 TEST_P(WebGLCompatibilityTest, DrawBuffers) 4703 { 4704 // Make sure we can use at least 4 attachments for the tests. 4705 bool useEXT = false; 4706 if (getClientMajorVersion() < 3) 4707 { 4708 ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_EXT_draw_buffers")); 4709 4710 glRequestExtensionANGLE("GL_EXT_draw_buffers"); 4711 useEXT = true; 4712 EXPECT_GL_NO_ERROR(); 4713 } 4714 4715 GLint maxDrawBuffers = 0; 4716 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); 4717 // Test skipped because MAX_DRAW_BUFFERS is too small. 4718 ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4); 4719 4720 // Clears all the renderbuffers to red. 4721 auto ClearEverythingToRed = [](GLRenderbuffer *renderbuffers) { 4722 GLFramebuffer clearFBO; 4723 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO); 4724 4725 glClearColor(1, 0, 0, 1); 4726 for (int i = 0; i < 4; ++i) 4727 { 4728 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 4729 renderbuffers[i]); 4730 glClear(GL_COLOR_BUFFER_BIT); 4731 } 4732 ASSERT_GL_NO_ERROR(); 4733 }; 4734 4735 // Checks that the renderbuffers specified by mask have the correct color 4736 auto CheckColors = [](GLRenderbuffer *renderbuffers, int mask, GLColor color) { 4737 GLFramebuffer readFBO; 4738 glBindFramebuffer(GL_FRAMEBUFFER, readFBO); 4739 4740 for (int attachmentIndex = 0; attachmentIndex < 4; ++attachmentIndex) 4741 { 4742 if (mask & (1 << attachmentIndex)) 4743 { 4744 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 4745 renderbuffers[attachmentIndex]); 4746 EXPECT_PIXEL_COLOR_EQ(0, 0, color) << "attachment " << attachmentIndex; 4747 } 4748 } 4749 ASSERT_GL_NO_ERROR(); 4750 }; 4751 4752 // Depending on whether we are using the extension or ES3, a different entrypoint must be called 4753 auto DrawBuffers = [](bool useEXT, int numBuffers, GLenum *buffers) { 4754 if (useEXT) 4755 { 4756 glDrawBuffersEXT(numBuffers, buffers); 4757 } 4758 else 4759 { 4760 glDrawBuffers(numBuffers, buffers); 4761 } 4762 }; 4763 4764 // Initialized the test framebuffer 4765 GLFramebuffer drawFBO; 4766 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO); 4767 4768 GLRenderbuffer renderbuffers[4]; 4769 for (int i = 0; i < 4; ++i) 4770 { 4771 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]); 4772 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1); 4773 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, 4774 renderbuffers[i]); 4775 } 4776 4777 ASSERT_GL_NO_ERROR(); 4778 4779 GLenum allDrawBuffers[] = { 4780 GL_COLOR_ATTACHMENT0, 4781 GL_COLOR_ATTACHMENT1, 4782 GL_COLOR_ATTACHMENT2, 4783 GL_COLOR_ATTACHMENT3, 4784 }; 4785 4786 GLenum halfDrawBuffers[] = { 4787 GL_NONE, 4788 GL_COLOR_ATTACHMENT1, 4789 GL_NONE, 4790 GL_COLOR_ATTACHMENT3, 4791 }; 4792 4793 // Test that when using gl_FragColor with no-array 4794 const char *fragESSL1 = 4795 R"(precision highp float; 4796 void main() 4797 { 4798 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 4799 })"; 4800 ANGLE_GL_PROGRAM(programESSL1, essl1_shaders::vs::Simple(), fragESSL1); 4801 4802 { 4803 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO); 4804 DrawBuffers(useEXT, 4, allDrawBuffers); 4805 drawQuad(programESSL1, essl1_shaders::PositionAttrib(), 0.5, 1.0, true); 4806 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4807 } 4808 4809 // Test what happens when rendering to a subset of the outputs. There is a behavior difference 4810 // between the extension and ES3. In the extension gl_FragData is implicitly declared as an 4811 // array of size MAX_DRAW_BUFFERS, so the WebGL spec stipulates that elements not written to 4812 // should default to 0. On the contrary, in ES3 outputs are specified one by one, so 4813 // attachments not declared in the shader should not be written to. 4814 const char *positionAttrib; 4815 const char *writeOddOutputsVert; 4816 const char *writeOddOutputsFrag; 4817 if (useEXT) 4818 { 4819 positionAttrib = essl1_shaders::PositionAttrib(); 4820 writeOddOutputsVert = essl1_shaders::vs::Simple(); 4821 writeOddOutputsFrag = 4822 R"(#extension GL_EXT_draw_buffers : require 4823 precision highp float; 4824 void main() 4825 { 4826 gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0); 4827 gl_FragData[3] = vec4(0.0, 1.0, 0.0, 1.0); 4828 })"; 4829 } 4830 else 4831 { 4832 positionAttrib = essl3_shaders::PositionAttrib(); 4833 writeOddOutputsVert = essl3_shaders::vs::Simple(); 4834 writeOddOutputsFrag = 4835 R"(#version 300 es 4836 precision highp float; 4837 layout(location = 1) out vec4 output1; 4838 layout(location = 3) out vec4 output2; 4839 void main() 4840 { 4841 output1 = vec4(0.0, 1.0, 0.0, 1.0); 4842 output2 = vec4(0.0, 1.0, 0.0, 1.0); 4843 })"; 4844 } 4845 ANGLE_GL_PROGRAM(writeOddOutputsProgram, writeOddOutputsVert, writeOddOutputsFrag); 4846 4847 // Test that attachments not written to get the "unwritten" color (useEXT) 4848 // Or INVALID_OPERATION is generated if there's active draw buffer receive no output 4849 { 4850 ClearEverythingToRed(renderbuffers); 4851 4852 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO); 4853 DrawBuffers(useEXT, 4, allDrawBuffers); 4854 drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true); 4855 4856 if (useEXT) 4857 { 4858 ASSERT_GL_NO_ERROR(); 4859 CheckColors(renderbuffers, 0b1010, GLColor::green); 4860 // In the extension, when an attachment isn't written to, it should get 0's 4861 CheckColors(renderbuffers, 0b0101, GLColor(0, 0, 0, 0)); 4862 } 4863 else 4864 { 4865 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4866 } 4867 } 4868 4869 // Test that attachments written to get the correct color from shader output but that even when 4870 // the extension is used, disabled attachments are not written at all and stay red. 4871 { 4872 ClearEverythingToRed(renderbuffers); 4873 4874 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO); 4875 DrawBuffers(useEXT, 4, halfDrawBuffers); 4876 drawQuad(writeOddOutputsProgram, positionAttrib, 0.5, 1.0, true); 4877 ASSERT_GL_NO_ERROR(); 4878 4879 CheckColors(renderbuffers, 0b1010, GLColor::green); 4880 CheckColors(renderbuffers, 0b0101, GLColor::red); 4881 } 4882 } 4883 4884 // Test that it's possible to generate mipmaps on unsized floating point textures once the 4885 // extensions have been enabled TEST_P(WebGLCompatibilityTest,GenerateMipmapUnsizedFloatingPointTexture)4886 TEST_P(WebGLCompatibilityTest, GenerateMipmapUnsizedFloatingPointTexture) 4887 { 4888 glRequestExtensionANGLE("GL_OES_texture_float"); 4889 glRequestExtensionANGLE("GL_CHROMIUM_color_buffer_float_rgba"); 4890 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float")); 4891 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba")); 4892 4893 GLTexture texture; 4894 glBindTexture(GL_TEXTURE_2D, texture); 4895 4896 constexpr GLColor32F data[4] = { 4897 kFloatRed, 4898 kFloatRed, 4899 kFloatGreen, 4900 kFloatBlue, 4901 }; 4902 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_FLOAT, data); 4903 ASSERT_GL_NO_ERROR(); 4904 4905 glGenerateMipmap(GL_TEXTURE_2D); 4906 EXPECT_GL_NO_ERROR(); 4907 } 4908 // Test that it's possible to generate mipmaps on unsized floating point textures once the 4909 // extensions have been enabled TEST_P(WebGLCompatibilityTest,GenerateMipmapSizedFloatingPointTexture)4910 TEST_P(WebGLCompatibilityTest, GenerateMipmapSizedFloatingPointTexture) 4911 { 4912 if (IsGLExtensionRequestable("GL_OES_texture_float")) 4913 { 4914 glRequestExtensionANGLE("GL_OES_texture_float"); 4915 } 4916 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float")); 4917 4918 if (IsGLExtensionRequestable("GL_EXT_texture_storage")) 4919 { 4920 glRequestExtensionANGLE("GL_EXT_texture_storage"); 4921 } 4922 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage")); 4923 4924 GLTexture texture; 4925 glBindTexture(GL_TEXTURE_2D, texture); 4926 4927 constexpr GLColor32F data[4] = { 4928 kFloatRed, 4929 kFloatRed, 4930 kFloatGreen, 4931 kFloatBlue, 4932 }; 4933 glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA32F, 2, 2); 4934 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, data); 4935 ASSERT_GL_NO_ERROR(); 4936 4937 glGenerateMipmap(GL_TEXTURE_2D); 4938 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4939 4940 if (IsGLExtensionRequestable("GL_EXT_color_buffer_float")) 4941 { 4942 // Format is renderable but not filterable 4943 glRequestExtensionANGLE("GL_EXT_color_buffer_float"); 4944 glGenerateMipmap(GL_TEXTURE_2D); 4945 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4946 } 4947 4948 if (IsGLExtensionRequestable("GL_EXT_color_buffer_float_linear")) 4949 { 4950 // Format is renderable but not filterable 4951 glRequestExtensionANGLE("GL_EXT_color_buffer_float_linear"); 4952 4953 if (IsGLExtensionEnabled("GL_EXT_color_buffer_float")) 4954 { 4955 // Format is filterable and renderable 4956 glGenerateMipmap(GL_TEXTURE_2D); 4957 EXPECT_GL_NO_ERROR(); 4958 } 4959 else 4960 { 4961 // Format is filterable but not renderable 4962 glGenerateMipmap(GL_TEXTURE_2D); 4963 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 4964 } 4965 } 4966 } 4967 4968 // Verify that a texture format is only allowed with extension enabled. validateTexImageExtensionFormat(GLenum format,const std::string & extName)4969 void WebGLCompatibilityTest::validateTexImageExtensionFormat(GLenum format, 4970 const std::string &extName) 4971 { 4972 // Verify texture format fails by default. 4973 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr); 4974 EXPECT_GL_ERROR(GL_INVALID_ENUM); 4975 4976 if (IsGLExtensionRequestable(extName)) 4977 { 4978 // Verify texture format is allowed once extension is enabled. 4979 glRequestExtensionANGLE(extName.c_str()); 4980 EXPECT_TRUE(IsGLExtensionEnabled(extName)); 4981 4982 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, GL_UNSIGNED_BYTE, nullptr); 4983 ASSERT_GL_NO_ERROR(); 4984 } 4985 } 4986 4987 // Test enabling various non-compressed texture format extensions TEST_P(WebGLCompatibilityTest,EnableTextureFormatExtensions)4988 TEST_P(WebGLCompatibilityTest, EnableTextureFormatExtensions) 4989 { 4990 ANGLE_SKIP_TEST_IF(IsOzone()); 4991 ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2); 4992 4993 GLTexture texture; 4994 glBindTexture(GL_TEXTURE_2D, texture); 4995 4996 // Verify valid format is allowed. 4997 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 4998 ASSERT_GL_NO_ERROR(); 4999 5000 // Verify invalid format fails. 5001 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA32F, GL_UNSIGNED_BYTE, nullptr); 5002 EXPECT_GL_ERROR(GL_INVALID_ENUM); 5003 5004 // Verify formats from enableable extensions. 5005 if (!IsOpenGLES()) 5006 { 5007 validateTexImageExtensionFormat(GL_RED_EXT, "GL_EXT_texture_rg"); 5008 } 5009 5010 validateTexImageExtensionFormat(GL_SRGB_EXT, "GL_EXT_texture_sRGB"); 5011 validateTexImageExtensionFormat(GL_BGRA_EXT, "GL_EXT_texture_format_BGRA8888"); 5012 } 5013 validateCompressedTexImageExtensionFormat(GLenum format,GLsizei width,GLsizei height,GLsizei blockSize,const std::string & extName,bool subImageAllowed)5014 void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum format, 5015 GLsizei width, 5016 GLsizei height, 5017 GLsizei blockSize, 5018 const std::string &extName, 5019 bool subImageAllowed) 5020 { 5021 std::vector<GLubyte> data(blockSize, 0u); 5022 5023 GLTexture texture; 5024 glBindTexture(GL_TEXTURE_2D, texture); 5025 5026 // Verify texture format fails by default. 5027 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data()); 5028 EXPECT_GL_ERROR(GL_INVALID_ENUM); 5029 5030 if (IsGLExtensionRequestable(extName)) 5031 { 5032 // Verify texture format is allowed once extension is enabled. 5033 glRequestExtensionANGLE(extName.c_str()); 5034 EXPECT_TRUE(IsGLExtensionEnabled(extName)); 5035 5036 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, blockSize, data.data()); 5037 EXPECT_GL_NO_ERROR(); 5038 5039 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, blockSize, 5040 data.data()); 5041 if (subImageAllowed) 5042 { 5043 EXPECT_GL_NO_ERROR(); 5044 } 5045 else 5046 { 5047 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 5048 } 5049 } 5050 } 5051 expectedByteLength(GLenum format,GLsizei width,GLsizei height)5052 GLint WebGLCompatibilityTest::expectedByteLength(GLenum format, GLsizei width, GLsizei height) 5053 { 5054 switch (format) 5055 { 5056 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 5057 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 5058 case GL_COMPRESSED_RED_RGTC1_EXT: 5059 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: 5060 return ((width + 3) / 4) * ((height + 3) / 4) * 8; 5061 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 5062 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 5063 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: 5064 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 5065 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT: 5066 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 5067 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 5068 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 5069 return ((width + 3) / 4) * ((height + 3) / 4) * 16; 5070 } 5071 5072 UNREACHABLE(); 5073 return 0; 5074 } 5075 testCompressedTexLevelDimension(GLenum format,GLint level,GLsizei width,GLsizei height,GLsizei expectedByteLength,GLenum expectedError,const char * explanation)5076 void WebGLCompatibilityTest::testCompressedTexLevelDimension(GLenum format, 5077 GLint level, 5078 GLsizei width, 5079 GLsizei height, 5080 GLsizei expectedByteLength, 5081 GLenum expectedError, 5082 const char *explanation) 5083 { 5084 std::vector<uint8_t> tempVector(expectedByteLength, 0); 5085 5086 EXPECT_GL_NO_ERROR(); 5087 5088 GLTexture sourceTexture; 5089 glBindTexture(GL_TEXTURE_2D, sourceTexture); 5090 glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, expectedByteLength, 5091 tempVector.data()); 5092 if (expectedError == 0) 5093 { 5094 EXPECT_GL_NO_ERROR() << explanation; 5095 } 5096 else 5097 { 5098 EXPECT_GL_ERROR(expectedError) << explanation; 5099 } 5100 5101 if (level == 0 && width > 0) 5102 { 5103 GLTexture sourceTextureStorage; 5104 glBindTexture(GL_TEXTURE_2D, sourceTextureStorage); 5105 5106 if (getClientMajorVersion() >= 3) 5107 { 5108 glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height); 5109 if (expectedError == 0) 5110 { 5111 EXPECT_GL_NO_ERROR() << explanation << " (texStorage2D)"; 5112 } 5113 else 5114 { 5115 EXPECT_GL_ERROR(expectedError) << explanation << " (texStorage2D)"; 5116 } 5117 } 5118 else 5119 { 5120 if (IsGLExtensionRequestable("GL_EXT_texture_storage")) 5121 { 5122 glRequestExtensionANGLE("GL_EXT_texture_storage"); 5123 ASSERT_TRUE(IsGLExtensionEnabled("GL_EXT_texture_storage")); 5124 5125 glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, width, height); 5126 if (expectedError == 0) 5127 { 5128 EXPECT_GL_NO_ERROR() << explanation << " (texStorage2DEXT)"; 5129 } 5130 else 5131 { 5132 EXPECT_GL_ERROR(expectedError) << explanation << " (texStorage2DEXT)"; 5133 } 5134 } 5135 } 5136 } 5137 } 5138 testCompressedTexImage(GLenum format)5139 void WebGLCompatibilityTest::testCompressedTexImage(GLenum format) 5140 { 5141 struct TestCase 5142 { 5143 GLint level; 5144 GLsizei width; 5145 GLsizei height; 5146 GLenum expectedError; 5147 const char *explanation; 5148 }; 5149 5150 constexpr TestCase testCases[] = { 5151 {0, 4, 3, GL_INVALID_OPERATION, "level is 0, height is not a multiple of 4"}, 5152 {0, 3, 4, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"}, 5153 {0, 2, 2, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"}, 5154 {0, 4, 4, GL_NO_ERROR, "is valid"}, 5155 {1, 1, 1, GL_INVALID_OPERATION, "implied base mip 2x2 is invalid"}, 5156 {1, 1, 2, GL_INVALID_OPERATION, "implied base mip 2x4 is invalid"}, 5157 {1, 2, 1, GL_INVALID_OPERATION, "implied base mip 4x2 is invalid"}, 5158 {1, 2, 2, GL_NO_ERROR, "implied base mip 4x4 is valid"}, 5159 }; 5160 5161 constexpr TestCase webgl2TestCases[] = { 5162 {0, 0, 0, GL_NO_ERROR, "0: 0x0 is valid"}, 5163 {0, 1, 1, GL_INVALID_OPERATION, "0: 1x1 is invalid"}, 5164 {0, 2, 2, GL_INVALID_OPERATION, "0: 2x2 is invalid"}, 5165 {0, 3, 3, GL_INVALID_OPERATION, "0: 3x3 is invalid"}, 5166 {0, 10, 10, GL_INVALID_OPERATION, "0: 10x10 is invalid"}, 5167 {0, 11, 11, GL_INVALID_OPERATION, "0: 11x11 is invalid"}, 5168 {0, 11, 12, GL_INVALID_OPERATION, "0: 11x12 is invalid"}, 5169 {0, 12, 11, GL_INVALID_OPERATION, "0: 12x11 is invalid"}, 5170 {0, 12, 12, GL_NO_ERROR, "0: 12x12 is valid"}, 5171 {1, 0, 0, GL_NO_ERROR, "1: 0x0 is valid"}, 5172 {1, 3, 3, GL_INVALID_OPERATION, "1: 3x3 is invalid"}, 5173 {1, 5, 5, GL_INVALID_OPERATION, "1: 5x5 is invalid"}, 5174 {1, 5, 6, GL_INVALID_OPERATION, "1: 5x6 is invalid"}, 5175 {1, 6, 5, GL_INVALID_OPERATION, "1: 6x5 is invalid"}, 5176 {1, 6, 6, GL_NO_ERROR, "1: 6x6 is valid"}, 5177 {2, 0, 0, GL_NO_ERROR, "2: 0x0 is valid"}, 5178 {2, 3, 3, GL_NO_ERROR, "2: 3x3 is valid"}, 5179 {3, 1, 3, GL_NO_ERROR, "3: 1x3 is valid"}, 5180 {3, 1, 1, GL_NO_ERROR, "3: 1x1 is valid"}, 5181 {2, 1, 3, GL_NO_ERROR, "implied base mip 4x12 is valid"}, 5182 }; 5183 5184 for (const TestCase &test : testCases) 5185 { 5186 testCompressedTexLevelDimension(format, test.level, test.width, test.height, 5187 expectedByteLength(format, test.width, test.height), 5188 test.expectedError, test.explanation); 5189 } 5190 5191 if (getClientMajorVersion() >= 3) 5192 { 5193 for (const TestCase &test : webgl2TestCases) 5194 { 5195 testCompressedTexLevelDimension(format, test.level, test.width, test.height, 5196 expectedByteLength(format, test.width, test.height), 5197 test.expectedError, test.explanation); 5198 } 5199 } 5200 } 5201 5202 // Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT1RGB)5203 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB) 5204 { 5205 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8, 5206 "GL_EXT_texture_compression_dxt1", true); 5207 } 5208 5209 // Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT1RGBA)5210 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGBA) 5211 { 5212 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8, 5213 "GL_EXT_texture_compression_dxt1", true); 5214 } 5215 5216 // Test enabling GL_ANGLE_texture_compression_dxt3 TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT3)5217 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3) 5218 { 5219 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 16, 5220 "GL_ANGLE_texture_compression_dxt3", true); 5221 } 5222 5223 // Test enabling GL_ANGLE_texture_compression_dxt5 TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT5)5224 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5) 5225 { 5226 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 16, 5227 "GL_ANGLE_texture_compression_dxt5", true); 5228 } 5229 5230 // Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_S3TC_DXT1_EXT TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT1SRGB)5231 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGB) 5232 { 5233 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8, 5234 "GL_EXT_texture_compression_s3tc_srgb", true); 5235 } 5236 5237 // Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT1SRGBA)5238 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1SRGBA) 5239 { 5240 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8, 5241 "GL_EXT_texture_compression_s3tc_srgb", true); 5242 } 5243 5244 // Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT3SRGBA)5245 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT3SRGBA) 5246 { 5247 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16, 5248 "GL_EXT_texture_compression_s3tc_srgb", true); 5249 } 5250 5251 // Test enabling GL_EXT_texture_compression_s3tc_srgb for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionDXT5SRGBA)5252 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT5SRGBA) 5253 { 5254 validateCompressedTexImageExtensionFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16, 5255 "GL_EXT_texture_compression_s3tc_srgb", true); 5256 } 5257 5258 // Test enabling GL_OES_compressed_ETC1_RGB8_texture TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionETC1)5259 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionETC1) 5260 { 5261 validateCompressedTexImageExtensionFormat( 5262 GL_ETC1_RGB8_OES, 4, 4, 8, "GL_OES_compressed_ETC1_RGB8_texture", 5263 IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture")); 5264 } 5265 5266 // Test enabling GL_ANGLE_lossy_etc_decode TEST_P(WebGLCompatibilityTest,EnableCompressedTextureExtensionLossyDecode)5267 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionLossyDecode) 5268 { 5269 validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 8, 5270 "GL_ANGLE_lossy_etc_decode", true); 5271 } 5272 5273 // Reject attempts to allocate too-large arrays in shaders. 5274 // This is an implementation-defined limit - crbug.com/1220237 . TEST_P(WebGLCompatibilityTest,ValidateArraySizes)5275 TEST_P(WebGLCompatibilityTest, ValidateArraySizes) 5276 { 5277 // Note: on macOS with ANGLE's OpenGL backend, getting anywhere 5278 // close to this limit causes pathologically slow shader 5279 // compilation in the driver. For the "ok" case, therefore, use a 5280 // fairly small array. 5281 constexpr char kVSArrayOK[] = 5282 R"(varying vec4 color; 5283 const int array_size = 500; 5284 void main() 5285 { 5286 mat2 array[array_size]; 5287 mat2 array2[array_size]; 5288 if (array[0][0][0] + array2[0][0][0] == 2.0) 5289 color = vec4(0.0, 1.0, 0.0, 1.0); 5290 else 5291 color = vec4(1.0, 0.0, 0.0, 1.0); 5292 })"; 5293 5294 constexpr char kVSArrayTooLarge[] = 5295 R"(varying vec4 color; 5296 // 16 MB / 32 aligned bytes per mat2 = 524288 5297 const int array_size = 524289; 5298 void main() 5299 { 5300 mat2 array[array_size]; 5301 if (array[0][0][0] == 2.0) 5302 color = vec4(0.0, 1.0, 0.0, 1.0); 5303 else 5304 color = vec4(1.0, 0.0, 0.0, 1.0); 5305 })"; 5306 5307 constexpr char kVSArrayMuchTooLarge[] = 5308 R"(varying vec4 color; 5309 const int array_size = 757000; 5310 void main() 5311 { 5312 mat2 array[array_size]; 5313 if (array[0][0][0] == 2.0) 5314 color = vec4(0.0, 1.0, 0.0, 1.0); 5315 else 5316 color = vec4(1.0, 0.0, 0.0, 1.0); 5317 })"; 5318 5319 constexpr char kFS[] = 5320 R"(precision mediump float; 5321 varying vec4 color; 5322 void main() 5323 { 5324 gl_FragColor = vec4(color.r - 0.5, 0.0, 0.0, 1.0); 5325 })"; 5326 5327 GLuint program = CompileProgram(kVSArrayOK, kFS); 5328 EXPECT_NE(0u, program); 5329 5330 program = CompileProgram(kVSArrayTooLarge, kFS); 5331 EXPECT_EQ(0u, program); 5332 5333 program = CompileProgram(kVSArrayMuchTooLarge, kFS); 5334 EXPECT_EQ(0u, program); 5335 } 5336 5337 // Reject attempts to allocate too-large structs in shaders. 5338 // This is an implementation-defined limit - crbug.com/1220237 . TEST_P(WebGLCompatibilityTest,ValidateStructSizes)5339 TEST_P(WebGLCompatibilityTest, ValidateStructSizes) 5340 { 5341 // Note: on macOS with ANGLE's OpenGL backend, getting anywhere 5342 // close to this limit causes pathologically slow shader 5343 // compilation in the driver. For this reason, only perform a 5344 // negative test. 5345 constexpr char kFSStructTooLarge[] = 5346 R"(precision mediump float; 5347 struct Light { 5348 // 2 GB / 32 aligned bytes per mat2 = 67108864 5349 mat2 array[67108865]; 5350 }; 5351 5352 uniform Light light; 5353 5354 void main() 5355 { 5356 if (light.array[0][0][0] == 2.0) 5357 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5358 else 5359 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5360 })"; 5361 5362 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFSStructTooLarge); 5363 EXPECT_EQ(0u, program); 5364 5365 // A second variation where the large array is on the variable itself not a member. 5366 constexpr char kFSStructTooLarge2[] = 5367 R"(precision mediump float; 5368 struct Light { 5369 mat2 array; 5370 }; 5371 5372 uniform Light light[67108865]; 5373 5374 void main() 5375 { 5376 if (light[0].array[0][0] == 2.0) 5377 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5378 else 5379 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5380 })"; 5381 5382 program = CompileProgram(essl1_shaders::vs::Simple(), kFSStructTooLarge2); 5383 EXPECT_EQ(0u, program); 5384 } 5385 5386 // Reject attempts to allocate too much private memory. 5387 // This is an implementation-defined limit - crbug.com/1431761. TEST_P(WebGLCompatibilityTest,ValidateTotalPrivateSize)5388 TEST_P(WebGLCompatibilityTest, ValidateTotalPrivateSize) 5389 { 5390 constexpr char kTooLargeGlobalMemory1[] = 5391 R"(precision mediump float; 5392 5393 // 16 MB / 16 bytes per vec4 = 1048576 5394 vec4 array[524288]; 5395 vec4 array2[524289]; 5396 5397 void main() 5398 { 5399 if (array[0].x + array[1].x == 0.) 5400 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5401 else 5402 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5403 })"; 5404 5405 constexpr char kTooLargeGlobalMemory2[] = 5406 R"(precision mediump float; 5407 5408 // 16 MB / 16 bytes per vec4 = 1048576 5409 vec4 array[524287]; 5410 vec4 array2[524287]; 5411 vec4 x, y, z; 5412 5413 void main() 5414 { 5415 if (array[0].x + array[1].x == x.w + y.w + z.w) 5416 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5417 else 5418 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5419 })"; 5420 5421 constexpr char kTooLargeGlobalAndLocalMemory1[] = 5422 R"(precision mediump float; 5423 5424 // 16 MB / 16 bytes per vec4 = 1048576 5425 vec4 array[524288]; 5426 5427 void main() 5428 { 5429 vec4 array2[524289]; 5430 if (array[0].x + array[1].x == 2.0) 5431 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5432 else 5433 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5434 })"; 5435 5436 // Note: The call stack is not taken into account for the purposes of total memory calculation. 5437 constexpr char kTooLargeGlobalAndLocalMemory2[] = 5438 R"(precision mediump float; 5439 5440 // 16 MB / 16 bytes per vec4 = 1048576 5441 vec4 array[524288]; 5442 5443 float f() 5444 { 5445 vec4 array2[524288]; 5446 return array2[0].x; 5447 } 5448 5449 float g() 5450 { 5451 vec4 array3[524287]; 5452 return array3[0].x; 5453 } 5454 5455 float h() 5456 { 5457 vec4 value; 5458 float value2; 5459 return value.x + value2; 5460 } 5461 5462 void main() 5463 { 5464 if (array[0].x + f() + g() + h() == 2.0) 5465 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5466 else 5467 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5468 })"; 5469 5470 constexpr char kTooLargeGlobalMemoryOverflow[] = 5471 R"(precision mediump float; 5472 5473 // 16 MB / 16 bytes per vec4 = 1048576 5474 // Create 256 arrays so each is small, but the total overflows a 32-bit number 5475 vec4 array[1048576], array2[1048576], array3[1048576], array4[1048576], array5[1048576]; 5476 vec4 array6[1048576], array7[1048576], array8[1048576], array9[1048576], array10[1048576]; 5477 vec4 array11[1048576], array12[1048576], array13[1048576], array14[1048576], array15[1048576]; 5478 vec4 array16[1048576], array17[1048576], array18[1048576], array19[1048576], array20[1048576]; 5479 vec4 array21[1048576], array22[1048576], array23[1048576], array24[1048576], array25[1048576]; 5480 vec4 array26[1048576], array27[1048576], array28[1048576], array29[1048576], array30[1048576]; 5481 vec4 array31[1048576], array32[1048576], array33[1048576], array34[1048576], array35[1048576]; 5482 vec4 array36[1048576], array37[1048576], array38[1048576], array39[1048576], array40[1048576]; 5483 vec4 array41[1048576], array42[1048576], array43[1048576], array44[1048576], array45[1048576]; 5484 vec4 array46[1048576], array47[1048576], array48[1048576], array49[1048576], array50[1048576]; 5485 vec4 array51[1048576], array52[1048576], array53[1048576], array54[1048576], array55[1048576]; 5486 vec4 array56[1048576], array57[1048576], array58[1048576], array59[1048576], array60[1048576]; 5487 vec4 array61[1048576], array62[1048576], array63[1048576], array64[1048576], array65[1048576]; 5488 vec4 array66[1048576], array67[1048576], array68[1048576], array69[1048576], array70[1048576]; 5489 vec4 array71[1048576], array72[1048576], array73[1048576], array74[1048576], array75[1048576]; 5490 vec4 array76[1048576], array77[1048576], array78[1048576], array79[1048576], array80[1048576]; 5491 vec4 array81[1048576], array82[1048576], array83[1048576], array84[1048576], array85[1048576]; 5492 vec4 array86[1048576], array87[1048576], array88[1048576], array89[1048576], array90[1048576]; 5493 vec4 array91[1048576], array92[1048576], array93[1048576], array94[1048576], array95[1048576]; 5494 vec4 array96[1048576], array97[1048576], array98[1048576], array99[1048576], array100[1048576]; 5495 vec4 array101[1048576], array102[1048576], array103[1048576], array104[1048576], array105[1048576]; 5496 vec4 array106[1048576], array107[1048576], array108[1048576], array109[1048576], array110[1048576]; 5497 vec4 array111[1048576], array112[1048576], array113[1048576], array114[1048576], array115[1048576]; 5498 vec4 array116[1048576], array117[1048576], array118[1048576], array119[1048576], array120[1048576]; 5499 vec4 array121[1048576], array122[1048576], array123[1048576], array124[1048576], array125[1048576]; 5500 vec4 array126[1048576], array127[1048576], array128[1048576], array129[1048576], array130[1048576]; 5501 vec4 array131[1048576], array132[1048576], array133[1048576], array134[1048576], array135[1048576]; 5502 vec4 array136[1048576], array137[1048576], array138[1048576], array139[1048576], array140[1048576]; 5503 vec4 array141[1048576], array142[1048576], array143[1048576], array144[1048576], array145[1048576]; 5504 vec4 array146[1048576], array147[1048576], array148[1048576], array149[1048576], array150[1048576]; 5505 vec4 array151[1048576], array152[1048576], array153[1048576], array154[1048576], array155[1048576]; 5506 vec4 array156[1048576], array157[1048576], array158[1048576], array159[1048576], array160[1048576]; 5507 vec4 array161[1048576], array162[1048576], array163[1048576], array164[1048576], array165[1048576]; 5508 vec4 array166[1048576], array167[1048576], array168[1048576], array169[1048576], array170[1048576]; 5509 vec4 array171[1048576], array172[1048576], array173[1048576], array174[1048576], array175[1048576]; 5510 vec4 array176[1048576], array177[1048576], array178[1048576], array179[1048576], array180[1048576]; 5511 vec4 array181[1048576], array182[1048576], array183[1048576], array184[1048576], array185[1048576]; 5512 vec4 array186[1048576], array187[1048576], array188[1048576], array189[1048576], array190[1048576]; 5513 vec4 array191[1048576], array192[1048576], array193[1048576], array194[1048576], array195[1048576]; 5514 vec4 array196[1048576], array197[1048576], array198[1048576], array199[1048576], array200[1048576]; 5515 vec4 array201[1048576], array202[1048576], array203[1048576], array204[1048576], array205[1048576]; 5516 vec4 array206[1048576], array207[1048576], array208[1048576], array209[1048576], array210[1048576]; 5517 vec4 array211[1048576], array212[1048576], array213[1048576], array214[1048576], array215[1048576]; 5518 vec4 array216[1048576], array217[1048576], array218[1048576], array219[1048576], array220[1048576]; 5519 vec4 array221[1048576], array222[1048576], array223[1048576], array224[1048576], array225[1048576]; 5520 vec4 array226[1048576], array227[1048576], array228[1048576], array229[1048576], array230[1048576]; 5521 vec4 array231[1048576], array232[1048576], array233[1048576], array234[1048576], array235[1048576]; 5522 vec4 array236[1048576], array237[1048576], array238[1048576], array239[1048576], array240[1048576]; 5523 vec4 array241[1048576], array242[1048576], array243[1048576], array244[1048576], array245[1048576]; 5524 vec4 array246[1048576], array247[1048576], array248[1048576], array249[1048576], array250[1048576]; 5525 vec4 array251[1048576], array252[1048576], array253[1048576], array254[1048576], array255[1048576]; 5526 vec4 array256[1048576]; 5527 5528 void main() 5529 { 5530 float f = array[0].x; f += array2[0].x; f += array3[0].x; f += array4[0].x; f += array5[0].x; 5531 f += array6[0].x; f += array7[0].x; f += array8[0].x; f += array9[0].x; f += array10[0].x; 5532 f += array11[0].x; f += array12[0].x; f += array13[0].x; f += array14[0].x; f += array15[0].x; 5533 f += array16[0].x; f += array17[0].x; f += array18[0].x; f += array19[0].x; f += array20[0].x; 5534 f += array21[0].x; f += array22[0].x; f += array23[0].x; f += array24[0].x; f += array25[0].x; 5535 f += array26[0].x; f += array27[0].x; f += array28[0].x; f += array29[0].x; f += array30[0].x; 5536 f += array31[0].x; f += array32[0].x; f += array33[0].x; f += array34[0].x; f += array35[0].x; 5537 f += array36[0].x; f += array37[0].x; f += array38[0].x; f += array39[0].x; f += array40[0].x; 5538 f += array41[0].x; f += array42[0].x; f += array43[0].x; f += array44[0].x; f += array45[0].x; 5539 f += array46[0].x; f += array47[0].x; f += array48[0].x; f += array49[0].x; f += array50[0].x; 5540 f += array51[0].x; f += array52[0].x; f += array53[0].x; f += array54[0].x; f += array55[0].x; 5541 f += array56[0].x; f += array57[0].x; f += array58[0].x; f += array59[0].x; f += array60[0].x; 5542 f += array61[0].x; f += array62[0].x; f += array63[0].x; f += array64[0].x; f += array65[0].x; 5543 f += array66[0].x; f += array67[0].x; f += array68[0].x; f += array69[0].x; f += array70[0].x; 5544 f += array71[0].x; f += array72[0].x; f += array73[0].x; f += array74[0].x; f += array75[0].x; 5545 f += array76[0].x; f += array77[0].x; f += array78[0].x; f += array79[0].x; f += array80[0].x; 5546 f += array81[0].x; f += array82[0].x; f += array83[0].x; f += array84[0].x; f += array85[0].x; 5547 f += array86[0].x; f += array87[0].x; f += array88[0].x; f += array89[0].x; f += array90[0].x; 5548 f += array91[0].x; f += array92[0].x; f += array93[0].x; f += array94[0].x; f += array95[0].x; 5549 f += array96[0].x; f += array97[0].x; f += array98[0].x; f += array99[0].x; f += array100[0].x; 5550 f += array101[0].x; f += array102[0].x; f += array103[0].x; f += array104[0].x; 5551 f += array105[0].x; f += array106[0].x; f += array107[0].x; f += array108[0].x; 5552 f += array109[0].x; f += array110[0].x; f += array111[0].x; f += array112[0].x; 5553 f += array113[0].x; f += array114[0].x; f += array115[0].x; f += array116[0].x; 5554 f += array117[0].x; f += array118[0].x; f += array119[0].x; f += array120[0].x; 5555 f += array121[0].x; f += array122[0].x; f += array123[0].x; f += array124[0].x; 5556 f += array125[0].x; f += array126[0].x; f += array127[0].x; f += array128[0].x; 5557 f += array129[0].x; f += array130[0].x; f += array131[0].x; f += array132[0].x; 5558 f += array133[0].x; f += array134[0].x; f += array135[0].x; f += array136[0].x; 5559 f += array137[0].x; f += array138[0].x; f += array139[0].x; f += array140[0].x; 5560 f += array141[0].x; f += array142[0].x; f += array143[0].x; f += array144[0].x; 5561 f += array145[0].x; f += array146[0].x; f += array147[0].x; f += array148[0].x; 5562 f += array149[0].x; f += array150[0].x; f += array151[0].x; f += array152[0].x; 5563 f += array153[0].x; f += array154[0].x; f += array155[0].x; f += array156[0].x; 5564 f += array157[0].x; f += array158[0].x; f += array159[0].x; f += array160[0].x; 5565 f += array161[0].x; f += array162[0].x; f += array163[0].x; f += array164[0].x; 5566 f += array165[0].x; f += array166[0].x; f += array167[0].x; f += array168[0].x; 5567 f += array169[0].x; f += array170[0].x; f += array171[0].x; f += array172[0].x; 5568 f += array173[0].x; f += array174[0].x; f += array175[0].x; f += array176[0].x; 5569 f += array177[0].x; f += array178[0].x; f += array179[0].x; f += array180[0].x; 5570 f += array181[0].x; f += array182[0].x; f += array183[0].x; f += array184[0].x; 5571 f += array185[0].x; f += array186[0].x; f += array187[0].x; f += array188[0].x; 5572 f += array189[0].x; f += array190[0].x; f += array191[0].x; f += array192[0].x; 5573 f += array193[0].x; f += array194[0].x; f += array195[0].x; f += array196[0].x; 5574 f += array197[0].x; f += array198[0].x; f += array199[0].x; f += array200[0].x; 5575 f += array201[0].x; f += array202[0].x; f += array203[0].x; f += array204[0].x; 5576 f += array205[0].x; f += array206[0].x; f += array207[0].x; f += array208[0].x; 5577 f += array209[0].x; f += array210[0].x; f += array211[0].x; f += array212[0].x; 5578 f += array213[0].x; f += array214[0].x; f += array215[0].x; f += array216[0].x; 5579 f += array217[0].x; f += array218[0].x; f += array219[0].x; f += array220[0].x; 5580 f += array221[0].x; f += array222[0].x; f += array223[0].x; f += array224[0].x; 5581 f += array225[0].x; f += array226[0].x; f += array227[0].x; f += array228[0].x; 5582 f += array229[0].x; f += array230[0].x; f += array231[0].x; f += array232[0].x; 5583 f += array233[0].x; f += array234[0].x; f += array235[0].x; f += array236[0].x; 5584 f += array237[0].x; f += array238[0].x; f += array239[0].x; f += array240[0].x; 5585 f += array241[0].x; f += array242[0].x; f += array243[0].x; f += array244[0].x; 5586 f += array245[0].x; f += array246[0].x; f += array247[0].x; f += array248[0].x; 5587 f += array249[0].x; f += array250[0].x; f += array251[0].x; f += array252[0].x; 5588 f += array253[0].x; f += array254[0].x; f += array255[0].x; f += array256[0].x; 5589 if (f == 2.0) 5590 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5591 else 5592 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5593 })"; 5594 5595 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemory1); 5596 EXPECT_EQ(0u, program); 5597 5598 program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemory2); 5599 EXPECT_EQ(0u, program); 5600 5601 program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalAndLocalMemory1); 5602 EXPECT_EQ(0u, program); 5603 5604 program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalAndLocalMemory2); 5605 EXPECT_EQ(0u, program); 5606 5607 program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemoryOverflow); 5608 EXPECT_EQ(0u, program); 5609 } 5610 5611 // Linking should fail when corresponding vertex/fragment uniform blocks have different precision 5612 // qualifiers. TEST_P(WebGL2CompatibilityTest,UniformBlockPrecisionMismatch)5613 TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch) 5614 { 5615 constexpr char kVS[] = 5616 R"(#version 300 es 5617 uniform Block { mediump vec4 val; }; 5618 void main() { gl_Position = val; })"; 5619 constexpr char kFS[] = 5620 R"(#version 300 es 5621 uniform Block { highp vec4 val; }; 5622 out highp vec4 out_FragColor; 5623 void main() { out_FragColor = val; })"; 5624 5625 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS); 5626 ASSERT_NE(0u, vs); 5627 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS); 5628 ASSERT_NE(0u, fs); 5629 5630 GLuint program = glCreateProgram(); 5631 5632 glAttachShader(program, vs); 5633 glDeleteShader(vs); 5634 glAttachShader(program, fs); 5635 glDeleteShader(fs); 5636 5637 glLinkProgram(program); 5638 GLint linkStatus; 5639 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); 5640 ASSERT_EQ(0, linkStatus); 5641 5642 glDeleteProgram(program); 5643 } 5644 5645 // Test no attribute vertex shaders TEST_P(WebGL2CompatibilityTest,NoAttributeVertexShader)5646 TEST_P(WebGL2CompatibilityTest, NoAttributeVertexShader) 5647 { 5648 constexpr char kVS[] = 5649 R"(#version 300 es 5650 void main() 5651 { 5652 5653 ivec2 xy = ivec2(gl_VertexID % 2, (gl_VertexID / 2 + gl_VertexID / 3) % 2); 5654 gl_Position = vec4(vec2(xy) * 2. - 1., 0, 1); 5655 })"; 5656 5657 ANGLE_GL_PROGRAM(program, kVS, essl3_shaders::fs::Red()); 5658 glUseProgram(program); 5659 5660 glDrawArrays(GL_TRIANGLES, 0, 6); 5661 ASSERT_GL_NO_ERROR(); 5662 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); 5663 } 5664 5665 // Tests bindAttribLocations for length limit TEST_P(WebGL2CompatibilityTest,BindAttribLocationLimitation)5666 TEST_P(WebGL2CompatibilityTest, BindAttribLocationLimitation) 5667 { 5668 constexpr int maxLocStringLength = 1024; 5669 const std::string tooLongString(maxLocStringLength + 1, '_'); 5670 5671 glBindAttribLocation(0, 0, static_cast<const GLchar *>(tooLongString.c_str())); 5672 5673 EXPECT_GL_ERROR(GL_INVALID_VALUE); 5674 } 5675 5676 // Tests getAttribLocation for length limit TEST_P(WebGL2CompatibilityTest,GetAttribLocationLengthLimitation)5677 TEST_P(WebGL2CompatibilityTest, GetAttribLocationLengthLimitation) 5678 { 5679 constexpr int maxLocStringLength = 1024; 5680 const std::string tooLongString(maxLocStringLength + 1, '_'); 5681 5682 glGetAttribLocation(0, static_cast<const GLchar *>(tooLongString.c_str())); 5683 5684 EXPECT_GL_ERROR(GL_INVALID_VALUE); 5685 } 5686 5687 // Covers a bug in transform feedback loop detection. TEST_P(WebGL2CompatibilityTest,TransformFeedbackCheckNullDeref)5688 TEST_P(WebGL2CompatibilityTest, TransformFeedbackCheckNullDeref) 5689 { 5690 constexpr char kVS[] = R"(attribute vec4 color; void main() { color.r; })"; 5691 constexpr char kFS[] = R"(void main(){})"; 5692 ANGLE_GL_PROGRAM(program, kVS, kFS); 5693 glUseProgram(program); 5694 5695 glEnableVertexAttribArray(0); 5696 glDrawArrays(GL_POINTS, 0, 1); 5697 5698 // This should fail because it is trying to pull a vertex with no buffer. 5699 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 5700 5701 GLBuffer buffer; 5702 glBindBuffer(GL_ARRAY_BUFFER, buffer); 5703 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, nullptr); 5704 5705 // This should fail because it is trying to pull a vertex from an empty buffer. 5706 glDrawArrays(GL_POINTS, 0, 1); 5707 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 5708 } 5709 5710 // We should forbid two transform feedback outputs going to the same buffer. TEST_P(WebGL2CompatibilityTest,TransformFeedbackDoubleBinding)5711 TEST_P(WebGL2CompatibilityTest, TransformFeedbackDoubleBinding) 5712 { 5713 constexpr char kVS[] = 5714 R"(attribute float a; varying float b; varying float c; void main() { b = a; c = a; })"; 5715 constexpr char kFS[] = R"(void main(){})"; 5716 ANGLE_GL_PROGRAM(program, kVS, kFS); 5717 static const char *varyings[] = {"b", "c"}; 5718 glTransformFeedbackVaryings(program, 2, varyings, GL_SEPARATE_ATTRIBS); 5719 glLinkProgram(program); 5720 glUseProgram(program); 5721 ASSERT_GL_NO_ERROR(); 5722 5723 // Bind the transform feedback varyings to non-overlapping regions of the same buffer. 5724 GLBuffer buffer; 5725 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, 4); 5726 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 1, buffer, 4, 4); 5727 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 8, nullptr, GL_STATIC_DRAW); 5728 ASSERT_GL_NO_ERROR(); 5729 // Two varyings bound to the same buffer should be an error. 5730 glBeginTransformFeedback(GL_POINTS); 5731 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 5732 } 5733 5734 // Check the return type of a given parameter upon getting the active uniforms. TEST_P(WebGL2CompatibilityTest,UniformVariablesReturnTypes)5735 TEST_P(WebGL2CompatibilityTest, UniformVariablesReturnTypes) 5736 { 5737 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); 5738 5739 std::vector<GLuint> validUniformIndices = {0}; 5740 std::vector<GLint> uniformNameLengthBuf(validUniformIndices.size()); 5741 5742 // This should fail because GL_UNIFORM_NAME_LENGTH cannot be used in WebGL2. 5743 glGetActiveUniformsiv(program, static_cast<GLsizei>(validUniformIndices.size()), 5744 &validUniformIndices[0], GL_UNIFORM_NAME_LENGTH, 5745 &uniformNameLengthBuf[0]); 5746 EXPECT_GL_ERROR(GL_INVALID_ENUM); 5747 } 5748 5749 // Tests an error case to ensure we don't crash. TEST_P(WebGLCompatibilityTest,DrawWithNoProgram)5750 TEST_P(WebGLCompatibilityTest, DrawWithNoProgram) 5751 { 5752 glDrawArrays(GL_TRIANGLES, 0, 6); 5753 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 5754 } 5755 5756 // Ensures that rendering to different texture levels of a sampled texture is supported. TEST_P(WebGL2CompatibilityTest,RenderToLevelsOfSampledTexture)5757 TEST_P(WebGL2CompatibilityTest, RenderToLevelsOfSampledTexture) 5758 { 5759 // TODO: Fix on Vulkan back-end. http://anglebug.com/40644733 5760 ANGLE_SKIP_TEST_IF(IsVulkan()); 5761 5762 constexpr GLsizei kTexSize = 2; 5763 constexpr GLsizei kTexLevels = 2; 5764 5765 std::vector<GLColor> texData(kTexSize * kTexSize, GLColor::green); 5766 5767 GLTexture sourceTexture; 5768 glBindTexture(GL_TEXTURE_2D, sourceTexture); 5769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 5771 glTexStorage2D(GL_TEXTURE_2D, kTexLevels, GL_RGBA8, kTexSize, kTexSize); 5772 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize, GL_RGBA, GL_UNSIGNED_BYTE, 5773 texData.data()); 5774 5775 GLFramebuffer fbo; 5776 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 5777 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTexture, 1); 5778 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 5779 glViewport(0, 0, kTexSize / 2, kTexSize / 2); 5780 5781 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D()); 5782 ASSERT_GL_NO_ERROR(); 5783 5784 // Should work - drawing from level 0 to level 1. 5785 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 5786 EXPECT_GL_NO_ERROR(); 5787 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 5788 5789 // Should not work - drawing from levels [0,1] to level 1. 5790 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); 5791 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 5792 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 5793 5794 // Should work - drawing with levels [0,1] to default FBO. 5795 glBindFramebuffer(GL_FRAMEBUFFER, 0); 5796 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 5797 5798 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 5799 EXPECT_GL_NO_ERROR(); 5800 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 5801 } 5802 5803 // Reject attempts to allocate too-large variables in shaders. 5804 // This is an implementation-defined limit - crbug.com/1220237 . TEST_P(WebGL2CompatibilityTest,ValidateTypeSizes)5805 TEST_P(WebGL2CompatibilityTest, ValidateTypeSizes) 5806 { 5807 constexpr char kFSArrayBlockTooLarge[] = R"(#version 300 es 5808 precision mediump float; 5809 // 1 + the maximum size this implementation allows. 5810 uniform LargeArrayBlock { 5811 vec4 large_array[134217729]; 5812 }; 5813 5814 out vec4 out_FragColor; 5815 5816 void main() 5817 { 5818 if (large_array[1].x == 2.0) 5819 out_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 5820 else 5821 out_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 5822 } 5823 )"; 5824 5825 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFSArrayBlockTooLarge); 5826 EXPECT_EQ(0u, program); 5827 } 5828 5829 // Ensure that new type size validation code added for 5830 // crbug.com/1220237 does not crash. TEST_P(WebGL2CompatibilityTest,ValidatingTypeSizesShouldNotCrash)5831 TEST_P(WebGL2CompatibilityTest, ValidatingTypeSizesShouldNotCrash) 5832 { 5833 constexpr char kFS1[] = R"(#version 300 es 5834 precision mediump float; 5835 out vec4 my_FragColor; 5836 5837 const vec4 constants[2] = vec4[] ( 5838 vec4(0.6, 0.3, 0.0, 3.0), 5839 vec4(-0.6, 0.7, 0.0, -2.0) 5840 ); 5841 5842 void main() 5843 { 5844 my_FragColor = constants[0] + constants[1]; 5845 return; 5846 })"; 5847 5848 constexpr char kFS2[] = R"(#version 300 es 5849 precision mediump float; 5850 out vec4 my_FragColor; 5851 5852 const vec4 constants[2] = vec4[] ( 5853 vec4(0.6, 0.3, 0.0, 3.0), 5854 vec4(-0.6, 0.7, 0.0, -2.0) 5855 ); 5856 5857 const vec4 constants2[2] = vec4[] ( 5858 constants[1], 5859 constants[0] 5860 ); 5861 5862 void main() 5863 { 5864 my_FragColor = constants2[0] + constants2[1]; 5865 return; 5866 })"; 5867 5868 constexpr char kFS3[] = R"(#version 300 es 5869 precision mediump float; 5870 out vec4 my_FragColor; 5871 5872 const vec4 constants[2] = vec4[] ( 5873 vec4(0.6, 0.3, 0.0, 3.0), 5874 vec4(-0.6, 0.7, 0.0, -2.0) 5875 ); 5876 5877 const vec4 constants2[2] = constants; 5878 5879 void main() 5880 { 5881 my_FragColor = constants2[0] + constants2[1]; 5882 return; 5883 })"; 5884 5885 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS1); 5886 EXPECT_NE(0u, program); 5887 5888 program = CompileProgram(essl3_shaders::vs::Simple(), kFS2); 5889 EXPECT_NE(0u, program); 5890 5891 program = CompileProgram(essl3_shaders::vs::Simple(), kFS3); 5892 EXPECT_NE(0u, program); 5893 } 5894 5895 // Verify glReadPixels will accept GL_RGBX8_ANGLE + GL_UNSIGNED_BYTE. TEST_P(WebGL2CompatibilityTest,ReadPixelsRgbx8AngleUnsignedByte)5896 TEST_P(WebGL2CompatibilityTest, ReadPixelsRgbx8AngleUnsignedByte) 5897 { 5898 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format")); 5899 5900 GLFramebuffer fb; 5901 glBindFramebuffer(GL_FRAMEBUFFER, fb); 5902 5903 GLTexture tex; 5904 glBindTexture(GL_TEXTURE_2D, tex); 5905 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, 1, 1); 5906 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5907 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 5908 5909 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); 5910 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 5911 5912 glBindFramebuffer(GL_FRAMEBUFFER, 0); 5913 5914 glClearColor(1.0, 0.0, 0.0, 1.0); 5915 glClear(GL_COLOR_BUFFER_BIT); 5916 ASSERT_GL_NO_ERROR(); 5917 5918 GLColor pixel; 5919 glReadPixels(0, 0, 1, 1, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, &pixel.R); 5920 ASSERT_GL_NO_ERROR(); 5921 5922 EXPECT_EQ(GLColor::red, pixel); 5923 } 5924 5925 // Test that masked-out draw attachments do not require fragment outputs. TEST_P(WebGL2CompatibilityTest,DrawWithMaskedOutAttachments)5926 TEST_P(WebGL2CompatibilityTest, DrawWithMaskedOutAttachments) 5927 { 5928 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_draw_buffers_indexed")); 5929 5930 GLFramebuffer fbo; 5931 GLRenderbuffer rbo[2]; 5932 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 5933 5934 glBindRenderbuffer(GL_RENDERBUFFER, rbo[0]); 5935 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1); 5936 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[0]); 5937 5938 glBindRenderbuffer(GL_RENDERBUFFER, rbo[1]); 5939 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1); 5940 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo[1]); 5941 5942 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 5943 5944 constexpr char kFS[] = R"(#version 300 es 5945 precision highp float; 5946 5947 layout(location = 0) out vec4 color; 5948 5949 void main() 5950 { 5951 color = vec4(1.0, 1.0, 1.0, 1.0); 5952 } 5953 )"; 5954 5955 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); 5956 glUseProgram(program); 5957 5958 GLenum bufs[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; 5959 glDrawBuffers(2, bufs); 5960 5961 // Error: no fragment output for attachment1 5962 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 5963 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 5964 5965 // No error: attachment1 is masked-out 5966 glColorMaskiOES(1, false, false, false, false); 5967 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 5968 EXPECT_GL_NO_ERROR(); 5969 } 5970 5971 // Test that ETC2/EAC formats are rejected by unextended WebGL 2.0 contexts. TEST_P(WebGL2CompatibilityTest,ETC2EACFormats)5972 TEST_P(WebGL2CompatibilityTest, ETC2EACFormats) 5973 { 5974 size_t byteLength = 8; 5975 constexpr uint8_t data[16] = {}; 5976 constexpr GLenum formats[] = {GL_COMPRESSED_R11_EAC, 5977 GL_COMPRESSED_SIGNED_R11_EAC, 5978 GL_COMPRESSED_RGB8_ETC2, 5979 GL_COMPRESSED_SRGB8_ETC2, 5980 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 5981 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 5982 GL_COMPRESSED_RG11_EAC, 5983 GL_COMPRESSED_SIGNED_RG11_EAC, 5984 GL_COMPRESSED_RGBA8_ETC2_EAC, 5985 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC}; 5986 5987 for (const auto &fmt : formats) 5988 { 5989 if (fmt == GL_COMPRESSED_RG11_EAC) 5990 byteLength = 16; 5991 5992 { 5993 GLTexture tex; 5994 glBindTexture(GL_TEXTURE_2D, tex); 5995 glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, 4, 4, 0, byteLength, data); 5996 EXPECT_GL_ERROR(GL_INVALID_ENUM); 5997 } 5998 5999 { 6000 GLTexture tex; 6001 glBindTexture(GL_TEXTURE_2D_ARRAY, tex); 6002 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, fmt, 4, 4, 1, 0, byteLength, data); 6003 EXPECT_GL_ERROR(GL_INVALID_ENUM); 6004 } 6005 6006 { 6007 GLTexture tex; 6008 glBindTexture(GL_TEXTURE_2D, tex); 6009 glTexStorage2D(GL_TEXTURE_2D, 1, fmt, 4, 4); 6010 EXPECT_GL_ERROR(GL_INVALID_ENUM); 6011 } 6012 6013 { 6014 GLTexture tex; 6015 glBindTexture(GL_TEXTURE_2D_ARRAY, tex); 6016 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, fmt, 4, 4, 1); 6017 EXPECT_GL_ERROR(GL_INVALID_ENUM); 6018 } 6019 } 6020 } 6021 6022 // Test that GL_HALF_FLOAT_OES type is rejected by WebGL 2.0 contexts. TEST_P(WebGL2CompatibilityTest,HalfFloatOesType)6023 TEST_P(WebGL2CompatibilityTest, HalfFloatOesType) 6024 { 6025 const std::array<std::pair<GLenum, GLenum>, 6> formats = {{{GL_R16F, GL_RED}, 6026 {GL_RG16F, GL_RG}, 6027 {GL_RGB16F, GL_RGB}, 6028 {GL_RGBA16F, GL_RGBA}, 6029 {GL_R11F_G11F_B10F, GL_RGB}, 6030 {GL_RGB9_E5, GL_RGB}}}; 6031 for (const auto &fmt : formats) 6032 { 6033 { 6034 GLTexture tex; 6035 glBindTexture(GL_TEXTURE_2D, tex); 6036 EXPECT_GL_NO_ERROR(); 6037 6038 glTexImage2D(GL_TEXTURE_2D, 0, fmt.first, 1, 1, 0, fmt.second, GL_HALF_FLOAT_OES, 6039 nullptr); 6040 EXPECT_GL_ERROR(GL_INVALID_ENUM); 6041 6042 glTexImage2D(GL_TEXTURE_2D, 0, fmt.first, 1, 1, 0, fmt.second, GL_HALF_FLOAT, nullptr); 6043 EXPECT_GL_NO_ERROR(); 6044 } 6045 { 6046 GLTexture tex; 6047 glBindTexture(GL_TEXTURE_3D, tex); 6048 EXPECT_GL_NO_ERROR(); 6049 6050 glTexImage3D(GL_TEXTURE_3D, 0, fmt.first, 1, 1, 1, 0, fmt.second, GL_HALF_FLOAT_OES, 6051 nullptr); 6052 EXPECT_GL_ERROR(GL_INVALID_ENUM); 6053 6054 glTexImage3D(GL_TEXTURE_3D, 0, fmt.first, 1, 1, 1, 0, fmt.second, GL_HALF_FLOAT, 6055 nullptr); 6056 EXPECT_GL_NO_ERROR(); 6057 } 6058 } 6059 } 6060 6061 // Test that unsigned integer samplers work with stencil textures. TEST_P(WebGL2CompatibilityTest,StencilTexturingStencil8)6062 TEST_P(WebGL2CompatibilityTest, StencilTexturingStencil8) 6063 { 6064 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_stencil8")); 6065 6066 const uint8_t stencilValue = 42; 6067 GLTexture tex; 6068 glBindTexture(GL_TEXTURE_2D, tex); 6069 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 6070 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 6071 glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX8, 1, 1, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 6072 &stencilValue); 6073 ASSERT_GL_NO_ERROR(); 6074 6075 constexpr char kFS[] = R"(#version 300 es 6076 out mediump vec4 color; 6077 uniform mediump usampler2D tex; 6078 void main() { 6079 color = vec4(vec3(texture(tex, vec2(0.0, 0.0))) / 255.0, 1.0); 6080 })"; 6081 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); 6082 6083 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6084 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(42, 0, 0, 255), 1); 6085 } 6086 6087 // Test that unsigned integer samplers work with combined depth/stencil textures. TEST_P(WebGL2CompatibilityTest,StencilTexturingCombined)6088 TEST_P(WebGL2CompatibilityTest, StencilTexturingCombined) 6089 { 6090 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_stencil_texturing")); 6091 6092 const uint32_t stencilValue = 42; 6093 GLTexture tex; 6094 glBindTexture(GL_TEXTURE_2D, tex); 6095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 6096 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 6097 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, GL_STENCIL_INDEX); 6098 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL, 6099 GL_UNSIGNED_INT_24_8, &stencilValue); 6100 ASSERT_GL_NO_ERROR(); 6101 6102 constexpr char kFS[] = R"(#version 300 es 6103 out mediump vec4 color; 6104 uniform mediump usampler2D tex; 6105 void main() { 6106 color = vec4(vec3(texture(tex, vec2(0.0, 0.0))) / 255.0, 1.0); 6107 })"; 6108 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); 6109 6110 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6111 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(42, 0, 0, 255), 1); 6112 } 6113 6114 // Regression test for syncing internal state for TexImage calls while there is an incomplete 6115 // framebuffer bound TEST_P(WebGL2CompatibilityTest,TexImageSyncWithIncompleteFramebufferBug)6116 TEST_P(WebGL2CompatibilityTest, TexImageSyncWithIncompleteFramebufferBug) 6117 { 6118 glColorMask(false, true, false, false); 6119 glClear(GL_COLOR_BUFFER_BIT); 6120 glViewport(100, 128, 65, 65537); 6121 6122 GLFramebuffer fb1; 6123 glBindFramebuffer(GL_FRAMEBUFFER, fb1); 6124 6125 GLRenderbuffer rb; 6126 glBindRenderbuffer(GL_RENDERBUFFER, rb); 6127 glRenderbufferStorage(GL_RENDERBUFFER, GL_RG8UI, 1304, 2041); 6128 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb); 6129 6130 GLTexture texture; 6131 glBindTexture(GL_TEXTURE_2D, texture); 6132 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 8, 8, 0, GL_RED_EXT, GL_UNSIGNED_BYTE, nullptr); 6133 } 6134 6135 // Test that "depth_unchanged" layout qualifier is rejected for WebGL contexts. TEST_P(WebGL2CompatibilityTest,FragDepthLayoutUnchanged)6136 TEST_P(WebGL2CompatibilityTest, FragDepthLayoutUnchanged) 6137 { 6138 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_conservative_depth")); 6139 6140 constexpr char kFS[] = R"(#version 300 es 6141 #extension GL_EXT_conservative_depth: enable 6142 out highp vec4 color; 6143 layout (depth_unchanged) out highp float gl_FragDepth; 6144 void main() { 6145 color = vec4(0.0, 0.0, 0.0, 1.0); 6146 gl_FragDepth = 1.0; 6147 })"; 6148 6149 GLProgram prg; 6150 prg.makeRaster(essl3_shaders::vs::Simple(), kFS); 6151 EXPECT_FALSE(prg.valid()); 6152 } 6153 6154 // Test that EXT_blend_func_extended does not allow omitting locations in WebGL 2.0 contexts. TEST_P(WebGL2CompatibilityTest,EXTBlendFuncExtendedNoLocations)6155 TEST_P(WebGL2CompatibilityTest, EXTBlendFuncExtendedNoLocations) 6156 { 6157 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended")); 6158 6159 constexpr char kFS[] = R"(#version 300 es 6160 #extension GL_EXT_blend_func_extended : require 6161 out highp vec4 color0; 6162 out highp vec4 color1; 6163 void main() { 6164 color0 = vec4(1.0, 0.0, 0.0, 1.0); 6165 color1 = vec4(0.0, 1.0, 0.0, 1.0); 6166 })"; 6167 6168 GLProgram prg; 6169 prg.makeRaster(essl3_shaders::vs::Simple(), kFS); 6170 EXPECT_FALSE(prg.valid()); 6171 } 6172 6173 // Test that fragment outputs may be omitted when enabling 6174 // SRC1 blend functions with all color channels masked out. TEST_P(WebGLCompatibilityTest,EXTBlendFuncExtendedMissingOutputsWithAllChannelsMaskedOut)6175 TEST_P(WebGLCompatibilityTest, EXTBlendFuncExtendedMissingOutputsWithAllChannelsMaskedOut) 6176 { 6177 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended")); 6178 6179 glEnable(GL_BLEND); 6180 glBlendFunc(GL_ONE, GL_SRC1_COLOR_EXT); 6181 glColorMask(false, false, false, false); 6182 6183 // Secondary output missing 6184 { 6185 constexpr char kFragColor[] = R"( 6186 void main() { 6187 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 6188 })"; 6189 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragColor); 6190 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0, true); 6191 EXPECT_GL_NO_ERROR(); 6192 } 6193 6194 // Primary output missing 6195 { 6196 constexpr char kSecondaryFragColor[] = R"(#extension GL_EXT_blend_func_extended : enable 6197 void main() { 6198 gl_SecondaryFragColorEXT = vec4(0.0, 1.0, 0.0, 1.0); 6199 })"; 6200 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kSecondaryFragColor); 6201 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0, true); 6202 EXPECT_GL_NO_ERROR(); 6203 } 6204 6205 // Both outputs missing 6206 { 6207 constexpr char kNone[] = "void main() {}"; 6208 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kNone); 6209 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0, true); 6210 EXPECT_GL_NO_ERROR(); 6211 } 6212 } 6213 6214 // Test that both fragment outputs must be statically used 6215 // when enabling SRC1 blend functions in WebGL 1.0 contexts. TEST_P(WebGLCompatibilityTest,EXTBlendFuncExtendedMissingOutputs)6216 TEST_P(WebGLCompatibilityTest, EXTBlendFuncExtendedMissingOutputs) 6217 { 6218 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended")); 6219 6220 glEnable(GL_BLEND); 6221 glBlendFunc(GL_ONE, GL_SRC1_COLOR_EXT); 6222 ASSERT_GL_NO_ERROR(); 6223 6224 { 6225 constexpr char kFragColor[] = R"( 6226 void main() { 6227 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 6228 })"; 6229 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragColor); 6230 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6231 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6232 } 6233 { 6234 constexpr char kSecondaryFragColor[] = R"(#extension GL_EXT_blend_func_extended : require 6235 void main() { 6236 gl_SecondaryFragColorEXT = vec4(0.0, 1.0, 0.0, 1.0); 6237 })"; 6238 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kSecondaryFragColor); 6239 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6240 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6241 } 6242 { 6243 constexpr char kFragColorAndSecondaryFragColor[] = 6244 R"(#extension GL_EXT_blend_func_extended : require 6245 void main() { 6246 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 6247 gl_SecondaryFragColorEXT = vec4(0.0, 1.0, 0.0, 1.0); 6248 })"; 6249 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragColorAndSecondaryFragColor); 6250 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6251 ASSERT_GL_NO_ERROR(); 6252 } 6253 } 6254 6255 // Test that both fragment outputs must be statically used 6256 // when enabling SRC1 blend functions in WebGL 1.0 contexts. TEST_P(WebGLCompatibilityTest,EXTBlendFuncExtendedMissingOutputsArrays)6257 TEST_P(WebGLCompatibilityTest, EXTBlendFuncExtendedMissingOutputsArrays) 6258 { 6259 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended")); 6260 6261 glEnable(GL_BLEND); 6262 glBlendFunc(GL_ONE, GL_SRC1_COLOR_EXT); 6263 ASSERT_GL_NO_ERROR(); 6264 6265 { 6266 constexpr char kFragData[] = R"( 6267 void main() { 6268 gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0); 6269 })"; 6270 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragData); 6271 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6272 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6273 } 6274 { 6275 constexpr char kSecondaryFragData[] = R"(#extension GL_EXT_blend_func_extended : require 6276 void main() { 6277 gl_SecondaryFragDataEXT[0] = vec4(0.0, 1.0, 0.0, 1.0); 6278 })"; 6279 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kSecondaryFragData); 6280 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6281 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6282 } 6283 { 6284 constexpr char kFragDataAndSecondaryFragData[] = 6285 R"(#extension GL_EXT_blend_func_extended : require 6286 void main() { 6287 gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0); 6288 gl_SecondaryFragDataEXT[0] = vec4(0.0, 1.0, 0.0, 1.0); 6289 })"; 6290 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragDataAndSecondaryFragData); 6291 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6292 ASSERT_GL_NO_ERROR(); 6293 } 6294 } 6295 6296 // Test that both fragment outputs must be statically used 6297 // when enabling SRC1 blend functions in WebGL 2.0 contexts. TEST_P(WebGL2CompatibilityTest,EXTBlendFuncExtendedMissingOutputs)6298 TEST_P(WebGL2CompatibilityTest, EXTBlendFuncExtendedMissingOutputs) 6299 { 6300 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended")); 6301 6302 glEnable(GL_BLEND); 6303 glBlendFunc(GL_ONE, GL_SRC1_COLOR_EXT); 6304 ASSERT_GL_NO_ERROR(); 6305 6306 { 6307 constexpr char kColor0[] = R"(#version 300 es 6308 out mediump vec4 color0; 6309 void main() { 6310 color0 = vec4(1.0, 0.0, 0.0, 1.0); 6311 })"; 6312 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kColor0); 6313 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6314 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6315 } 6316 { 6317 constexpr char kColor1[] = R"(#version 300 es 6318 #extension GL_EXT_blend_func_extended : require 6319 layout(location = 0, index = 1) out mediump vec4 color1; 6320 void main() { 6321 color1 = vec4(0.0, 1.0, 0.0, 1.0); 6322 })"; 6323 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kColor1); 6324 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6325 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6326 } 6327 { 6328 constexpr char kColor0AndColor1[] = R"(#version 300 es 6329 #extension GL_EXT_blend_func_extended : require 6330 layout(location = 0, index = 0) out mediump vec4 color0; 6331 layout(location = 0, index = 1) out mediump vec4 color1; 6332 void main() { 6333 color0 = vec4(1.0, 0.0, 0.0, 1.0); 6334 color1 = vec4(0.0, 1.0, 0.0, 1.0); 6335 })"; 6336 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kColor0AndColor1); 6337 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6338 ASSERT_GL_NO_ERROR(); 6339 } 6340 } 6341 6342 // Test that both fragment outputs must be statically used 6343 // when enabling SRC1 blend functions in WebGL 2.0 contexts. TEST_P(WebGL2CompatibilityTest,EXTBlendFuncExtendedMissingOutputsArrays)6344 TEST_P(WebGL2CompatibilityTest, EXTBlendFuncExtendedMissingOutputsArrays) 6345 { 6346 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended")); 6347 6348 glEnable(GL_BLEND); 6349 glBlendFunc(GL_ONE, GL_SRC1_COLOR_EXT); 6350 ASSERT_GL_NO_ERROR(); 6351 6352 { 6353 constexpr char kArrayColor0[] = R"(#version 300 es 6354 out mediump vec4 color0[1]; 6355 void main() { 6356 color0[0] = vec4(1.0, 0.0, 0.0, 1.0); 6357 })"; 6358 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kArrayColor0); 6359 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6360 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6361 } 6362 { 6363 constexpr char kArrayColor1[] = R"(#version 300 es 6364 #extension GL_EXT_blend_func_extended : require 6365 layout(location = 0, index = 1) out mediump vec4 color1[1]; 6366 void main() { 6367 color1[0] = vec4(0.0, 1.0, 0.0, 1.0); 6368 })"; 6369 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kArrayColor1); 6370 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6371 ASSERT_GL_ERROR(GL_INVALID_OPERATION); 6372 } 6373 { 6374 constexpr char kArrayColor0AndColor0[] = R"(#version 300 es 6375 #extension GL_EXT_blend_func_extended : require 6376 layout(location = 0, index = 0) out mediump vec4 color0[1]; 6377 layout(location = 0, index = 1) out mediump vec4 color1[1]; 6378 void main() { 6379 color0[0] = vec4(1.0, 0.0, 0.0, 1.0); 6380 color1[0] = vec4(0.0, 1.0, 0.0, 1.0); 6381 })"; 6382 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kArrayColor0AndColor0); 6383 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true); 6384 ASSERT_GL_NO_ERROR(); 6385 } 6386 } 6387 6388 // Test that vertex conversion correctly no-ops when the vertex format requires conversion but there 6389 // are no vertices to convert. TEST_P(WebGLCompatibilityTest,ConversionWithNoVertices)6390 TEST_P(WebGLCompatibilityTest, ConversionWithNoVertices) 6391 { 6392 constexpr char kVS[] = R"(precision highp float; 6393 attribute vec3 attr1; 6394 void main(void) { 6395 gl_Position = vec4(attr1, 1.0); 6396 })"; 6397 6398 constexpr char kFS[] = R"(precision highp float; 6399 void main(void) { 6400 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); 6401 })"; 6402 6403 GLBuffer buffer; 6404 glBindBuffer(GL_ARRAY_BUFFER, buffer); 6405 std::array<int8_t, 12> data = { 6406 1, 6407 }; 6408 glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(data[0]), data.data(), GL_STATIC_DRAW); 6409 6410 ANGLE_GL_PROGRAM(program, kVS, kFS); 6411 glBindAttribLocation(program, 0, "attr1"); 6412 glLinkProgram(program); 6413 ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true)); 6414 glUseProgram(program); 6415 6416 // Set the offset of the attribute past the end of the buffer but use a format that requires 6417 // conversion in Vulkan 6418 glEnableVertexAttribArray(0); 6419 glVertexAttribPointer(0, 3, GL_BYTE, true, 128, reinterpret_cast<void *>(256)); 6420 6421 glDrawArrays(GL_TRIANGLES, 0, 3); 6422 // Either no error or invalid operation is okay. 6423 } 6424 6425 // Tests that using an out of bounds draw offset with a dynamic array succeeds. TEST_P(WebGLCompatibilityTest,DynamicVertexArrayOffsetOutOfBounds)6426 TEST_P(WebGLCompatibilityTest, DynamicVertexArrayOffsetOutOfBounds) 6427 { 6428 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); 6429 glUseProgram(program); 6430 6431 GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib()); 6432 ASSERT_NE(-1, posLoc); 6433 6434 glEnableVertexAttribArray(posLoc); 6435 GLBuffer buf; 6436 glBindBuffer(GL_ARRAY_BUFFER, buf); 6437 glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const void *>(500)); 6438 glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_DYNAMIC_DRAW); 6439 glDrawArrays(GL_TRIANGLES, 0, 3); 6440 6441 // Either no error or invalid operation is okay. 6442 } 6443 6444 // Covers situations where vertex conversion could read out of bounds. TEST_P(WebGL2CompatibilityTest,OutOfBoundsByteAttribute)6445 TEST_P(WebGL2CompatibilityTest, OutOfBoundsByteAttribute) 6446 { 6447 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); 6448 glUseProgram(testProgram); 6449 6450 GLBuffer buffer; 6451 glBindBuffer(GL_ARRAY_BUFFER, buffer); 6452 glBufferData(GL_ARRAY_BUFFER, 2, nullptr, GL_STREAM_COPY); 6453 6454 glEnableVertexAttribArray(0); 6455 glVertexAttribPointer(0, 4, GL_BYTE, false, 0xff, reinterpret_cast<const void *>(0xfe)); 6456 6457 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 1, 10, 1000); 6458 } 6459 6460 // Test for a mishandling of instanced vertex attributes with zero-sized buffers bound on Apple 6461 // OpenGL drivers. TEST_P(WebGL2CompatibilityTest,DrawWithZeroSizedBuffer)6462 TEST_P(WebGL2CompatibilityTest, DrawWithZeroSizedBuffer) 6463 { 6464 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red()); 6465 glUseProgram(program); 6466 6467 GLBuffer buffer; 6468 glBindBuffer(GL_ARRAY_BUFFER, buffer); 6469 6470 GLint posLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib()); 6471 glEnableVertexAttribArray(posLocation); 6472 6473 glVertexAttribDivisor(posLocation, 1); 6474 glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 9, 6475 reinterpret_cast<void *>(0x41424344)); 6476 ASSERT_GL_NO_ERROR(); 6477 6478 glDrawArrays(GL_TRIANGLES, 0, 6); 6479 // This should be caught as an invalid draw 6480 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6481 } 6482 6483 // Test that draw calls exceeding the vertex attribute range are caught in the presence of both 6484 // instanced and non-instanced attributes. TEST_P(WebGL2CompatibilityTest,DrawWithInstancedAndNonInstancedAttributes)6485 TEST_P(WebGL2CompatibilityTest, DrawWithInstancedAndNonInstancedAttributes) 6486 { 6487 if (IsGLExtensionRequestable("GL_ANGLE_base_vertex_base_instance")) 6488 { 6489 glRequestExtensionANGLE("GL_ANGLE_base_vertex_base_instance"); 6490 } 6491 6492 const bool hasBaseInstance = IsGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance"); 6493 6494 constexpr char kVS[] = R"(#version 300 es 6495 in vec4 attr1; 6496 in vec2 attr2; 6497 in vec4 attr3; 6498 in vec3 attr4; 6499 6500 out vec4 v1; 6501 out vec2 v2; 6502 out vec4 v3; 6503 out vec3 v4; 6504 6505 void main() 6506 { 6507 v1 = attr1; 6508 v2 = attr2; 6509 v3 = attr3; 6510 v4 = attr4; 6511 gl_Position = vec4(0, 0, 0, 0); 6512 })"; 6513 6514 constexpr char kFS[] = R"(#version 300 es 6515 precision mediump float; 6516 6517 in vec4 v1; 6518 in vec2 v2; 6519 in vec4 v3; 6520 in vec3 v4; 6521 6522 out vec4 color; 6523 6524 void main() 6525 { 6526 color = v1 + v2.xyxy + v3 + v4.xyxz; 6527 })"; 6528 6529 ANGLE_GL_PROGRAM(program, kVS, kFS); 6530 glUseProgram(program); 6531 6532 const GLint attrLocations[4] = { 6533 glGetAttribLocation(program, "attr1"), 6534 glGetAttribLocation(program, "attr2"), 6535 glGetAttribLocation(program, "attr3"), 6536 glGetAttribLocation(program, "attr4"), 6537 }; 6538 6539 GLBuffer buffers[4]; 6540 6541 // Set up all the buffers as such: 6542 // 6543 // Buffer 1: 64 bytes + (offset) 124 6544 // Buffer 2: 16 bytes + (offset) 212 6545 // Buffer 3: 128 bytes + (offset) 76 6546 // Buffer 4: 96 bytes + (offset) 52 6547 constexpr GLsizei kBufferSizes[4] = { 6548 64, 6549 16, 6550 128, 6551 96, 6552 }; 6553 constexpr GLsizei kBufferOffsets[4] = { 6554 124, 6555 212, 6556 76, 6557 52, 6558 }; 6559 // Attribute component count corresponding to the shader 6560 constexpr GLint kAttrComponents[4] = { 6561 4, 6562 2, 6563 4, 6564 3, 6565 }; 6566 // Attribute types 6567 constexpr GLenum kAttrTypes[4] = { 6568 GL_SHORT, 6569 GL_BYTE, 6570 GL_FLOAT, 6571 GL_UNSIGNED_SHORT, 6572 }; 6573 // Attribute strides. 6574 // 6575 // - Buffer 1 has 64 bytes, each attribute is 8 bytes. With a stride of 12, 5 vertices can be 6576 // drawn from this buffer. 6577 // - Buffer 2 has 16 bytes, each attribute is 2 bytes. With a stride of 0, 8 vertices can be 6578 // drawn from this buffer. 6579 // - Buffer 3 has 128 bytes, each attribute is 16 bytes. With a stride of 20, 6 vertices can be 6580 // drawn from this buffer. 6581 // - Buffer 4 has 96 bytes, each attribute is 6 bytes. With a stride of 8, 12 vertices can be 6582 // drawn from this buffer. 6583 constexpr GLsizei kAttrStrides[4] = { 6584 12, 6585 0, 6586 20, 6587 8, 6588 }; 6589 6590 for (int i = 0; i < 4; ++i) 6591 { 6592 glBindBuffer(GL_ARRAY_BUFFER, buffers[i]); 6593 glBufferData(GL_ARRAY_BUFFER, kBufferSizes[i] + kBufferOffsets[i], nullptr, GL_STATIC_DRAW); 6594 6595 glEnableVertexAttribArray(attrLocations[i]); 6596 glVertexAttribPointer(attrLocations[i], kAttrComponents[i], kAttrTypes[i], GL_TRUE, 6597 kAttrStrides[i], reinterpret_cast<void *>(kBufferOffsets[i])); 6598 } 6599 ASSERT_GL_NO_ERROR(); 6600 6601 // Without any attribute divisors, the maximum vertex attribute allowed is min(5, 8, 6, 12) with 6602 // non-instanced draws. 6603 glDrawArrays(GL_POINTS, 0, 4); 6604 EXPECT_GL_NO_ERROR(); 6605 glDrawArrays(GL_POINTS, 0, 5); 6606 EXPECT_GL_NO_ERROR(); 6607 glDrawArrays(GL_POINTS, 0, 6); 6608 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6609 glDrawArrays(GL_POINTS, 1, 5); 6610 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6611 glDrawArrays(GL_POINTS, 1, 4); 6612 EXPECT_GL_NO_ERROR(); 6613 glDrawArrays(GL_POINTS, 4, 1); 6614 EXPECT_GL_NO_ERROR(); 6615 glDrawArrays(GL_POINTS, 4, 2); 6616 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6617 glDrawArrays(GL_POINTS, 5, 1); 6618 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6619 glDrawArrays(GL_POINTS, 200, 1); 6620 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6621 // Same with instanced draws. 6622 glDrawArraysInstanced(GL_POINTS, 0, 4, 10); 6623 EXPECT_GL_NO_ERROR(); 6624 glDrawArraysInstanced(GL_POINTS, 0, 5, 1); 6625 EXPECT_GL_NO_ERROR(); 6626 glDrawArraysInstanced(GL_POINTS, 0, 6, 5); 6627 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6628 glDrawArraysInstanced(GL_POINTS, 1, 5, 1); 6629 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6630 glDrawArraysInstanced(GL_POINTS, 1, 4, 22); 6631 EXPECT_GL_NO_ERROR(); 6632 glDrawArraysInstanced(GL_POINTS, 4, 1, 1240); 6633 EXPECT_GL_NO_ERROR(); 6634 glDrawArraysInstanced(GL_POINTS, 4, 2, 1); 6635 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6636 glDrawArraysInstanced(GL_POINTS, 5, 1, 6); 6637 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6638 glDrawArraysInstanced(GL_POINTS, 200, 1, 100); 6639 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6640 6641 // With a divisor on attribute 1, that attribute can reference up to vertex #5 (as first 6642 // attribute), while the rest are limited to min(8, 6, 12) as their maximum vertex attribute. 6643 glVertexAttribDivisor(attrLocations[0], 5); 6644 6645 glDrawArrays(GL_POINTS, 0, 5); 6646 EXPECT_GL_NO_ERROR(); 6647 glDrawArrays(GL_POINTS, 0, 6); 6648 EXPECT_GL_NO_ERROR(); 6649 glDrawArrays(GL_POINTS, 0, 7); 6650 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6651 // The following passes because attribute 1 only accesses index 0 regardless of first 6652 glDrawArrays(GL_POINTS, 4, 2); 6653 EXPECT_GL_NO_ERROR(); 6654 // The following fails because attribute 3 accesses vertices [4, 7) 6655 glDrawArrays(GL_POINTS, 4, 3); 6656 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6657 glDrawArrays(GL_POINTS, 5, 1); 6658 EXPECT_GL_NO_ERROR(); 6659 6660 // With instanced rendering, the same limits as above hold. Additionally, attribute 1 does no 6661 // longer access only a single vertex, but it accesses instanceCount/5 (5 being the divisor) 6662 // elements. 6663 // The following passes because attribute 1 accesses vertices [0, 4) 6664 glDrawArraysInstanced(GL_POINTS, 0, 5, 20); 6665 EXPECT_GL_NO_ERROR(); 6666 // The following passes because attribute 1 accesses vertices [0, 5) 6667 glDrawArraysInstanced(GL_POINTS, 0, 6, 25); 6668 EXPECT_GL_NO_ERROR(); 6669 // The following fails because of the limit on non-instanced attributes 6670 glDrawArraysInstanced(GL_POINTS, 0, 7, 1); 6671 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6672 // The following fails because attribute 1 accesses vertices [0, 6) 6673 glDrawArraysInstanced(GL_POINTS, 0, 4, 26); 6674 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6675 // The following passes because attribute 1 accesses vertices [0, 2). Recall that first vertex 6676 // is ignored for instanced attributes. 6677 glDrawArraysInstanced(GL_POINTS, 3, 3, 9); 6678 EXPECT_GL_NO_ERROR(); 6679 glDrawArraysInstanced(GL_POINTS, 3, 3, 10); 6680 EXPECT_GL_NO_ERROR(); 6681 glDrawArraysInstanced(GL_POINTS, 3, 3, 11); 6682 EXPECT_GL_NO_ERROR(); 6683 glDrawArraysInstanced(GL_POINTS, 5, 1, 1); 6684 EXPECT_GL_NO_ERROR(); 6685 6686 if (hasBaseInstance) 6687 { 6688 // The following passes because attribute 1 accesses vertices [0, 3) 6689 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 15, 0); 6690 EXPECT_GL_NO_ERROR(); 6691 // The following passes because attribute 1 accesses vertices [1, 4) 6692 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 15, 5); 6693 EXPECT_GL_NO_ERROR(); 6694 // The following passes because attribute 1 accesses vertices [0, 4) 6695 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 17, 3); 6696 EXPECT_GL_NO_ERROR(); 6697 // The following passes because attribute 1 accesses vertices [3, 5) 6698 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 10, 15); 6699 EXPECT_GL_NO_ERROR(); 6700 // The following fails because attribute 1 accesses vertices [3, 6) 6701 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 11, 15); 6702 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6703 // The following fails because attribute 1 accesses vertex 6 6704 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 1, 25); 6705 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6706 } 6707 6708 // With a divisor on attribute 3, that attribute can reference up to vertex #6 (as first 6709 // attribute), while the rest are limited to min(8, 12) as their maximum vertex attribute. 6710 glVertexAttribDivisor(attrLocations[2], 3); 6711 6712 glDrawArrays(GL_POINTS, 0, 7); 6713 EXPECT_GL_NO_ERROR(); 6714 glDrawArrays(GL_POINTS, 0, 8); 6715 EXPECT_GL_NO_ERROR(); 6716 glDrawArrays(GL_POINTS, 0, 9); 6717 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6718 // The following passes because attribute 1 and 3 only access index 0 regardless of first and 6719 // count 6720 glDrawArrays(GL_POINTS, 4, 4); 6721 EXPECT_GL_NO_ERROR(); 6722 // The following fails because attribute 2 accesses vertices [4, 9) 6723 glDrawArrays(GL_POINTS, 4, 5); 6724 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6725 glDrawArrays(GL_POINTS, 5, 1); 6726 EXPECT_GL_NO_ERROR(); 6727 glDrawArrays(GL_POINTS, 6, 1); 6728 EXPECT_GL_NO_ERROR(); 6729 6730 // With instanced rendering, the same limits as above hold. Additionally, attribute 1 accesses 6731 // instanceCount/5 and attribute 3 accesses instanceCount/3 elements. 6732 // The following passes because attribute 1 accesses vertices [0, 4), and attribute 3 accesses 6733 // vertices [0, 6) 6734 glDrawArraysInstanced(GL_POINTS, 0, 5, 18); 6735 EXPECT_GL_NO_ERROR(); 6736 glDrawArraysInstanced(GL_POINTS, 0, 8, 18); 6737 EXPECT_GL_NO_ERROR(); 6738 // The following fails because attribute 3 accesses vertices [0, 7) 6739 glDrawArraysInstanced(GL_POINTS, 0, 5, 19); 6740 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6741 // The following fails because of the limit on non-instanced attributes 6742 glDrawArraysInstanced(GL_POINTS, 0, 9, 1); 6743 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6744 // The following passes because attribute 1 accesses vertices [0, 3), and attribute 3 accesses 6745 // vertices [0, 4) 6746 glDrawArraysInstanced(GL_POINTS, 2, 4, 11); 6747 EXPECT_GL_NO_ERROR(); 6748 glDrawArraysInstanced(GL_POINTS, 2, 4, 12); 6749 EXPECT_GL_NO_ERROR(); 6750 // The following passes because attribute 3 accesses vertices [0, 5). Attribute 1 still 6751 // accesses within limits of [0, 3) 6752 glDrawArraysInstanced(GL_POINTS, 2, 4, 13); 6753 EXPECT_GL_NO_ERROR(); 6754 glDrawArraysInstanced(GL_POINTS, 5, 1, 1); 6755 EXPECT_GL_NO_ERROR(); 6756 6757 if (hasBaseInstance) 6758 { 6759 // The following passes because attribute 1 accesses vertices [0, 4), and attribute 3 6760 // accesses vertices [0, 6) 6761 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 18, 0); 6762 EXPECT_GL_NO_ERROR(); 6763 // The following fails because attribute 3 accesses vertices [0, 7) 6764 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 19, 0); 6765 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6766 // The following fails because attribute 3 accesses vertices [1, 7) 6767 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 18, 1); 6768 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6769 // The following passes because attribute 3 accesses vertices [3, 6) 6770 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 7, 11); 6771 EXPECT_GL_NO_ERROR(); 6772 // The following fails because attribute 3 accesses vertices [3, 7) 6773 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 2, 4, 8, 11); 6774 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6775 } 6776 6777 // With a divisor on attribute 2, that attribute can reference up to vertex #8 (as first 6778 // attribute), and with a divisor on attribute 4, it can reference up to vertex #12. There is 6779 // no particular limit on the maxmium vertex attribute when not instanced. 6780 glVertexAttribDivisor(attrLocations[1], 3); 6781 glVertexAttribDivisor(attrLocations[3], 1); 6782 6783 // The following passes because all attributes only access index 0 6784 glDrawArrays(GL_POINTS, 0, 123); 6785 EXPECT_GL_NO_ERROR(); 6786 glDrawArrays(GL_POINTS, 4, 500); 6787 EXPECT_GL_NO_ERROR(); 6788 glDrawArrays(GL_POINTS, 5, 1); 6789 EXPECT_GL_NO_ERROR(); 6790 glDrawArrays(GL_POINTS, 231, 1); 6791 EXPECT_GL_NO_ERROR(); 6792 6793 // With instanced rendering, the same limits as above hold. 6794 // 6795 // Attribute 1 accesses instanceCount/5 elements (note: buffer fits 5 vertices) 6796 // Attribute 2 accesses instanceCount/3 elements (note: buffer fits 8 vertices) 6797 // Attribute 3 accesses instanceCount/3 elements (note: buffer fits 6 vertices) 6798 // Attribute 4 accesses instanceCount/1 elements (note: buffer fits 12 vertices) 6799 // 6800 // Only instances [0, 12) are valid. 6801 glDrawArraysInstanced(GL_POINTS, 0, 123, 1); 6802 EXPECT_GL_NO_ERROR(); 6803 // The following passes because attributes accessed are: 6804 // [0, 3), [0, 4), [0, 4), [0, 12) 6805 glDrawArraysInstanced(GL_POINTS, 0, 123, 12); 6806 EXPECT_GL_NO_ERROR(); 6807 // The following fails because attributes accessed are: 6808 // [0, 3), [0, 5), [0, 5), [0, 13) 6809 // \-- overflow 6810 glDrawArraysInstanced(GL_POINTS, 0, 123, 13); 6811 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6812 // The following passes because attributes accessed are: 6813 // [0, 2), [0, 3), [0, 3), [0, 9) 6814 glDrawArraysInstanced(GL_POINTS, 3, 359, 9); 6815 EXPECT_GL_NO_ERROR(); 6816 // The following fails because attributes accessed are: 6817 // [0, 3), [0, 5), [0, 5), [0, 13) 6818 // \-- overflow 6819 glDrawArraysInstanced(GL_POINTS, 3, 359, 13); 6820 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6821 // The following passes because attributes accessed are: 6822 // [0, 1), [0, 2), [0, 2), [0, 5) 6823 glDrawArraysInstanced(GL_POINTS, 120, 359, 5); 6824 EXPECT_GL_NO_ERROR(); 6825 6826 if (hasBaseInstance) 6827 { 6828 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 120, 359, 12, 0); 6829 EXPECT_GL_NO_ERROR(); 6830 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 120, 359, 11, 1); 6831 EXPECT_GL_NO_ERROR(); 6832 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 120, 359, 1, 11); 6833 EXPECT_GL_NO_ERROR(); 6834 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 120, 359, 2, 11); 6835 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6836 glDrawArraysInstancedBaseInstanceANGLE(GL_POINTS, 120, 359, 1, 14); 6837 EXPECT_GL_ERROR(GL_INVALID_OPERATION); 6838 } 6839 } 6840 6841 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(WebGLCompatibilityTest); 6842 6843 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2CompatibilityTest); 6844 ANGLE_INSTANTIATE_TEST_ES3(WebGL2CompatibilityTest); 6845 } // namespace angle 6846