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

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: Add new tests and add doc to handle new rotation request in |Rotate()|. 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(aura::Window* root_window) {
78 return root_window->GetChildById(kShellWindowId_ScreenRotationContainer);
79 }
80
80 // Returns true if the rotation between |initial_rotation| and |new_rotation| is 81 // Returns true if the rotation between |initial_rotation| and |new_rotation| is
81 // 180 degrees. 82 // 180 degrees.
82 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, 83 bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
83 display::Display::Rotation new_rotation) { 84 display::Display::Rotation new_rotation) {
84 return (initial_rotation + 2) % 4 == new_rotation; 85 return (initial_rotation + 2) % 4 == new_rotation;
85 } 86 }
86 87
87 // Returns the initial degrees the old layer animation to begin with. 88 // Returns the initial degrees the old layer animation to begin with.
88 int GetInitialDegrees(display::Display::Rotation initial_rotation, 89 int GetInitialDegrees(display::Display::Rotation initial_rotation,
89 display::Display::Rotation new_rotation) { 90 display::Display::Rotation new_rotation) {
90 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); 91 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
91 } 92 }
92 93
93 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner 94 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
94 // when notified that a layer animation has ended or was aborted. 95 // Add the cloned/copied layer tree into the root, so it will be rendered.
95 class LayerCleanupObserver : public ui::LayerAnimationObserver { 96 root_window->layer()->Add(layer);
96 public: 97 root_window->layer()->StackAtTop(layer);
97 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_|
98 // instance and the |animator_| isn't detaching itself as an observer when
99 // being destroyed. However, ideally, when |animator_| is destroying,
100 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and
101 // delete |this| before |animator_| deleted.
102 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator);
103 ~LayerCleanupObserver() override;
104
105 // ui::LayerAnimationObserver:
106 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
107 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
108 void OnLayerAnimationScheduled(
109 ui::LayerAnimationSequence* sequence) override {}
110
111 protected:
112 // ui::LayerAnimationObserver:
113 bool RequiresNotificationWhenAnimatorDestroyed() const override {
114 return true;
115 }
116 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override;
117 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override;
118
119 private:
120 base::WeakPtr<ScreenRotationAnimator> animator_;
121
122 // The LayerAnimationSequence that |this| has been attached to. Defaults to
123 // nullptr.
124 ui::LayerAnimationSequence* sequence_;
125
126 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver);
127 };
128
129 LayerCleanupObserver::LayerCleanupObserver(
130 base::WeakPtr<ScreenRotationAnimator> animator)
131 : animator_(animator), sequence_(nullptr) {}
132
133 LayerCleanupObserver::~LayerCleanupObserver() {
134 // We must eplicitly detach from |sequence_| because we return true from
135 // RequiresNotificationWhenAnimatorDestroyed.
136 if (sequence_)
137 sequence_->RemoveObserver(this);
138 } 98 }
139 99
140 void LayerCleanupObserver::OnLayerAnimationEnded( 100 void AddLayerBelowWindowLayer(aura::Window* root_window,
141 ui::LayerAnimationSequence* sequence) { 101 ui::Layer* top_layer,
142 if (animator_) 102 ui::Layer* layer) {
143 animator_->ProcessAnimationQueue(); 103 // Add the cloned/copied layer tree into the root, so it will be rendered.
144 104 root_window->layer()->Add(layer);
145 delete this; 105 root_window->layer()->StackBelow(layer, top_layer);
146 } 106 }
147 107
148 void LayerCleanupObserver::OnLayerAnimationAborted( 108 // The Callback will be invoked when all animation sequences have
149 ui::LayerAnimationSequence* sequence) { 109 // finished. |observer| will be destroyed after invoking the Callback if it
150 if (animator_) 110 // returns true.
151 animator_->ProcessAnimationQueue(); 111 bool AnimationEndedCallback(
152 112 base::WeakPtr<ScreenRotationAnimator> animator,
153 delete this; 113 const ui::CallbackLayerAnimationObserver& observer) {
114 if (animator)
115 animator->ProcessAnimationQueue();
116 return true;
154 } 117 }
155 118
156 void LayerCleanupObserver::OnAttachedToSequence( 119 // Creates a Transform for the old layer in screen rotation animation.
157 ui::LayerAnimationSequence* sequence) { 120 gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
158 sequence_ = sequence; 121 display::Display::Rotation old_rotation,
122 display::Display::Rotation new_rotation,
123 const display::Display& display) {
124 gfx::Transform inverse;
125 CHECK(CreateRotationTransform(old_rotation, new_rotation, display)
126 .GetInverse(&inverse));
127 return inverse;
159 } 128 }
160 129
161 void LayerCleanupObserver::OnDetachedFromSequence( 130 // The |request_id| changed since last copy request, which means a
162 ui::LayerAnimationSequence* sequence) { 131 // new rotation stated, we need to ignore this copy result.
163 DCHECK_EQ(sequence, sequence_); 132 bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) {
164 sequence_ = nullptr; 133 DCHECK(request_id <= current_request_id);
134 return request_id < current_request_id;
135 }
136
137 // In the following cases, abort rotation:
138 // 1) if the display was removed,
139 // 2) the copy request has been canceled or failed. It would fail if,
140 // for examples: a) The layer is removed from the compositor and destroye
141 // before committing the request to the compositor. b) The compositor is
142 // shutdown.
143 bool AbortRotation(int64_t display_id, cc::CopyOutputResult* result) {
144 return !IsDisplayIdValid(display_id) || result->IsEmpty();
145 }
146
147 // Creates a black mask layer and returns the |layer_owner|.
148 std::unique_ptr<ui::LayerOwner> CreateBlackMaskLayerOwner(
149 const gfx::Rect& rect) {
150 std::unique_ptr<ui::Layer> black_mask_layer =
151 base::MakeUnique<ui::Layer>(ui::LAYER_SOLID_COLOR);
152 black_mask_layer->SetBounds(rect);
153 black_mask_layer->SetColor(SK_ColorBLACK);
154 std::unique_ptr<ui::LayerOwner> black_mask_layer_owner =
155 base::MakeUnique<ui::LayerOwner>();
156 black_mask_layer_owner->SetLayer(std::move(black_mask_layer));
157 return black_mask_layer_owner;
165 } 158 }
166 159
167 class ScreenRotationAnimationMetricsReporter 160 class ScreenRotationAnimationMetricsReporter
168 : public ui::AnimationMetricsReporter { 161 : public ui::AnimationMetricsReporter {
169 public: 162 public:
170 ScreenRotationAnimationMetricsReporter() {} 163 ScreenRotationAnimationMetricsReporter() {}
171 ~ScreenRotationAnimationMetricsReporter() override {} 164 ~ScreenRotationAnimationMetricsReporter() override {}
172 165
173 void Report(int value) override { 166 void Report(int value) override {
174 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); 167 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
175 } 168 }
176 169
177 private: 170 private:
178 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); 171 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
179 }; 172 };
180 173
181 } // namespace 174 } // namespace
182 175
183 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) 176 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
184 : display_id_(display_id), 177 : display_id_(display_id),
185 screen_rotation_state_(IDLE), 178 screen_rotation_state_(IDLE),
186 rotation_request_id_(0), 179 rotation_request_id_(0),
187 metrics_reporter_( 180 metrics_reporter_(
188 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), 181 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
189 disable_animation_timers_for_test_(false), 182 disable_animation_timers_for_test_(false),
183 has_switch_ash_enable_smooth_screen_rotation_(
184 base::CommandLine::ForCurrentProcess()->HasSwitch(
185 switches::kAshEnableSmoothScreenRotation)),
186 root_window_(GetRootWindow(display_id_)),
187 screen_rotation_container_layer_(
188 GetScreenRotationContainer(root_window_)->layer()),
190 weak_factory_(this) {} 189 weak_factory_(this) {}
191 190
192 ScreenRotationAnimator::~ScreenRotationAnimator() { 191 ScreenRotationAnimator::~ScreenRotationAnimator() {
193 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from 192 // To prevent a call to |AnimationEndedCallback()| from calling a method on
194 // calling a method on the |animator_|. 193 // the |animator_|.
195 weak_factory_.InvalidateWeakPtrs(); 194 weak_factory_.InvalidateWeakPtrs();
196 195
197 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in 196 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
198 // order to make sure |metrics_reporter_| outlives the attached animation 197 // order to make sure |metrics_reporter_| outlives the attached animation
199 // sequence. 198 // sequence.
200 old_layer_tree_owner_.reset(); 199 old_layer_tree_owner_.reset();
201 metrics_reporter_.reset(); 200 metrics_reporter_.reset();
202 } 201 }
203 202
204 void ScreenRotationAnimator::StartRotationAnimation( 203 void ScreenRotationAnimator::StartRotationAnimation(
205 std::unique_ptr<ScreenRotationRequest> rotation_request) { 204 std::unique_ptr<ScreenRotationRequest> rotation_request) {
206 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 205 if (has_switch_ash_enable_smooth_screen_rotation_) {
207 switches::kAshEnableSmoothScreenRotation)) { 206 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
208 RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request)); 207 cc::CopyOutputRequest::CreateRequest(
208 CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request)));
209 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
210 screen_rotation_state_ = COPY_REQUESTED;
209 } else { 211 } else {
210 CreateOldLayerTree(); 212 StartSlowAnimation(std::move(rotation_request));
211 AnimateRotation(std::move(rotation_request));
212 } 213 }
213 } 214 }
214 215
215 void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation( 216 void ScreenRotationAnimator::StartSlowAnimation(
216 std::unique_ptr<ScreenRotationRequest> rotation_request) { 217 std::unique_ptr<ScreenRotationRequest> rotation_request) {
217 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = 218 CreateOldLayerTree();
218 cc::CopyOutputRequest::CreateRequest( 219 SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
219 CreateAfterCopyCallback(std::move(rotation_request))); 220 rotation_request->source);
220 ui::Layer* layer = GetRootWindow(display_id_)->layer(); 221 AnimateRotation(std::move(rotation_request));
221 copy_output_request->set_area(gfx::Rect(layer->size())); 222 }
222 layer->RequestCopyOfOutput(std::move(copy_output_request));
223 223
224 screen_rotation_state_ = COPY_REQUESTED; 224 void ScreenRotationAnimator::SetRotation(
225 display::Display::Rotation old_rotation,
226 display::Display::Rotation new_rotation,
227 display::Display::RotationSource source) {
228 Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation,
229 source);
230 const display::Display display =
231 Shell::Get()->display_manager()->GetDisplayForId(display_id_);
232 old_layer_tree_owner_->root()->SetTransform(
233 CreateScreenRotationOldLayerTransformForDisplay(old_rotation,
234 new_rotation, display));
235 }
236
237 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
238 std::unique_ptr<cc::CopyOutputRequest> copy_output_request) {
239 copy_output_request->set_area(
240 gfx::Rect(screen_rotation_container_layer_->size()));
241 screen_rotation_container_layer_->RequestCopyOfOutput(
242 std::move(copy_output_request));
225 } 243 }
226 244
227 ScreenRotationAnimator::CopyCallback 245 ScreenRotationAnimator::CopyCallback
228 ScreenRotationAnimator::CreateAfterCopyCallback( 246 ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
229 std::unique_ptr<ScreenRotationRequest> rotation_request) { 247 std::unique_ptr<ScreenRotationRequest> rotation_request) {
230 return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, 248 return base::Bind(&ScreenRotationAnimator::
249 OnScreenRotationContainerLayerCopiedBeforeRotation,
231 weak_factory_.GetWeakPtr(), 250 weak_factory_.GetWeakPtr(),
232 base::Passed(&rotation_request)); 251 base::Passed(&rotation_request));
233 } 252 }
234 253
235 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( 254 ScreenRotationAnimator::CopyCallback
255 ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
256 std::unique_ptr<ScreenRotationRequest> rotation_request) {
257 return base::Bind(&ScreenRotationAnimator::
258 OnScreenRotationContainerLayerCopiedAfterRotation,
259 weak_factory_.GetWeakPtr(),
260 base::Passed(&rotation_request));
261 }
262
263 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
236 std::unique_ptr<ScreenRotationRequest> rotation_request, 264 std::unique_ptr<ScreenRotationRequest> rotation_request,
237 std::unique_ptr<cc::CopyOutputResult> result) { 265 std::unique_ptr<cc::CopyOutputResult> result) {
238 DCHECK(rotation_request->id <= rotation_request_id_); 266 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; 267 return;
243 268 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(); 269 ProcessAnimationQueue();
252 return; 270 return;
253 } 271 }
254 272
255 CopyOldLayerTree(std::move(result)); 273 old_layer_tree_owner_ = CopyLayerTree(std::move(result));
274 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
275 SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
276 rotation_request->source);
277 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
278 cc::CopyOutputRequest::CreateRequest(
279 CreateAfterCopyCallbackAfterRotation(std::move(rotation_request)));
280 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
281 }
282
283 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
284 std::unique_ptr<ScreenRotationRequest> rotation_request,
285 std::unique_ptr<cc::CopyOutputResult> result) {
286 if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
287 return;
288 if (AbortRotation(display_id_, result.get())) {
289 ProcessAnimationQueue();
290 return;
291 }
292
293 new_layer_tree_owner_ = CopyLayerTree(std::move(result));
294 AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(),
295 new_layer_tree_owner_->root());
256 AnimateRotation(std::move(rotation_request)); 296 AnimateRotation(std::move(rotation_request));
257 } 297 }
258 298
259 void ScreenRotationAnimator::CreateOldLayerTree() { 299 void ScreenRotationAnimator::CreateOldLayerTree() {
oshima 2017/04/18 18:32:25 can you rename this to CreateOldLayerTreeForSlowAn
wutao 2017/04/18 19:56:58 Done.
260 old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_)); 300 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
301 // |screen_rotation_container_layer_| needs update after |RecreateLayers()|.
302 screen_rotation_container_layer_ =
303 GetScreenRotationContainer(root_window_)->layer();
304 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
261 } 305 }
262 306
263 void ScreenRotationAnimator::CopyOldLayerTree( 307 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
264 std::unique_ptr<cc::CopyOutputResult> result) { 308 std::unique_ptr<cc::CopyOutputResult> result) {
265 cc::TextureMailbox texture_mailbox; 309 cc::TextureMailbox texture_mailbox;
266 std::unique_ptr<cc::SingleReleaseCallback> release_callback; 310 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
267 result->TakeTexture(&texture_mailbox, &release_callback); 311 result->TakeTexture(&texture_mailbox, &release_callback);
268 DCHECK(texture_mailbox.IsTexture()); 312 DCHECK(texture_mailbox.IsTexture());
269 313
270 aura::Window* root_window = GetRootWindow(display_id_); 314 gfx::Rect rect(screen_rotation_container_layer_->size());
oshima 2017/04/18 18:32:25 nit: const
wutao 2017/04/18 19:56:58 Done.
271 gfx::Rect rect(root_window->layer()->size());
272 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); 315 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
273 copy_layer->SetBounds(rect); 316 copy_layer->SetBounds(rect);
274 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), 317 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
275 rect.size()); 318 rect.size());
276 old_layer_tree_owner_ = 319 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
277 base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
278 } 320 }
279 321
280 void ScreenRotationAnimator::AnimateRotation( 322 void ScreenRotationAnimator::AnimateRotation(
281 std::unique_ptr<ScreenRotationRequest> rotation_request) { 323 std::unique_ptr<ScreenRotationRequest> rotation_request) {
282 screen_rotation_state_ = ROTATING; 324 screen_rotation_state_ = ROTATING;
283 325 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
284 aura::Window* root_window = GetRootWindow(display_id_); 326 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( 327 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
299 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); 328 rotation_request->old_rotation, rotation_request->new_rotation);
300
301 const base::TimeDelta duration = 329 const base::TimeDelta duration =
302 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); 330 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
303
304 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; 331 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
305 332 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, 333 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
311 rotated_screen_bounds.height() / 2); 334 rotated_screen_bounds.height() / 2);
312 335
313 ui::Layer* screen_rotation_container_layer = 336 ui::Layer* new_root_layer;
314 root_window->GetChildById(kShellWindowId_ScreenRotationContainer) 337 if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) {
315 ->layer(); 338 new_root_layer = new_layer_tree_owner_->root();
316 std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = 339 // Add a black mask layer on top of |screen_rotation_container_layer_|.
340 black_mask_layer_owner_ = CreateBlackMaskLayerOwner(
341 gfx::Rect(screen_rotation_container_layer_->size()));
342 AddLayerBelowWindowLayer(root_window_, new_root_layer,
343 black_mask_layer_owner_->layer());
344 } else {
345 new_root_layer = screen_rotation_container_layer_;
346 }
347
348 std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation =
317 base::MakeUnique<ScreenRotationAnimation>( 349 base::MakeUnique<ScreenRotationAnimation>(
318 screen_rotation_container_layer, kRotationDegrees * rotation_factor, 350 new_root_layer, kRotationDegrees * rotation_factor,
319 0 /* end_degrees */, screen_rotation_container_layer->opacity(), 351 0 /* end_degrees */, new_root_layer->opacity(),
320 screen_rotation_container_layer->opacity() /* target_opacity */, 352 new_root_layer->opacity() /* target_opacity */, pivot, duration,
321 pivot, duration, tween_type); 353 tween_type);
322 354
323 ui::LayerAnimator* current_layer_animator = 355 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
324 screen_rotation_container_layer->GetAnimator(); 356 new_layer_animator->set_preemption_strategy(
325 current_layer_animator->set_preemption_strategy(
326 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 357 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
327 std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = 358 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
328 base::MakeUnique<ui::LayerAnimationSequence>( 359 base::MakeUnique<ui::LayerAnimationSequence>(
329 std::move(current_layer_screen_rotation)); 360 std::move(new_layer_screen_rotation));
330 current_layer_animator->StartAnimation(
331 current_layer_animation_sequence.release());
332 361
362 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
363 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
333 // The old layer will also be transformed into the new orientation. We will 364 // 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 365 // 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 366 // orientation's center point and use that center point as the pivot for the
336 // rotation animation. 367 // rotation animation.
337 gfx::Transform translate_transform; 368 gfx::Transform translate_transform;
338 translate_transform.Translate( 369 translate_transform.Translate(
339 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, 370 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
340 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); 371 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
341 old_root_layer->SetTransform(translate_transform); 372 old_root_layer->SetTransform(translate_transform);
342 373
343 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = 374 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
344 base::MakeUnique<ScreenRotationAnimation>( 375 base::MakeUnique<ScreenRotationAnimation>(
345 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, 376 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
346 (old_layer_initial_rotation_degrees - kRotationDegrees) * 377 (old_layer_initial_rotation_degrees - kRotationDegrees) *
347 rotation_factor, 378 rotation_factor,
348 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, 379 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
349 tween_type); 380 tween_type);
350 381
351 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); 382 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
352 old_layer_animator->set_preemption_strategy( 383 old_layer_animator->set_preemption_strategy(
353 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 384 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
354 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = 385 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
355 base::MakeUnique<ui::LayerAnimationSequence>( 386 base::MakeUnique<ui::LayerAnimationSequence>(
356 std::move(old_layer_screen_rotation)); 387 std::move(old_layer_screen_rotation));
357 // Add an observer so that the cloned layers can be cleaned up with the 388
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 389 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
362 // control the animation. 390 // control the animation.
363 if (disable_animation_timers_for_test_) 391 if (disable_animation_timers_for_test_) {
392 if (new_layer_tree_owner_)
393 new_layer_animator->set_disable_timer_for_test(true);
364 old_layer_animator->set_disable_timer_for_test(true); 394 old_layer_animator->set_disable_timer_for_test(true);
395 }
365 old_layer_animation_sequence->SetAnimationMetricsReporter( 396 old_layer_animation_sequence->SetAnimationMetricsReporter(
366 metrics_reporter_.get()); 397 metrics_reporter_.get());
398
399 // Add an observer so that the cloned/copied layers can be cleaned up with the
400 // animation completes/aborts.
401 ui::CallbackLayerAnimationObserver* observer =
402 new ui::CallbackLayerAnimationObserver(
403 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr()));
404 if (new_layer_tree_owner_)
405 new_layer_animator->AddObserver(observer);
406 new_layer_animator->StartAnimation(new_layer_animation_sequence.release());
407 old_layer_animator->AddObserver(observer);
367 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); 408 old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
409 observer->SetActive();
368 } 410 }
369 411
370 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, 412 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
371 display::Display::RotationSource source) { 413 display::Display::RotationSource source) {
372 if (GetCurrentScreenRotation(display_id_) == new_rotation) 414 const display::Display::Rotation current_rotation =
415 GetCurrentScreenRotation(display_id_);
416 rotation_request_id_++;
417
418 // 1. If |current_rotation| equals to |new_rotation|:
419 // 1.1 When |screen_rotation_state_| is IDEL: we already at the target
420 // rotation, we should stop and call |ProcessAnimationQueue()| to nofity
421 // |screen_rotation_animator_observers_|.
422 // 1.2 When |screen_rotation_state_| is ROTATING: we already called
423 // |DisplayManager::SetDisplayRotation()| for previous rotation request
424 // and at the target rotation we should stop and call
425 // |ProcessAnimationQueue()| to nofity
426 // |screen_rotation_animator_observers_|.
427 // 1.3 When |screen_rotation_state_| is COPY_REQUESTED:
428 // 1.3.1 Before the first copy callback, we have not called
429 // |DisplayManager::SetDisplayRotation()|, but we increased the
430 // |rotation_request_id_| so that the first copy callback will be
431 // skipped. We should stop and call |ProcessAnimationQueue()| to nofity
432 // |screen_rotation_animator_observers_|.
433 // 1.3.2 Before the second copy callback, we have called
434 // |DisplayManager::SetDisplayRotation()|, we also increased the
435 // |rotation_request_id_| so that the second copy callback will exit.
436 // We should stop and call |ProcessAnimationQueue()| to nofity
437 // |screen_rotation_animator_observers_|.
438 // 2. If |current_rotation| dose not equal to |new_rotation|:
439 // 2.1 When |screen_rotation_state_| is IDEL: we should call
440 // |StartRotationAnimation()|.
441 // 2.2 When |screen_rotation_state_| is ROTATING: we should set
442 // |last_pending_request_| and |StopAnimating()| to process the
443 // |last_pending_request_| in the |AnimationEndedCallback()|.
444 // 2.3 When |screen_rotation_state_| is COPY_REQUESTED:
445 // 2.3.1 Before the first copy callback, we have not called
446 // |DisplayManager::SetDisplayRotation()|, but increased the
447 // |rotation_request_id_| so that the first copy callback will be
448 // skipped. We should call |StartRotationAnimation()|.
449 // 2.3.2 Before the second copy callback, we have called
450 // |DisplayManager::SetDisplayRotation()| and increased the
451 // |rotation_request_id_| so that the second copy callback will be
452 // skipped. We should call |StartRotationAnimation()|.
oshima 2017/04/18 18:32:25 You don't have to explain everything that the code
wutao 2017/04/18 19:56:58 Done.
453
454 // The actions for 1.1, 1.2, 1.3.1, and 1.3.2 are the same.
455 if (current_rotation == new_rotation) {
456 // We need to call |ProcessAnimationQueue()| to notify
457 // |screen_rotation_animator_observers_|.
458 ProcessAnimationQueue();
373 return; 459 return;
460 }
374 461
375 rotation_request_id_++;
376 std::unique_ptr<ScreenRotationRequest> rotation_request = 462 std::unique_ptr<ScreenRotationRequest> rotation_request =
377 base::MakeUnique<ScreenRotationRequest>(rotation_request_id_, 463 base::MakeUnique<ScreenRotationRequest>(
378 new_rotation, source); 464 rotation_request_id_, current_rotation, new_rotation, source);
379 465 // The actions for 2.1, 2.3.1, and 2.3.2 are the same.
380 switch (screen_rotation_state_) { 466 switch (screen_rotation_state_) {
381 case IDLE: 467 case IDLE:
382 case COPY_REQUESTED: 468 case COPY_REQUESTED:
383 StartRotationAnimation(std::move(rotation_request)); 469 StartRotationAnimation(std::move(rotation_request));
384 break; 470 break;
385 case ROTATING: 471 case ROTATING:
386 last_pending_request_ = std::move(rotation_request); 472 last_pending_request_ = std::move(rotation_request);
387 // The pending request will be processed when the 473 // The pending request will be processed when the
388 // OnLayerAnimation(Ended|Aborted) methods should be called after 474 // |AnimationEndedCallback()| should be called after |StopAnimating()|.
389 // |StopAnimating()|.
390 StopAnimating(); 475 StopAnimating();
391 break; 476 break;
392 } 477 }
393 } 478 }
394 479
395 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( 480 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver(
396 ScreenRotationAnimatorObserver* observer) { 481 ScreenRotationAnimatorObserver* observer) {
397 screen_rotation_animator_observers_.AddObserver(observer); 482 screen_rotation_animator_observers_.AddObserver(observer);
398 } 483 }
399 484
400 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( 485 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
401 ScreenRotationAnimatorObserver* observer) { 486 ScreenRotationAnimatorObserver* observer) {
402 screen_rotation_animator_observers_.RemoveObserver(observer); 487 screen_rotation_animator_observers_.RemoveObserver(observer);
403 } 488 }
404 489
405 void ScreenRotationAnimator::ProcessAnimationQueue() { 490 void ScreenRotationAnimator::ProcessAnimationQueue() {
406 screen_rotation_state_ = IDLE; 491 screen_rotation_state_ = IDLE;
492 if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
493 root_window_->layer()->Remove(black_mask_layer_owner_->layer());
407 old_layer_tree_owner_.reset(); 494 old_layer_tree_owner_.reset();
495 new_layer_tree_owner_.reset();
496 black_mask_layer_owner_.reset();
408 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { 497 if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
409 display::Display::Rotation new_rotation = 498 display::Display::Rotation new_rotation =
410 last_pending_request_->new_rotation; 499 last_pending_request_->new_rotation;
411 display::Display::RotationSource source = last_pending_request_->source; 500 display::Display::RotationSource source = last_pending_request_->source;
412 last_pending_request_.reset(); 501 last_pending_request_.reset();
oshima 2017/04/18 18:32:25 Looking more closely, looks like this increases th
wutao 2017/04/18 19:56:58 Thanks to catch the double increasing request id.
413 Rotate(new_rotation, source); 502 Rotate(new_rotation, source);
414 return; 503 return;
415 } 504 }
416 505
417 for (auto& observer : screen_rotation_animator_observers_) 506 for (auto& observer : screen_rotation_animator_observers_)
418 observer.OnScreenRotationAnimationFinished(this); 507 observer.OnScreenRotationAnimationFinished(this);
419 } 508 }
420 509
421 void ScreenRotationAnimator::set_disable_animation_timers_for_test(
422 bool disable_timers) {
423 disable_animation_timers_for_test_ = disable_timers;
424 }
425
426 void ScreenRotationAnimator::StopAnimating() { 510 void ScreenRotationAnimator::StopAnimating() {
427 GetRootWindow(display_id_) 511 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
428 ->GetChildById(kShellWindowId_ScreenRotationContainer) 512 // the rotation request comes before the copy request finished.
429 ->layer()
430 ->GetAnimator()
431 ->StopAnimating();
432 if (old_layer_tree_owner_) 513 if (old_layer_tree_owner_)
433 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); 514 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
515 if (new_layer_tree_owner_)
516 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
517 if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
518 root_window_->layer()->Remove(black_mask_layer_owner_->layer());
434 } 519 }
435 520
436 } // namespace ash 521 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698