blob: 9c6bf5f6a265e267233df974a15b4f00b9571f2f [file] [log] [blame]
bruthig37f9cad02015-03-12 22:28:501// 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 Cookb0bf8e82017-04-09 17:01:447#include "ash/ash_switches.h"
oshimae2818922015-07-28 01:18:528#include "ash/display/window_tree_host_manager.h"
wutao33576082017-04-14 18:51:109#include "ash/public/cpp/shell_window_ids.h"
bruthig37f9cad02015-03-12 22:28:5010#include "ash/rotator/screen_rotation_animation.h"
wutao6ddafa32017-03-18 03:10:0811#include "ash/rotator/screen_rotation_animator_observer.h"
bruthig37f9cad02015-03-12 22:28:5012#include "ash/shell.h"
wutao6d394112017-04-20 02:17:3513#include "ash/utility/transformer_util.h"
bruthig37f9cad02015-03-12 22:28:5014#include "base/command_line.h"
ratsunnybd5087e2016-12-17 05:19:2515#include "base/memory/ptr_util.h"
wutao3f08f812017-03-25 03:06:3316#include "base/metrics/histogram_macros.h"
bruthig37f9cad02015-03-12 22:28:5017#include "base/time/time.h"
wutao2c0ca182017-04-06 22:40:5418#include "cc/output/copy_output_request.h"
19#include "cc/output/copy_output_result.h"
bruthig37f9cad02015-03-12 22:28:5020#include "ui/aura/window.h"
wutao6d394112017-04-20 02:17:3521#include "ui/compositor/callback_layer_animation_observer.h"
bruthig37f9cad02015-03-12 22:28:5022#include "ui/compositor/layer.h"
wutao3f08f812017-03-25 03:06:3323#include "ui/compositor/layer_animation_element.h"
bruthig37f9cad02015-03-12 22:28:5024#include "ui/compositor/layer_animation_sequence.h"
25#include "ui/compositor/layer_animator.h"
26#include "ui/compositor/layer_owner.h"
27#include "ui/compositor/layer_tree_owner.h"
oshimaf84b0da722016-04-27 19:47:1928#include "ui/display/display.h"
rjkroege72f8154f2016-10-29 00:49:0229#include "ui/display/manager/display_manager.h"
rjkroege259c01882016-08-30 19:29:5030#include "ui/display/manager/managed_display_info.h"
bruthig37f9cad02015-03-12 22:28:5031#include "ui/gfx/animation/tween.h"
bruthig37f9cad02015-03-12 22:28:5032#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
39namespace ash {
40
41namespace {
42
bruthigaff7d0f2015-09-01 17:46:5543// The number of degrees that the rotation animations animate through.
44const int kRotationDegrees = 20;
bruthig37f9cad02015-03-12 22:28:5045
bruthig2ce3f232015-04-02 15:21:3546// The time it takes for the rotation animations to run.
bruthig37f9cad02015-03-12 22:28:5047const int kRotationDurationInMs = 250;
48
wutao6ddafa32017-03-18 03:10:0849// The rotation factors.
50const int kCounterClockWiseRotationFactor = 1;
51const int kClockWiseRotationFactor = -1;
52
wutao6ddafa32017-03-18 03:10:0853display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
skycb4be5b2017-04-06 17:52:4554 return Shell::Get()
bruthig37f9cad02015-03-12 22:28:5055 ->display_manager()
56 ->GetDisplayInfo(display_id)
jonrossd01de7f2015-04-23 19:52:0057 .GetActiveRotation();
bruthig37f9cad02015-03-12 22:28:5058}
59
wutao6ddafa32017-03-18 03:10:0860bool IsDisplayIdValid(int64_t display_id) {
skycb4be5b2017-04-06 17:52:4561 return Shell::Get()->display_manager()->IsDisplayIdValid(display_id);
wutao6ddafa32017-03-18 03:10:0862}
63
64// 180 degree rotations should animate clock-wise.
65int GetRotationFactor(display::Display::Rotation initial_rotation,
66 display::Display::Rotation new_rotation) {
67 return (initial_rotation + 3) % 4 == new_rotation
68 ? kCounterClockWiseRotationFactor
69 : kClockWiseRotationFactor;
70}
71
72aura::Window* GetRootWindow(int64_t display_id) {
skycb4be5b2017-04-06 17:52:4573 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId(
74 display_id);
wutao6ddafa32017-03-18 03:10:0875}
76
wutao6d394112017-04-20 02:17:3577aura::Window* GetScreenRotationContainer(aura::Window* root_window) {
78 return root_window->GetChildById(kShellWindowId_ScreenRotationContainer);
79}
80
bruthig37f9cad02015-03-12 22:28:5081// Returns true if the rotation between |initial_rotation| and |new_rotation| is
82// 180 degrees.
oshimaf84b0da722016-04-27 19:47:1983bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
84 display::Display::Rotation new_rotation) {
bruthig37f9cad02015-03-12 22:28:5085 return (initial_rotation + 2) % 4 == new_rotation;
86}
87
wutao6ddafa32017-03-18 03:10:0888// Returns the initial degrees the old layer animation to begin with.
89int GetInitialDegrees(display::Display::Rotation initial_rotation,
90 display::Display::Rotation new_rotation) {
91 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
92}
93
wutao6d394112017-04-20 02:17:3594void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
95 // Add the cloned/copied layer tree into the root, so it will be rendered.
96 root_window->layer()->Add(layer);
97 root_window->layer()->StackAtTop(layer);
bruthig37f9cad02015-03-12 22:28:5098}
99
wutao6d394112017-04-20 02:17:35100void AddLayerBelowWindowLayer(aura::Window* root_window,
101 ui::Layer* top_layer,
102 ui::Layer* layer) {
103 // Add the cloned/copied layer tree into the root, so it will be rendered.
104 root_window->layer()->Add(layer);
105 root_window->layer()->StackBelow(layer, top_layer);
bruthig37f9cad02015-03-12 22:28:50106}
107
wutao6d394112017-04-20 02:17:35108// The Callback will be invoked when all animation sequences have
109// finished. |observer| will be destroyed after invoking the Callback if it
110// returns true.
111bool AnimationEndedCallback(
112 base::WeakPtr<ScreenRotationAnimator> animator,
113 const ui::CallbackLayerAnimationObserver& observer) {
114 if (animator)
115 animator->ProcessAnimationQueue();
116 return true;
bruthig37f9cad02015-03-12 22:28:50117}
118
wutao6d394112017-04-20 02:17:35119// Creates a Transform for the old layer in screen rotation animation.
120gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
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;
bruthig37f9cad02015-03-12 22:28:50128}
129
wutao6d394112017-04-20 02:17:35130// The |request_id| changed since last copy request, which means a
131// new rotation stated, we need to ignore this copy result.
132bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) {
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.
143bool 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|.
148std::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;
bruthig37f9cad02015-03-12 22:28:50158}
159
wutao3f08f812017-03-25 03:06:33160class ScreenRotationAnimationMetricsReporter
161 : public ui::AnimationMetricsReporter {
162 public:
163 ScreenRotationAnimationMetricsReporter() {}
164 ~ScreenRotationAnimationMetricsReporter() override {}
165
166 void Report(int value) override {
167 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
168 }
169
170 private:
171 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
172};
173
wutao6ddafa32017-03-18 03:10:08174} // namespace
jonross7351feb2015-04-23 22:10:26175
wutao6ddafa32017-03-18 03:10:08176ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
177 : display_id_(display_id),
wutao4a485532017-04-11 00:04:28178 screen_rotation_state_(IDLE),
wutao88733df2017-04-13 19:39:06179 rotation_request_id_(0),
wutao3f08f812017-03-25 03:06:33180 metrics_reporter_(
181 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
wutao6ddafa32017-03-18 03:10:08182 disable_animation_timers_for_test_(false),
wutao6d394112017-04-20 02:17:35183 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()),
wutao6ddafa32017-03-18 03:10:08189 weak_factory_(this) {}
190
wutao3f08f812017-03-25 03:06:33191ScreenRotationAnimator::~ScreenRotationAnimator() {
wutao6d394112017-04-20 02:17:35192 // To prevent a call to |AnimationEndedCallback()| from calling a method on
193 // the |animator_|.
wutao3f08f812017-03-25 03:06:33194 weak_factory_.InvalidateWeakPtrs();
195
196 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
197 // order to make sure |metrics_reporter_| outlives the attached animation
198 // sequence.
199 old_layer_tree_owner_.reset();
200 metrics_reporter_.reset();
201}
wutao6ddafa32017-03-18 03:10:08202
wutao2c0ca182017-04-06 22:40:54203void ScreenRotationAnimator::StartRotationAnimation(
204 std::unique_ptr<ScreenRotationRequest> rotation_request) {
wutao6d394112017-04-20 02:17:35205 const display::Display::Rotation current_rotation =
206 GetCurrentScreenRotation(display_id_);
207 if (current_rotation == rotation_request->new_rotation) {
208 // We need to call |ProcessAnimationQueue()| to prepare for next rotation
209 // request.
wutao2c0ca182017-04-06 22:40:54210 ProcessAnimationQueue();
wutao2c0ca182017-04-06 22:40:54211 return;
212 }
213
wutao6d394112017-04-20 02:17:35214 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;
221 } else {
222 StartSlowAnimation(std::move(rotation_request));
223 }
224}
225
226void ScreenRotationAnimator::StartSlowAnimation(
227 std::unique_ptr<ScreenRotationRequest> rotation_request) {
228 CreateOldLayerTreeForSlowAnimation();
229 SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
230 rotation_request->source);
wutao2c0ca182017-04-06 22:40:54231 AnimateRotation(std::move(rotation_request));
232}
233
wutao6d394112017-04-20 02:17:35234void 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));
wutao2c0ca182017-04-06 22:40:54245}
246
wutao6d394112017-04-20 02:17:35247void 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));
253}
254
255ScreenRotationAnimator::CopyCallback
256ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
257 std::unique_ptr<ScreenRotationRequest> rotation_request) {
258 return base::Bind(&ScreenRotationAnimator::
259 OnScreenRotationContainerLayerCopiedBeforeRotation,
260 weak_factory_.GetWeakPtr(),
261 base::Passed(&rotation_request));
262}
263
264ScreenRotationAnimator::CopyCallback
265ScreenRotationAnimator::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
273void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
274 std::unique_ptr<ScreenRotationRequest> rotation_request,
275 std::unique_ptr<cc::CopyOutputResult> result) {
276 if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
277 return;
278 if (AbortRotation(display_id_, result.get())) {
279 ProcessAnimationQueue();
280 return;
281 }
282
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
293void 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());
306 AnimateRotation(std::move(rotation_request));
307}
308
309void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() {
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());
315}
316
317std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
wutao2c0ca182017-04-06 22:40:54318 std::unique_ptr<cc::CopyOutputResult> result) {
319 cc::TextureMailbox texture_mailbox;
320 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
321 result->TakeTexture(&texture_mailbox, &release_callback);
322 DCHECK(texture_mailbox.IsTexture());
323
wutao6d394112017-04-20 02:17:35324 const gfx::Rect rect(screen_rotation_container_layer_->size());
wutao2c0ca182017-04-06 22:40:54325 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
326 copy_layer->SetBounds(rect);
327 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
328 rect.size());
wutao6d394112017-04-20 02:17:35329 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
wutao2c0ca182017-04-06 22:40:54330}
331
wutao6ddafa32017-03-18 03:10:08332void ScreenRotationAnimator::AnimateRotation(
333 std::unique_ptr<ScreenRotationRequest> rotation_request) {
wutao4a485532017-04-11 00:04:28334 screen_rotation_state_ = ROTATING;
wutao6d394112017-04-20 02:17:35335 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
336 rotation_request->new_rotation);
wutao6ddafa32017-03-18 03:10:08337 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
wutao6d394112017-04-20 02:17:35338 rotation_request->old_rotation, rotation_request->new_rotation);
bruthigaff7d0f2015-09-01 17:46:55339 const base::TimeDelta duration =
340 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
bruthigaff7d0f2015-09-01 17:46:55341 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
wutao6d394112017-04-20 02:17:35342 const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds();
bruthig37f9cad02015-03-12 22:28:50343 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
344 rotated_screen_bounds.height() / 2);
345
wutao6d394112017-04-20 02:17:35346 ui::Layer* new_root_layer;
347 if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) {
348 new_root_layer = new_layer_tree_owner_->root();
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 =
wutao33576082017-04-14 18:51:10359 base::MakeUnique<ScreenRotationAnimation>(
wutao6d394112017-04-20 02:17:35360 new_root_layer, kRotationDegrees * rotation_factor,
361 0 /* end_degrees */, new_root_layer->opacity(),
362 new_root_layer->opacity() /* target_opacity */, pivot, duration,
363 tween_type);
bruthig37f9cad02015-03-12 22:28:50364
wutao6d394112017-04-20 02:17:35365 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
366 new_layer_animator->set_preemption_strategy(
wutao33576082017-04-14 18:51:10367 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
wutao6d394112017-04-20 02:17:35368 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
wutao33576082017-04-14 18:51:10369 base::MakeUnique<ui::LayerAnimationSequence>(
wutao6d394112017-04-20 02:17:35370 std::move(new_layer_screen_rotation));
bruthig37f9cad02015-03-12 22:28:50371
wutao6d394112017-04-20 02:17:35372 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
373 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
bruthig37f9cad02015-03-12 22:28:50374 // The old layer will also be transformed into the new orientation. We will
375 // translate it so that the old layer's center point aligns with the new
376 // orientation's center point and use that center point as the pivot for the
377 // rotation animation.
378 gfx::Transform translate_transform;
379 translate_transform.Translate(
380 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
381 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
wutao6ddafa32017-03-18 03:10:08382 old_root_layer->SetTransform(translate_transform);
bruthig37f9cad02015-03-12 22:28:50383
wutao33576082017-04-14 18:51:10384 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
ratsunnybd5087e2016-12-17 05:19:25385 base::MakeUnique<ScreenRotationAnimation>(
wutao6ddafa32017-03-18 03:10:08386 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
bruthigaff7d0f2015-09-01 17:46:55387 (old_layer_initial_rotation_degrees - kRotationDegrees) *
388 rotation_factor,
wutao6ddafa32017-03-18 03:10:08389 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
390 tween_type);
bruthig37f9cad02015-03-12 22:28:50391
wutao33576082017-04-14 18:51:10392 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
393 old_layer_animator->set_preemption_strategy(
bruthig37f9cad02015-03-12 22:28:50394 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
wutao33576082017-04-14 18:51:10395 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
396 base::MakeUnique<ui::LayerAnimationSequence>(
397 std::move(old_layer_screen_rotation));
wutao6d394112017-04-20 02:17:35398
wutao6ddafa32017-03-18 03:10:08399 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
400 // control the animation.
wutao6d394112017-04-20 02:17:35401 if (disable_animation_timers_for_test_) {
402 if (new_layer_tree_owner_)
403 new_layer_animator->set_disable_timer_for_test(true);
wutao33576082017-04-14 18:51:10404 old_layer_animator->set_disable_timer_for_test(true);
wutao6d394112017-04-20 02:17:35405 }
wutao33576082017-04-14 18:51:10406 old_layer_animation_sequence->SetAnimationMetricsReporter(
407 metrics_reporter_.get());
wutao33576082017-04-14 18:51:10408
wutao6d394112017-04-20 02:17:35409 // 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);
418 old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
419 observer->SetActive();
bruthigf57a7bba2015-04-24 21:19:31420}
421
oshimaf84b0da722016-04-27 19:47:19422void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
423 display::Display::RotationSource source) {
wutao6d394112017-04-20 02:17:35424 // |rotation_request_id_| is used to skip stale requests. Before the layer
425 // CopyOutputResult callback called, there could have new rotation request.
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.
wutao88733df2017-04-13 19:39:06429 rotation_request_id_++;
wutao6ddafa32017-03-18 03:10:08430 std::unique_ptr<ScreenRotationRequest> rotation_request =
wutao88733df2017-04-13 19:39:06431 base::MakeUnique<ScreenRotationRequest>(rotation_request_id_,
432 new_rotation, source);
wutao4a485532017-04-11 00:04:28433 switch (screen_rotation_state_) {
434 case IDLE:
wutao88733df2017-04-13 19:39:06435 case COPY_REQUESTED:
wutao4a485532017-04-11 00:04:28436 StartRotationAnimation(std::move(rotation_request));
437 break;
438 case ROTATING:
439 last_pending_request_ = std::move(rotation_request);
440 // The pending request will be processed when the
wutao6d394112017-04-20 02:17:35441 // |AnimationEndedCallback()| should be called after |StopAnimating()|.
wutao4a485532017-04-11 00:04:28442 StopAnimating();
443 break;
wutao6ddafa32017-03-18 03:10:08444 }
445}
446
447void ScreenRotationAnimator::AddScreenRotationAnimatorObserver(
448 ScreenRotationAnimatorObserver* observer) {
449 screen_rotation_animator_observers_.AddObserver(observer);
450}
451
452void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
453 ScreenRotationAnimatorObserver* observer) {
454 screen_rotation_animator_observers_.RemoveObserver(observer);
455}
456
wutao6ddafa32017-03-18 03:10:08457void ScreenRotationAnimator::ProcessAnimationQueue() {
wutao4a485532017-04-11 00:04:28458 screen_rotation_state_ = IDLE;
wutao6d394112017-04-20 02:17:35459 if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
460 root_window_->layer()->Remove(black_mask_layer_owner_->layer());
wutao6ddafa32017-03-18 03:10:08461 old_layer_tree_owner_.reset();
wutao6d394112017-04-20 02:17:35462 new_layer_tree_owner_.reset();
463 black_mask_layer_owner_.reset();
wutao6ddafa32017-03-18 03:10:08464 if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
wutao6d394112017-04-20 02:17:35465 StartRotationAnimation(std::move(last_pending_request_));
wutao6ddafa32017-03-18 03:10:08466 return;
467 }
468
wutao6d394112017-04-20 02:17:35469 // This is only used in test to notify animator observer.
wutao6ddafa32017-03-18 03:10:08470 for (auto& observer : screen_rotation_animator_observers_)
471 observer.OnScreenRotationAnimationFinished(this);
472}
473
wutao6ddafa32017-03-18 03:10:08474void ScreenRotationAnimator::StopAnimating() {
wutao6d394112017-04-20 02:17:35475 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
476 // the rotation request comes before the copy request finished.
wutao33576082017-04-14 18:51:10477 if (old_layer_tree_owner_)
478 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
wutao6d394112017-04-20 02:17:35479 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());
bruthig37f9cad02015-03-12 22:28:50483}
484
485} // namespace ash