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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: ash/rotator/screen_rotation_animator.cc
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
index 102b8d0e7b3082f7ff25656d2f1243ecad206e22..f1f393467199bed821fd1e4e8a72c236e48c1a15 100644
--- a/ash/rotator/screen_rotation_animator.cc
+++ b/ash/rotator/screen_rotation_animator.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "ash/common/ash_switches.h"
#include "ash/display/window_tree_host_manager.h"
#include "ash/rotator/screen_rotation_animation.h"
#include "ash/rotator/screen_rotation_animator_observer.h"
@@ -16,6 +17,8 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_element.h"
@@ -185,20 +188,13 @@ class ScreenRotationAnimationMetricsReporter
} // namespace
-struct ScreenRotationAnimator::ScreenRotationRequest {
- ScreenRotationRequest(display::Display::Rotation to_rotation,
- display::Display::RotationSource from_source)
- : new_rotation(to_rotation), source(from_source) {}
- display::Display::Rotation new_rotation;
- display::Display::RotationSource source;
-};
-
ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
: display_id_(display_id),
is_rotating_(false),
metrics_reporter_(
base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
disable_animation_timers_for_test_(false),
+ enable_smooth_rotation_for_test_(false),
weak_factory_(this) {}
ScreenRotationAnimator::~ScreenRotationAnimator() {
@@ -213,9 +209,85 @@ ScreenRotationAnimator::~ScreenRotationAnimator() {
metrics_reporter_.reset();
}
+void ScreenRotationAnimator::StartRotationAnimation(
+ std::unique_ptr<ScreenRotationRequest> rotation_request) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshEnableSmoothScreenRotation) ||
+ 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.
+ RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request));
+ } else {
+ CreateOldLayerTree();
+ AnimateRotation(std::move(rotation_request));
+ }
+}
+
+void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation(
+ std::unique_ptr<ScreenRotationRequest> rotation_request) {
+ std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
+ CreateAfterCopyCallback(std::move(rotation_request));
+ ui::Layer* layer = GetRootWindow(display_id_)->layer();
+ copy_output_request->set_area(gfx::Rect(layer->size()));
+ layer->RequestCopyOfOutput(std::move(copy_output_request));
+}
+
+std::unique_ptr<cc::CopyOutputRequest>
+ScreenRotationAnimator::CreateAfterCopyCallback(
+ std::unique_ptr<ScreenRotationRequest> rotation_request) {
+ return cc::CopyOutputRequest::CreateRequest(
+ base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation,
+ weak_factory_.GetWeakPtr(), base::Passed(&rotation_request)));
+}
+
+void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation(
+ std::unique_ptr<ScreenRotationRequest> rotation_request,
+ std::unique_ptr<cc::CopyOutputResult> result) {
+ // If display was removed, should abort rotation.
+ if (!IsDisplayIdValid(display_id_)) {
+ ProcessAnimationQueue();
+ return;
+ }
+ // Fall back to recreate layers solution when the copy request has been
+ // canceled or failed. It would fail if, for examples: a) The layer is removed
+ // from the compositor and destroyed before committing the request to the
+ // compositor. b) The compositor is shutdown.
+ if (result->IsEmpty())
+ CreateOldLayerTree();
+ else
+ CopyOldLayerTree(std::move(result));
+ AnimateRotation(std::move(rotation_request));
+}
+
+void ScreenRotationAnimator::CreateOldLayerTree() {
+ old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_));
+}
+
+void ScreenRotationAnimator::CopyOldLayerTree(
+ std::unique_ptr<cc::CopyOutputResult> result) {
+ cc::TextureMailbox texture_mailbox;
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+ result->TakeTexture(&texture_mailbox, &release_callback);
+ DCHECK(texture_mailbox.IsTexture());
+
+ aura::Window* root_window = GetRootWindow(display_id_);
+ gfx::Rect rect(root_window->layer()->size());
+ std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
+ copy_layer->SetBounds(rect);
+ copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
+ rect.size());
+ old_layer_tree_owner_ =
+ base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
+}
+
void ScreenRotationAnimator::AnimateRotation(
std::unique_ptr<ScreenRotationRequest> rotation_request) {
aura::Window* root_window = GetRootWindow(display_id_);
+ std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer(
+ new LayerCleanupObserver(weak_factory_.GetWeakPtr()));
+ ui::Layer* old_root_layer = old_layer_tree_owner_->root();
+ old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree");
+ // Add the cloned layer tree in to the root, so it will be rendered.
+ root_window->layer()->Add(old_root_layer);
+ root_window->layer()->StackAtTop(old_root_layer);
const gfx::Rect original_screen_bounds = root_window->GetTargetBounds();
@@ -230,18 +302,6 @@ void ScreenRotationAnimator::AnimateRotation(
const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
- std::unique_ptr<ui::LayerTreeOwner> old_layer_tree =
- ::wm::RecreateLayers(root_window);
- old_layer_tree->root()->set_name("ScreenRotationAnimator:old_layer_tree");
-
- // Add the cloned layer tree in to the root, so it will be rendered.
- root_window->layer()->Add(old_layer_tree->root());
- root_window->layer()->StackAtTop(old_layer_tree->root());
-
- old_layer_tree_owner_ = std::move(old_layer_tree);
- std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer(
- new LayerCleanupObserver(weak_factory_.GetWeakPtr()));
-
Shell::GetInstance()->display_manager()->SetDisplayRotation(
display_id_, rotation_request->new_rotation, rotation_request->source);
@@ -249,7 +309,6 @@ void ScreenRotationAnimator::AnimateRotation(
const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
rotated_screen_bounds.height() / 2);
- ui::Layer* old_root_layer = old_layer_tree_owner_->root();
// We must animate each non-cloned child layer individually because the cloned
// layer was added as a child to |root_window|'s layer so that it will be
// rendered.
@@ -328,7 +387,7 @@ void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
StopAnimating();
} else {
is_rotating_ = true;
- AnimateRotation(std::move(rotation_request));
+ StartRotationAnimation(std::move(rotation_request));
}
}
@@ -362,6 +421,11 @@ void ScreenRotationAnimator::set_disable_animation_timers_for_test(
disable_animation_timers_for_test_ = disable_timers;
}
+void ScreenRotationAnimator::set_enable_smooth_rotation_for_test(
+ bool enable_smooth_rotation) {
+ enable_smooth_rotation_for_test_ = enable_smooth_rotation;
+}
+
void ScreenRotationAnimator::StopAnimating() {
aura::Window* root_window = GetRootWindow(display_id_);
for (ui::Layer* child_layer : root_window->layer()->children()) {

Powered by Google App Engine
This is Rietveld 408576698