(merge) Avoid cloning of layer tree when using mirror windows

This patch fixes one of the reasons for the transparent chrome window
bug.
We clone the window layer tree after we create a mirror window for
overview mode. This does not work well with transferable resource and
when to release them. This was resulting in empty resource texture
being displayed in cloned + mirrored windows at times. The resource
was being released as soon as the original layer was destroyed after
cloning.


The reason cloning was performed on the mirror window was to purge the
texture memory being used by the now minimized window. Recreating the
layer tree allowed the ui to delete the old layer tree and thus the old
textures.

This patch replaces the cloning that happens after a mirror window tree
is created while achieving the same goal of purging unneeded texture
memory by tricking the compositor into resetting its visibility.

           mode, solid color layer

Bug: 923595
Change-Id: I56c9a201922a4d0f2047b08979fa3f0589789c37
Component: ui layer, delegated frame host, stale content, overview
Reviewed-on: https://chromium-review.googlesource.com/c/1448119
Commit-Queue: Malay Keshav <malaykeshav@chromium.org>
Reviewed-by: Malay Keshav <malaykeshav@chromium.org>
Reviewed-by: Sammie Quon <sammiequon@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#628469}(cherry picked from commit 6b9172ee53eec7bec1fa390d67b7e4cd22e54422)
Reviewed-on: https://chromium-review.googlesource.com/c/1452483
Cr-Commit-Position: refs/branch-heads/3683@{#166}
Cr-Branched-From: e51029943e0a38dd794b73caaf6373d5496ae783-refs/heads/master@{#625896}
diff --git a/ash/app_list/home_launcher_gesture_handler.cc b/ash/app_list/home_launcher_gesture_handler.cc
index becb851..fb886c8 100644
--- a/ash/app_list/home_launcher_gesture_handler.cc
+++ b/ash/app_list/home_launcher_gesture_handler.cc
@@ -473,16 +473,20 @@
     window2_->ResetOpacityAndTransform();
 
   if (is_final_state_show) {
-    wm::HideAndMinimizeWithoutAnimation(GetWindow1());
+    std::vector<aura::Window*> windows_to_hide_minimize;
+    windows_to_hide_minimize.push_back(GetWindow1());
 
     if (window2_)
-      wm::HideAndMinimizeWithoutAnimation(GetWindow2());
+      windows_to_hide_minimize.push_back(GetWindow2());
 
     // Minimize the hidden windows so they can be used normally with alt+tab
     // and overview. Minimize in reverse order to preserve mru ordering.
-    std::reverse(hidden_windows_.begin(), hidden_windows_.end());
-    for (auto* window : hidden_windows_)
-      wm::HideAndMinimizeWithoutAnimation(window);
+    windows_to_hide_minimize.resize(windows_to_hide_minimize.size() +
+                                    hidden_windows_.size());
+    std::copy(hidden_windows_.rbegin(), hidden_windows_.rend(),
+              windows_to_hide_minimize.end() - hidden_windows_.size());
+    wm::HideAndMaybeMinimizeWithoutAnimation(windows_to_hide_minimize,
+                                             /*minimize=*/true);
   } else {
     // Reshow all windows previously hidden.
     for (auto* window : hidden_windows_) {
@@ -823,9 +827,10 @@
       if (window->IsVisible()) {
         hidden_windows_.push_back(window);
         window->AddObserver(this);
-        wm::HideWithoutAnimation(window);
       }
     }
+    wm::HideAndMaybeMinimizeWithoutAnimation(hidden_windows_,
+                                             /*minimize=*/false);
   }
 
   return true;
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc
index c8228bc..9a898f9 100644
--- a/ash/wm/overview/overview_controller.cc
+++ b/ash/wm/overview/overview_controller.cc
@@ -4,6 +4,7 @@
 
 #include "ash/wm/overview/overview_controller.h"
 
+#include <algorithm>
 #include <vector>
 
 #include "ash/app_list/app_list_controller_impl.h"
@@ -332,11 +333,15 @@
       // those widgets will be slid out of overview. Otherwise,
       // HomeLauncherGestureHandler will handle sliding the windows out and when
       // this function is called, we do not need to create minimized widgets.
-      for (aura::Window* window : windows) {
-        if (wm::GetWindowState(window)->IsMinimized())
-          continue;
-        wm::HideAndMinimizeWithoutAnimation(window);
-      }
+      std::vector<aura::Window*> windows_to_hide_minimize(windows.size());
+      auto it = std::copy_if(
+          windows.begin(), windows.end(), windows_to_hide_minimize.begin(),
+          [](aura::Window* window) {
+            return !wm::GetWindowState(window)->IsMinimized();
+          });
+      windows_to_hide_minimize.resize(
+          std::distance(windows_to_hide_minimize.begin(), it));
+      wm::HideAndMaybeMinimizeWithoutAnimation(windows_to_hide_minimize, true);
     }
 
     OnSelectionEnded();
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc
index 5c14180..359fa18 100644
--- a/ash/wm/window_util.cc
+++ b/ash/wm/window_util.cc
@@ -312,21 +312,28 @@
   }
 }
 
