Commit 35283853 authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Chromium LUCI CQ

CopyLayerContentToLayer that copies the content to existing layer

instead of new layer. This will be used to address performance
related issue.

Bug: None
Test: covered by unittest

Change-Id: I3b6b0bfdd8ab4fb11b21fd7b84f677169023bfe9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2560549
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarSammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#833097}
parent ee95e437
......@@ -2262,6 +2262,7 @@ test("ash_unittests") {
"tray_action/test_tray_action_client.cc",
"tray_action/test_tray_action_client.h",
"tray_action/tray_action_unittest.cc",
"utility/layer_util_unittest.cc",
"utility/screenshot_controller_unittest.cc",
"wallpaper/wallpaper_controller_unittest.cc",
"wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc",
......
......@@ -43,6 +43,23 @@ void CopyToNewLayerOnCopyRequestFinished(
std::move(layer_copy_callback).Run(std::move(copy_layer));
}
void CopyToLayerOnCopyRequestFinished(
GetTargetLayerCallback get_target_layer_callback,
std::unique_ptr<viz::CopyOutputResult> copy_result) {
if (get_target_layer_callback.IsCancelled())
return;
if (!copy_result || copy_result->IsEmpty())
return;
ui::Layer* layer = nullptr;
std::move(get_target_layer_callback).Run(&layer);
if (!layer)
return;
CopyCopyOutputResultToLayer(std::move(copy_result), layer);
}
} // namespace
std::unique_ptr<ui::Layer> CreateLayerFromCopyOutputResult(
......@@ -64,4 +81,17 @@ void CopyLayerContentToNewLayer(ui::Layer* layer, LayerCopyCallback callback) {
layer->RequestCopyOfOutput(std::move(copy_request));
}
void CopyLayerContentToLayer(ui::Layer* layer,
GetTargetLayerCallback callback) {
auto new_callback =
base::BindOnce(&CopyToLayerOnCopyRequestFinished, std::move(callback));
auto copy_request = std::make_unique<viz::CopyOutputRequest>(
viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
std::move(new_callback));
gfx::Rect bounds(layer->size());
copy_request->set_area(bounds);
copy_request->set_result_selection(bounds);
layer->RequestCopyOfOutput(std::move(copy_request));
}
} // namespace ash
......@@ -7,6 +7,7 @@
#include <memory>
#include "ash/ash_export.h"
#include "base/callback.h"
namespace ui {
......@@ -18,16 +19,25 @@ class CopyOutputResult;
}
namespace ash {
using LayerCopyCallback =
base::OnceCallback<void(std::unique_ptr<ui::Layer> new_layer)>;
// Creates the new layer using the image in |copy_result|.
std::unique_ptr<ui::Layer> CreateLayerFromCopyOutputResult(
ASH_EXPORT std::unique_ptr<ui::Layer> CreateLayerFromCopyOutputResult(
std::unique_ptr<viz::CopyOutputResult> copy_result);
using LayerCopyCallback =
base::OnceCallback<void(std::unique_ptr<ui::Layer> new_layer)>;
// Creates a new layer that has a copy of the |layer|'s content. This is an
// async API and a new layer will be passed to the |callback| when copy is done.
void CopyLayerContentToNewLayer(ui::Layer* layer, LayerCopyCallback callback);
ASH_EXPORT void CopyLayerContentToNewLayer(ui::Layer* layer,
LayerCopyCallback callback);
using GetTargetLayerCallback = base::OnceCallback<void(ui::Layer**)>;
// Copy the content of |original_layer| to a new layer given via |callback|.
// This is an async API and |callback| is called when the copy result is ready.
ASH_EXPORT void CopyLayerContentToLayer(ui::Layer* original_layer,
GetTargetLayerCallback callback);
} // namespace ash
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/utility/layer_util.h"
#include "base/cancelable_callback.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/timer/timer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/test/test_compositor_host.h"
#include "ui/compositor/test/test_context_factories.h"
#include "ui/gfx/geometry/rect.h"
namespace ash {
namespace {
class LayerUtilTest : public testing::Test {
public:
LayerUtilTest() = default;
LayerUtilTest(const LayerUtilTest&) = delete;
LayerUtilTest& operator=(const LayerUtilTest&) = delete;
~LayerUtilTest() override = default;
// testing::Test:
void SetUp() override {
context_factories_ = std::make_unique<ui::TestContextFactories>(false);
const gfx::Rect bounds(300, 300);
host_.reset(ui::TestCompositorHost::Create(
bounds, context_factories_->GetContextFactory()));
host_->Show();
compositor()->SetRootLayer(&root_);
}
void TearDown() override {
host_.reset();
context_factories_.reset();
}
void Advance(const base::TimeDelta& delta) {
task_environment_.FastForwardBy(delta);
}
void GenerateOneFrame() { compositor()->ScheduleFullRedraw(); }
ui::Compositor* compositor() { return host_->GetCompositor(); }
ui::Layer* root_layer() { return &root_; }
private:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME,
base::test::TaskEnvironment::MainThreadType::UI};
std::unique_ptr<ui::TestContextFactories> context_factories_;
std::unique_ptr<ui::TestCompositorHost> host_;
ui::Layer root_;
};
} // namespace
TEST_F(LayerUtilTest, CopyContentToExistingLayer) {
ui::Layer layer1;
layer1.SetBounds(gfx::Rect(100, 100));
root_layer()->Add(&layer1);
ui::Layer layer2;
layer2.SetBounds(gfx::Rect(100, 100));
root_layer()->Add(&layer2);
{
bool called = false;
base::CancelableOnceCallback<void(ui::Layer**)> cancelable;
cancelable.Reset(base::BindLambdaForTesting([&](ui::Layer** dummy) {
called = true;
*dummy = &layer2;
}));
CopyLayerContentToLayer(&layer1, cancelable.callback());
GenerateOneFrame();
Advance(base::TimeDelta::FromMilliseconds(16));
EXPECT_TRUE(called);
}
// Test cancel scenario.
{
bool called = false;
base::CancelableOnceCallback<void(ui::Layer**)> cancelable;
cancelable.Reset(base::BindLambdaForTesting([&](ui::Layer** dummy) {
called = true;
*dummy = &layer2;
}));
CopyLayerContentToLayer(&layer1, cancelable.callback());
cancelable.Cancel();
GenerateOneFrame();
Advance(base::TimeDelta::FromMilliseconds(16));
EXPECT_FALSE(called);
}
}
} // namespace ash
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment