Delay 10 minutes before we switch the YUV overlay format from BGRA8888.

On Windows, To prevent it from switching back and forth between
YUV and BGRA8888, Wait for at least 10 minutes before we re-try
YUV. On a system that can promote BGRA8888 but not YUV, the
overlay switches format space every second if we don't delay the
re-try for the YUV format.

Bug: 1188856
Change-Id: If06485a0d362bd5b00627e3b94b2d870843c3568
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2803845
Commit-Queue: Maggie Chen <magchen@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#871741}
diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc
index 6889bc6f..cefbf6b 100644
--- a/ui/gl/swap_chain_presenter.cc
+++ b/ui/gl/swap_chain_presenter.cc
@@ -30,6 +30,11 @@
 namespace gl {
 namespace {
 
+// When in BGRA888 overlay format, wait for this time delta before retrying
+// YUV format.
+constexpr base::TimeDelta kDelayForRetryingYUVFormat =
+    base::TimeDelta::FromMinutes(10);
+
 // Some drivers fail to correctly handle BT.709 video in overlays. This flag
 // converts them to BT.601 in the video processor.
 const base::Feature kFallbackBT709VideoToBT601{
@@ -235,6 +240,7 @@
     Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device)
     : layer_tree_(layer_tree),
       window_(window),
+      switched_to_BGRA8888_time_tick_(base::TimeTicks::Now()),
       d3d11_device_(d3d11_device),
       dcomp_device_(dcomp_device),
       is_on_battery_power_(
@@ -274,12 +280,21 @@
 
   if (swap_chain_format_ == yuv_overlay_format) {
     // Switch to BGRA once 3/4 of presents are composed.
-    if (composition_count >= (PresentationHistory::kPresentsToStore * 3 / 4))
+    if (composition_count >= (PresentationHistory::kPresentsToStore * 3 / 4)) {
+      switched_to_BGRA8888_time_tick_ = base::TimeTicks::Now();
       return DXGI_FORMAT_B8G8R8A8_UNORM;
+    }
   } else {
-    // Switch to YUV once 3/4 are using overlays (or unknown).
-    if (composition_count < (PresentationHistory::kPresentsToStore / 4))
+    // To prevent it from switching back and forth between YUV and BGRA8888,
+    // Wait for at least 10 minutes before we re-try YUV. On a system that
+    // can promote BGRA8888 but not YUV, the format change might cause
+    // flickers.
+    base::TimeDelta time_delta =
+        base::TimeTicks::Now() - switched_to_BGRA8888_time_tick_;
+    if (time_delta >= kDelayForRetryingYUVFormat) {
+      presentation_history_.Clear();
       return yuv_overlay_format;
+    }
   }
   return swap_chain_format_;
 }
diff --git a/ui/gl/swap_chain_presenter.h b/ui/gl/swap_chain_presenter.h
index c93bbca..afc17b0 100644
--- a/ui/gl/swap_chain_presenter.h
+++ b/ui/gl/swap_chain_presenter.h
@@ -12,6 +12,7 @@
 
 #include "base/containers/circular_deque.h"
 #include "base/power_monitor/power_monitor.h"
+#include "base/time/time.h"
 #include "base/win/scoped_handle.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gl/dc_renderer_layer_params.h"
@@ -202,6 +203,9 @@
   // Current swap chain format.
   DXGI_FORMAT swap_chain_format_ = DXGI_FORMAT_B8G8R8A8_UNORM;
 
+  // Last time tick when switching to BGRA8888 format.
+  base::TimeTicks switched_to_BGRA8888_time_tick_;
+
   // Whether the swap chain was reallocated, and next present will be the first.
   bool first_present_ = false;