Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/rotator/screen_rotation_animator.h" | 5 #include "ash/rotator/screen_rotation_animator.h" |
| 6 | 6 |
| 7 #include <string> | |
| 8 #include <utility> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "ash/ash_switches.h" | 7 #include "ash/ash_switches.h" |
| 12 #include "ash/display/window_tree_host_manager.h" | 8 #include "ash/display/window_tree_host_manager.h" |
| 13 #include "ash/public/cpp/shell_window_ids.h" | 9 #include "ash/public/cpp/shell_window_ids.h" |
| 14 #include "ash/rotator/screen_rotation_animation.h" | 10 #include "ash/rotator/screen_rotation_animation.h" |
| 15 #include "ash/rotator/screen_rotation_animator_observer.h" | 11 #include "ash/rotator/screen_rotation_animator_observer.h" |
| 16 #include "ash/shell.h" | 12 #include "ash/shell.h" |
| 13 #include "ash/utility/transformer_util.h" | |
| 17 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 18 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 19 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 20 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 21 #include "cc/output/copy_output_request.h" | 18 #include "cc/output/copy_output_request.h" |
| 22 #include "cc/output/copy_output_result.h" | 19 #include "cc/output/copy_output_result.h" |
| 23 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
| 21 #include "ui/compositor/callback_layer_animation_observer.h" | |
| 24 #include "ui/compositor/layer.h" | 22 #include "ui/compositor/layer.h" |
| 25 #include "ui/compositor/layer_animation_element.h" | 23 #include "ui/compositor/layer_animation_element.h" |
| 26 #include "ui/compositor/layer_animation_observer.h" | |
| 27 #include "ui/compositor/layer_animation_sequence.h" | 24 #include "ui/compositor/layer_animation_sequence.h" |
| 28 #include "ui/compositor/layer_animator.h" | 25 #include "ui/compositor/layer_animator.h" |
| 29 #include "ui/compositor/layer_owner.h" | 26 #include "ui/compositor/layer_owner.h" |
| 30 #include "ui/compositor/layer_tree_owner.h" | 27 #include "ui/compositor/layer_tree_owner.h" |
| 31 #include "ui/display/display.h" | 28 #include "ui/display/display.h" |
| 32 #include "ui/display/manager/display_manager.h" | 29 #include "ui/display/manager/display_manager.h" |
| 33 #include "ui/display/manager/managed_display_info.h" | 30 #include "ui/display/manager/managed_display_info.h" |
| 34 #include "ui/gfx/animation/tween.h" | 31 #include "ui/gfx/animation/tween.h" |
| 35 #include "ui/gfx/geometry/point.h" | 32 #include "ui/gfx/geometry/point.h" |
| 36 #include "ui/gfx/geometry/rect.h" | 33 #include "ui/gfx/geometry/rect.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 return (initial_rotation + 3) % 4 == new_rotation | 67 return (initial_rotation + 3) % 4 == new_rotation |
| 71 ? kCounterClockWiseRotationFactor | 68 ? kCounterClockWiseRotationFactor |
| 72 : kClockWiseRotationFactor; | 69 : kClockWiseRotationFactor; |
| 73 } | 70 } |
| 74 | 71 |
| 75 aura::Window* GetRootWindow(int64_t display_id) { | 72 aura::Window* GetRootWindow(int64_t display_id) { |
| 76 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( | 73 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( |
| 77 display_id); | 74 display_id); |
| 78 } | 75 } |
| 79 | 76 |
| 77 aura::Window* GetScreenRotationContainer(aura::Window* root_window) { | |
| 78 return root_window->GetChildById(kShellWindowId_ScreenRotationContainer); | |
| 79 } | |
| 80 | |
| 80 // Returns true if the rotation between |initial_rotation| and |new_rotation| is | 81 // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
| 81 // 180 degrees. | 82 // 180 degrees. |
| 82 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, | 83 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
| 83 display::Display::Rotation new_rotation) { | 84 display::Display::Rotation new_rotation) { |
| 84 return (initial_rotation + 2) % 4 == new_rotation; | 85 return (initial_rotation + 2) % 4 == new_rotation; |
| 85 } | 86 } |
| 86 | 87 |
| 87 // Returns the initial degrees the old layer animation to begin with. | 88 // Returns the initial degrees the old layer animation to begin with. |
| 88 int GetInitialDegrees(display::Display::Rotation initial_rotation, | 89 int GetInitialDegrees(display::Display::Rotation initial_rotation, |
| 89 display::Display::Rotation new_rotation) { | 90 display::Display::Rotation new_rotation) { |
| 90 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); | 91 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
| 91 } | 92 } |
| 92 | 93 |
| 93 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner | 94 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { |
| 94 // when notified that a layer animation has ended or was aborted. | 95 // Add the cloned/copied layer tree into the root, so it will be rendered. |
| 95 class LayerCleanupObserver : public ui::LayerAnimationObserver { | 96 root_window->layer()->Add(layer); |
| 96 public: | 97 root_window->layer()->StackAtTop(layer); |
| 97 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_| | |
| 98 // instance and the |animator_| isn't detaching itself as an observer when | |
| 99 // being destroyed. However, ideally, when |animator_| is destroying, | |
| 100 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and | |
| 101 // delete |this| before |animator_| deleted. | |
| 102 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator); | |
| 103 ~LayerCleanupObserver() override; | |
| 104 | |
| 105 // ui::LayerAnimationObserver: | |
| 106 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; | |
| 107 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; | |
| 108 void OnLayerAnimationScheduled( | |
| 109 ui::LayerAnimationSequence* sequence) override {} | |
| 110 | |
| 111 protected: | |
| 112 // ui::LayerAnimationObserver: | |
| 113 bool RequiresNotificationWhenAnimatorDestroyed() const override { | |
| 114 return true; | |
| 115 } | |
| 116 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; | |
| 117 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; | |
| 118 | |
| 119 private: | |
| 120 base::WeakPtr<ScreenRotationAnimator> animator_; | |
| 121 | |
| 122 // The LayerAnimationSequence that |this| has been attached to. Defaults to | |
| 123 // nullptr. | |
| 124 ui::LayerAnimationSequence* sequence_; | |
| 125 | |
| 126 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); | |
| 127 }; | |
| 128 | |
| 129 LayerCleanupObserver::LayerCleanupObserver( | |
| 130 base::WeakPtr<ScreenRotationAnimator> animator) | |
| 131 : animator_(animator), sequence_(nullptr) {} | |
| 132 | |
| 133 LayerCleanupObserver::~LayerCleanupObserver() { | |
| 134 // We must eplicitly detach from |sequence_| because we return true from | |
| 135 // RequiresNotificationWhenAnimatorDestroyed. | |
| 136 if (sequence_) | |
| 137 sequence_->RemoveObserver(this); | |
| 138 } | 98 } |
| 139 | 99 |
| 140 void LayerCleanupObserver::OnLayerAnimationEnded( | 100 void AddLayerBelowWindowLayer(aura::Window* root_window, |
| 141 ui::LayerAnimationSequence* sequence) { | 101 ui::Layer* top_layer, |
| 142 if (animator_) | 102 ui::Layer* layer) { |
| 143 animator_->ProcessAnimationQueue(); | 103 // Add the cloned/copied layer tree into the root, so it will be rendered. |
| 144 | 104 root_window->layer()->Add(layer); |
| 145 delete this; | 105 root_window->layer()->StackBelow(layer, top_layer); |
| 146 } | 106 } |
| 147 | 107 |
| 148 void LayerCleanupObserver::OnLayerAnimationAborted( | 108 // The Callback will be invoked when all animation sequences have |
| 149 ui::LayerAnimationSequence* sequence) { | 109 // finished. |observer| will be destroyed after invoking the Callback if it |
| 150 if (animator_) | 110 // returns true. |
| 151 animator_->ProcessAnimationQueue(); | 111 bool AnimationEndedCallback( |
| 152 | 112 base::WeakPtr<ScreenRotationAnimator> animator, |
| 153 delete this; | 113 const ui::CallbackLayerAnimationObserver& observer) { |
| 114 if (animator) | |
| 115 animator->ProcessAnimationQueue(); | |
| 116 return true; | |
| 154 } | 117 } |
| 155 | 118 |
| 156 void LayerCleanupObserver::OnAttachedToSequence( | 119 // Creates a Transform for the old layer in screen rotation animation. |
| 157 ui::LayerAnimationSequence* sequence) { | 120 gfx::Transform CreateScreenRotationOldLayerTransformForDisplay( |
| 158 sequence_ = sequence; | 121 display::Display::Rotation old_rotation, |
| 122 display::Display::Rotation new_rotation, | |
| 123 const display::Display& display) { | |
| 124 gfx::Transform inverse; | |
| 125 CHECK(CreateRotationTransform(old_rotation, new_rotation, display) | |
| 126 .GetInverse(&inverse)); | |
| 127 return inverse; | |
| 159 } | 128 } |
| 160 | 129 |
| 161 void LayerCleanupObserver::OnDetachedFromSequence( | 130 // The |request_id| changed since last copy request, which means a |
| 162 ui::LayerAnimationSequence* sequence) { | 131 // new rotation stated, we need to ignore this copy result. |
| 163 DCHECK_EQ(sequence, sequence_); | 132 bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) { |
| 164 sequence_ = nullptr; | 133 DCHECK(request_id <= current_request_id); |
| 134 return request_id < current_request_id; | |
| 135 } | |
| 136 | |
| 137 // In the following cases, abort rotation: | |
| 138 // 1) if the display was removed, | |
| 139 // 2) the copy request has been canceled or failed. It would fail if, | |
| 140 // for examples: a) The layer is removed from the compositor and destroye | |
| 141 // before committing the request to the compositor. b) The compositor is | |
| 142 // shutdown. | |
| 143 bool AbortRotation(int64_t display_id, cc::CopyOutputResult* result) { | |
| 144 return !IsDisplayIdValid(display_id) || result->IsEmpty(); | |
| 145 } | |
| 146 | |
| 147 // Creates a black mask layer and returns the |layer_owner|. | |
| 148 std::unique_ptr<ui::LayerOwner> CreateBlackMaskLayerOwner( | |
| 149 const gfx::Rect& rect) { | |
| 150 std::unique_ptr<ui::Layer> black_mask_layer = | |
| 151 base::MakeUnique<ui::Layer>(ui::LAYER_SOLID_COLOR); | |
| 152 black_mask_layer->SetBounds(rect); | |
| 153 black_mask_layer->SetColor(SK_ColorBLACK); | |
| 154 std::unique_ptr<ui::LayerOwner> black_mask_layer_owner = | |
| 155 base::MakeUnique<ui::LayerOwner>(); | |
| 156 black_mask_layer_owner->SetLayer(std::move(black_mask_layer)); | |
| 157 return black_mask_layer_owner; | |
| 165 } | 158 } |
| 166 | 159 |
| 167 class ScreenRotationAnimationMetricsReporter | 160 class ScreenRotationAnimationMetricsReporter |
| 168 : public ui::AnimationMetricsReporter { | 161 : public ui::AnimationMetricsReporter { |
| 169 public: | 162 public: |
| 170 ScreenRotationAnimationMetricsReporter() {} | 163 ScreenRotationAnimationMetricsReporter() {} |
| 171 ~ScreenRotationAnimationMetricsReporter() override {} | 164 ~ScreenRotationAnimationMetricsReporter() override {} |
| 172 | 165 |
| 173 void Report(int value) override { | 166 void Report(int value) override { |
| 174 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); | 167 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
| 175 } | 168 } |
| 176 | 169 |
| 177 private: | 170 private: |
| 178 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); | 171 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); |
| 179 }; | 172 }; |
| 180 | 173 |
| 181 } // namespace | 174 } // namespace |
| 182 | 175 |
| 183 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) | 176 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) |
| 184 : display_id_(display_id), | 177 : display_id_(display_id), |
| 185 screen_rotation_state_(IDLE), | 178 screen_rotation_state_(IDLE), |
| 186 rotation_request_id_(0), | 179 rotation_request_id_(0), |
| 187 metrics_reporter_( | 180 metrics_reporter_( |
| 188 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), | 181 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), |
| 189 disable_animation_timers_for_test_(false), | 182 disable_animation_timers_for_test_(false), |
| 183 has_switch_ash_enable_smooth_screen_rotation_( | |
| 184 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 185 switches::kAshEnableSmoothScreenRotation)), | |
| 186 root_window_(GetRootWindow(display_id_)), | |
| 187 screen_rotation_container_layer_( | |
| 188 GetScreenRotationContainer(root_window_)->layer()), | |
| 190 weak_factory_(this) {} | 189 weak_factory_(this) {} |
| 191 | 190 |
| 192 ScreenRotationAnimator::~ScreenRotationAnimator() { | 191 ScreenRotationAnimator::~ScreenRotationAnimator() { |
| 193 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from | 192 // To prevent a call to |AnimationEndedCallback()| from calling a method on |
| 194 // calling a method on the |animator_|. | 193 // the |animator_|. |
| 195 weak_factory_.InvalidateWeakPtrs(); | 194 weak_factory_.InvalidateWeakPtrs(); |
| 196 | 195 |
| 197 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in | 196 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in |
| 198 // order to make sure |metrics_reporter_| outlives the attached animation | 197 // order to make sure |metrics_reporter_| outlives the attached animation |
| 199 // sequence. | 198 // sequence. |
| 200 old_layer_tree_owner_.reset(); | 199 old_layer_tree_owner_.reset(); |
| 201 metrics_reporter_.reset(); | 200 metrics_reporter_.reset(); |
| 202 } | 201 } |
| 203 | 202 |
| 204 void ScreenRotationAnimator::StartRotationAnimation( | 203 void ScreenRotationAnimator::StartRotationAnimation( |
| 205 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 204 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| 206 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 205 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 |
| OLD | NEW |