| Index: cc/trees/layer_tree_host_unittest_checkerimaging.cc
|
| diff --git a/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/cc/trees/layer_tree_host_unittest_checkerimaging.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..580fa3e8363750231bfdefba0131195cbd2613dc
|
| --- /dev/null
|
| +++ b/cc/trees/layer_tree_host_unittest_checkerimaging.cc
|
| @@ -0,0 +1,196 @@
|
| +// Copyright 2017 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 "cc/base/completion_event.h"
|
| +#include "cc/test/begin_frame_args_test.h"
|
| +#include "cc/test/fake_content_layer_client.h"
|
| +#include "cc/test/fake_external_begin_frame_source.h"
|
| +#include "cc/test/fake_picture_layer.h"
|
| +#include "cc/test/layer_tree_test.h"
|
| +#include "cc/test/skia_common.h"
|
| +#include "cc/test/test_compositor_frame_sink.h"
|
| +#include "cc/trees/layer_tree_impl.h"
|
| +
|
| +namespace cc {
|
| +namespace {
|
| +
|
| +class LayerTreeHostCheckerImagingTest : public LayerTreeTest {
|
| + public:
|
| + void BeginTest() override { PostSetNeedsCommitToMainThread(); }
|
| + void AfterTest() override {}
|
| +
|
| + void InitializeSettings(LayerTreeSettings* settings) override {
|
| + settings->image_decode_tasks_enabled = true;
|
| + settings->enable_checker_imaging = true;
|
| + }
|
| +
|
| + void SetupTree() override {
|
| + // Set up a content client which creates the following tiling, x denoting
|
| + // the image to checker:
|
| + // |---|---|---|---|
|
| + // | x | x | | |
|
| + // |---|---|---|---|
|
| + // | x | x | | |
|
| + // |---|---|---|---|
|
| + gfx::Size layer_size(1000, 500);
|
| + content_layer_client_.set_bounds(layer_size);
|
| + content_layer_client_.set_fill_with_nonsolid_color(true);
|
| + sk_sp<SkImage> checkerable_image =
|
| + CreateDiscardableImage(gfx::Size(450, 450));
|
| + content_layer_client_.add_draw_image(checkerable_image, gfx::Point(0, 0),
|
| + PaintFlags());
|
| +
|
| + layer_tree_host()->SetRootLayer(
|
| + FakePictureLayer::Create(&content_layer_client_));
|
| + layer_tree_host()->root_layer()->SetBounds(layer_size);
|
| + LayerTreeTest::SetupTree();
|
| + }
|
| +
|
| + void FlushImageDecodeTasks() {
|
| + CompletionEvent completion_event;
|
| + image_worker_task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind([](CompletionEvent* event) { event->Signal(); },
|
| + base::Unretained(&completion_event)));
|
| + completion_event.Wait();
|
| + }
|
| +
|
| + private:
|
| + // Accessed only on the main thread.
|
| + FakeContentLayerClient content_layer_client_;
|
| +};
|
| +
|
| +class LayerTreeHostCheckerImagingTestMergeWithMainFrame
|
| + : public LayerTreeHostCheckerImagingTest {
|
| + void BeginMainFrame(const BeginFrameArgs& args) override {
|
| + if (layer_tree_host()->SourceFrameNumber() == 1) {
|
| + // The first commit has happened, invalidate a tile outside the region
|
| + // for the image to ensure that the final invalidation on the pending
|
| + // tree is the union of this and impl-side invalidation.
|
| + layer_tree_host()->root_layer()->SetNeedsDisplayRect(
|
| + gfx::Rect(600, 0, 50, 500));
|
| + layer_tree_host()->SetNeedsCommit();
|
| + }
|
| + }
|
| +
|
| + void ReadyToCommitOnThread(LayerTreeHostImpl* host_impl) override {
|
| + if (num_of_commits_ == 1) {
|
| + // Send the blocked invalidation request before notifying that we're ready
|
| + // to commit, since the invalidation will be merged with the commit.
|
| + host_impl->BlockImplSideInvalidationRequestsForTesting(false);
|
| + }
|
| + }
|
| +
|
| + void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
|
| + switch (++num_of_commits_) {
|
| + case 1: {
|
| + // The first commit has happened. Run all tasks on the image worker to
|
| + // ensure that the decode completion triggers an impl-side invalidation
|
| + // request.
|
| + FlushImageDecodeTasks();
|
| +
|
| + // Block notifying the scheduler of this request until we get a commit.
|
| + host_impl->BlockImplSideInvalidationRequestsForTesting(true);
|
| + host_impl->SetNeedsCommit();
|
| + } break;
|
| + case 2: {
|
| + // Ensure that the expected tiles are invalidated on the sync tree.
|
| + PictureLayerImpl* sync_layer_impl = static_cast<PictureLayerImpl*>(
|
| + host_impl->sync_tree()->root_layer_for_testing());
|
| + PictureLayerTiling* sync_tiling =
|
| + sync_layer_impl->picture_layer_tiling_set()
|
| + ->FindTilingWithResolution(TileResolution::HIGH_RESOLUTION);
|
| +
|
| + for (int i = 0; i < 4; i++) {
|
| + for (int j = 0; j < 2; j++) {
|
| + Tile* tile =
|
| + sync_tiling->TileAt(i, j) ? sync_tiling->TileAt(i, j) : nullptr;
|
| +
|
| + // If this is the pending tree, then only the invalidated tiles
|
| + // exist and have a raster task. If its the active tree, then only
|
| + // the invalidated tiles have a raster task.
|
| + if (i < 3) {
|
| + EXPECT_TRUE(tile->HasRasterTask());
|
| + } else if (host_impl->pending_tree()) {
|
| + EXPECT_EQ(tile, nullptr);
|
| + } else {
|
| + EXPECT_FALSE(tile->HasRasterTask());
|
| + }
|
| + }
|
| + }
|
| + EndTest();
|
| + } break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + void AfterTest() override { EXPECT_EQ(num_of_commits_, 2); }
|
| +
|
| + int num_of_commits_ = 0;
|
| +};
|
| +
|
| +SINGLE_AND_MULTI_THREAD_TEST_F(
|
| + LayerTreeHostCheckerImagingTestMergeWithMainFrame);
|
| +
|
| +class LayerTreeHostCheckerImagingTestImplSideTree
|
| + : public LayerTreeHostCheckerImagingTest {
|
| + void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
|
| + ++num_of_impl_side_invalidations_;
|
| +
|
| + // The source_frame_number of the sync tree should be from the first main
|
| + // frame, since this is an impl-side sync tree.
|
| + EXPECT_EQ(host_impl->sync_tree()->source_frame_number(), 0);
|
| +
|
| + // Ensure that the expected tiles are invalidated on the sync tree.
|
| + PictureLayerImpl* sync_layer_impl = static_cast<PictureLayerImpl*>(
|
| + host_impl->sync_tree()->root_layer_for_testing());
|
| + PictureLayerTiling* sync_tiling =
|
| + sync_layer_impl->picture_layer_tiling_set()->FindTilingWithResolution(
|
| + TileResolution::HIGH_RESOLUTION);
|
| +
|
| + for (int i = 0; i < 4; i++) {
|
| + for (int j = 0; j < 2; j++) {
|
| + Tile* tile =
|
| + sync_tiling->TileAt(i, j) ? sync_tiling->TileAt(i, j) : nullptr;
|
| +
|
| + // If this is the pending tree, then only the invalidated tiles
|
| + // exist and have a raster task. If its the active tree, then only
|
| + // the invalidated tiles have a raster task.
|
| + if (i < 2) {
|
| + EXPECT_TRUE(tile->HasRasterTask());
|
| + } else if (host_impl->pending_tree()) {
|
| + EXPECT_EQ(tile, nullptr);
|
| + } else {
|
| + EXPECT_FALSE(tile->HasRasterTask());
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
|
| + num_of_commits_++;
|
| + }
|
| +
|
| + void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
|
| + num_of_activations_++;
|
| + if (num_of_activations_ == 2)
|
| + EndTest();
|
| + }
|
| +
|
| + void AfterTest() override {
|
| + EXPECT_EQ(num_of_activations_, 2);
|
| + EXPECT_EQ(num_of_commits_, 1);
|
| + EXPECT_EQ(num_of_impl_side_invalidations_, 1);
|
| + }
|
| +
|
| + int num_of_activations_ = 0;
|
| + int num_of_commits_ = 0;
|
| + int num_of_impl_side_invalidations_ = 0;
|
| +};
|
| +
|
| +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCheckerImagingTestImplSideTree);
|
| +
|
| +} // namespace
|
| +} // namespace cc
|
|
|