-void HideAndMinimizeWithoutAnimation(aura::Window* window) {
-  // Disable the animations using |disable|. However, doing so will skip
-  // detaching and recreating layers that animating does which has memory
-  // implications, so use recreate layers to get the same effect. See
-  // crbug.com/924802.
-  ScopedAnimationDisabler disable(window);
-  window->Hide();
-  wm::GetWindowState(window)->Minimize();
-  std::unique_ptr<ui::LayerTreeOwner> owner = ::wm::RecreateLayers(window);
-}
+void HideAndMaybeMinimizeWithoutAnimation(std::vector<aura::Window*> windows,
+                                          bool minimize) {
+  for (auto* window : windows) {
+    ScopedAnimationDisabler disable(window);
 
-void HideWithoutAnimation(aura::Window* window) {
-  ScopedAnimationDisabler disable(window);
-  window->Hide();
-  std::unique_ptr<ui::LayerTreeOwner> owner = ::wm::RecreateLayers(window);
+    // ARC windows are minimized asynchronously, so hide here now.
+    // TODO(oshima): Investigate better way to handle ARC apps immediately.
+    window->Hide();
+
+    if (minimize)
+      wm::GetWindowState(window)->Minimize();
+  }
+  if (windows.size()) {
+    // Disable the animations using |disable|. However, doing so will skip
+    // detaching the resources associated with the layer. So we have to trick
+    // the compositor into releasing the resources.
+    // crbug.com/924802.
+    auto* compositor = windows[0]->layer()->GetCompositor();
+    bool was_visible = compositor->IsVisible();
+    compositor->SetVisible(false);
+    compositor->SetVisible(was_visible);
+  }
 }
 
 }  // namespace wm
diff --git a/ash/wm/window_util.h b/ash/wm/window_util.h
index 1121290721..5ea393d 100644
--- a/ash/wm/window_util.h
+++ b/ash/wm/window_util.h
@@ -116,10 +116,12 @@
 ASH_EXPORT void RemoveTransientDescendants(
     std::vector<aura::Window*>* out_window_list);
 
-// Minimizes or hides |window| without any animations, in case users what it to
-// hide right away or apply their own animations.
-ASH_EXPORT void HideAndMinimizeWithoutAnimation(aura::Window* window);
-ASH_EXPORT void HideWithoutAnimation(aura::Window* window);
+// Hides a list of |windows| without any animations, in case users wants to hide
+// them right away or apply their own animations. Setting |minimize| to true
+// will result in also setting the window states to minimized.
+ASH_EXPORT void HideAndMaybeMinimizeWithoutAnimation(
+    std::vector<aura::Window*> windows,
+    bool minimize);
 
 }  // namespace wm
 }  // namespace ash