bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "ash/rotator/screen_rotation_animator.h" |
| 6 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 7 | #include "ash/ash_switches.h" |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 8 | #include "ash/public/cpp/shell_window_ids.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 9 | #include "ash/rotator/screen_rotation_animation.h" |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 10 | #include "ash/rotator/screen_rotation_animator_observer.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 11 | #include "ash/shell.h" |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 12 | #include "ash/utility/transformer_util.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 13 | #include "base/command_line.h" |
ratsunny | bd5087e | 2016-12-17 05:19:25 | [diff] [blame] | 14 | #include "base/memory/ptr_util.h" |
wutao | 3f08f81 | 2017-03-25 03:06:33 | [diff] [blame] | 15 | #include "base/metrics/histogram_macros.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 16 | #include "base/time/time.h" |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 17 | #include "cc/output/copy_output_request.h" |
| 18 | #include "cc/output/copy_output_result.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 19 | #include "ui/aura/window.h" |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 20 | #include "ui/compositor/callback_layer_animation_observer.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 21 | #include "ui/compositor/layer.h" |
wutao | 3f08f81 | 2017-03-25 03:06:33 | [diff] [blame] | 22 | #include "ui/compositor/layer_animation_element.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 23 | #include "ui/compositor/layer_animation_sequence.h" |
| 24 | #include "ui/compositor/layer_animator.h" |
| 25 | #include "ui/compositor/layer_owner.h" |
| 26 | #include "ui/compositor/layer_tree_owner.h" |
oshima | f84b0da72 | 2016-04-27 19:47:19 | [diff] [blame] | 27 | #include "ui/display/display.h" |
rjkroege | 72f8154f | 2016-10-29 00:49:02 | [diff] [blame] | 28 | #include "ui/display/manager/display_manager.h" |
rjkroege | 259c0188 | 2016-08-30 19:29:50 | [diff] [blame] | 29 | #include "ui/display/manager/managed_display_info.h" |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 30 | #include "ui/display/screen.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 31 | #include "ui/gfx/animation/tween.h" |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 32 | #include "ui/gfx/geometry/point.h" |
| 33 | #include "ui/gfx/geometry/rect.h" |
| 34 | #include "ui/gfx/geometry/rect_f.h" |
| 35 | #include "ui/gfx/transform.h" |
| 36 | #include "ui/gfx/transform_util.h" |
| 37 | #include "ui/wm/core/window_util.h" |
| 38 | |
| 39 | namespace ash { |
| 40 | |
| 41 | namespace { |
| 42 | |
bruthig | aff7d0f | 2015-09-01 17:46:55 | [diff] [blame] | 43 | // The number of degrees that the rotation animations animate through. |
| 44 | const int kRotationDegrees = 20; |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 45 | |
bruthig | 2ce3f23 | 2015-04-02 15:21:35 | [diff] [blame] | 46 | // The time it takes for the rotation animations to run. |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 47 | const int kRotationDurationInMs = 250; |
| 48 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 49 | // The rotation factors. |
| 50 | const int kCounterClockWiseRotationFactor = 1; |
| 51 | const int kClockWiseRotationFactor = -1; |
| 52 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 53 | display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { |
sky | cb4be5b | 2017-04-06 17:52:45 | [diff] [blame] | 54 | return Shell::Get() |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 55 | ->display_manager() |
| 56 | ->GetDisplayInfo(display_id) |
jonross | d01de7f | 2015-04-23 19:52:00 | [diff] [blame] | 57 | .GetActiveRotation(); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 58 | } |
| 59 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 60 | // 180 degree rotations should animate clock-wise. |
| 61 | int GetRotationFactor(display::Display::Rotation initial_rotation, |
| 62 | display::Display::Rotation new_rotation) { |
| 63 | return (initial_rotation + 3) % 4 == new_rotation |
| 64 | ? kCounterClockWiseRotationFactor |
| 65 | : kClockWiseRotationFactor; |
| 66 | } |
| 67 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 68 | aura::Window* GetScreenRotationContainer(aura::Window* root_window) { |
| 69 | return root_window->GetChildById(kShellWindowId_ScreenRotationContainer); |
| 70 | } |
| 71 | |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 72 | // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
| 73 | // 180 degrees. |
oshima | f84b0da72 | 2016-04-27 19:47:19 | [diff] [blame] | 74 | bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
| 75 | display::Display::Rotation new_rotation) { |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 76 | return (initial_rotation + 2) % 4 == new_rotation; |
| 77 | } |
| 78 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 79 | // Returns the initial degrees the old layer animation to begin with. |
| 80 | int GetInitialDegrees(display::Display::Rotation initial_rotation, |
| 81 | display::Display::Rotation new_rotation) { |
| 82 | return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
| 83 | } |
| 84 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 85 | void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { |
| 86 | // Add the cloned/copied layer tree into the root, so it will be rendered. |
| 87 | root_window->layer()->Add(layer); |
| 88 | root_window->layer()->StackAtTop(layer); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 89 | } |
| 90 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 91 | void AddLayerBelowWindowLayer(aura::Window* root_window, |
| 92 | ui::Layer* top_layer, |
| 93 | ui::Layer* layer) { |
| 94 | // Add the cloned/copied layer tree into the root, so it will be rendered. |
| 95 | root_window->layer()->Add(layer); |
| 96 | root_window->layer()->StackBelow(layer, top_layer); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 97 | } |
| 98 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 99 | // The Callback will be invoked when all animation sequences have |
| 100 | // finished. |observer| will be destroyed after invoking the Callback if it |
| 101 | // returns true. |
| 102 | bool AnimationEndedCallback( |
| 103 | base::WeakPtr<ScreenRotationAnimator> animator, |
| 104 | const ui::CallbackLayerAnimationObserver& observer) { |
| 105 | if (animator) |
| 106 | animator->ProcessAnimationQueue(); |
| 107 | return true; |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 108 | } |
| 109 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 110 | // Creates a Transform for the old layer in screen rotation animation. |
| 111 | gfx::Transform CreateScreenRotationOldLayerTransformForDisplay( |
| 112 | display::Display::Rotation old_rotation, |
| 113 | display::Display::Rotation new_rotation, |
| 114 | const display::Display& display) { |
| 115 | gfx::Transform inverse; |
| 116 | CHECK(CreateRotationTransform(old_rotation, new_rotation, display) |
| 117 | .GetInverse(&inverse)); |
| 118 | return inverse; |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 119 | } |
| 120 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 121 | // The |request_id| changed since last copy request, which means a |
| 122 | // new rotation stated, we need to ignore this copy result. |
| 123 | bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) { |
| 124 | DCHECK(request_id <= current_request_id); |
| 125 | return request_id < current_request_id; |
| 126 | } |
| 127 | |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 128 | bool RootWindowChangedForDisplayId(aura::Window* root_window, |
| 129 | int64_t display_id) { |
Scott Violet | 596bb4634 | 2017-06-21 14:43:13 | [diff] [blame] | 130 | return root_window != Shell::GetRootWindowForDisplayId(display_id); |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 131 | } |
| 132 | |
| 133 | // Creates a mask layer and returns the |mask_layer_tree_owner|. |
| 134 | std::unique_ptr<ui::LayerTreeOwner> CreateMaskLayerTreeOwner( |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 135 | const gfx::Rect& rect) { |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 136 | std::unique_ptr<ui::Layer> mask_layer = |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 137 | base::MakeUnique<ui::Layer>(ui::LAYER_SOLID_COLOR); |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 138 | mask_layer->SetBounds(rect); |
| 139 | mask_layer->SetColor(SK_ColorBLACK); |
| 140 | return base::MakeUnique<ui::LayerTreeOwner>(std::move(mask_layer)); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 141 | } |
| 142 | |
wutao | 3f08f81 | 2017-03-25 03:06:33 | [diff] [blame] | 143 | class ScreenRotationAnimationMetricsReporter |
| 144 | : public ui::AnimationMetricsReporter { |
| 145 | public: |
wutao | 883ea6f | 2017-05-16 19:40:51 | [diff] [blame] | 146 | ScreenRotationAnimationMetricsReporter() = default; |
| 147 | ~ScreenRotationAnimationMetricsReporter() override = default; |
wutao | 3f08f81 | 2017-03-25 03:06:33 | [diff] [blame] | 148 | |
| 149 | void Report(int value) override { |
| 150 | UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
| 151 | } |
| 152 | |
| 153 | private: |
| 154 | DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); |
| 155 | }; |
| 156 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 157 | } // namespace |
jonross | 7351feb | 2015-04-23 22:10:26 | [diff] [blame] | 158 | |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 159 | ScreenRotationAnimator::ScreenRotationAnimator(aura::Window* root_window) |
| 160 | : root_window_(root_window), |
wutao | 4a48553 | 2017-04-11 00:04:28 | [diff] [blame] | 161 | screen_rotation_state_(IDLE), |
wutao | 88733df | 2017-04-13 19:39:06 | [diff] [blame] | 162 | rotation_request_id_(0), |
wutao | 3f08f81 | 2017-03-25 03:06:33 | [diff] [blame] | 163 | metrics_reporter_( |
| 164 | base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 165 | disable_animation_timers_for_test_(false), |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 166 | has_switch_ash_disable_smooth_screen_rotation_( |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 167 | base::CommandLine::ForCurrentProcess()->HasSwitch( |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 168 | switches::kAshDisableSmoothScreenRotation)), |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 169 | weak_factory_(this) {} |
| 170 | |
wutao | 3f08f81 | 2017-03-25 03:06:33 | [diff] [blame] | 171 | ScreenRotationAnimator::~ScreenRotationAnimator() { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 172 | // To prevent a call to |AnimationEndedCallback()| from calling a method on |
| 173 | // the |animator_|. |
wutao | 3f08f81 | 2017-03-25 03:06:33 | [diff] [blame] | 174 | weak_factory_.InvalidateWeakPtrs(); |
| 175 | |
| 176 | // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in |
| 177 | // order to make sure |metrics_reporter_| outlives the attached animation |
| 178 | // sequence. |
| 179 | old_layer_tree_owner_.reset(); |
| 180 | metrics_reporter_.reset(); |
| 181 | } |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 182 | |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 183 | void ScreenRotationAnimator::StartRotationAnimation( |
| 184 | std::unique_ptr<ScreenRotationRequest> rotation_request) { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 185 | const display::Display::Rotation current_rotation = |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 186 | GetCurrentScreenRotation(rotation_request->display_id); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 187 | if (current_rotation == rotation_request->new_rotation) { |
| 188 | // We need to call |ProcessAnimationQueue()| to prepare for next rotation |
| 189 | // request. |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 190 | ProcessAnimationQueue(); |
| 191 | return; |
| 192 | } |
| 193 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 194 | rotation_request->old_rotation = current_rotation; |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 195 | if (has_switch_ash_disable_smooth_screen_rotation_) { |
| 196 | StartSlowAnimation(std::move(rotation_request)); |
| 197 | } else { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 198 | std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| 199 | cc::CopyOutputRequest::CreateRequest( |
| 200 | CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request))); |
| 201 | RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
| 202 | screen_rotation_state_ = COPY_REQUESTED; |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 203 | } |
| 204 | } |
| 205 | |
| 206 | void ScreenRotationAnimator::StartSlowAnimation( |
| 207 | std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| 208 | CreateOldLayerTreeForSlowAnimation(); |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 209 | SetRotation(rotation_request->display_id, rotation_request->old_rotation, |
| 210 | rotation_request->new_rotation, rotation_request->source); |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 211 | AnimateRotation(std::move(rotation_request)); |
| 212 | } |
| 213 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 214 | void ScreenRotationAnimator::SetRotation( |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 215 | int64_t display_id, |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 216 | display::Display::Rotation old_rotation, |
| 217 | display::Display::Rotation new_rotation, |
| 218 | display::Display::RotationSource source) { |
wutao | eb55205 | 2017-05-10 22:35:29 | [diff] [blame] | 219 | // Allow compositor locks to extend timeout, so that screen rotation only |
| 220 | // takes output copy after contents are properlly resized, such as wallpaper |
| 221 | // and ARC apps. |
| 222 | ui::Compositor* compositor = root_window_->layer()->GetCompositor(); |
| 223 | compositor->set_allow_locks_to_extend_timeout(true); |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 224 | Shell::Get()->display_manager()->SetDisplayRotation(display_id, new_rotation, |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 225 | source); |
wutao | eb55205 | 2017-05-10 22:35:29 | [diff] [blame] | 226 | compositor->set_allow_locks_to_extend_timeout(false); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 227 | const display::Display display = |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 228 | Shell::Get()->display_manager()->GetDisplayForId(display_id); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 229 | old_layer_tree_owner_->root()->SetTransform( |
| 230 | CreateScreenRotationOldLayerTransformForDisplay(old_rotation, |
| 231 | new_rotation, display)); |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 232 | } |
| 233 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 234 | void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer( |
| 235 | std::unique_ptr<cc::CopyOutputRequest> copy_output_request) { |
wutao | a0f3ea2a | 2017-06-20 03:26:31 | [diff] [blame] | 236 | ui::Layer* screen_rotation_container_layer = |
| 237 | GetScreenRotationContainer(root_window_)->layer(); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 238 | copy_output_request->set_area( |
wutao | a0f3ea2a | 2017-06-20 03:26:31 | [diff] [blame] | 239 | gfx::Rect(screen_rotation_container_layer->size())); |
| 240 | screen_rotation_container_layer->RequestCopyOfOutput( |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 241 | std::move(copy_output_request)); |
| 242 | } |
| 243 | |
| 244 | ScreenRotationAnimator::CopyCallback |
| 245 | ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation( |
| 246 | std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| 247 | return base::Bind(&ScreenRotationAnimator:: |
| 248 | OnScreenRotationContainerLayerCopiedBeforeRotation, |
| 249 | weak_factory_.GetWeakPtr(), |
| 250 | base::Passed(&rotation_request)); |
| 251 | } |
| 252 | |
| 253 | ScreenRotationAnimator::CopyCallback |
| 254 | ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation( |
| 255 | std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| 256 | return base::Bind(&ScreenRotationAnimator:: |
| 257 | OnScreenRotationContainerLayerCopiedAfterRotation, |
| 258 | weak_factory_.GetWeakPtr(), |
| 259 | base::Passed(&rotation_request)); |
| 260 | } |
| 261 | |
| 262 | void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation( |
| 263 | std::unique_ptr<ScreenRotationRequest> rotation_request, |
| 264 | std::unique_ptr<cc::CopyOutputResult> result) { |
| 265 | if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) |
| 266 | return; |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 267 | // Abort rotation and animation if the display was removed or the |
| 268 | // |root_window| was changed for |display_id|. |
| 269 | if (RootWindowChangedForDisplayId(root_window_, |
| 270 | rotation_request->display_id)) { |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 271 | ProcessAnimationQueue(); |
| 272 | return; |
| 273 | } |
| 274 | // Abort animation and set the rotation to target rotation when the copy |
| 275 | // request has been canceled or failed. It would fail if, for examples: a) The |
| 276 | // layer is removed from the compositor and destroye before committing the |
| 277 | // request to the compositor. b) The compositor is shutdown. |
| 278 | if (result->IsEmpty()) { |
| 279 | Shell::Get()->display_manager()->SetDisplayRotation( |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 280 | rotation_request->display_id, rotation_request->new_rotation, |
| 281 | rotation_request->source); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 282 | ProcessAnimationQueue(); |
| 283 | return; |
| 284 | } |
| 285 | |
| 286 | old_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
| 287 | AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root()); |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 288 | SetRotation(rotation_request->display_id, rotation_request->old_rotation, |
| 289 | rotation_request->new_rotation, rotation_request->source); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 290 | std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| 291 | cc::CopyOutputRequest::CreateRequest( |
| 292 | CreateAfterCopyCallbackAfterRotation(std::move(rotation_request))); |
| 293 | RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
| 294 | } |
| 295 | |
| 296 | void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation( |
| 297 | std::unique_ptr<ScreenRotationRequest> rotation_request, |
| 298 | std::unique_ptr<cc::CopyOutputResult> result) { |
| 299 | if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) |
| 300 | return; |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 301 | // In the following cases, abort animation: |
| 302 | // 1) if the display was removed, |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 303 | // 2) if the |root_window| was changed for |display_id|, |
| 304 | // 3) the copy request has been canceled or failed. It would fail if, |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 305 | // for examples: a) The layer is removed from the compositor and destroye |
| 306 | // before committing the request to the compositor. b) The compositor is |
| 307 | // shutdown. |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 308 | if (RootWindowChangedForDisplayId(root_window_, |
| 309 | rotation_request->display_id) || |
| 310 | result->IsEmpty()) { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 311 | ProcessAnimationQueue(); |
| 312 | return; |
| 313 | } |
| 314 | |
| 315 | new_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
| 316 | AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(), |
| 317 | new_layer_tree_owner_->root()); |
| 318 | AnimateRotation(std::move(rotation_request)); |
| 319 | } |
| 320 | |
| 321 | void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() { |
| 322 | old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 323 | AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root()); |
| 324 | } |
| 325 | |
| 326 | std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree( |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 327 | std::unique_ptr<cc::CopyOutputResult> result) { |
Fady Samuel | 2a725ce5 | 2017-07-11 22:30:00 | [diff] [blame] | 328 | viz::TextureMailbox texture_mailbox; |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 329 | std::unique_ptr<cc::SingleReleaseCallback> release_callback; |
| 330 | result->TakeTexture(&texture_mailbox, &release_callback); |
| 331 | DCHECK(texture_mailbox.IsTexture()); |
wutao | a0f3ea2a | 2017-06-20 03:26:31 | [diff] [blame] | 332 | const gfx::Rect rect( |
| 333 | GetScreenRotationContainer(root_window_)->layer()->size()); |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 334 | std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); |
| 335 | copy_layer->SetBounds(rect); |
| 336 | copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), |
| 337 | rect.size()); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 338 | return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); |
wutao | 2c0ca18 | 2017-04-06 22:40:54 | [diff] [blame] | 339 | } |
| 340 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 341 | void ScreenRotationAnimator::AnimateRotation( |
| 342 | std::unique_ptr<ScreenRotationRequest> rotation_request) { |
wutao | 4a48553 | 2017-04-11 00:04:28 | [diff] [blame] | 343 | screen_rotation_state_ = ROTATING; |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 344 | const int rotation_factor = GetRotationFactor(rotation_request->old_rotation, |
| 345 | rotation_request->new_rotation); |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 346 | const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 347 | rotation_request->old_rotation, rotation_request->new_rotation); |
bruthig | aff7d0f | 2015-09-01 17:46:55 | [diff] [blame] | 348 | const base::TimeDelta duration = |
| 349 | base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
bruthig | aff7d0f | 2015-09-01 17:46:55 | [diff] [blame] | 350 | const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 351 | const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds(); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 352 | const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, |
| 353 | rotated_screen_bounds.height() / 2); |
| 354 | |
wutao | a0f3ea2a | 2017-06-20 03:26:31 | [diff] [blame] | 355 | ui::Layer* screen_rotation_container_layer = |
| 356 | GetScreenRotationContainer(root_window_)->layer(); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 357 | ui::Layer* new_root_layer; |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 358 | if (!new_layer_tree_owner_ || |
| 359 | has_switch_ash_disable_smooth_screen_rotation_) { |
wutao | a0f3ea2a | 2017-06-20 03:26:31 | [diff] [blame] | 360 | new_root_layer = screen_rotation_container_layer; |
wutao | b161bf2 | 2017-04-26 16:55:03 | [diff] [blame] | 361 | } else { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 362 | new_root_layer = new_layer_tree_owner_->root(); |
wutao | a0f3ea2a | 2017-06-20 03:26:31 | [diff] [blame] | 363 | // Add a black mask layer on top of |screen_rotation_container_layer|. |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 364 | mask_layer_tree_owner_ = CreateMaskLayerTreeOwner( |
wutao | a0f3ea2a | 2017-06-20 03:26:31 | [diff] [blame] | 365 | gfx::Rect(screen_rotation_container_layer->size())); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 366 | AddLayerBelowWindowLayer(root_window_, new_root_layer, |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 367 | mask_layer_tree_owner_->root()); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 368 | } |
| 369 | |
| 370 | std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation = |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 371 | base::MakeUnique<ScreenRotationAnimation>( |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 372 | new_root_layer, kRotationDegrees * rotation_factor, |
| 373 | 0 /* end_degrees */, new_root_layer->opacity(), |
| 374 | new_root_layer->opacity() /* target_opacity */, pivot, duration, |
| 375 | tween_type); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 376 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 377 | ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator(); |
| 378 | new_layer_animator->set_preemption_strategy( |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 379 | ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 380 | std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence = |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 381 | base::MakeUnique<ui::LayerAnimationSequence>( |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 382 | std::move(new_layer_screen_rotation)); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 383 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 384 | ui::Layer* old_root_layer = old_layer_tree_owner_->root(); |
| 385 | const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds(); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 386 | // The old layer will also be transformed into the new orientation. We will |
| 387 | // translate it so that the old layer's center point aligns with the new |
| 388 | // orientation's center point and use that center point as the pivot for the |
| 389 | // rotation animation. |
| 390 | gfx::Transform translate_transform; |
| 391 | translate_transform.Translate( |
| 392 | (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, |
| 393 | (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 394 | old_root_layer->SetTransform(translate_transform); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 395 | |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 396 | std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = |
ratsunny | bd5087e | 2016-12-17 05:19:25 | [diff] [blame] | 397 | base::MakeUnique<ScreenRotationAnimation>( |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 398 | old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, |
bruthig | aff7d0f | 2015-09-01 17:46:55 | [diff] [blame] | 399 | (old_layer_initial_rotation_degrees - kRotationDegrees) * |
| 400 | rotation_factor, |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 401 | old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, |
| 402 | tween_type); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 403 | |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 404 | ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); |
| 405 | old_layer_animator->set_preemption_strategy( |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 406 | ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 407 | std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = |
| 408 | base::MakeUnique<ui::LayerAnimationSequence>( |
| 409 | std::move(old_layer_screen_rotation)); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 410 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 411 | // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to |
| 412 | // control the animation. |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 413 | if (disable_animation_timers_for_test_) { |
| 414 | if (new_layer_tree_owner_) |
| 415 | new_layer_animator->set_disable_timer_for_test(true); |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 416 | old_layer_animator->set_disable_timer_for_test(true); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 417 | } |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 418 | old_layer_animation_sequence->SetAnimationMetricsReporter( |
| 419 | metrics_reporter_.get()); |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 420 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 421 | // Add an observer so that the cloned/copied layers can be cleaned up with the |
| 422 | // animation completes/aborts. |
| 423 | ui::CallbackLayerAnimationObserver* observer = |
| 424 | new ui::CallbackLayerAnimationObserver( |
| 425 | base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr())); |
| 426 | if (new_layer_tree_owner_) |
| 427 | new_layer_animator->AddObserver(observer); |
| 428 | new_layer_animator->StartAnimation(new_layer_animation_sequence.release()); |
| 429 | old_layer_animator->AddObserver(observer); |
| 430 | old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); |
| 431 | observer->SetActive(); |
bruthig | f57a7bba | 2015-04-24 21:19:31 | [diff] [blame] | 432 | } |
| 433 | |
oshima | f84b0da72 | 2016-04-27 19:47:19 | [diff] [blame] | 434 | void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
| 435 | display::Display::RotationSource source) { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 436 | // |rotation_request_id_| is used to skip stale requests. Before the layer |
| 437 | // CopyOutputResult callback called, there could have new rotation request. |
| 438 | // Increases |rotation_request_id_| for each new request and in the callback, |
| 439 | // we compare the |rotation_request.id| and |rotation_request_id_| to |
| 440 | // determine the stale status. |
wutao | 88733df | 2017-04-13 19:39:06 | [diff] [blame] | 441 | rotation_request_id_++; |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 442 | const int64_t display_id = |
| 443 | display::Screen::GetScreen()->GetDisplayNearestWindow(root_window_).id(); |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 444 | std::unique_ptr<ScreenRotationRequest> rotation_request = |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 445 | base::MakeUnique<ScreenRotationRequest>(rotation_request_id_, display_id, |
wutao | 88733df | 2017-04-13 19:39:06 | [diff] [blame] | 446 | new_rotation, source); |
wutao | 4a48553 | 2017-04-11 00:04:28 | [diff] [blame] | 447 | switch (screen_rotation_state_) { |
| 448 | case IDLE: |
wutao | 88733df | 2017-04-13 19:39:06 | [diff] [blame] | 449 | case COPY_REQUESTED: |
wutao | 4a48553 | 2017-04-11 00:04:28 | [diff] [blame] | 450 | StartRotationAnimation(std::move(rotation_request)); |
| 451 | break; |
| 452 | case ROTATING: |
| 453 | last_pending_request_ = std::move(rotation_request); |
| 454 | // The pending request will be processed when the |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 455 | // |AnimationEndedCallback()| should be called after |StopAnimating()|. |
wutao | 4a48553 | 2017-04-11 00:04:28 | [diff] [blame] | 456 | StopAnimating(); |
| 457 | break; |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 458 | } |
| 459 | } |
| 460 | |
| 461 | void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( |
| 462 | ScreenRotationAnimatorObserver* observer) { |
| 463 | screen_rotation_animator_observers_.AddObserver(observer); |
| 464 | } |
| 465 | |
| 466 | void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( |
| 467 | ScreenRotationAnimatorObserver* observer) { |
| 468 | screen_rotation_animator_observers_.RemoveObserver(observer); |
| 469 | } |
| 470 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 471 | void ScreenRotationAnimator::ProcessAnimationQueue() { |
wutao | 4a48553 | 2017-04-11 00:04:28 | [diff] [blame] | 472 | screen_rotation_state_ = IDLE; |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 473 | old_layer_tree_owner_.reset(); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 474 | new_layer_tree_owner_.reset(); |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 475 | mask_layer_tree_owner_.reset(); |
| 476 | if (last_pending_request_ && |
| 477 | !RootWindowChangedForDisplayId(root_window_, |
| 478 | last_pending_request_->display_id)) { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 479 | StartRotationAnimation(std::move(last_pending_request_)); |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 480 | return; |
| 481 | } |
| 482 | |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 483 | // This is only used in test to notify animator observer. |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 484 | for (auto& observer : screen_rotation_animator_observers_) |
| 485 | observer.OnScreenRotationAnimationFinished(this); |
| 486 | } |
| 487 | |
wutao | 6ddafa3 | 2017-03-18 03:10:08 | [diff] [blame] | 488 | void ScreenRotationAnimator::StopAnimating() { |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 489 | // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another |
| 490 | // the rotation request comes before the copy request finished. |
wutao | 3357608 | 2017-04-14 18:51:10 | [diff] [blame] | 491 | if (old_layer_tree_owner_) |
| 492 | old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
wutao | 6d39411 | 2017-04-20 02:17:35 | [diff] [blame] | 493 | if (new_layer_tree_owner_) |
| 494 | new_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
wutao | c18f66c | 2017-06-02 18:11:01 | [diff] [blame] | 495 | mask_layer_tree_owner_.reset(); |
bruthig | 37f9cad0 | 2015-03-12 22:28:50 | [diff] [blame] | 496 | } |
| 497 | |
| 498 | } // namespace ash |