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