[Merge 131] Tweak SurfaceLayerImpl DrawQuad transform for pixel-alignment.

This CL adds code (behind a disabled-by-default feature) to
snap DrawQuads for SurfaceLayerImpl to the pixel grid. This
is necessary to reduce/remove fuzziness in text in out-of-process
iframes (OOPIFs) when a fractional scale-transform is applied
to the OOPIF's owner.

Since this tweak can also affect other users of SurfaceLayerImpl
(e.g. <canvas>), initially this will land disabled.

This CL also adds tests for scaled OOPIFs vs. same-process
iframes (with different scrollbar configurations), and OOPIFs
with a fractional translate-transform. Since the new OOPIF
behavior differs from same-process iframes rendering the same
content, and since the OOPIF behavior appears to be an improvement,
the tests use fuzzy pixel matching to allow these tests to use
the same-process results as reftest expectations. The test are
expected to fail when the feature is not enabled.

(cherry picked from commit 08985dafaca72e571068309ad0dd8266574d4edf)

Bug: 359279545
Change-Id: Ic8e13a68462f98d39e72a29c809541533933df62
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5842653
Commit-Queue: James Maclean <wjmaclean@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1372031}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6001399
Commit-Queue: Jonathan Ross <jonross@chromium.org>
Cr-Commit-Position: refs/branch-heads/6778@{#1879}
Cr-Branched-From: b21671ca172dcfd1566d41a770b2808e7fa7cd88-refs/heads/main@{#1368529}
diff --git a/cc/base/features.cc b/cc/base/features.cc
index b28fe43..32535f5 100644
--- a/cc/base/features.cc
+++ b/cc/base/features.cc
@@ -12,6 +12,13 @@
 
 namespace features {
 
+// When enabled, this forces composited textures for SurfaceLayerImpls to be
+// aligned to the pixel grid. Lack of alignment can lead to blur, noticeably so
+// in text. https://crbug.com/359279545
+BASE_FEATURE(kAlignSurfaceLayerImplToPixelGrid,
+             "AlignSurfaceLayerImplToPixelGrid",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Uses the Resume method instead of the Catch-up method for animated images.
 // - Catch-up behavior tries to keep animated images in pace with wall-clock
 //   time. This might require decoding several animation frames if the
diff --git a/cc/base/features.h b/cc/base/features.h
index 56bd65ba..da2815b 100644
--- a/cc/base/features.h
+++ b/cc/base/features.h
@@ -14,6 +14,7 @@
 
 namespace features {
 
+CC_BASE_EXPORT BASE_DECLARE_FEATURE(kAlignSurfaceLayerImplToPixelGrid);
 CC_BASE_EXPORT BASE_DECLARE_FEATURE(kAnimatedImageResume);
 CC_BASE_EXPORT extern bool IsImpulseScrollAnimationEnabled();
 CC_BASE_EXPORT BASE_DECLARE_FEATURE(kSynchronizedScrolling);
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index 1c61ab0..d8240ec 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -18,6 +18,7 @@
 #include "cc/trees/occlusion.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
 
 namespace cc {
 
@@ -225,6 +226,24 @@
   // Unless the client explicitly specifies otherwise, don't block on
   // |surface_range_| more than once.
   deadline_in_frames_ = 0u;
+
+  if (!base::FeatureList::IsEnabled(
+          features::kAlignSurfaceLayerImplToPixelGrid)) {
+    return;
+  }
+
+  // Don't allow DrawQuads to align on non-pixel boundaries.
+  gfx::Vector2dF quad_rect_offset = quad_rect.OffsetFromOrigin();
+  gfx::PointF rect_offset_in_target =
+      shared_quad_state->quad_to_target_transform.MapPoint(
+          gfx::PointF(quad_rect_offset.x(), quad_rect_offset.x()));
+  gfx::Vector2dF adjustment =
+      gfx::Vector2dF(rect_offset_in_target.x(), rect_offset_in_target.y()) -
+      gfx::Vector2dF(gfx::ToRoundedVector2d(gfx::Vector2dF(
+          rect_offset_in_target.x(), rect_offset_in_target.y())));
+  if (!adjustment.IsZero()) {
+    shared_quad_state->quad_to_target_transform.PostTranslate(-adjustment);
+  }
 }
 
 bool SurfaceLayerImpl::is_surface_layer() const {
diff --git a/cc/layers/surface_layer_impl_unittest.cc b/cc/layers/surface_layer_impl_unittest.cc
index 002dee44..df0b08c5 100644
--- a/cc/layers/surface_layer_impl_unittest.cc
+++ b/cc/layers/surface_layer_impl_unittest.cc
@@ -5,10 +5,13 @@
 #include "cc/layers/surface_layer_impl.h"
 
 #include <stddef.h>
+
 #include <utility>
 
 #include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread.h"
+#include "cc/base/features.h"
 #include "cc/layers/append_quads_data.h"
 #include "cc/test/layer_tree_impl_test_base.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -371,5 +374,47 @@
   EXPECT_TRUE(updated);
 }
 
+class SurfaceLayerImplAlignToPixelGridTest : public testing::Test {
+ public:
+  SurfaceLayerImplAlignToPixelGridTest() {
+    scoped_feature_list_.InitWithFeatures(
+        {features::kAlignSurfaceLayerImplToPixelGrid}, {});
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(SurfaceLayerImplAlignToPixelGridTest, FractionalOffsetSnapsToPixelGrid) {
+  gfx::Size layer_size(200, 200);
+  gfx::Size viewport_size(1000, 1000);
+  LayerTreeImplTestBase impl;
+  SurfaceLayerImpl* surface_layer_impl =
+      impl.AddLayerInActiveTree<SurfaceLayerImpl>();
+  surface_layer_impl->SetBounds(layer_size);
+  surface_layer_impl->SetDrawsContent(true);
+  CopyProperties(impl.root_layer(), surface_layer_impl);
+
+  // Create transform with fractional translation.
+  gfx::Transform transform;
+  transform.PostTranslate(0.3, 0.7);
+  EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
+
+  impl.CalcDrawProps(viewport_size);
+  surface_layer_impl->draw_properties().target_space_transform = transform;
+
+  // Compute RenderPass, with DrawQuads for SurfaceLayer.
+  auto render_pass = viz::CompositorRenderPass::Create();
+  AppendQuadsData data;
+  surface_layer_impl->AppendQuads(render_pass.get(), &data);
+
+  // Verify that the DrawQuads for the SurfaceLayer have an integral offset.
+  ASSERT_EQ(1U, render_pass->shared_quad_state_list.size());
+  viz::SharedQuadState* state =
+      render_pass->shared_quad_state_list.ElementAt(0);
+  gfx::Transform quad_to_target_transform = state->quad_to_target_transform;
+  EXPECT_TRUE(quad_to_target_transform.IsIdentityOrIntegerTranslation());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index c5b7d81d..ad59931 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -8915,6 +8915,11 @@
      flag_descriptions::kAnimatedImageResumeDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kAnimatedImageResume)},
 
+    {"align-surface-layer-impl-to-pixel-grid",
+     flag_descriptions::kAlignSurfaceLayerImplToPixelGridName,
+     flag_descriptions::kAlignSurfaceLayerImplToPixelGridDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kAlignSurfaceLayerImplToPixelGrid)},
+
 #if !BUILDFLAG(IS_ANDROID)
     {"sct-auditing", flag_descriptions::kSCTAuditingName,
      flag_descriptions::kSCTAuditingDescription, kOsDesktop,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 43a70f1..a48bafa 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -71,6 +71,13 @@
     "expiry_milestone": 135
   },
   {
+    "name": "align-surface-layer-impl-to-pixel-grid",
+    "owners": [
+      "wjmaclean@google.com", "pdr@google.com", "jonross@google.com"
+    ],
+    "expiry_milestone": 145
+  },
+  {
     "name": "align-wakeups",
     "owners": [
       "etiennep@google.com", "fdoray@google.com"
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index f31b352..84fc41fb 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -48,6 +48,16 @@
 const char kAcceleratedVideoEncodeDescription[] =
     "Hardware-accelerated video encode where available.";
 
+const char kAlignSurfaceLayerImplToPixelGridName[] =
+    "Align SurfaceLayerImpls to pixel grid";
+const char kAlignSurfaceLayerImplToPixelGridDescription[] =
+    "Align SurfaceLayerImpl compositor textures to pixel grid. This is "
+    "important when an iframe is rendered cross-process to its parent, "
+    "and fails to align with the pixel grid (e.g. when the parent frame "
+    "has a non-integral scale factor). Failure to align to the pixel grid "
+    "can result in the iframe's text becoming blurry. SurfaceLayerImpl also "
+    "is used for <canvas>, which may also benefit from the alignment.";
+
 const char kAlignWakeUpsName[] = "Align delayed wake ups at 125 Hz";
 const char kAlignWakeUpsDescription[] =
     "Run most delayed tasks with a non-zero delay (including DOM Timers) on a "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 11f1399..459a2e8 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -58,6 +58,9 @@
 extern const char kAiSettingsPageRefreshName[];
 extern const char kAiSettingsPageRefreshDescription[];
 
+extern const char kAlignSurfaceLayerImplToPixelGridName[];
+extern const char kAlignSurfaceLayerImplToPixelGridDescription[];
+
 extern const char kAlignWakeUpsName[];
 extern const char kAlignWakeUpsDescription[];
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 5792ca1..cbd2b90e 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4143,6 +4143,20 @@
 
 crbug.com/910979 http/tests/html/validation-bubble-oopif-clip.html [ Crash Failure Pass Timeout ]
 
+# The following tests are expected to pass when the feature kAlignCrossProcessFramesToPixelGrid
+# is enabled, and fail otherwise. Note: the fuzzy limits for these tests were set
+# based on testing on Linux, and may need adjustment before turning this feature on for all
+# platforms.
+crbug.com/359279545 http/tests/html/scaled-oopif-text-not-blurry.html [ Failure ]
+crbug.com/359279545 http/tests/html/scaled-oopif-scrollbar-both.html [ Failure ]
+crbug.com/359279545 http/tests/html/scaled-oopif-scrollbar-vertical.html [ Failure ]
+crbug.com/359279545 http/tests/html/scaled-oopif-scrollbar-horizontal.html [ Failure ]
+crbug.com/359279545 http/tests/html/translated-oopif-text-not-blurry.html [ Failure ]
+crbug.com/359279545 http/tests/html/translated-oopif-scrollbar-both.html [ Failure ]
+crbug.com/359279545 http/tests/html/translated-oopif-scrollbar-vertical.html [ Failure ]
+crbug.com/359279545 http/tests/html/translated-oopif-scrollbar-horizontal.html [ Failure ]
+crbug.com/359279545 compositing/video/video-subpixel.html [ Failure ]
+
 # Sheriff 2019-02-01, 2019-02-19
 # These are crashy on Win10, and seem to leave processes lying around, causing the swarming
 # task to hang.
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 8c8ad9e7..66f5cfcd 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -51,6 +51,24 @@
     "expires": "Nov 1, 2024"
   },
   {
+    "prefix": "align-surface-layer",
+    "platforms": ["Linux", "Mac", "Win"],
+    "bases": [
+      "compositing/video/video-subpixel.html",
+      "http/tests/html/scaled-oopif-text-not-blurry.html",
+      "http/tests/html/scaled-oopif-scrollbar-both.html",
+      "http/tests/html/scaled-oopif-scrollbar-vertical.html",
+      "http/tests/html/scaled-oopif-scrollbar-horizontal.html",
+      "http/tests/html/translated-oopif-text-not-blurry.html",
+      "http/tests/html/translated-oopif-scrollbar-both.html",
+      "http/tests/html/translated-oopif-scrollbar-vertical.html",
+      "http/tests/html/translated-oopif-scrollbar-horizontal.html"
+    ],
+    "args": ["--enable-features=AlignSurfaceLayerImplToPixelGrid"],
+    "owners": ["wjmaclean@chromium.org", "pdr@chromium.org"],
+    "expires": "Mar 1, 2025"
+  },
+  {
     "prefix": "pna-permission",
     "platforms": ["Linux", "Mac", "Win"],
     "bases": ["external/wpt/fetch/private-network-access"],
diff --git a/third_party/blink/web_tests/compositing/video/resources/line.webm b/third_party/blink/web_tests/compositing/video/resources/line.webm
new file mode 100644
index 0000000..2746a820
--- /dev/null
+++ b/third_party/blink/web_tests/compositing/video/resources/line.webm
Binary files differ
diff --git a/third_party/blink/web_tests/compositing/video/video-subpixel-expected.html b/third_party/blink/web_tests/compositing/video/video-subpixel-expected.html
new file mode 100644
index 0000000..d2eb1844
--- /dev/null
+++ b/third_party/blink/web_tests/compositing/video/video-subpixel-expected.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<video src="resources/line.webm" style="transform: translate(0.0px, 0.0px);"></video>
+<br>
+<video src="resources/line.webm" style="transform: translate(1.0px, 0.0px);"></video>
diff --git a/third_party/blink/web_tests/compositing/video/video-subpixel.html b/third_party/blink/web_tests/compositing/video/video-subpixel.html
new file mode 100644
index 0000000..1698ada
--- /dev/null
+++ b/third_party/blink/web_tests/compositing/video/video-subpixel.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<link rel=match href="video-subpixel-expected.html">
+<video src="resources/line.webm" style="transform: translate(0.4px, 0);"></video>
+<br>
+<video src="resources/line.webm" style="transform: translate(0.6px, 0);"></video>
diff --git a/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-both.html b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-both.html
new file mode 100644
index 0000000..e471cb72
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-both.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 400px; height: 400px"></div>
diff --git a/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-horizontal.html b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-horizontal.html
new file mode 100644
index 0000000..568a823
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-horizontal.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<style>html { overflow-y: hidden }</style>
+<div style="width: 400px; height: 400px"></div>
diff --git a/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-vertical.html b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-vertical.html
new file mode 100644
index 0000000..df73dce3
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-scrollbar-vertical.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<style>html { overflow-x: hidden }</style>
+<div style="width: 400px; height: 400px"></div>
diff --git a/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-text.html b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-text.html
new file mode 100644
index 0000000..ffdb0484
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/resources/scaled-oopif-text.html
@@ -0,0 +1 @@
+<!DOCTYPE html>This is some text
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-both-expected.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-both-expected.html
new file mode 100644
index 0000000..ac7c0d8
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-both-expected.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!-- For generating expected output, use a same-process iframe -->
+    <iframe style="border: 1px solid black"
+            srcdoc="<!doctype html><div style='width: 400px; height: 400px'></div>"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-both.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-both.html
new file mode 100644
index 0000000..2c952367
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-both.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="scaled-oopif-text-not-blurry-expected.html">
+  <!-- The pixel differences in this test are due to a misrendering of the
+       border along the edges of the scrollbar corner block. -->
+  <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-1000">
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe src="http://localhost:8080/html/resources/scaled-oopif-scrollbar-both.html"
+            style="border: 1px solid black; overflow: scroll"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-horizontal-expected.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-horizontal-expected.html
new file mode 100644
index 0000000..984ae4c
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-horizontal-expected.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!-- For generating expected output, use a same-process iframe -->
+    <iframe style="border: 1px solid black"
+            srcdoc="<!doctype html><style>html { overflow-y: hidden }</style><div style='width: 400px; height: 400px'></div>"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-horizontal.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-horizontal.html
new file mode 100644
index 0000000..fc2dd47
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-horizontal.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="scaled-oopif-scrollbar-vertical-expected.html">
+  <!-- The pixel differences in this test are due to a misrendering of the
+       border along the edges of the scrollbar corner block. -->
+  <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-700">
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe src="http://localhost:8080/html/resources/scaled-oopif-scrollbar-horizontal.html"
+            style="border: 1px solid black; overflow-y: scroll; overflow-x: hidden"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-vertical-expected.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-vertical-expected.html
new file mode 100644
index 0000000..b2a1ec5
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-vertical-expected.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!-- For generating expected output, use a same-process iframe -->
+    <iframe style="border: 1px solid black"
+            srcdoc="<!doctype html><style>html { overflow-x: hidden }</style><div style='width: 400px; height: 400px'></div>"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-vertical.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-vertical.html
new file mode 100644
index 0000000..22c189d
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-scrollbar-vertical.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="scaled-oopif-scrollbar-vertical-expected.html">
+  <!-- The pixel differences in this test are due to a misrendering of the
+       border along the edges of the scrollbar corner block. -->
+  <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-300">
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe src="http://localhost:8080/html/resources/scaled-oopif-scrollbar-vertical.html"
+            style="border: 1px solid black; overflow-y: scroll; overflow-x: hidden"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-text-not-blurry-expected.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-text-not-blurry-expected.html
new file mode 100644
index 0000000..d5da63a
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-text-not-blurry-expected.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!-- For generating expected output, use a same-process iframe -->
+    <iframe style="border: 1px solid black"
+            srcdoc="<!doctype html>This is some text"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/scaled-oopif-text-not-blurry.html b/third_party/blink/web_tests/http/tests/html/scaled-oopif-text-not-blurry.html
new file mode 100644
index 0000000..ad97624
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/scaled-oopif-text-not-blurry.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="scaled-oopif-text-not-blurry-expected.html">
+  <!-- The pixel differences below appear to be text kerning changes
+       between same-process and cross-process iframes. -->
+  <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-750">
+  <body style="transform: scale(0.9)">
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe src="http://localhost:8080/html/resources/scaled-oopif-text.html"
+            style="border: 1px solid black; scrolling="no""></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-both-expected.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-both-expected.html
new file mode 100644
index 0000000..af76af7
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-both-expected.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            srcdoc="<!doctype html><div style='width: 400px; height: 400px'></div>"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-both.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-both.html
new file mode 100644
index 0000000..f80c71f2
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-both.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="translated-oopif-scrollbar-both-expected.html">
+  <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-1500">
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            src="http://localhost:8080/html/resources/scaled-oopif-scrollbar-both.html"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-horizontal-expected.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-horizontal-expected.html
new file mode 100644
index 0000000..90dbad6
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-horizontal-expected.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            srcdoc="<!doctype html><style>html { overflow-y: hidden }</style><div style='width: 400px; height: 400px'></div>"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-horizontal.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-horizontal.html
new file mode 100644
index 0000000..5613f0a
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-horizontal.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="translated-oopif-scrollbar-horizontal-expected.html">
+  <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-1500">
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            src="http://localhost:8080/html/resources/scaled-oopif-scrollbar-horizontal.html"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-vertical-expected.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-vertical-expected.html
new file mode 100644
index 0000000..2f354357
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-vertical-expected.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            srcdoc="<!doctype html><style>html { overflow-x: hidden }</style><div style='width: 400px; height: 400px'></div>"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-vertical.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-vertical.html
new file mode 100644
index 0000000..c906df2
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-scrollbar-vertical.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="translated-oopif-scrollbar-vertical-expected.html">
+  <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-600">
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            src="http://localhost:8080/html/resources/scaled-oopif-scrollbar-vertical.html"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-text-not-blurry-expected.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-text-not-blurry-expected.html
new file mode 100644
index 0000000..fa6dd24
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-text-not-blurry-expected.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!-- For generating expected output, use a same-process iframe -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            srcdoc="<!doctype html>This is some text">
+    </iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/html/translated-oopif-text-not-blurry.html b/third_party/blink/web_tests/http/tests/html/translated-oopif-text-not-blurry.html
new file mode 100644
index 0000000..c181756
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/translated-oopif-text-not-blurry.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <link rel=author href="mailto:wjmaclean@chromium.org">
+  <link rel=match href="scaled-oopif-text-not-blurry-expected.html">
+  <body>
+    <h1>Mainframe with text and an out-of-process iframe</h1>
+    This is some mainframe text.<p>
+    <!--  use of localhost below will make the iframe an OOPIF -->
+    <iframe style="transform: translate(0.5px, 0.5px)"
+            src="http://localhost:8080/html/resources/scaled-oopif-text.html"></iframe>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/virtual/align-surface-layer/README.md b/third_party/blink/web_tests/virtual/align-surface-layer/README.md
new file mode 100644
index 0000000..83557ae
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/align-surface-layer/README.md
@@ -0,0 +1,11 @@
+# virtual/align-surface-layer
+
+## Summary
+
+At present, the feature AlignSurfaceLayerImplToPixelGrid is off by
+default. In order that the tests written specifically for this feature
+are also run with the feature enabled, this virtual test suite turns
+the feature on for the required tests.
+
+The associated tests are marked as FAIL in TestExpectations, but should
+not crash.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 600e56e..77c225af 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -19648,6 +19648,7 @@
   <int value="-269966631" label="UnifiedPasswordManagerErrorMessages:enabled"/>
   <int value="-269440655"
       label="AutofillDownstreamCvcPromptUseGooglePayLogo:disabled"/>
+  <int value="-269321347" label="AlignSurfaceLayerImplToPixelGrid:enabled"/>
   <int value="-269227049" label="PersistentQuotaIsTemporaryQuota:enabled"/>
   <int value="-268897347" label="DisableCameraFrameRotationAtSource:disabled"/>
   <int value="-268549184"
@@ -23582,6 +23583,7 @@
   <int value="1343713259" label="ArcPrintSpoolerExperiment:disabled"/>
   <int value="1344833841" label="ImeThread:enabled"/>
   <int value="1345192233" label="VaapiVideoDecoder:enabled"/>
+  <int value="1345482545" label="AlignSurfaceLayerImplToPixelGrid:disabled"/>
   <int value="1346018846"
       label="ForceSupervisedUserReauthenticationForBlockedSites:enabled"/>
   <int value="1346994602" label="SyncPseudoUSSDictionary:enabled"/>