OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/rotator/screen_rotation_animator.h" | 5 #include "ash/rotator/screen_rotation_animator.h" |
6 | 6 |
7 #include <string> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "ash/ash_switches.h" | 7 #include "ash/ash_switches.h" |
12 #include "ash/display/window_tree_host_manager.h" | 8 #include "ash/display/window_tree_host_manager.h" |
13 #include "ash/public/cpp/shell_window_ids.h" | 9 #include "ash/public/cpp/shell_window_ids.h" |
14 #include "ash/rotator/screen_rotation_animation.h" | 10 #include "ash/rotator/screen_rotation_animation.h" |
15 #include "ash/rotator/screen_rotation_animator_observer.h" | 11 #include "ash/rotator/screen_rotation_animator_observer.h" |
16 #include "ash/shell.h" | 12 #include "ash/shell.h" |
| 13 #include "ash/utility/transformer_util.h" |
17 #include "base/command_line.h" | 14 #include "base/command_line.h" |
18 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
19 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
20 #include "base/time/time.h" | 17 #include "base/time/time.h" |
21 #include "cc/output/copy_output_request.h" | 18 #include "cc/output/copy_output_request.h" |
22 #include "cc/output/copy_output_result.h" | 19 #include "cc/output/copy_output_result.h" |
23 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
| 21 #include "ui/compositor/callback_layer_animation_observer.h" |
24 #include "ui/compositor/layer.h" | 22 #include "ui/compositor/layer.h" |
25 #include "ui/compositor/layer_animation_element.h" | 23 #include "ui/compositor/layer_animation_element.h" |
26 #include "ui/compositor/layer_animation_observer.h" | |
27 #include "ui/compositor/layer_animation_sequence.h" | 24 #include "ui/compositor/layer_animation_sequence.h" |
28 #include "ui/compositor/layer_animator.h" | 25 #include "ui/compositor/layer_animator.h" |
29 #include "ui/compositor/layer_owner.h" | 26 #include "ui/compositor/layer_owner.h" |
30 #include "ui/compositor/layer_tree_owner.h" | 27 #include "ui/compositor/layer_tree_owner.h" |
31 #include "ui/display/display.h" | 28 #include "ui/display/display.h" |
32 #include "ui/display/manager/display_manager.h" | 29 #include "ui/display/manager/display_manager.h" |
33 #include "ui/display/manager/managed_display_info.h" | 30 #include "ui/display/manager/managed_display_info.h" |
34 #include "ui/gfx/animation/tween.h" | 31 #include "ui/gfx/animation/tween.h" |
35 #include "ui/gfx/geometry/point.h" | 32 #include "ui/gfx/geometry/point.h" |
36 #include "ui/gfx/geometry/rect.h" | 33 #include "ui/gfx/geometry/rect.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 return (initial_rotation + 3) % 4 == new_rotation | 67 return (initial_rotation + 3) % 4 == new_rotation |
71 ? kCounterClockWiseRotationFactor | 68 ? kCounterClockWiseRotationFactor |
72 : kClockWiseRotationFactor; | 69 : kClockWiseRotationFactor; |
73 } | 70 } |
74 | 71 |
75 aura::Window* GetRootWindow(int64_t display_id) { | 72 aura::Window* GetRootWindow(int64_t display_id) { |
76 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( | 73 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( |
77 display_id); | 74 display_id); |
78 } | 75 } |
79 | 76 |
| 77 aura::Window* GetScreenRotationContainer(aura::Window* root_window) { |
| 78 return root_window->GetChildById(kShellWindowId_ScreenRotationContainer); |
| 79 } |
| 80 |
80 // Returns true if the rotation between |initial_rotation| and |new_rotation| is | 81 // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
81 // 180 degrees. | 82 // 180 degrees. |
82 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, | 83 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
83 display::Display::Rotation new_rotation) { | 84 display::Display::Rotation new_rotation) { |
84 return (initial_rotation + 2) % 4 == new_rotation; | 85 return (initial_rotation + 2) % 4 == new_rotation; |
85 } | 86 } |
86 | 87 |
87 // Returns the initial degrees the old layer animation to begin with. | 88 // Returns the initial degrees the old layer animation to begin with. |
88 int GetInitialDegrees(display::Display::Rotation initial_rotation, | 89 int GetInitialDegrees(display::Display::Rotation initial_rotation, |
89 display::Display::Rotation new_rotation) { | 90 display::Display::Rotation new_rotation) { |
90 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); | 91 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
91 } | 92 } |
92 | 93 |
93 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner | 94 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { |
94 // when notified that a layer animation has ended or was aborted. | 95 // Add the cloned/copied layer tree into the root, so it will be rendered. |
95 class LayerCleanupObserver : public ui::LayerAnimationObserver { | 96 root_window->layer()->Add(layer); |
96 public: | 97 root_window->layer()->StackAtTop(layer); |
97 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_| | |
98 // instance and the |animator_| isn't detaching itself as an observer when | |
99 // being destroyed. However, ideally, when |animator_| is destroying, | |
100 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and | |
101 // delete |this| before |animator_| deleted. | |
102 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator); | |
103 ~LayerCleanupObserver() override; | |
104 | |
105 // ui::LayerAnimationObserver: | |
106 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; | |
107 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; | |
108 void OnLayerAnimationScheduled( | |
109 ui::LayerAnimationSequence* sequence) override {} | |
110 | |
111 protected: | |
112 // ui::LayerAnimationObserver: | |
113 bool RequiresNotificationWhenAnimatorDestroyed() const override { | |
114 return true; | |
115 } | |
116 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; | |
117 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; | |
118 | |
119 private: | |
120 base::WeakPtr<ScreenRotationAnimator> animator_; | |
121 | |
122 // The LayerAnimationSequence that |this| has been attached to. Defaults to | |
123 // nullptr. | |
124 ui::LayerAnimationSequence* sequence_; | |
125 | |
126 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); | |
127 }; | |
128 | |
129 LayerCleanupObserver::LayerCleanupObserver( | |
130 base::WeakPtr<ScreenRotationAnimator> animator) | |
131 : animator_(animator), sequence_(nullptr) {} | |
132 | |
133 LayerCleanupObserver::~LayerCleanupObserver() { | |
134 // We must eplicitly detach from |sequence_| because we return true from | |
135 // RequiresNotificationWhenAnimatorDestroyed. | |
136 if (sequence_) | |
137 sequence_->RemoveObserver(this); | |
138 } | 98 } |
139 | 99 |
140 void LayerCleanupObserver::OnLayerAnimationEnded( | 100 void AddLayerBelowWindowLayer(aura::Window* root_window, |
141 ui::LayerAnimationSequence* sequence) { | 101 ui::Layer* top_layer, |
142 if (animator_) | 102 ui::Layer* layer) { |
143 animator_->ProcessAnimationQueue(); | 103 // Add the cloned/copied layer tree into the root, so it will be rendered. |
144 | 104 root_window->layer()->Add(layer); |
145 delete this; | 105 root_window->layer()->StackBelow(layer, top_layer); |
146 } | 106 } |
147 | 107 |
148 void LayerCleanupObserver::OnLayerAnimationAborted( | 108 // The Callback will be invoked when all animation sequences have |
149 ui::LayerAnimationSequence* sequence) { | 109 // finished. |observer| will be destroyed after invoking the Callback if it |
150 if (animator_) | 110 // returns true. |
151 animator_->ProcessAnimationQueue(); | 111 bool AnimationEndedCallback( |
152 | 112 base::WeakPtr<ScreenRotationAnimator> animator, |
153 delete this; | 113 const ui::CallbackLayerAnimationObserver& observer) { |
| 114 if (animator) |
| 115 animator->ProcessAnimationQueue(); |
| 116 return true; |
154 } | 117 } |
155 | 118 |
156 void LayerCleanupObserver::OnAttachedToSequence( | 119 // Creates a Transform for the old layer in screen rotation animation. |
157 ui::LayerAnimationSequence* sequence) { | 120 gfx::Transform CreateScreenRotationOldLayerTransformForDisplay( |
158 sequence_ = sequence; | 121 display::Display::Rotation old_rotation, |
| 122 display::Display::Rotation new_rotation, |
| 123 const display::Display& display) { |
| 124 gfx::Transform inverse; |
| 125 CHECK(CreateRotationTransform(old_rotation, new_rotation, display) |
| 126 .GetInverse(&inverse)); |
| 127 return inverse; |
159 } | 128 } |
160 | 129 |
161 void LayerCleanupObserver::OnDetachedFromSequence( | 130 // The |request_id| changed since last copy request, which means a |
162 ui::LayerAnimationSequence* sequence) { | 131 // new rotation stated, we need to ignore this copy result. |
163 DCHECK_EQ(sequence, sequence_); | 132 bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) { |
164 sequence_ = nullptr; | 133 DCHECK(request_id <= current_request_id); |
| 134 return request_id < current_request_id; |
| 135 } |
| 136 |
| 137 // In the following cases, abort rotation: |
| 138 // 1) if the display was removed, |
| 139 // 2) the copy request has been canceled or failed. It would fail if, |
| 140 // for examples: a) The layer is removed from the compositor and destroye |
| 141 // before committing the request to the compositor. b) The compositor is |
| 142 // shutdown. |
| 143 bool AbortRotation(int64_t display_id, cc::CopyOutputResult* result) { |
| 144 return !IsDisplayIdValid(display_id) || result->IsEmpty(); |
| 145 } |
| 146 |
| 147 // Creates a black mask layer and returns the |layer_owner|. |
| 148 std::unique_ptr<ui::LayerOwner> CreateBlackMaskLayerOwner( |
| 149 const gfx::Rect& rect) { |
| 150 std::unique_ptr<ui::Layer> black_mask_layer = |
| 151 base::MakeUnique<ui::Layer>(ui::LAYER_SOLID_COLOR); |
| 152 black_mask_layer->SetBounds(rect); |
| 153 black_mask_layer->SetColor(SK_ColorBLACK); |
| 154 std::unique_ptr<ui::LayerOwner> black_mask_layer_owner = |
| 155 base::MakeUnique<ui::LayerOwner>(); |
| 156 black_mask_layer_owner->SetLayer(std::move(black_mask_layer)); |
| 157 return black_mask_layer_owner; |
165 } | 158 } |
166 | 159 |
167 class ScreenRotationAnimationMetricsReporter | 160 class ScreenRotationAnimationMetricsReporter |
168 : public ui::AnimationMetricsReporter { | 161 : public ui::AnimationMetricsReporter { |
169 public: | 162 public: |
170 ScreenRotationAnimationMetricsReporter() {} | 163 ScreenRotationAnimationMetricsReporter() {} |
171 ~ScreenRotationAnimationMetricsReporter() override {} | 164 ~ScreenRotationAnimationMetricsReporter() override {} |
172 | 165 |
173 void Report(int value) override { | 166 void Report(int value) override { |
174 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); | 167 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
175 } | 168 } |
176 | 169 |
177 private: | 170 private: |
178 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); | 171 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); |
179 }; | 172 }; |
180 | 173 |
181 } // namespace | 174 } // namespace |
182 | 175 |
183 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) | 176 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) |
184 : display_id_(display_id), | 177 : display_id_(display_id), |
185 screen_rotation_state_(IDLE), | 178 screen_rotation_state_(IDLE), |
186 rotation_request_id_(0), | 179 rotation_request_id_(0), |
187 metrics_reporter_( | 180 metrics_reporter_( |
188 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), | 181 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), |
189 disable_animation_timers_for_test_(false), | 182 disable_animation_timers_for_test_(false), |
| 183 has_switch_ash_enable_smooth_screen_rotation_( |
| 184 base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 185 switches::kAshEnableSmoothScreenRotation)), |
| 186 root_window_(GetRootWindow(display_id_)), |
| 187 screen_rotation_container_layer_( |
| 188 GetScreenRotationContainer(root_window_)->layer()), |
190 weak_factory_(this) {} | 189 weak_factory_(this) {} |
191 | 190 |
192 ScreenRotationAnimator::~ScreenRotationAnimator() { | 191 ScreenRotationAnimator::~ScreenRotationAnimator() { |
193 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from | 192 // To prevent a call to |AnimationEndedCallback()| from calling a method on |
194 // calling a method on the |animator_|. | 193 // the |animator_|. |
195 weak_factory_.InvalidateWeakPtrs(); | 194 weak_factory_.InvalidateWeakPtrs(); |
196 | 195 |
197 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in | 196 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in |
198 // order to make sure |metrics_reporter_| outlives the attached animation | 197 // order to make sure |metrics_reporter_| outlives the attached animation |
199 // sequence. | 198 // sequence. |
200 old_layer_tree_owner_.reset(); | 199 old_layer_tree_owner_.reset(); |
201 metrics_reporter_.reset(); | 200 metrics_reporter_.reset(); |
202 } | 201 } |
203 | 202 |
204 void ScreenRotationAnimator::StartRotationAnimation( | 203 void ScreenRotationAnimator::StartRotationAnimation( |
205 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 204 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
206 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 205 const display::Display::Rotation current_rotation = |
207 switches::kAshEnableSmoothScreenRotation)) { | 206 GetCurrentScreenRotation(display_id_); |
208 RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request)); | 207 if (current_rotation == rotation_request->new_rotation) { |
| 208 // We need to call |ProcessAnimationQueue()| to prepare for next rotation |
| 209 // request. |
| 210 ProcessAnimationQueue(); |
| 211 return; |
| 212 } |
| 213 |
| 214 rotation_request->old_rotation = current_rotation; |
| 215 if (has_switch_ash_enable_smooth_screen_rotation_) { |
| 216 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| 217 cc::CopyOutputRequest::CreateRequest( |
| 218 CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request))); |
| 219 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
| 220 screen_rotation_state_ = COPY_REQUESTED; |
209 } else { | 221 } else { |
210 CreateOldLayerTree(); | 222 StartSlowAnimation(std::move(rotation_request)); |
211 AnimateRotation(std::move(rotation_request)); | |
212 } | 223 } |
213 } | 224 } |
214 | 225 |
215 void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation( | 226 void ScreenRotationAnimator::StartSlowAnimation( |
216 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 227 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
217 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = | 228 CreateOldLayerTreeForSlowAnimation(); |
218 cc::CopyOutputRequest::CreateRequest( | 229 SetRotation(rotation_request->old_rotation, rotation_request->new_rotation, |
219 CreateAfterCopyCallback(std::move(rotation_request))); | 230 rotation_request->source); |
220 ui::Layer* layer = GetRootWindow(display_id_)->layer(); | 231 AnimateRotation(std::move(rotation_request)); |
221 copy_output_request->set_area(gfx::Rect(layer->size())); | 232 } |
222 layer->RequestCopyOfOutput(std::move(copy_output_request)); | |
223 | 233 |
224 screen_rotation_state_ = COPY_REQUESTED; | 234 void ScreenRotationAnimator::SetRotation( |
| 235 display::Display::Rotation old_rotation, |
| 236 display::Display::Rotation new_rotation, |
| 237 display::Display::RotationSource source) { |
| 238 Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation, |
| 239 source); |
| 240 const display::Display display = |
| 241 Shell::Get()->display_manager()->GetDisplayForId(display_id_); |
| 242 old_layer_tree_owner_->root()->SetTransform( |
| 243 CreateScreenRotationOldLayerTransformForDisplay(old_rotation, |
| 244 new_rotation, display)); |
| 245 } |
| 246 |
| 247 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer( |
| 248 std::unique_ptr<cc::CopyOutputRequest> copy_output_request) { |
| 249 copy_output_request->set_area( |
| 250 gfx::Rect(screen_rotation_container_layer_->size())); |
| 251 screen_rotation_container_layer_->RequestCopyOfOutput( |
| 252 std::move(copy_output_request)); |
225 } | 253 } |
226 | 254 |
227 ScreenRotationAnimator::CopyCallback | 255 ScreenRotationAnimator::CopyCallback |
228 ScreenRotationAnimator::CreateAfterCopyCallback( | 256 ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation( |
229 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 257 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
230 return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, | 258 return base::Bind(&ScreenRotationAnimator:: |
| 259 OnScreenRotationContainerLayerCopiedBeforeRotation, |
231 weak_factory_.GetWeakPtr(), | 260 weak_factory_.GetWeakPtr(), |
232 base::Passed(&rotation_request)); | 261 base::Passed(&rotation_request)); |
233 } | 262 } |
234 | 263 |
235 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( | 264 ScreenRotationAnimator::CopyCallback |
| 265 ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation( |
| 266 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| 267 return base::Bind(&ScreenRotationAnimator:: |
| 268 OnScreenRotationContainerLayerCopiedAfterRotation, |
| 269 weak_factory_.GetWeakPtr(), |
| 270 base::Passed(&rotation_request)); |
| 271 } |
| 272 |
| 273 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation( |
236 std::unique_ptr<ScreenRotationRequest> rotation_request, | 274 std::unique_ptr<ScreenRotationRequest> rotation_request, |
237 std::unique_ptr<cc::CopyOutputResult> result) { | 275 std::unique_ptr<cc::CopyOutputResult> result) { |
238 DCHECK(rotation_request->id <= rotation_request_id_); | 276 if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) |
239 // The |rotation_request_id_| changed since last copy request, which means a | |
240 // new rotation stated, we need to ignore this copy result. | |
241 if (rotation_request->id < rotation_request_id_) | |
242 return; | 277 return; |
243 | 278 if (AbortRotation(display_id_, result.get())) { |
244 // In the following cases, abort rotation: | |
245 // 1) if the display was removed, | |
246 // 2) the copy request has been canceled or failed. It would fail if, | |
247 // for examples: a) The layer is removed from the compositor and destroye | |
248 // before committing the request to the compositor. b) The compositor is | |
249 // shutdown. | |
250 if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) { | |
251 ProcessAnimationQueue(); | 279 ProcessAnimationQueue(); |
252 return; | 280 return; |
253 } | 281 } |
254 | 282 |
255 CopyOldLayerTree(std::move(result)); | 283 old_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
| 284 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root()); |
| 285 SetRotation(rotation_request->old_rotation, rotation_request->new_rotation, |
| 286 rotation_request->source); |
| 287 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| 288 cc::CopyOutputRequest::CreateRequest( |
| 289 CreateAfterCopyCallbackAfterRotation(std::move(rotation_request))); |
| 290 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
| 291 } |
| 292 |
| 293 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation( |
| 294 std::unique_ptr<ScreenRotationRequest> rotation_request, |
| 295 std::unique_ptr<cc::CopyOutputResult> result) { |
| 296 if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) |
| 297 return; |
| 298 if (AbortRotation(display_id_, result.get())) { |
| 299 ProcessAnimationQueue(); |
| 300 return; |
| 301 } |
| 302 |
| 303 new_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
| 304 AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(), |
| 305 new_layer_tree_owner_->root()); |
256 AnimateRotation(std::move(rotation_request)); | 306 AnimateRotation(std::move(rotation_request)); |
257 } | 307 } |
258 | 308 |
259 void ScreenRotationAnimator::CreateOldLayerTree() { | 309 void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() { |
260 old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_)); | 310 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_); |
| 311 // |screen_rotation_container_layer_| needs update after |RecreateLayers()|. |
| 312 screen_rotation_container_layer_ = |
| 313 GetScreenRotationContainer(root_window_)->layer(); |
| 314 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root()); |
261 } | 315 } |
262 | 316 |
263 void ScreenRotationAnimator::CopyOldLayerTree( | 317 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree( |
264 std::unique_ptr<cc::CopyOutputResult> result) { | 318 std::unique_ptr<cc::CopyOutputResult> result) { |
265 cc::TextureMailbox texture_mailbox; | 319 cc::TextureMailbox texture_mailbox; |
266 std::unique_ptr<cc::SingleReleaseCallback> release_callback; | 320 std::unique_ptr<cc::SingleReleaseCallback> release_callback; |
267 result->TakeTexture(&texture_mailbox, &release_callback); | 321 result->TakeTexture(&texture_mailbox, &release_callback); |
268 DCHECK(texture_mailbox.IsTexture()); | 322 DCHECK(texture_mailbox.IsTexture()); |
269 | 323 |
270 aura::Window* root_window = GetRootWindow(display_id_); | 324 const gfx::Rect rect(screen_rotation_container_layer_->size()); |
271 gfx::Rect rect(root_window->layer()->size()); | |
272 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); | 325 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); |
273 copy_layer->SetBounds(rect); | 326 copy_layer->SetBounds(rect); |
274 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), | 327 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), |
275 rect.size()); | 328 rect.size()); |
276 old_layer_tree_owner_ = | 329 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); |
277 base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); | |
278 } | 330 } |
279 | 331 |
280 void ScreenRotationAnimator::AnimateRotation( | 332 void ScreenRotationAnimator::AnimateRotation( |
281 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 333 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
282 screen_rotation_state_ = ROTATING; | 334 screen_rotation_state_ = ROTATING; |
283 | 335 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation, |
284 aura::Window* root_window = GetRootWindow(display_id_); | 336 rotation_request->new_rotation); |
285 std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer( | |
286 new LayerCleanupObserver(weak_factory_.GetWeakPtr())); | |
287 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); | |
288 old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree"); | |
289 // Add the cloned layer tree in to the root, so it will be rendered. | |
290 root_window->layer()->Add(old_root_layer); | |
291 root_window->layer()->StackAtTop(old_root_layer); | |
292 | |
293 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); | |
294 | |
295 const int rotation_factor = GetRotationFactor( | |
296 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | |
297 | |
298 const int old_layer_initial_rotation_degrees = GetInitialDegrees( | 337 const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
299 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | 338 rotation_request->old_rotation, rotation_request->new_rotation); |
300 | |
301 const base::TimeDelta duration = | 339 const base::TimeDelta duration = |
302 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); | 340 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
303 | |
304 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; | 341 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; |
305 | 342 const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds(); |
306 Shell::Get()->display_manager()->SetDisplayRotation( | |
307 display_id_, rotation_request->new_rotation, rotation_request->source); | |
308 | |
309 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); | |
310 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, | 343 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, |
311 rotated_screen_bounds.height() / 2); | 344 rotated_screen_bounds.height() / 2); |
312 | 345 |
313 ui::Layer* screen_rotation_container_layer = | 346 ui::Layer* new_root_layer; |
314 root_window->GetChildById(kShellWindowId_ScreenRotationContainer) | 347 if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) { |
315 ->layer(); | 348 new_root_layer = new_layer_tree_owner_->root(); |
316 std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = | 349 // Add a black mask layer on top of |screen_rotation_container_layer_|. |
| 350 black_mask_layer_owner_ = CreateBlackMaskLayerOwner( |
| 351 gfx::Rect(screen_rotation_container_layer_->size())); |
| 352 AddLayerBelowWindowLayer(root_window_, new_root_layer, |
| 353 black_mask_layer_owner_->layer()); |
| 354 } else { |
| 355 new_root_layer = screen_rotation_container_layer_; |
| 356 } |
| 357 |
| 358 std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation = |
317 base::MakeUnique<ScreenRotationAnimation>( | 359 base::MakeUnique<ScreenRotationAnimation>( |
318 screen_rotation_container_layer, kRotationDegrees * rotation_factor, | 360 new_root_layer, kRotationDegrees * rotation_factor, |
319 0 /* end_degrees */, screen_rotation_container_layer->opacity(), | 361 0 /* end_degrees */, new_root_layer->opacity(), |
320 screen_rotation_container_layer->opacity() /* target_opacity */, | 362 new_root_layer->opacity() /* target_opacity */, pivot, duration, |
321 pivot, duration, tween_type); | 363 tween_type); |
322 | 364 |
323 ui::LayerAnimator* current_layer_animator = | 365 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator(); |
324 screen_rotation_container_layer->GetAnimator(); | 366 new_layer_animator->set_preemption_strategy( |
325 current_layer_animator->set_preemption_strategy( | |
326 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 367 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
327 std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = | 368 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence = |
328 base::MakeUnique<ui::LayerAnimationSequence>( | 369 base::MakeUnique<ui::LayerAnimationSequence>( |
329 std::move(current_layer_screen_rotation)); | 370 std::move(new_layer_screen_rotation)); |
330 current_layer_animator->StartAnimation( | |
331 current_layer_animation_sequence.release()); | |
332 | 371 |
| 372 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); |
| 373 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds(); |
333 // The old layer will also be transformed into the new orientation. We will | 374 // The old layer will also be transformed into the new orientation. We will |
334 // translate it so that the old layer's center point aligns with the new | 375 // translate it so that the old layer's center point aligns with the new |
335 // orientation's center point and use that center point as the pivot for the | 376 // orientation's center point and use that center point as the pivot for the |
336 // rotation animation. | 377 // rotation animation. |
337 gfx::Transform translate_transform; | 378 gfx::Transform translate_transform; |
338 translate_transform.Translate( | 379 translate_transform.Translate( |
339 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, | 380 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, |
340 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); | 381 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); |
341 old_root_layer->SetTransform(translate_transform); | 382 old_root_layer->SetTransform(translate_transform); |
342 | 383 |
343 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = | 384 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = |
344 base::MakeUnique<ScreenRotationAnimation>( | 385 base::MakeUnique<ScreenRotationAnimation>( |
345 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, | 386 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, |
346 (old_layer_initial_rotation_degrees - kRotationDegrees) * | 387 (old_layer_initial_rotation_degrees - kRotationDegrees) * |
347 rotation_factor, | 388 rotation_factor, |
348 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, | 389 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, |
349 tween_type); | 390 tween_type); |
350 | 391 |
351 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); | 392 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); |
352 old_layer_animator->set_preemption_strategy( | 393 old_layer_animator->set_preemption_strategy( |
353 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 394 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
354 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = | 395 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = |
355 base::MakeUnique<ui::LayerAnimationSequence>( | 396 base::MakeUnique<ui::LayerAnimationSequence>( |
356 std::move(old_layer_screen_rotation)); | 397 std::move(old_layer_screen_rotation)); |
357 // Add an observer so that the cloned layers can be cleaned up with the | 398 |
358 // animation completes/aborts. | |
359 old_layer_animation_sequence->AddObserver( | |
360 old_layer_cleanup_observer.release()); | |
361 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to | 399 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to |
362 // control the animation. | 400 // control the animation. |
363 if (disable_animation_timers_for_test_) | 401 if (disable_animation_timers_for_test_) { |
| 402 if (new_layer_tree_owner_) |
| 403 new_layer_animator->set_disable_timer_for_test(true); |
364 old_layer_animator->set_disable_timer_for_test(true); | 404 old_layer_animator->set_disable_timer_for_test(true); |
| 405 } |
365 old_layer_animation_sequence->SetAnimationMetricsReporter( | 406 old_layer_animation_sequence->SetAnimationMetricsReporter( |
366 metrics_reporter_.get()); | 407 metrics_reporter_.get()); |
| 408 |
| 409 // Add an observer so that the cloned/copied layers can be cleaned up with the |
| 410 // animation completes/aborts. |
| 411 ui::CallbackLayerAnimationObserver* observer = |
| 412 new ui::CallbackLayerAnimationObserver( |
| 413 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr())); |
| 414 if (new_layer_tree_owner_) |
| 415 new_layer_animator->AddObserver(observer); |
| 416 new_layer_animator->StartAnimation(new_layer_animation_sequence.release()); |
| 417 old_layer_animator->AddObserver(observer); |
367 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); | 418 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); |
368 | 419 observer->SetActive(); |
369 rotation_request.reset(); | |
370 } | 420 } |
371 | 421 |
372 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, | 422 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
373 display::Display::RotationSource source) { | 423 display::Display::RotationSource source) { |
374 if (GetCurrentScreenRotation(display_id_) == new_rotation) | 424 // |rotation_request_id_| is used to skip stale requests. Before the layer |
375 return; | 425 // CopyOutputResult callback called, there could have new rotation request. |
376 | 426 // Increases |rotation_request_id_| for each new request and in the callback, |
| 427 // we compare the |rotation_request.id| and |rotation_request_id_| to |
| 428 // determine the stale status. |
377 rotation_request_id_++; | 429 rotation_request_id_++; |
378 std::unique_ptr<ScreenRotationRequest> rotation_request = | 430 std::unique_ptr<ScreenRotationRequest> rotation_request = |
379 base::MakeUnique<ScreenRotationRequest>(rotation_request_id_, | 431 base::MakeUnique<ScreenRotationRequest>(rotation_request_id_, |
380 new_rotation, source); | 432 new_rotation, source); |
381 | |
382 switch (screen_rotation_state_) { | 433 switch (screen_rotation_state_) { |
383 case IDLE: | 434 case IDLE: |
384 case COPY_REQUESTED: | 435 case COPY_REQUESTED: |
385 StartRotationAnimation(std::move(rotation_request)); | 436 StartRotationAnimation(std::move(rotation_request)); |
386 break; | 437 break; |
387 case ROTATING: | 438 case ROTATING: |
388 last_pending_request_ = std::move(rotation_request); | 439 last_pending_request_ = std::move(rotation_request); |
389 // The pending request will be processed when the | 440 // The pending request will be processed when the |
390 // OnLayerAnimation(Ended|Aborted) methods should be called after | 441 // |AnimationEndedCallback()| should be called after |StopAnimating()|. |
391 // |StopAnimating()|. | |
392 StopAnimating(); | 442 StopAnimating(); |
393 break; | 443 break; |
394 } | 444 } |
395 } | 445 } |
396 | 446 |
397 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( | 447 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( |
398 ScreenRotationAnimatorObserver* observer) { | 448 ScreenRotationAnimatorObserver* observer) { |
399 screen_rotation_animator_observers_.AddObserver(observer); | 449 screen_rotation_animator_observers_.AddObserver(observer); |
400 } | 450 } |
401 | 451 |
402 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( | 452 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( |
403 ScreenRotationAnimatorObserver* observer) { | 453 ScreenRotationAnimatorObserver* observer) { |
404 screen_rotation_animator_observers_.RemoveObserver(observer); | 454 screen_rotation_animator_observers_.RemoveObserver(observer); |
405 } | 455 } |
406 | 456 |
407 void ScreenRotationAnimator::ProcessAnimationQueue() { | 457 void ScreenRotationAnimator::ProcessAnimationQueue() { |
408 screen_rotation_state_ = IDLE; | 458 screen_rotation_state_ = IDLE; |
| 459 if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_) |
| 460 root_window_->layer()->Remove(black_mask_layer_owner_->layer()); |
409 old_layer_tree_owner_.reset(); | 461 old_layer_tree_owner_.reset(); |
| 462 new_layer_tree_owner_.reset(); |
| 463 black_mask_layer_owner_.reset(); |
410 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { | 464 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { |
411 display::Display::Rotation new_rotation = | 465 StartRotationAnimation(std::move(last_pending_request_)); |
412 last_pending_request_->new_rotation; | |
413 display::Display::RotationSource source = last_pending_request_->source; | |
414 last_pending_request_.reset(); | |
415 Rotate(new_rotation, source); | |
416 return; | 466 return; |
417 } | 467 } |
418 | 468 |
| 469 // This is only used in test to notify animator observer. |
419 for (auto& observer : screen_rotation_animator_observers_) | 470 for (auto& observer : screen_rotation_animator_observers_) |
420 observer.OnScreenRotationAnimationFinished(this); | 471 observer.OnScreenRotationAnimationFinished(this); |
421 } | 472 } |
422 | 473 |
423 void ScreenRotationAnimator::set_disable_animation_timers_for_test( | |
424 bool disable_timers) { | |
425 disable_animation_timers_for_test_ = disable_timers; | |
426 } | |
427 | |
428 void ScreenRotationAnimator::StopAnimating() { | 474 void ScreenRotationAnimator::StopAnimating() { |
429 GetRootWindow(display_id_) | 475 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another |
430 ->GetChildById(kShellWindowId_ScreenRotationContainer) | 476 // the rotation request comes before the copy request finished. |
431 ->layer() | |
432 ->GetAnimator() | |
433 ->StopAnimating(); | |
434 if (old_layer_tree_owner_) | 477 if (old_layer_tree_owner_) |
435 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); | 478 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
| 479 if (new_layer_tree_owner_) |
| 480 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
| 481 if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_) |
| 482 root_window_->layer()->Remove(black_mask_layer_owner_->layer()); |
436 } | 483 } |
437 | 484 |
438 } // namespace ash | 485 } // namespace ash |
OLD | NEW |