Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(301)

Side by Side Diff: ash/rotator/screen_rotation_animator.cc

Issue 2790583004: Add second copy request after screen rotation to flatten the layers in animation. (Closed)
Patch Set: Move some functions to ash/utility/transformer_util. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/common/ash_switches.h" 7 #include "ash/common/ash_switches.h"
12 #include "ash/display/window_tree_host_manager.h" 8 #include "ash/display/window_tree_host_manager.h"
9 #include "ash/public/cpp/shell_window_ids.h"
13 #include "ash/rotator/screen_rotation_animation.h" 10 #include "ash/rotator/screen_rotation_animation.h"
14 #include "ash/rotator/screen_rotation_animator_observer.h" 11 #include "ash/rotator/screen_rotation_animator_observer.h"
15 #include "ash/shell.h" 12 #include "ash/shell.h"
13 #include "ash/utility/transformer_util.h"
16 #include "base/command_line.h" 14 #include "base/command_line.h"
17 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
18 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
19 #include "base/time/time.h" 17 #include "base/time/time.h"
20 #include "cc/output/copy_output_request.h" 18 #include "cc/output/copy_output_request.h"
21 #include "cc/output/copy_output_result.h" 19 #include "cc/output/copy_output_result.h"
22 #include "ui/aura/window.h" 20 #include "ui/aura/window.h"
21 #include "ui/compositor/callback_layer_animation_observer.h"
23 #include "ui/compositor/layer.h" 22 #include "ui/compositor/layer.h"
24 #include "ui/compositor/layer_animation_element.h" 23 #include "ui/compositor/layer_animation_element.h"
25 #include "ui/compositor/layer_animation_observer.h"
26 #include "ui/compositor/layer_animation_sequence.h" 24 #include "ui/compositor/layer_animation_sequence.h"
27 #include "ui/compositor/layer_animator.h" 25 #include "ui/compositor/layer_animator.h"
28 #include "ui/compositor/layer_owner.h" 26 #include "ui/compositor/layer_owner.h"
29 #include "ui/compositor/layer_tree_owner.h" 27 #include "ui/compositor/layer_tree_owner.h"
30 #include "ui/display/display.h" 28 #include "ui/display/display.h"
31 #include "ui/display/manager/display_manager.h" 29 #include "ui/display/manager/display_manager.h"
32 #include "ui/display/manager/managed_display_info.h" 30 #include "ui/display/manager/managed_display_info.h"
33 #include "ui/gfx/animation/tween.h" 31 #include "ui/gfx/animation/tween.h"
34 #include "ui/gfx/geometry/point.h" 32 #include "ui/gfx/geometry/point.h"
35 #include "ui/gfx/geometry/rect.h" 33 #include "ui/gfx/geometry/rect.h"
36 #include "ui/gfx/geometry/rect_f.h" 34 #include "ui/gfx/geometry/rect_f.h"
37 #include "ui/gfx/transform.h" 35 #include "ui/gfx/transform.h"
38 #include "ui/gfx/transform_util.h" 36 #include "ui/gfx/transform_util.h"
39 #include "ui/wm/core/window_util.h" 37 #include "ui/wm/core/window_util.h"
40 38
41 namespace ash { 39 namespace ash {
42 40
43 namespace { 41 namespace {
44 42
45 // The number of degrees that the rotation animations animate through. 43 // The number of degrees that the rotation animations animate through.
46 const int kRotationDegrees = 20; 44 const int kRotationDegrees = 20;
47 45
48 // The time it takes for the rotation animations to run. 46 // The time it takes for the rotation animations to run.
49 const int kRotationDurationInMs = 250; 47 const int kRotationDurationInMs = 250;
50 48
51 // The rotation factors. 49 // The rotation factors.
52 const int kCounterClockWiseRotationFactor = 1; 50 const int kCounterClockWiseRotationFactor = 1;
53 const int kClockWiseRotationFactor = -1; 51 const int kClockWiseRotationFactor = -1;
54 52
55 // Aborts the active animations of the layer, and recurses upon its child
56 // layers.
57 void AbortAnimations(ui::Layer* layer) {
58 for (ui::Layer* child_layer : layer->children())
59 AbortAnimations(child_layer);
60 layer->GetAnimator()->AbortAllAnimations();
61 }
62
63 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { 53 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
64 return Shell::Get() 54 return Shell::Get()
65 ->display_manager() 55 ->display_manager()
66 ->GetDisplayInfo(display_id) 56 ->GetDisplayInfo(display_id)
67 .GetActiveRotation(); 57 .GetActiveRotation();
68 } 58 }
69 59
70 bool IsDisplayIdValid(int64_t display_id) { 60 bool IsDisplayIdValid(int64_t display_id) {
71 return Shell::Get()->display_manager()->IsDisplayIdValid(display_id); 61 return Shell::Get()->display_manager()->IsDisplayIdValid(display_id);
72 } 62 }
73 63
74 // 180 degree rotations should animate clock-wise. 64 // 180 degree rotations should animate clock-wise.
75 int GetRotationFactor(display::Display::Rotation initial_rotation, 65 int GetRotationFactor(display::Display::Rotation initial_rotation,
76 display::Display::Rotation new_rotation) { 66 display::Display::Rotation new_rotation) {
77 return (initial_rotation + 3) % 4 == new_rotation 67 return (initial_rotation + 3) % 4 == new_rotation
78 ? kCounterClockWiseRotationFactor 68 ? kCounterClockWiseRotationFactor
79 : kClockWiseRotationFactor; 69 : kClockWiseRotationFactor;
80 } 70 }
81 71
82 aura::Window* GetRootWindow(int64_t display_id) { 72 aura::Window* GetRootWindow(int64_t display_id) {
83 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( 73 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId(
84 display_id); 74 display_id);
85 } 75 }
86 76
77 aura::Window* GetScreenRotationContainer(int64_t display_id) {
78 return GetRootWindow(display_id)
79 ->GetChildById(kShellWindowId_ScreenRotationContainer);
80 }
81
87 // Returns true if the rotation between |initial_rotation| and |new_rotation| is 82 // Returns true if the rotation between |initial_rotation| and |new_rotation| is
88 // 180 degrees. 83 // 180 degrees.
89 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, 84 bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
90 display::Display::Rotation new_rotation) { 85 display::Display::Rotation new_rotation) {
91 return (initial_rotation + 2) % 4 == new_rotation; 86 return (initial_rotation + 2) % 4 == new_rotation;
92 } 87 }
93 88
94 // Returns the initial degrees the old layer animation to begin with. 89 // Returns the initial degrees the old layer animation to begin with.
95 int GetInitialDegrees(display::Display::Rotation initial_rotation, 90 int GetInitialDegrees(display::Display::Rotation initial_rotation,
96 display::Display::Rotation new_rotation) { 91 display::Display::Rotation new_rotation) {
97 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); 92 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
98 } 93 }
99 94
100 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner 95 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
101 // when notified that a layer animation has ended or was aborted. 96 // Add the cloned/copied layer tree into the root, so it will be rendered.
102 class LayerCleanupObserver : public ui::LayerAnimationObserver { 97 root_window->layer()->Add(layer);
103 public: 98 root_window->layer()->StackAtTop(layer);
104 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_|
105 // instance and the |animator_| isn't detaching itself as an observer when
106 // being destroyed. However, ideally, when |animator_| is destroying,
107 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and
108 // delete |this| before |animator_| deleted.
109 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator);
110 ~LayerCleanupObserver() override;
111
112 // ui::LayerAnimationObserver:
113 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
114 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
115 void OnLayerAnimationScheduled(
116 ui::LayerAnimationSequence* sequence) override {}
117
118 protected:
119 // ui::LayerAnimationObserver:
120 bool RequiresNotificationWhenAnimatorDestroyed() const override {
121 return true;
122 }
123 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override;
124 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override;
125
126 private:
127 base::WeakPtr<ScreenRotationAnimator> animator_;
128
129 // The LayerAnimationSequence that |this| has been attached to. Defaults to
130 // nullptr.
131 ui::LayerAnimationSequence* sequence_;
132
133 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver);
134 };
135
136 LayerCleanupObserver::LayerCleanupObserver(
137 base::WeakPtr<ScreenRotationAnimator> animator)
138 : animator_(animator), sequence_(nullptr) {}
139
140 LayerCleanupObserver::~LayerCleanupObserver() {
141 // We must eplicitly detach from |sequence_| because we return true from
142 // RequiresNotificationWhenAnimatorDestroyed.
143 if (sequence_)
144 sequence_->RemoveObserver(this);
145 } 99 }
146 100
147 void LayerCleanupObserver::OnLayerAnimationEnded( 101 // The Callback will be invoked when all animation sequences have
148 ui::LayerAnimationSequence* sequence) { 102 // finished. |observer| will be destroyed after invoking the Callback if it
149 if (animator_) 103 // returns true.
150 animator_->ProcessAnimationQueue(); 104 bool AnimationEndedCallback(
151 105 base::WeakPtr<ScreenRotationAnimator> animator,
152 delete this; 106 const ui::CallbackLayerAnimationObserver& observer) {
107 if (animator)
108 animator->ProcessAnimationQueue();
109 return true;
153 } 110 }
154 111
155 void LayerCleanupObserver::OnLayerAnimationAborted( 112 // Creates a Transform for the old layer in screen rotation animation.
156 ui::LayerAnimationSequence* sequence) { 113 gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
157 if (animator_) 114 display::Display::Rotation new_rotation,
158 animator_->ProcessAnimationQueue(); 115 display::Display::Rotation old_rotation,
159 116 const display::Display& display) {
160 delete this; 117 gfx::Transform inverse;
161 } 118 CHECK(CreateRotationTransform(old_rotation, new_rotation, display)
162 119 .GetInverse(&inverse));
163 void LayerCleanupObserver::OnAttachedToSequence( 120 return inverse;
164 ui::LayerAnimationSequence* sequence) {
165 sequence_ = sequence;
166 }
167
168 void LayerCleanupObserver::OnDetachedFromSequence(
169 ui::LayerAnimationSequence* sequence) {
170 DCHECK_EQ(sequence, sequence_);
171 sequence_ = nullptr;
172 } 121 }
173 122
174 class ScreenRotationAnimationMetricsReporter 123 class ScreenRotationAnimationMetricsReporter
175 : public ui::AnimationMetricsReporter { 124 : public ui::AnimationMetricsReporter {
176 public: 125 public:
177 ScreenRotationAnimationMetricsReporter() {} 126 ScreenRotationAnimationMetricsReporter() {}
178 ~ScreenRotationAnimationMetricsReporter() override {} 127 ~ScreenRotationAnimationMetricsReporter() override {}
179 128
180 void Report(int value) override { 129 void Report(int value) override {
181 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); 130 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
182 } 131 }
183 132
184 private: 133 private:
185 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); 134 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
186 }; 135 };
187 136
188 } // namespace 137 } // namespace
189 138
190 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) 139 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
191 : display_id_(display_id), 140 : display_id_(display_id),
192 is_rotating_(false), 141 is_rotating_(false),
193 metrics_reporter_( 142 metrics_reporter_(
194 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), 143 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
195 disable_animation_timers_for_test_(false), 144 disable_animation_timers_for_test_(false),
145 has_switch_ash_enable_smooth_screen_rotation_(false),
146 screen_rotation_container_layer_(
147 GetScreenRotationContainer(display_id_)->layer()),
148 root_window_(GetRootWindow(display_id_)),
196 weak_factory_(this) {} 149 weak_factory_(this) {}
197 150
198 ScreenRotationAnimator::~ScreenRotationAnimator() { 151 ScreenRotationAnimator::~ScreenRotationAnimator() {
199 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from 152 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from
200 // calling a method on the |animator_|. 153 // calling a method on the |animator_|.
201 weak_factory_.InvalidateWeakPtrs(); 154 weak_factory_.InvalidateWeakPtrs();
202 155
203 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in 156 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
204 // order to make sure |metrics_reporter_| outlives the attached animation 157 // order to make sure |metrics_reporter_| outlives the attached animation
205 // sequence. 158 // sequence.
206 old_layer_tree_owner_.reset(); 159 old_layer_tree_owner_.reset();
207 metrics_reporter_.reset(); 160 metrics_reporter_.reset();
208 } 161 }
209 162
210 void ScreenRotationAnimator::StartRotationAnimation( 163 void ScreenRotationAnimator::StartRotationAnimation(
211 std::unique_ptr<ScreenRotationRequest> rotation_request) { 164 std::unique_ptr<ScreenRotationRequest> rotation_request) {
212 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 165 if (has_switch_ash_enable_smooth_screen_rotation_) {
213 switches::kAshEnableSmoothScreenRotation)) { 166 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
214 RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request)); 167 cc::CopyOutputRequest::CreateRequest(
168 CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request)));
169 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
215 } else { 170 } else {
216 CreateOldLayerTree(); 171 StartSlowAnimation(std::move(rotation_request));
217 AnimateRotation(std::move(rotation_request));
218 } 172 }
219 } 173 }
220 174
221 void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation( 175 void ScreenRotationAnimator::StartSlowAnimation(
222 std::unique_ptr<ScreenRotationRequest> rotation_request) { 176 std::unique_ptr<ScreenRotationRequest> rotation_request) {
223 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = 177 CreateOldLayerTree();
224 cc::CopyOutputRequest::CreateRequest( 178 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation,
225 CreateAfterCopyCallback(std::move(rotation_request))); 179 rotation_request->source);
226 ui::Layer* layer = GetRootWindow(display_id_)->layer(); 180 AnimateRotation(std::move(rotation_request));
227 copy_output_request->set_area(gfx::Rect(layer->size())); 181 }
228 layer->RequestCopyOfOutput(std::move(copy_output_request)); 182
183 void ScreenRotationAnimator::SetRotation(
184 display::Display::Rotation new_rotation,
185 display::Display::Rotation old_rotation,
186 display::Display::RotationSource source) {
187 Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation,
188 source);
189 const display::Display display =
190 Shell::Get()->display_manager()->GetDisplayForId(display_id_);
191 old_layer_tree_owner_->root()->SetTransform(
192 CreateScreenRotationOldLayerTransformForDisplay(new_rotation,
193 old_rotation, display));
194 }
195
196 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
197 std::unique_ptr<cc::CopyOutputRequest> copy_output_request) {
198 copy_output_request->set_area(
199 gfx::Rect(screen_rotation_container_layer_->size()));
200 screen_rotation_container_layer_->RequestCopyOfOutput(
201 std::move(copy_output_request));
229 } 202 }
230 203
231 ScreenRotationAnimator::CopyCallback 204 ScreenRotationAnimator::CopyCallback
232 ScreenRotationAnimator::CreateAfterCopyCallback( 205 ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
233 std::unique_ptr<ScreenRotationRequest> rotation_request) { 206 std::unique_ptr<ScreenRotationRequest> rotation_request) {
234 return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, 207 return base::Bind(&ScreenRotationAnimator::
208 OnScreenRotationContainerLayerCopiedBeforeRotation,
235 weak_factory_.GetWeakPtr(), 209 weak_factory_.GetWeakPtr(),
236 base::Passed(&rotation_request)); 210 base::Passed(&rotation_request));
237 } 211 }
238 212
239 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( 213 ScreenRotationAnimator::CopyCallback
214 ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
215 std::unique_ptr<ScreenRotationRequest> rotation_request) {
216 return base::Bind(&ScreenRotationAnimator::
217 OnScreenRotationContainerLayerCopiedAfterRotation,
218 weak_factory_.GetWeakPtr(),
219 base::Passed(&rotation_request));
220 }
221
222 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
240 std::unique_ptr<ScreenRotationRequest> rotation_request, 223 std::unique_ptr<ScreenRotationRequest> rotation_request,
241 std::unique_ptr<cc::CopyOutputResult> result) { 224 std::unique_ptr<cc::CopyOutputResult> result) {
242 // If display was removed, should abort rotation. 225 // In the following cases, abort rotation:
243 if (!IsDisplayIdValid(display_id_)) { 226 // 1) if the display was removed,
227 // 2) the copy request has been canceled or failed. It would fail if,
228 // for examples: a) The layer is removed from the compositor and destroye
229 // before committing the request to the compositor. b) The compositor is
230 // shutdown.
231 if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) {
244 ProcessAnimationQueue(); 232 ProcessAnimationQueue();
233 rotation_request.reset();
245 return; 234 return;
246 } 235 }
247 236
248 // Fall back to recreate layers solution when the copy request has been 237 old_layer_tree_owner_ = CopyLayerTree(std::move(result));
249 // canceled or failed. It would fail if, for examples: a) The layer is removed 238 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation,
250 // from the compositor and destroyed before committing the request to the 239 rotation_request->source);
251 // compositor. b) The compositor is shutdown. 240 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
252 if (result->IsEmpty()) 241 cc::CopyOutputRequest::CreateRequest(
253 CreateOldLayerTree(); 242 CreateAfterCopyCallbackAfterRotation(std::move(rotation_request)));
254 else 243 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
255 CopyOldLayerTree(std::move(result)); 244 }
245
246 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
247 std::unique_ptr<ScreenRotationRequest> rotation_request,
248 std::unique_ptr<cc::CopyOutputResult> result) {
249 // In the following cases, abort rotation:
250 // 1) if the display was removed,
251 // 2) the copy request has been canceled or failed. It would fail if,
252 // for examples: a) The layer is removed from the compositor and destroye
253 // before committing the request to the compositor. b) The compositor is
254 // shutdown.
255 if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) {
256 ProcessAnimationQueue();
257 rotation_request.reset();
258 return;
259 }
260
261 new_layer_tree_owner_ = CopyLayerTree(std::move(result));
256 AnimateRotation(std::move(rotation_request)); 262 AnimateRotation(std::move(rotation_request));
257 } 263 }
258 264
259 void ScreenRotationAnimator::CreateOldLayerTree() { 265 void ScreenRotationAnimator::CreateOldLayerTree() {
260 old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_)); 266 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
267 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
261 } 268 }
262 269
263 void ScreenRotationAnimator::CopyOldLayerTree( 270 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
264 std::unique_ptr<cc::CopyOutputResult> result) { 271 std::unique_ptr<cc::CopyOutputResult> result) {
265 cc::TextureMailbox texture_mailbox; 272 cc::TextureMailbox texture_mailbox;
266 std::unique_ptr<cc::SingleReleaseCallback> release_callback; 273 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
267 result->TakeTexture(&texture_mailbox, &release_callback); 274 result->TakeTexture(&texture_mailbox, &release_callback);
268 DCHECK(texture_mailbox.IsTexture()); 275 DCHECK(texture_mailbox.IsTexture());
269 276
270 aura::Window* root_window = GetRootWindow(display_id_); 277 gfx::Rect rect(root_window_->layer()->size());
271 gfx::Rect rect(root_window->layer()->size());
272 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); 278 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
273 copy_layer->SetBounds(rect); 279 copy_layer->SetBounds(rect);
274 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), 280 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
275 rect.size()); 281 rect.size());
276 old_layer_tree_owner_ = 282
277 base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); 283 AddLayerAtTopOfWindowLayers(root_window_, copy_layer.get());
284 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
278 } 285 }
279 286
280 void ScreenRotationAnimator::AnimateRotation( 287 void ScreenRotationAnimator::AnimateRotation(
281 std::unique_ptr<ScreenRotationRequest> rotation_request) { 288 std::unique_ptr<ScreenRotationRequest> rotation_request) {
282 aura::Window* root_window = GetRootWindow(display_id_); 289 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
283 std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer( 290 rotation_request->new_rotation);
284 new LayerCleanupObserver(weak_factory_.GetWeakPtr()));
285 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
286 old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree");
287 // Add the cloned layer tree in to the root, so it will be rendered.
288 root_window->layer()->Add(old_root_layer);
289 root_window->layer()->StackAtTop(old_root_layer);
290
291 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds();
292
293 const int rotation_factor = GetRotationFactor(
294 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation);
295
296 const int old_layer_initial_rotation_degrees = GetInitialDegrees( 291 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
297 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); 292 rotation_request->old_rotation, rotation_request->new_rotation);
298
299 const base::TimeDelta duration = 293 const base::TimeDelta duration =
300 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); 294 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
301
302 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; 295 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
303 296 const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds();
304 Shell::Get()->display_manager()->SetDisplayRotation(
305 display_id_, rotation_request->new_rotation, rotation_request->source);
306
307 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds();
308 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, 297 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
309 rotated_screen_bounds.height() / 2); 298 rotated_screen_bounds.height() / 2);
310 299
311 // We must animate each non-cloned child layer individually because the cloned 300 ui::Layer* new_root_layer;
312 // layer was added as a child to |root_window|'s layer so that it will be 301 if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) {
313 // rendered. 302 // Make the current layers invisible if the copy request after rotation is
314 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and 303 // succeesful.
315 // its current children so that we only need to initiate two 304 screen_rotation_container_layer_->SetOpacity(0.0f);
316 // LayerAnimationSequences. One for the new layers and one for the old layer. 305 new_root_layer = new_layer_tree_owner_->root();
317 for (ui::Layer* child_layer : root_window->layer()->children()) { 306 } else {
318 // Skip the cloned layer because it has a different animation. 307 new_root_layer = screen_rotation_container_layer_;
319 if (child_layer == old_root_layer)
320 continue;
321
322 std::unique_ptr<ScreenRotationAnimation> screen_rotation =
323 base::MakeUnique<ScreenRotationAnimation>(
324 child_layer, kRotationDegrees * rotation_factor,
325 0 /* end_degrees */, child_layer->opacity(),
326 1.0f /* target_opacity */, pivot, duration, tween_type);
327
328 ui::LayerAnimator* animator = child_layer->GetAnimator();
329 animator->set_preemption_strategy(
330 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
331 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence =
332 base::MakeUnique<ui::LayerAnimationSequence>(
333 std::move(screen_rotation));
334 animator->StartAnimation(animation_sequence.release());
335 } 308 }
336 309
310 std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation =
311 base::MakeUnique<ScreenRotationAnimation>(
312 new_root_layer, kRotationDegrees * rotation_factor,
313 0 /* end_degrees */, 0.0f,
314 new_root_layer->opacity() /* target_opacity */, pivot, duration,
315 tween_type);
316
317 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
318 new_layer_animator->set_preemption_strategy(
319 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
320 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
321 base::MakeUnique<ui::LayerAnimationSequence>(
322 std::move(new_layer_screen_rotation));
323
324 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
325 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
337 // The old layer will also be transformed into the new orientation. We will 326 // The old layer will also be transformed into the new orientation. We will
338 // translate it so that the old layer's center point aligns with the new 327 // translate it so that the old layer's center point aligns with the new
339 // orientation's center point and use that center point as the pivot for the 328 // orientation's center point and use that center point as the pivot for the
340 // rotation animation. 329 // rotation animation.
341 gfx::Transform translate_transform; 330 gfx::Transform translate_transform;
342 translate_transform.Translate( 331 translate_transform.Translate(
343 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, 332 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
344 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); 333 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
345 old_root_layer->SetTransform(translate_transform); 334 old_root_layer->SetTransform(translate_transform);
346 335
347 std::unique_ptr<ScreenRotationAnimation> screen_rotation = 336 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
348 base::MakeUnique<ScreenRotationAnimation>( 337 base::MakeUnique<ScreenRotationAnimation>(
349 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, 338 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
350 (old_layer_initial_rotation_degrees - kRotationDegrees) * 339 (old_layer_initial_rotation_degrees - kRotationDegrees) *
351 rotation_factor, 340 rotation_factor,
352 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, 341 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
353 tween_type); 342 tween_type);
354 343
355 ui::LayerAnimator* animator = old_root_layer->GetAnimator(); 344 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
356 animator->set_preemption_strategy( 345 old_layer_animator->set_preemption_strategy(
357 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 346 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
358 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = 347 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
359 base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation)); 348 base::MakeUnique<ui::LayerAnimationSequence>(
360 // Add an observer so that the cloned layers can be cleaned up with the 349 std::move(old_layer_screen_rotation));
361 // animation completes/aborts. 350
362 animation_sequence->AddObserver(old_layer_cleanup_observer.release());
363 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to 351 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
364 // control the animation. 352 // control the animation.
365 if (disable_animation_timers_for_test_) 353 if (disable_animation_timers_for_test_) {
366 animator->set_disable_timer_for_test(true); 354 if (new_layer_tree_owner_)
367 animation_sequence->SetAnimationMetricsReporter(metrics_reporter_.get()); 355 new_layer_animator->set_disable_timer_for_test(true);
368 animator->StartAnimation(animation_sequence.release()); 356 old_layer_animator->set_disable_timer_for_test(true);
357 }
358 old_layer_animation_sequence->SetAnimationMetricsReporter(
359 metrics_reporter_.get());
360
361 // Add an observer so that the cloned/copied layers can be cleaned up with the
362 // animation completes/aborts.
363 ui::CallbackLayerAnimationObserver* observer =
364 new ui::CallbackLayerAnimationObserver(
365 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr()));
366 if (new_layer_tree_owner_)
367 new_layer_animator->AddObserver(observer);
368 new_layer_animator->StartAnimation(new_layer_animation_sequence.release());
369 old_layer_animator->AddObserver(observer);
370 old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
371 observer->SetActive();
369 372
370 rotation_request.reset(); 373 rotation_request.reset();
371 } 374 }
372 375
373 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, 376 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
374 display::Display::RotationSource source) { 377 display::Display::RotationSource source) {
375 if (GetCurrentScreenRotation(display_id_) == new_rotation) 378 const display::Display::Rotation current_rotation =
379 GetCurrentScreenRotation(display_id_);
380 if (current_rotation == new_rotation)
376 return; 381 return;
377 382
383 has_switch_ash_enable_smooth_screen_rotation_ =
384 base::CommandLine::ForCurrentProcess()->HasSwitch(
385 switches::kAshEnableSmoothScreenRotation);
386
378 std::unique_ptr<ScreenRotationRequest> rotation_request = 387 std::unique_ptr<ScreenRotationRequest> rotation_request =
379 base::MakeUnique<ScreenRotationRequest>(new_rotation, source); 388 base::MakeUnique<ScreenRotationRequest>(current_rotation, new_rotation,
389 source);
380 390
381 if (is_rotating_) { 391 if (is_rotating_) {
382 last_pending_request_ = std::move(rotation_request); 392 last_pending_request_ = std::move(rotation_request);
383 // The pending request will be processed when the 393 // The pending request will be processed when the
384 // OnLayerAnimation(Ended|Aborted) methods should be called after 394 // OnLayerAnimation(Ended|Aborted) methods should be called after
385 // StopAnimating(). 395 // StopAnimating().
386 StopAnimating(); 396 StopAnimating();
387 } else { 397 } else {
388 is_rotating_ = true; 398 is_rotating_ = true;
389 StartRotationAnimation(std::move(rotation_request)); 399 StartRotationAnimation(std::move(rotation_request));
390 } 400 }
391 } 401 }
392 402
393 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( 403 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver(
394 ScreenRotationAnimatorObserver* observer) { 404 ScreenRotationAnimatorObserver* observer) {
395 screen_rotation_animator_observers_.AddObserver(observer); 405 screen_rotation_animator_observers_.AddObserver(observer);
396 } 406 }
397 407
398 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( 408 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
399 ScreenRotationAnimatorObserver* observer) { 409 ScreenRotationAnimatorObserver* observer) {
400 screen_rotation_animator_observers_.RemoveObserver(observer); 410 screen_rotation_animator_observers_.RemoveObserver(observer);
401 } 411 }
402 412
403 void ScreenRotationAnimator::ProcessAnimationQueue() { 413 void ScreenRotationAnimator::ProcessAnimationQueue() {
404 is_rotating_ = false; 414 is_rotating_ = false;
415 if (IsDisplayIdValid(display_id_))
416 screen_rotation_container_layer_->SetOpacity(1.0f);
405 old_layer_tree_owner_.reset(); 417 old_layer_tree_owner_.reset();
418 new_layer_tree_owner_.reset();
406 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { 419 if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
407 std::unique_ptr<ScreenRotationRequest> rotation_request = 420 std::unique_ptr<ScreenRotationRequest> rotation_request =
408 std::move(last_pending_request_); 421 std::move(last_pending_request_);
409 Rotate(rotation_request->new_rotation, rotation_request->source); 422 Rotate(rotation_request->new_rotation, rotation_request->source);
410 rotation_request.reset(); 423 rotation_request.reset();
411 return; 424 return;
412 } 425 }
413 426
414 for (auto& observer : screen_rotation_animator_observers_) 427 for (auto& observer : screen_rotation_animator_observers_)
415 observer.OnScreenRotationAnimationFinished(this); 428 observer.OnScreenRotationAnimationFinished(this);
416 } 429 }
417 430
418 void ScreenRotationAnimator::set_disable_animation_timers_for_test( 431 void ScreenRotationAnimator::set_disable_animation_timers_for_test(
419 bool disable_timers) { 432 bool disable_timers) {
420 disable_animation_timers_for_test_ = disable_timers; 433 disable_animation_timers_for_test_ = disable_timers;
421 } 434 }
422 435
423 void ScreenRotationAnimator::StopAnimating() { 436 void ScreenRotationAnimator::StopAnimating() {
424 aura::Window* root_window = GetRootWindow(display_id_); 437 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
425 for (ui::Layer* child_layer : root_window->layer()->children()) { 438 // the rotation request comes before the copy request finished.
426 if (child_layer == old_layer_tree_owner_->root()) 439 if (old_layer_tree_owner_)
427 continue; 440 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
428 441 if (new_layer_tree_owner_) {
429 child_layer->GetAnimator()->StopAnimating(); 442 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
430 } 443 }
431 444 if (IsDisplayIdValid(display_id_))
432 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); 445 screen_rotation_container_layer_->SetOpacity(1.0f);
433 } 446 }
434 447
435 } // namespace ash 448 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698