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

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

Issue 2780823002: Uses copy request to flatten the layers to do screen rotation animation. (Closed)
Patch Set: Add tests for enable_smooth_screen_rotation code path. 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> 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"
20 #include "ui/compositor/layer.h" 23 #include "ui/compositor/layer.h"
21 #include "ui/compositor/layer_animation_element.h" 24 #include "ui/compositor/layer_animation_element.h"
22 #include "ui/compositor/layer_animation_observer.h" 25 #include "ui/compositor/layer_animation_observer.h"
23 #include "ui/compositor/layer_animation_sequence.h" 26 #include "ui/compositor/layer_animation_sequence.h"
24 #include "ui/compositor/layer_animator.h" 27 #include "ui/compositor/layer_animator.h"
25 #include "ui/compositor/layer_owner.h" 28 #include "ui/compositor/layer_owner.h"
26 #include "ui/compositor/layer_tree_owner.h" 29 #include "ui/compositor/layer_tree_owner.h"
27 #include "ui/display/display.h" 30 #include "ui/display/display.h"
28 #include "ui/display/manager/display_manager.h" 31 #include "ui/display/manager/display_manager.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 void Report(int value) override { 181 void Report(int value) override {
179 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); 182 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
180 } 183 }
181 184
182 private: 185 private:
183 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); 186 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
184 }; 187 };
185 188
186 } // namespace 189 } // namespace
187 190
188 struct ScreenRotationAnimator::ScreenRotationRequest {
189 ScreenRotationRequest(display::Display::Rotation to_rotation,
190 display::Display::RotationSource from_source)
191 : new_rotation(to_rotation), source(from_source) {}
192 display::Display::Rotation new_rotation;
193 display::Display::RotationSource source;
194 };
195
196 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) 191 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
197 : display_id_(display_id), 192 : display_id_(display_id),
198 is_rotating_(false), 193 is_rotating_(false),
199 metrics_reporter_( 194 metrics_reporter_(
200 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), 195 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
201 disable_animation_timers_for_test_(false), 196 disable_animation_timers_for_test_(false),
197 enable_smooth_rotation_for_test_(false),
202 weak_factory_(this) {} 198 weak_factory_(this) {}
203 199
204 ScreenRotationAnimator::~ScreenRotationAnimator() { 200 ScreenRotationAnimator::~ScreenRotationAnimator() {
205 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from 201 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from
206 // calling a method on the |animator_|. 202 // calling a method on the |animator_|.
207 weak_factory_.InvalidateWeakPtrs(); 203 weak_factory_.InvalidateWeakPtrs();
208 204
209 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in 205 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
210 // order to make sure |metrics_reporter_| outlives the attached animation 206 // order to make sure |metrics_reporter_| outlives the attached animation
211 // sequence. 207 // sequence.
212 old_layer_tree_owner_.reset(); 208 old_layer_tree_owner_.reset();
213 metrics_reporter_.reset(); 209 metrics_reporter_.reset();
214 } 210 }
215 211
212 void ScreenRotationAnimator::StartRotationAnimation(
213 std::unique_ptr<ScreenRotationRequest> rotation_request) {
214 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
215 switches::kAshEnableSmoothScreenRotation) ||
216 enable_smooth_rotation_for_test_) {
oshima 2017/04/04 20:23:13 you can just add the switch in the test.
wutao 2017/04/05 00:09:22 Done.
217 RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request));
218 } else {
219 CreateOldLayerTree();
220 AnimateRotation(std::move(rotation_request));
221 }
222 }
223
224 void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation(
225 std::unique_ptr<ScreenRotationRequest> rotation_request) {
226 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
227 CreateAfterCopyCallback(std::move(rotation_request));
228 ui::Layer* layer = GetRootWindow(display_id_)->layer();
229 copy_output_request->set_area(gfx::Rect(layer->size()));
230 layer->RequestCopyOfOutput(std::move(copy_output_request));
231 }
232
233 std::unique_ptr<cc::CopyOutputRequest>
234 ScreenRotationAnimator::CreateAfterCopyCallback(
235 std::unique_ptr<ScreenRotationRequest> rotation_request) {
236 return cc::CopyOutputRequest::CreateRequest(
237 base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation,
238 weak_factory_.GetWeakPtr(), base::Passed(&rotation_request)));
239 }
240
241 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation(
242 std::unique_ptr<ScreenRotationRequest> rotation_request,
243 std::unique_ptr<cc::CopyOutputResult> result) {
244 // If display was removed, should abort rotation.
245 if (!IsDisplayIdValid(display_id_)) {
246 ProcessAnimationQueue();
247 return;
248 }
249 // Fall back to recreate layers solution when the copy request has been
250 // canceled or failed. It would fail if, for examples: a) The layer is removed
251 // from the compositor and destroyed before committing the request to the
252 // compositor. b) The compositor is shutdown.
253 if (result->IsEmpty())
254 CreateOldLayerTree();
255 else
256 CopyOldLayerTree(std::move(result));
257 AnimateRotation(std::move(rotation_request));
258 }
259
260 void ScreenRotationAnimator::CreateOldLayerTree() {
261 old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_));
262 }
263
264 void ScreenRotationAnimator::CopyOldLayerTree(
265 std::unique_ptr<cc::CopyOutputResult> result) {
266 cc::TextureMailbox texture_mailbox;
267 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
268 result->TakeTexture(&texture_mailbox, &release_callback);
269 DCHECK(texture_mailbox.IsTexture());
270
271 aura::Window* root_window = GetRootWindow(display_id_);
272 gfx::Rect rect(root_window->layer()->size());
273 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
274 copy_layer->SetBounds(rect);
275 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
276 rect.size());
277 old_layer_tree_owner_ =
278 base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
279 }
280
216 void ScreenRotationAnimator::AnimateRotation( 281 void ScreenRotationAnimator::AnimateRotation(
217 std::unique_ptr<ScreenRotationRequest> rotation_request) { 282 std::unique_ptr<ScreenRotationRequest> rotation_request) {
218 aura::Window* root_window = GetRootWindow(display_id_); 283 aura::Window* root_window = GetRootWindow(display_id_);
284 std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer(
285 new LayerCleanupObserver(weak_factory_.GetWeakPtr()));
286 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
287 old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree");
288 // Add the cloned layer tree in to the root, so it will be rendered.
289 root_window->layer()->Add(old_root_layer);
290 root_window->layer()->StackAtTop(old_root_layer);
219 291
220 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); 292 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds();
221 293
222 const int rotation_factor = GetRotationFactor( 294 const int rotation_factor = GetRotationFactor(
223 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); 295 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation);
224 296
225 const int old_layer_initial_rotation_degrees = GetInitialDegrees( 297 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
226 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); 298 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation);
227 299
228 const base::TimeDelta duration = 300 const base::TimeDelta duration =
229 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); 301 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
230 302
231 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; 303 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
232 304
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( 305 Shell::GetInstance()->display_manager()->SetDisplayRotation(
246 display_id_, rotation_request->new_rotation, rotation_request->source); 306 display_id_, rotation_request->new_rotation, rotation_request->source);
247 307
248 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); 308 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds();
249 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, 309 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
250 rotated_screen_bounds.height() / 2); 310 rotated_screen_bounds.height() / 2);
251 311
252 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
253 // We must animate each non-cloned child layer individually because the cloned 312 // We must animate each non-cloned child layer individually because the cloned
254 // layer was added as a child to |root_window|'s layer so that it will be 313 // layer was added as a child to |root_window|'s layer so that it will be
255 // rendered. 314 // rendered.
256 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and 315 // 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 316 // its current children so that we only need to initiate two
258 // LayerAnimationSequences. One for the new layers and one for the old layer. 317 // LayerAnimationSequences. One for the new layers and one for the old layer.
259 for (ui::Layer* child_layer : root_window->layer()->children()) { 318 for (ui::Layer* child_layer : root_window->layer()->children()) {
260 // Skip the cloned layer because it has a different animation. 319 // Skip the cloned layer because it has a different animation.
261 if (child_layer == old_root_layer) 320 if (child_layer == old_root_layer)
262 continue; 321 continue;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 base::MakeUnique<ScreenRotationRequest>(new_rotation, source); 380 base::MakeUnique<ScreenRotationRequest>(new_rotation, source);
322 381
323 if (is_rotating_) { 382 if (is_rotating_) {
324 last_pending_request_ = std::move(rotation_request); 383 last_pending_request_ = std::move(rotation_request);
325 // The pending request will be processed when the 384 // The pending request will be processed when the
326 // OnLayerAnimation(Ended|Aborted) methods should be called after 385 // OnLayerAnimation(Ended|Aborted) methods should be called after
327 // StopAnimating(). 386 // StopAnimating().
328 StopAnimating(); 387 StopAnimating();
329 } else { 388 } else {
330 is_rotating_ = true; 389 is_rotating_ = true;
331 AnimateRotation(std::move(rotation_request)); 390 StartRotationAnimation(std::move(rotation_request));
332 } 391 }
333 } 392 }
334 393
335 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( 394 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver(
336 ScreenRotationAnimatorObserver* observer) { 395 ScreenRotationAnimatorObserver* observer) {
337 screen_rotation_animator_observers_.AddObserver(observer); 396 screen_rotation_animator_observers_.AddObserver(observer);
338 } 397 }
339 398
340 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( 399 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
341 ScreenRotationAnimatorObserver* observer) { 400 ScreenRotationAnimatorObserver* observer) {
(...skipping 13 matching lines...) Expand all
355 414
356 for (auto& observer : screen_rotation_animator_observers_) 415 for (auto& observer : screen_rotation_animator_observers_)
357 observer.OnScreenRotationAnimationFinished(this); 416 observer.OnScreenRotationAnimationFinished(this);
358 } 417 }
359 418
360 void ScreenRotationAnimator::set_disable_animation_timers_for_test( 419 void ScreenRotationAnimator::set_disable_animation_timers_for_test(
361 bool disable_timers) { 420 bool disable_timers) {
362 disable_animation_timers_for_test_ = disable_timers; 421 disable_animation_timers_for_test_ = disable_timers;
363 } 422 }
364 423
424 void ScreenRotationAnimator::set_enable_smooth_rotation_for_test(
425 bool enable_smooth_rotation) {
426 enable_smooth_rotation_for_test_ = enable_smooth_rotation;
427 }
428
365 void ScreenRotationAnimator::StopAnimating() { 429 void ScreenRotationAnimator::StopAnimating() {
366 aura::Window* root_window = GetRootWindow(display_id_); 430 aura::Window* root_window = GetRootWindow(display_id_);
367 for (ui::Layer* child_layer : root_window->layer()->children()) { 431 for (ui::Layer* child_layer : root_window->layer()->children()) {
368 if (child_layer == old_layer_tree_owner_->root()) 432 if (child_layer == old_layer_tree_owner_->root())
369 continue; 433 continue;
370 434
371 child_layer->GetAnimator()->StopAnimating(); 435 child_layer->GetAnimator()->StopAnimating();
372 } 436 }
373 437
374 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); 438 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
375 } 439 }
376 440
377 } // namespace ash 441 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698