CVE-2026-10881
Overview
Files Changed
src/libANGLE/renderer/gl/StateManagerGL.cppsrc/libANGLE/renderer/gl/StateManagerGL.hsrc/tests/angle_end2end_tests_expectations.txtsrc/tests/capture_replay_tests/capture_replay_expectations.txtsrc/tests/gl_tests/CopyTextureTest.cpp
Patch
From 1c82f3a0bd18d2046fa38ccffffbcc45891f0301 Mon Sep 17 00:00:00 2001
From: Geoff Lang <geofflang@chromium.org>
Date: Fri, 17 Apr 2026 18:03:58 -0400
Subject: [PATCH] GL: Mark StateManagerGL internal buffer state dirty on bind
When changing state, StateManagerGL would set local dirty bits which
would be synchronized on the next syncState by ORing them with the
frontend dirty bits. This was not done for internal buffer binding
changes and allowed for incorrect pixel buffers to be bound on
ReadPixels or TexImage calls.
Fixed: chromium:498904293
Fixed: chromium:503768143
Change-Id: I42f5acfdb709f327205f0f8cc04c3f11f1bd2b79
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7774027
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
---
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index c0dea01..0d2bf2a 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -473,6 +473,7 @@
{
mBuffers[target] = buffer;
mFunctions->bindBuffer(gl::ToGLenum(target), buffer);
+ setBufferBindingDirty(target);
}
}
@@ -491,6 +492,7 @@
binding.size = static_cast<size_t>(-1);
mBuffers[target] = buffer;
mFunctions->bindBufferBase(gl::ToGLenum(target), static_cast<GLuint>(index), buffer);
+ setBufferBindingDirty(target);
}
}
@@ -2949,6 +2951,56 @@
"GL_VERTEX_ARRAY_BINDING");
}
+void StateManagerGL::setBufferBindingDirty(gl::BufferBinding binding)
+{
+ switch (binding)
+ {
+ case gl::BufferBinding::Array:
+ // Nothing to do. Array buffer bindings are set before vertex attrib calls.
+ break;
+ case gl::BufferBinding::AtomicCounter:
+ mLocalDirtyBits.set(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
+ break;
+ case gl::BufferBinding::CopyRead:
+ // Nothing to do. CopyRead does not affect any operations.
+ break;
+ case gl::BufferBinding::CopyWrite:
+ // Nothing to do. CopyWrite does not affect any operations.
+ break;
+ case gl::BufferBinding::DispatchIndirect:
+ mLocalDirtyBits.set(gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
+ break;
+ case gl::BufferBinding::DrawIndirect:
+ mLocalDirtyBits.set(gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
+ break;
+ case gl::BufferBinding::ElementArray:
+ // Managed by the VAO
+ break;
+ case gl::BufferBinding::PixelPack:
+ mLocalDirtyBits.set(gl::state::DIRTY_BIT_PACK_BUFFER_BINDING);
+ break;
+ case gl::BufferBinding::PixelUnpack:
+ mLocalDirtyBits.set(gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING);
+ break;
+ case gl::BufferBinding::ShaderStorage:
+ mLocalDirtyBits.set(gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
+ break;
+ case gl::BufferBinding::Texture:
+ // Not implemented in the GL backend
+ UNREACHABLE();
+ break;
+ case gl::BufferBinding::TransformFeedback:
+ // Transform feedback buffer bindings are tracked in TransformFeedbackGL
+ UNREACHABLE();
+ break;
+ case gl::BufferBinding::Uniform:
+ mLocalDirtyBits.set(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
template <>
void StateManagerGL::get(GLenum name, GLboolean *value)
{
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.h b/src/libANGLE/renderer/gl/StateManagerGL.h
index bad9aa5..795a690 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -365,6 +365,8 @@
void updateDispatchIndirectBufferBinding(const gl::Context *context);
void updateDrawIndirectBufferBinding(const gl::Context *context);
+ void setBufferBindingDirty(gl::BufferBinding binding);
+
template <typename T>
void get(GLenum name, T *value);
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
index 003d9b3..3e44278 100644
--- a/src/tests/angle_end2end_tests_expectations.txt
+++ b/src/tests/angle_end2end_tests_expectations.txt
@@ -1561,6 +1561,9 @@
42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8SRGBTest.Test/* = SKIP
42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8Test.Test/* = SKIP
+// NVIDIA GLES specific failures with DXT texture uploads
+498904293 WIN NVIDIA GLES : DXT1CompressedTextureTestWebGL2.InitializeTextureContents/* = SKIP
+
// Takes several minutes to complete with ASAN / TSAN
42263997 ASAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
42266388 TSAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
diff --git a/src/tests/capture_replay_tests/capture_replay_expectations.txt b/src/tests/capture_replay_tests/capture_replay_expectations.txt
index 201c64a..5df1eab 100644
--- a/src/tests/capture_replay_tests/capture_replay_expectations.txt
+++ b/src/tests/capture_replay_tests/capture_replay_expectations.txt
@@ -81,6 +81,7 @@
42264831 : FramebufferTest_ES3.ChangeAttachmentThenInvalidateAndDraw/* = SKIP_FOR_CAPTURE
42264831 : FramebufferTest_ES3.RenderAndInvalidateImmutableTextureWithBeyondMaxLevel/* = SKIP_FOR_CAPTURE
490170083 : CopyTextureTestES3.SRGBWithPackParameters/* = SKIP_FOR_CAPTURE
+498904293 : CopyTextureTestES3.PBOSynchronization/* = SKIP_FOR_CAPTURE
# The following tests fail with forceRobustResourceInit
# They were accidentally passing until http://crrev/c/5588816
diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp
index 07d490c..6df23a9 100644
--- a/src/tests/gl_tests/CopyTextureTest.cpp
+++ b/src/tests/gl_tests/CopyTextureTest.cpp
@@ -2725,6 +2725,59 @@
EXPECT_PIXEL_COLOR_EQ(0, 0, kSourceColor);
}
+// Test that copies that trigger internal readbacks do not interfere with the frontend PBO state.
+TEST_P(CopyTextureTestES3, PBOSynchronization)
+{
+ ANGLE_SKIP_TEST_IF(!checkExtensions());
+ ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_sRGB"));
+
+ GLTexture backbufferTex;
+ glBindTexture(GL_TEXTURE_2D, backbufferTex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+ GLFramebuffer fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, backbufferTex, 0);
+
+ glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_GL_NO_ERROR();
+
+ // Set the PBO and write some data to it. It will be synchronized in the backend
+ GLBuffer pbo;
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+ glBufferData(GL_PIXEL_PACK_BUFFER, 4096, nullptr, GL_STATIC_DRAW);
+ glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ // Copy into an SRGB texture which does an internal readback
+ glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ EXPECT_GL_NO_ERROR();
+
+ glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
+ nullptr);
+ EXPECT_GL_NO_ERROR();
+
+ glCopySubTextureCHROMIUM(mTextures[1], 0, GL_TEXTURE_2D, mTextures[0], 0, 0, 0, 0, 0, 1, 1,
+ false, false, false);
+ EXPECT_GL_NO_ERROR();
+
+ // Read pixels again, should still go to the PBO
+ glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid *>(1024));
+
+ uint8_t *mappedPtr =
+ static_cast<uint8_t *>(glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 4096, GL_MAP_READ_BIT));
+ EXPECT_GL_NO_ERROR();
+
+ EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr));
+ EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr + 1024));
+
+ glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
+ EXPECT_GL_NO_ERROR();
+}
+
// Test that the right error type is triggered when
// OES_EGL_image_external_essl3 is required but not supported
TEST_P(CopyTextureTestES3, CopySubTextureMissingRequiredExtension)
Regression Test / PoC
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
index 003d9b3..3e44278 100644
--- a/src/tests/angle_end2end_tests_expectations.txt
+++ b/src/tests/angle_end2end_tests_expectations.txt
@@ -1561,6 +1561,9 @@
42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8SRGBTest.Test/* = SKIP
42265943 WIN INTEL OPENGL : CompressedTextureETC2RGBA8Test.Test/* = SKIP
+// NVIDIA GLES specific failures with DXT texture uploads
+498904293 WIN NVIDIA GLES : DXT1CompressedTextureTestWebGL2.InitializeTextureContents/* = SKIP
+
// Takes several minutes to complete with ASAN / TSAN
42263997 ASAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
42266388 TSAN VULKAN SWIFTSHADER : ClipCullDistanceTest.SizeCheckCombined/* = SKIP
diff --git a/src/tests/capture_replay_tests/capture_replay_expectations.txt b/src/tests/capture_replay_tests/capture_replay_expectations.txt
index 201c64a..5df1eab 100644
--- a/src/tests/capture_replay_tests/capture_replay_expectations.txt
+++ b/src/tests/capture_replay_tests/capture_replay_expectations.txt
@@ -81,6 +81,7 @@
42264831 : FramebufferTest_ES3.ChangeAttachmentThenInvalidateAndDraw/* = SKIP_FOR_CAPTURE
42264831 : FramebufferTest_ES3.RenderAndInvalidateImmutableTextureWithBeyondMaxLevel/* = SKIP_FOR_CAPTURE
490170083 : CopyTextureTestES3.SRGBWithPackParameters/* = SKIP_FOR_CAPTURE
+498904293 : CopyTextureTestES3.PBOSynchronization/* = SKIP_FOR_CAPTURE
# The following tests fail with forceRobustResourceInit
# They were accidentally passing until http://crrev/c/5588816
diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp
index 07d490c..6df23a9 100644
--- a/src/tests/gl_tests/CopyTextureTest.cpp
+++ b/src/tests/gl_tests/CopyTextureTest.cpp
@@ -2725,6 +2725,59 @@
EXPECT_PIXEL_COLOR_EQ(0, 0, kSourceColor);
}
+// Test that copies that trigger internal readbacks do not interfere with the frontend PBO state.
+TEST_P(CopyTextureTestES3, PBOSynchronization)
+{
+ ANGLE_SKIP_TEST_IF(!checkExtensions());
+ ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_sRGB"));
+
+ GLTexture backbufferTex;
+ glBindTexture(GL_TEXTURE_2D, backbufferTex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+ GLFramebuffer fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, backbufferTex, 0);
+
+ glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_GL_NO_ERROR();
+
+ // Set the PBO and write some data to it. It will be synchronized in the backend
+ GLBuffer pbo;
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+ glBufferData(GL_PIXEL_PACK_BUFFER, 4096, nullptr, GL_STATIC_DRAW);
+ glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ // Copy into an SRGB texture which does an internal readback
+ glBindTexture(GL_TEXTURE_2D, mTextures[1]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ EXPECT_GL_NO_ERROR();
+
+ glBindTexture(GL_TEXTURE_2D, mTextures[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
+ nullptr);
+ EXPECT_GL_NO_ERROR();
+
+ glCopySubTextureCHROMIUM(mTextures[1], 0, GL_TEXTURE_2D, mTextures[0], 0, 0, 0, 0, 0, 1, 1,
+ false, false, false);
+ EXPECT_GL_NO_ERROR();
+
+ // Read pixels again, should still go to the PBO
+ glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid *>(1024));
+
+ uint8_t *mappedPtr =
+ static_cast<uint8_t *>(glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 4096, GL_MAP_READ_BIT));
+ EXPECT_GL_NO_ERROR();
+
+ EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr));
+ EXPECT_EQ(GLColor::red, *reinterpret_cast<GLColor *>(mappedPtr + 1024));
+
+ glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
+ EXPECT_GL_NO_ERROR();
+}
+
// Test that the right error type is triggered when
// OES_EGL_image_external_essl3 is required but not supported
TEST_P(CopyTextureTestES3, CopySubTextureMissingRequiredExtension)
Original Bug Report
Arbitrary Memory Read and Write in ANGLE GL Backend via PBO Desync
VULNERABILITY DETAILS
A severe state desynchronization vulnerability exists in the ANGLE OpenGL backend (CopySubTextureCHROMIUM), leading to Arbitrary R/W in the GPU process.
The root cause resides in BlitGL::copySubTextureCPUReadback. When performing a CPU fallback copy, the code explicitly unbinds the PIXEL_PACK_BUFFER mappings through the GL backend StateManagerGL using setPixelPackBuffer(context, nullptr) [0]. An identical mechanism unbinds the PIXEL_UNPACK_BUFFER via setPixelUnpackBuffer [1].
gl::PixelPackState pack;
pack.alignment = 1;
ANGLE_TRY(mStateManager->setPixelPackState(context, pack));
ANGLE_TRY(mStateManager->setPixelPackBuffer(context, nullptr)); // [0]
// ...
gl::PixelUnpackState unpack;
unpack.alignment = 1;
ANGLE_TRY(mStateManager->setPixelUnpackState(context, unpack));
ANGLE_TRY(mStateManager->setPixelUnpackBuffer(context, nullptr)); // [1]
These functions effectively propagate the glBindBuffer command directly to the native GPU driver via StateManagerGL::bindBuffer [2].
angle::Result StateManagerGL::setPixelUnpackBuffer(const gl::Context *context,
const gl::Buffer *pixelBuffer)
{
GLuint bufferID = 0;
if (pixelBuffer != nullptr)
{
bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
}
bindBuffer(gl::BufferBinding::PixelUnpack, bufferID); // [2]
return angle::Result::Continue;
}
However, they silently bypass the ANGLE frontend tracking system (gl::State). Crucially, the frontend’s dirty bits (such as DIRTY_BIT_UNPACK_BUFFER_BINDING) are never set.
Because the frontend gl::State tracking and the native OpenGL driver state become desynchronized, the underlying native GL driver lacks the PBO binding (it was set to 0), while the frontend continues to believe the PBO is actively bound. When a subsequent API call takes an offset, the native driver treats the user-supplied offset as a raw CPU/Host pointer, enabling arbitrary memory operations.
Vulnerability Exploit
The PoC leverages the desynchronization bug to transform a PBO offset into an arbitrary memory pointer. The process relies on intentionally triggering a CPU fallback path (e.g., via copyTextureCHROMIUM), which silently unbinds the PIXEL_PACK_BUFFER in the native OpenGL driver while the ANGLE frontend state remains intact.
Steps to achieve an arbitrary write:
- Desynchronize the
PIXEL_PACK_BUFFERstate. - Manipulate the frontend state system (e.g., via dummy
readPixelscalls) to clear dirty bits, preventing the buffer from re-binding to the driver. - Call
readPixelsusing a controlled integer (e.g.0x41414141) as theoffset. - Since the native OpenGL driver considers the PBO unbound (id = 0), it interprets the
offsetas an absolute virtual memory pointer, writing pixel data directly to this address.
The arbitrary read is achieved via a similar state desynchronization for PIXEL_UNPACK_BUFFER during operations like texSubImage2D.
Arbitrary Write Crash Site
Thread 1 "chrome" received signal SIGSEGV, Segmentation fault.
__memcpy_avx_unaligned_erms ()
at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:271
warning: 271 ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: No such file or directory
(gdb) x/i $pc
=> 0x7f264e788aa1 <__memcpy_avx_unaligned_erms+33>: vmovdqu %ymm0,(%rdi)
(gdb) i r rdi
rdi 0x41414141 1094795585
(gdb) i r ymm0
ymm0 {v16_bfloat16 = {0x4242 <repeats 16 times>}, v16_half = {0x4242 <repeats 16 times>}, v8_float = {0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242}, v4_double = {0x4242424242424242, 0x4242424242424242, 0x4242424242424242, 0x4242424242424242}, v32_int8 = {0x42 <repeats 32 times>}, v16_int16 = {0x4242 <repeats 16 times>}, v8_int32 = {0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242, 0x42424242}, v4_int64 = {0x4242424242424242, 0x4242424242424242, 0x4242424242424242, 0x4242424242424242}, v2_int128 = {0x42424242424242424242424242424242, 0x42424242424242424242424242424242}}
(gdb) bt
#0 __memcpy_avx_unaligned_erms ()
at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:271
#1 0x000056c2930d7edc in __interceptor_memcpy ()
#2 0x00007b221f1b443e in ??? ()
at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#3 0x00007b221f20cc9b in ??? ()
at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#4 0x00007b221f1b4d3a in ??? ()
at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#5 0x00007b221f1b50d5 in ??? ()
at /lib/x86_64-linux-gnu/libgallium-25.2.8-0ubuntu0.24.04.1.so
#6 0x00007b2241cca380 in readPixelsAllAtOnce ()
at ../../third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp:1684
#7 0x00007b2241cc9442 in readPixels ()
at ../../third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp:816
// ...
BISECTION
Introduced by ANGLE upstream commit [0] which added the CPU fallback implementation for CopyTextureCHROMIUM on OpenGL but failed to safely track buffer unbindings within the frontend state.
This regression was rolled into Chromium in commit [1].
[0] https://chromium.googlesource.com/angle/angle/+/aadc8f376a2c797db98d69d308c9980ca818f57f (Implement the CPU fallback for CopyTextureCHROMIUM on OpenGL)
[1] https://chromium.googlesource.com/chromium/src/+/236105a6afc95bfab50b0a3e3487c85cc049b49c (Roll ANGLE 79f7104..92996b0)
VERSION
Chrome Version: HEAD
Operating System: Linux
REPRODUCTION CASE
- Apply renderer.patch and build Chromium with ASan.
- Host the
poc.htmlon an HTTP server. - Run Chrome against the PoC.
$ python3 -m http.server 8000
$ ./out/asan/chrome "http://localhost:8000/poc.html"
CRASH INFORMATION
Type of crash: GPU process
Crash log: Attached asan_read.txt (Arbitrary Read) and asan_write.txt (Arbitrary Write).
CREDIT INFORMATION
Reporter credit: Anonymous
- http://localhost:8000/poc.html
- https://chromium.googlesource.com/angle/angle/+/aadc8f376a2c797db98d69d308c9980ca818f57f
- https://chromium.googlesource.com/chromium/src/+/236105a6afc95bfab50b0a3e3487c85cc049b49c
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp;drc=a76e73df11cbb5466e8a1c8b3c9c04ce4a981f7b;l=865
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp;drc=a76e73df11cbb5466e8a1c8b3c9c04ce4a981f7b;l=883
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp;drc=a76e73df11cbb5466e8a1c8b3c9c04ce4a981f7b;l=642