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

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: Rebased on all the changes previously. 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/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
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(int64_t display_id) {
78 return GetRootWindow(display_id)
79 ->GetChildById(kShellWindowId_ScreenRotationContainer);
80 }
81
80 // 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
81 // 180 degrees. 83 // 180 degrees.
82 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, 84 bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
83 display::Display::Rotation new_rotation) { 85 display::Display::Rotation new_rotation) {
84 return (initial_rotation + 2) % 4 == new_rotation; 86 return (initial_rotation + 2) % 4 == new_rotation;
85 } 87 }
86 88
87 // Returns the initial degrees the old layer animation to begin with. 89 // Returns the initial degrees the old layer animation to begin with.
88 int GetInitialDegrees(display::Display::Rotation initial_rotation, 90 int GetInitialDegrees(display::Display::Rotation initial_rotation,
89 display::Display::Rotation new_rotation) { 91 display::Display::Rotation new_rotation) {
90 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); 92 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
91 } 93 }
92 94
93 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner 95 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
94 // 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.
95 class LayerCleanupObserver : public ui::LayerAnimationObserver { 97 root_window->layer()->Add(layer);
96 public: 98 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 } 99 }
139 100
140 void LayerCleanupObserver::OnLayerAnimationEnded( 101 // The Callback will be invoked when all animation sequences have
141 ui::LayerAnimationSequence* sequence) { 102 // finished. |observer| will be destroyed after invoking the Callback if it
142 if (animator_) 103 // returns true.
143 animator_->ProcessAnimationQueue(); 104 bool AnimationEndedCallback(
144 105 base::WeakPtr<ScreenRotationAnimator> animator,
145 delete this; 106 const ui::CallbackLayerAnimationObserver& observer) {
107 if (animator)
108 animator->ProcessAnimationQueue();
109 return true;
146 } 110 }
147 111
148 void LayerCleanupObserver::OnLayerAnimationAborted( 112 // Creates a Transform for the old layer in screen rotation animation.
149 ui::LayerAnimationSequence* sequence) { 113 gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
150 if (animator_) 114 display::Display::Rotation new_rotation,
151 animator_->ProcessAnimationQueue(); 115 display::Display::Rotation old_rotation,
152 116 const display::Display& display) {
153 delete this; 117 gfx::Transform inverse;
118 CHECK(CreateRotationTransform(old_rotation, new_rotation, display)
119 .GetInverse(&inverse));
120 return inverse;
154 } 121 }
155 122
156 void LayerCleanupObserver::OnAttachedToSequence( 123 // The |request_id| changed since last copy request, which means a
157 ui::LayerAnimationSequence* sequence) { 124 // new rotation stated, we need to ignore this copy result.
158 sequence_ = sequence; 125 bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) {
126 DCHECK(request_id <= current_request_id);
127 return request_id < current_request_id;
159 } 128 }
160 129
161 void LayerCleanupObserver::OnDetachedFromSequence( 130 // In the following cases, abort rotation:
162 ui::LayerAnimationSequence* sequence) { 131 // 1) if the display was removed,
163 DCHECK_EQ(sequence, sequence_); 132 // 2) the copy request has been canceled or failed. It would fail if,
164 sequence_ = nullptr; 133 // for examples: a) The layer is removed from the compositor and destroye
134 // before committing the request to the compositor. b) The compositor is
135 // shutdown.
136 bool AbortRotation(int64_t display_id, cc::CopyOutputResult* result) {
137 return !IsDisplayIdValid(display_id) || result->IsEmpty();
165 } 138 }
166 139
167 class ScreenRotationAnimationMetricsReporter 140 class ScreenRotationAnimationMetricsReporter
168 : public ui::AnimationMetricsReporter { 141 : public ui::AnimationMetricsReporter {
169 public: 142 public:
170 ScreenRotationAnimationMetricsReporter() {} 143 ScreenRotationAnimationMetricsReporter() {}
171 ~ScreenRotationAnimationMetricsReporter() override {} 144 ~ScreenRotationAnimationMetricsReporter() override {}
172 145
173 void Report(int value) override { 146 void Report(int value) override {
174 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); 147 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
175 } 148 }
176 149
177 private: 150 private:
178 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); 151 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
179 }; 152 };
180 153
181 } // namespace 154 } // namespace
182 155
183 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) 156 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
184 : display_id_(display_id), 157 : display_id_(display_id),
185 screen_rotation_state_(IDLE), 158 screen_rotation_state_(IDLE),
186 rotation_request_id_(0), 159 rotation_request_id_(0),
187 metrics_reporter_( 160 metrics_reporter_(
188 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), 161 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
189 disable_animation_timers_for_test_(false), 162 disable_animation_timers_for_test_(false),
163 has_switch_ash_enable_smooth_screen_rotation_(false),
164 screen_rotation_container_layer_(
165 GetScreenRotationContainer(display_id_)->layer()),
oshima 2017/04/14 04:54:26 use root_window_ to get the rotation container.
wutao 2017/04/14 07:48:28 Done.
166 root_window_(GetRootWindow(display_id_)),
190 weak_factory_(this) {} 167 weak_factory_(this) {}
191 168
192 ScreenRotationAnimator::~ScreenRotationAnimator() { 169 ScreenRotationAnimator::~ScreenRotationAnimator() {
193 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from 170 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from
194 // calling a method on the |animator_|. 171 // calling a method on the |animator_|.
195 weak_factory_.InvalidateWeakPtrs(); 172 weak_factory_.InvalidateWeakPtrs();
196 173
197 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in 174 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
198 // order to make sure |metrics_reporter_| outlives the attached animation 175 // order to make sure |metrics_reporter_| outlives the attached animation
199 // sequence. 176 // sequence.
200 old_layer_tree_owner_.reset(); 177 old_layer_tree_owner_.reset();
201 metrics_reporter_.reset(); 178 metrics_reporter_.reset();
202 } 179 }
203 180
204 void ScreenRotationAnimator::StartRotationAnimation( 181 void ScreenRotationAnimator::StartRotationAnimation(
205 std::unique_ptr<ScreenRotationRequest> rotation_request) { 182 std::unique_ptr<ScreenRotationRequest> rotation_request) {
206 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 183 if (has_switch_ash_enable_smooth_screen_rotation_) {
207 switches::kAshEnableSmoothScreenRotation)) { 184 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
208 RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request)); 185 cc::CopyOutputRequest::CreateRequest(
186 CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request)));
187 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
188 screen_rotation_state_ = COPY_REQUESTED;
209 } else { 189 } else {
210 CreateOldLayerTree(); 190 StartSlowAnimation(std::move(rotation_request));
211 AnimateRotation(std::move(rotation_request));
212 } 191 }
213 } 192 }
214 193
215 void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation( 194 void ScreenRotationAnimator::StartSlowAnimation(
216 std::unique_ptr<ScreenRotationRequest> rotation_request) { 195 std::unique_ptr<ScreenRotationRequest> rotation_request) {
217 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = 196 CreateOldLayerTree();
218 cc::CopyOutputRequest::CreateRequest( 197 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation,
219 CreateAfterCopyCallback(std::move(rotation_request))); 198 rotation_request->source);
220 ui::Layer* layer = GetRootWindow(display_id_)->layer(); 199 AnimateRotation(std::move(rotation_request));
221 copy_output_request->set_area(gfx::Rect(layer->size())); 200 }
222 layer->RequestCopyOfOutput(std::move(copy_output_request));
223 201
224 screen_rotation_state_ = COPY_REQUESTED; 202 void ScreenRotationAnimator::SetRotation(
203 display::Display::Rotation new_rotation,
204 display::Display::Rotation old_rotation,
205 display::Display::RotationSource source) {
206 Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation,
207 source);
208 const display::Display display =
209 Shell::Get()->display_manager()->GetDisplayForId(display_id_);
210 old_layer_tree_owner_->root()->SetTransform(
211 CreateScreenRotationOldLayerTransformForDisplay(new_rotation,
212 old_rotation, display));
213 }
214
215 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
216 std::unique_ptr<cc::CopyOutputRequest> copy_output_request) {
217 copy_output_request->set_area(
218 gfx::Rect(screen_rotation_container_layer_->size()));
219 screen_rotation_container_layer_->RequestCopyOfOutput(
220 std::move(copy_output_request));
225 } 221 }
226 222
227 ScreenRotationAnimator::CopyCallback 223 ScreenRotationAnimator::CopyCallback
228 ScreenRotationAnimator::CreateAfterCopyCallback( 224 ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
229 std::unique_ptr<ScreenRotationRequest> rotation_request) { 225 std::unique_ptr<ScreenRotationRequest> rotation_request) {
230 return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, 226 return base::Bind(&ScreenRotationAnimator::
227 OnScreenRotationContainerLayerCopiedBeforeRotation,
231 weak_factory_.GetWeakPtr(), 228 weak_factory_.GetWeakPtr(),
232 base::Passed(&rotation_request)); 229 base::Passed(&rotation_request));
233 } 230 }
234 231
235 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( 232 ScreenRotationAnimator::CopyCallback
233 ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
234 std::unique_ptr<ScreenRotationRequest> rotation_request) {
235 return base::Bind(&ScreenRotationAnimator::
236 OnScreenRotationContainerLayerCopiedAfterRotation,
237 weak_factory_.GetWeakPtr(),
238 base::Passed(&rotation_request));
239 }
240
241 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
236 std::unique_ptr<ScreenRotationRequest> rotation_request, 242 std::unique_ptr<ScreenRotationRequest> rotation_request,
237 std::unique_ptr<cc::CopyOutputResult> result) { 243 std::unique_ptr<cc::CopyOutputResult> result) {
238 DCHECK(rotation_request->id <= rotation_request_id_); 244 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; 245 return;
243 246 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(); 247 ProcessAnimationQueue();
252 return; 248 return;
253 } 249 }
254 250
255 CopyOldLayerTree(std::move(result)); 251 old_layer_tree_owner_ = CopyLayerTree(std::move(result));
252 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation,
253 rotation_request->source);
254 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
255 cc::CopyOutputRequest::CreateRequest(
256 CreateAfterCopyCallbackAfterRotation(std::move(rotation_request)));
257 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
258 }
259
260 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
261 std::unique_ptr<ScreenRotationRequest> rotation_request,
262 std::unique_ptr<cc::CopyOutputResult> result) {
263 if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
264 return;
265 if (AbortRotation(display_id_, result.get())) {
266 ProcessAnimationQueue();
267 return;
268 }
269
270 new_layer_tree_owner_ = CopyLayerTree(std::move(result));
256 AnimateRotation(std::move(rotation_request)); 271 AnimateRotation(std::move(rotation_request));
257 } 272 }
258 273
259 void ScreenRotationAnimator::CreateOldLayerTree() { 274 void ScreenRotationAnimator::CreateOldLayerTree() {
260 old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_)); 275 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
276 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
261 } 277 }
262 278
263 void ScreenRotationAnimator::CopyOldLayerTree( 279 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
264 std::unique_ptr<cc::CopyOutputResult> result) { 280 std::unique_ptr<cc::CopyOutputResult> result) {
265 cc::TextureMailbox texture_mailbox; 281 cc::TextureMailbox texture_mailbox;
266 std::unique_ptr<cc::SingleReleaseCallback> release_callback; 282 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
267 result->TakeTexture(&texture_mailbox, &release_callback); 283 result->TakeTexture(&texture_mailbox, &release_callback);
268 DCHECK(texture_mailbox.IsTexture()); 284 DCHECK(texture_mailbox.IsTexture());
269 285
270 aura::Window* root_window = GetRootWindow(display_id_); 286 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>(); 287 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
273 copy_layer->SetBounds(rect); 288 copy_layer->SetBounds(rect);
274 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), 289 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
275 rect.size()); 290 rect.size());
276 old_layer_tree_owner_ = 291
277 base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); 292 AddLayerAtTopOfWindowLayers(root_window_, copy_layer.get());
293 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
278 } 294 }
279 295
280 void ScreenRotationAnimator::AnimateRotation( 296 void ScreenRotationAnimator::AnimateRotation(
281 std::unique_ptr<ScreenRotationRequest> rotation_request) { 297 std::unique_ptr<ScreenRotationRequest> rotation_request) {
282 screen_rotation_state_ = ROTATING; 298 screen_rotation_state_ = ROTATING;
283 299 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
284 aura::Window* root_window = GetRootWindow(display_id_); 300 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( 301 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
299 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); 302 rotation_request->old_rotation, rotation_request->new_rotation);
300
301 const base::TimeDelta duration = 303 const base::TimeDelta duration =
302 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); 304 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
303
304 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; 305 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
305 306 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, 307 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
311 rotated_screen_bounds.height() / 2); 308 rotated_screen_bounds.height() / 2);
312 309
313 ui::Layer* screen_rotation_container_layer = 310 ui::Layer* new_root_layer;
314 root_window->GetChildById(kShellWindowId_ScreenRotationContainer) 311 if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) {
315 ->layer(); 312 // Make the current layers invisible if the copy request after rotation is
316 std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = 313 // succeesful.
314 screen_rotation_container_layer_->SetOpacity(0.0f);
315 new_root_layer = new_layer_tree_owner_->root();
316 } else {
317 new_root_layer = screen_rotation_container_layer_;
318 }
319
320 std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation =
317 base::MakeUnique<ScreenRotationAnimation>( 321 base::MakeUnique<ScreenRotationAnimation>(
318 screen_rotation_container_layer, kRotationDegrees * rotation_factor, 322 new_root_layer, kRotationDegrees * rotation_factor,
319 0 /* end_degrees */, 0.0f, 323 0 /* end_degrees */, 0.0f,
320 screen_rotation_container_layer->opacity() /* target_opacity */, 324 new_root_layer->opacity() /* target_opacity */, pivot, duration,
321 pivot, duration, tween_type); 325 tween_type);
322 326
323 ui::LayerAnimator* current_layer_animator = 327 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
324 screen_rotation_container_layer->GetAnimator(); 328 new_layer_animator->set_preemption_strategy(
325 current_layer_animator->set_preemption_strategy(
326 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 329 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
327 std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = 330 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
328 base::MakeUnique<ui::LayerAnimationSequence>( 331 base::MakeUnique<ui::LayerAnimationSequence>(
329 std::move(current_layer_screen_rotation)); 332 std::move(new_layer_screen_rotation));
330 current_layer_animator->StartAnimation(
331 current_layer_animation_sequence.release());
332 333
334 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
335 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
333 // The old layer will also be transformed into the new orientation. We will 336 // 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 337 // 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 338 // orientation's center point and use that center point as the pivot for the
336 // rotation animation. 339 // rotation animation.
337 gfx::Transform translate_transform; 340 gfx::Transform translate_transform;
338 translate_transform.Translate( 341 translate_transform.Translate(
339 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, 342 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
340 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); 343 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
341 old_root_layer->SetTransform(translate_transform); 344 old_root_layer->SetTransform(translate_transform);
342 345
343 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = 346 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
344 base::MakeUnique<ScreenRotationAnimation>( 347 base::MakeUnique<ScreenRotationAnimation>(
345 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, 348 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
346 (old_layer_initial_rotation_degrees - kRotationDegrees) * 349 (old_layer_initial_rotation_degrees - kRotationDegrees) *
347 rotation_factor, 350 rotation_factor,
348 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, 351 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
349 tween_type); 352 tween_type);
350 353
351 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); 354 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
352 old_layer_animator->set_preemption_strategy( 355 old_layer_animator->set_preemption_strategy(
353 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 356 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
354 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = 357 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
355 base::MakeUnique<ui::LayerAnimationSequence>( 358 base::MakeUnique<ui::LayerAnimationSequence>(
356 std::move(old_layer_screen_rotation)); 359 std::move(old_layer_screen_rotation));
357 // Add an observer so that the cloned layers can be cleaned up with the 360
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 361 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
362 // control the animation. 362 // control the animation.
363 if (disable_animation_timers_for_test_) 363 if (disable_animation_timers_for_test_) {
364 if (new_layer_tree_owner_)
365 new_layer_animator->set_disable_timer_for_test(true);
364 old_layer_animator->set_disable_timer_for_test(true); 366 old_layer_animator->set_disable_timer_for_test(true);
367 }
365 old_layer_animation_sequence->SetAnimationMetricsReporter( 368 old_layer_animation_sequence->SetAnimationMetricsReporter(
366 metrics_reporter_.get()); 369 metrics_reporter_.get());
370
371 // Add an observer so that the cloned/copied layers can be cleaned up with the
372 // animation completes/aborts.
373 ui::CallbackLayerAnimationObserver* observer =
374 new ui::CallbackLayerAnimationObserver(
375 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr()));
376 if (new_layer_tree_owner_)
377 new_layer_animator->AddObserver(observer);
378 new_layer_animator->StartAnimation(new_layer_animation_sequence.release());
379 old_layer_animator->AddObserver(observer);
367 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); 380 old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
381 observer->SetActive();
368 } 382 }
369 383
370 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, 384 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
371 display::Display::RotationSource source) { 385 display::Display::RotationSource source) {
372 if (GetCurrentScreenRotation(display_id_) == new_rotation) 386 const display::Display::Rotation current_rotation =
387 GetCurrentScreenRotation(display_id_);
388 if (current_rotation == new_rotation)
373 return; 389 return;
374 390
391 has_switch_ash_enable_smooth_screen_rotation_ =
392 base::CommandLine::ForCurrentProcess()->HasSwitch(
oshima 2017/04/14 04:54:26 initialize it in ctor
wutao 2017/04/14 07:48:28 Done. I also need to add a setter for test so that
393 switches::kAshEnableSmoothScreenRotation);
394
375 rotation_request_id_++; 395 rotation_request_id_++;
376 std::unique_ptr<ScreenRotationRequest> rotation_request = 396 std::unique_ptr<ScreenRotationRequest> rotation_request =
377 base::MakeUnique<ScreenRotationRequest>(rotation_request_id_, 397 base::MakeUnique<ScreenRotationRequest>(
378 new_rotation, source); 398 rotation_request_id_, current_rotation, new_rotation, source);
379
380 switch (screen_rotation_state_) { 399 switch (screen_rotation_state_) {
381 case IDLE: 400 case IDLE:
382 case COPY_REQUESTED: 401 case COPY_REQUESTED:
383 StartRotationAnimation(std::move(rotation_request)); 402 StartRotationAnimation(std::move(rotation_request));
384 break; 403 break;
385 case ROTATING: 404 case ROTATING:
386 last_pending_request_ = std::move(rotation_request); 405 last_pending_request_ = std::move(rotation_request);
387 // The pending request will be processed when the 406 // The pending request will be processed when the
388 // OnLayerAnimation(Ended|Aborted) methods should be called after 407 // OnLayerAnimation(Ended|Aborted) methods should be called after
389 // |StopAnimating()|. 408 // |StopAnimating()|.
390 StopAnimating(); 409 StopAnimating();
391 break; 410 break;
392 } 411 }
393 } 412 }
394 413
395 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( 414 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver(
396 ScreenRotationAnimatorObserver* observer) { 415 ScreenRotationAnimatorObserver* observer) {
397 screen_rotation_animator_observers_.AddObserver(observer); 416 screen_rotation_animator_observers_.AddObserver(observer);
398 } 417 }
399 418
400 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( 419 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
401 ScreenRotationAnimatorObserver* observer) { 420 ScreenRotationAnimatorObserver* observer) {
402 screen_rotation_animator_observers_.RemoveObserver(observer); 421 screen_rotation_animator_observers_.RemoveObserver(observer);
403 } 422 }
404 423
405 void ScreenRotationAnimator::ProcessAnimationQueue() { 424 void ScreenRotationAnimator::ProcessAnimationQueue() {
406 screen_rotation_state_ = IDLE; 425 screen_rotation_state_ = IDLE;
426 if (IsDisplayIdValid(display_id_))
427 screen_rotation_container_layer_->SetOpacity(1.0f);
407 old_layer_tree_owner_.reset(); 428 old_layer_tree_owner_.reset();
429 new_layer_tree_owner_.reset();
408 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { 430 if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
409 display::Display::Rotation new_rotation = 431 display::Display::Rotation new_rotation =
410 last_pending_request_->new_rotation; 432 last_pending_request_->new_rotation;
411 display::Display::RotationSource source = last_pending_request_->source; 433 display::Display::RotationSource source = last_pending_request_->source;
412 last_pending_request_.reset(); 434 last_pending_request_.reset();
413 Rotate(new_rotation, source); 435 Rotate(new_rotation, source);
414 return; 436 return;
415 } 437 }
416 438
417 for (auto& observer : screen_rotation_animator_observers_) 439 for (auto& observer : screen_rotation_animator_observers_)
418 observer.OnScreenRotationAnimationFinished(this); 440 observer.OnScreenRotationAnimationFinished(this);
419 } 441 }
420 442
421 void ScreenRotationAnimator::set_disable_animation_timers_for_test( 443 void ScreenRotationAnimator::set_disable_animation_timers_for_test(
422 bool disable_timers) { 444 bool disable_timers) {
423 disable_animation_timers_for_test_ = disable_timers; 445 disable_animation_timers_for_test_ = disable_timers;
424 } 446 }
425 447
426 void ScreenRotationAnimator::StopAnimating() { 448 void ScreenRotationAnimator::StopAnimating() {
427 GetRootWindow(display_id_) 449 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
428 ->GetChildById(kShellWindowId_ScreenRotationContainer) 450 // the rotation request comes before the copy request finished.
429 ->layer()
430 ->GetAnimator()
431 ->StopAnimating();
432 if (old_layer_tree_owner_) 451 if (old_layer_tree_owner_)
433 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); 452 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
453 if (new_layer_tree_owner_)
454 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
455 if (IsDisplayIdValid(display_id_))
456 screen_rotation_container_layer_->SetOpacity(1.0f);
434 } 457 }
435 458
436 } // namespace ash 459 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698