Index: cc/tiles/tile_manager_unittest.cc |
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc |
index b410cc006afbee128f9eea77e880ece3d2c632e1..73d7277253599312ac4d91b590f8d39ba34ebd14 100644 |
--- a/cc/tiles/tile_manager_unittest.cc |
+++ b/cc/tiles/tile_manager_unittest.cc |
@@ -29,6 +29,7 @@ |
#include "cc/test/fake_recording_source.h" |
#include "cc/test/fake_tile_manager.h" |
#include "cc/test/fake_tile_task_manager.h" |
+#include "cc/test/skia_common.h" |
#include "cc/test/test_layer_tree_host_base.h" |
#include "cc/test/test_task_graph_runner.h" |
#include "cc/test/test_tile_priorities.h" |
@@ -2327,7 +2328,7 @@ class CheckerImagingTileManagerTest : public TestLayerTreeHostBase { |
void TearDown() override { |
// Allow all tasks on the image worker to run now. Any scheduled decodes |
// will be aborted. |
- image_worker_task_runner()->set_run_tasks_synchronously(true); |
+ task_runner_->set_run_tasks_synchronously(true); |
} |
LayerTreeSettings CreateSettings() override { |
@@ -2351,8 +2352,11 @@ class CheckerImagingTileManagerTest : public TestLayerTreeHostBase { |
return base::MakeUnique<SynchronousTaskGraphRunner>(); |
} |
- SynchronousSimpleTaskRunner* image_worker_task_runner() const { |
- return task_runner_.get(); |
+ void FlushDecodeTasks() { |
+ while (task_runner_->HasPendingTask()) { |
+ task_runner_->RunUntilIdle(); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
} |
private: |
@@ -2366,6 +2370,7 @@ TEST_F(CheckerImagingTileManagerTest, |
std::unique_ptr<FakeRecordingSource> recording_source = |
FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); |
+ recording_source->set_fill_with_nonsolid_color(true); |
recording_source->SetGenerateDiscardableImagesMetadata(true); |
sk_sp<SkImage> image = SkImage::MakeFromGenerator( |
@@ -2402,5 +2407,254 @@ TEST_F(CheckerImagingTileManagerTest, |
EXPECT_FALSE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting()); |
} |
+TEST_F(CheckerImagingTileManagerTest, BuildsImageDecodeQueueAsExpected) { |
+ const gfx::Size layer_bounds(900, 900); |
+ |
+ std::unique_ptr<FakeRecordingSource> recording_source = |
+ FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); |
+ recording_source->set_fill_with_nonsolid_color(true); |
+ recording_source->SetGenerateDiscardableImagesMetadata(true); |
+ |
+ int dimension = 450; |
+ sk_sp<SkImage> image1 = |
+ CreateDiscardableImage(gfx::Size(dimension, dimension)); |
+ sk_sp<SkImage> image2 = |
+ CreateDiscardableImage(gfx::Size(dimension, dimension)); |
+ sk_sp<SkImage> image3 = |
+ CreateDiscardableImage(gfx::Size(dimension, dimension)); |
+ recording_source->add_draw_image(image1, gfx::Point(0, 0)); |
+ recording_source->add_draw_image(image2, gfx::Point(600, 0)); |
+ recording_source->add_draw_image(image3, gfx::Point(0, 600)); |
+ |
+ recording_source->Rerecord(); |
+ scoped_refptr<RasterSource> raster_source = |
+ RasterSource::CreateFromRecordingSource(recording_source.get(), false); |
+ |
+ gfx::Size tile_size(500, 500); |
+ Region invalidation((gfx::Rect(layer_bounds))); |
+ SetupPendingTree(raster_source, tile_size, invalidation); |
+ |
+ PictureLayerTilingSet* tiling_set = |
+ pending_layer()->picture_layer_tiling_set(); |
+ PictureLayerTiling* pending_tiling = tiling_set->tiling_at(0); |
+ pending_tiling->set_resolution(HIGH_RESOLUTION); |
+ pending_tiling->CreateAllTilesForTesting(); |
+ pending_tiling->SetTilePriorityRectsForTesting( |
+ gfx::Rect(layer_bounds), // Visible rect. |
+ gfx::Rect(layer_bounds), // Skewport rect. |
+ gfx::Rect(layer_bounds), // Soon rect. |
+ gfx::Rect(layer_bounds)); // Eventually rect. |
+ |
+ // PrepareTiles and make sure we account correctly for tiles that have been |
+ // scheduled with checkered images. |
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); |
+ EXPECT_TRUE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting()); |
+ |
+ for (int i = 0; i < 2; i++) { |
+ for (int j = 0; j < 2; j++) { |
+ const Tile* tile = pending_tiling->TileAt(i, j); |
+ EXPECT_TRUE(tile->HasRasterTask()); |
+ if (i == 1 && j == 1) |
+ EXPECT_FALSE(tile->raster_task_scheduled_with_checker_images()); |
+ else |
+ EXPECT_TRUE(tile->raster_task_scheduled_with_checker_images()); |
+ } |
+ } |
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 3); |
+ |
+ // Now raster all the tiles and make sure these tiles are still accounted for |
+ // with checkered images. |
+ static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle(); |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_FALSE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting()); |
+ for (int i = 0; i < 2; i++) { |
+ for (int j = 0; j < 2; j++) { |
+ const Tile* tile = pending_tiling->TileAt(i, j); |
+ EXPECT_FALSE(tile->HasRasterTask()); |
+ EXPECT_FALSE(tile->raster_task_scheduled_with_checker_images()); |
+ EXPECT_TRUE(tile->draw_info().has_resource()); |
+ if (i == 1 && j == 1) |
+ EXPECT_FALSE(tile->draw_info().is_checker_imaged()); |
+ else |
+ EXPECT_TRUE(tile->draw_info().is_checker_imaged()); |
+ } |
+ } |
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 3); |
+ |
+ // Activate the pending tree. |
+ ActivateTree(); |
+ |
+ // Set empty tile priority rects so an empty image decode queue is used. |
+ gfx::Rect empty_rect; |
+ PictureLayerTiling* active_tiling = |
+ active_layer()->picture_layer_tiling_set()->tiling_at(0); |
+ active_tiling->SetTilePriorityRectsForTesting( |
+ gfx::Rect(empty_rect), // Visible rect. |
+ gfx::Rect(empty_rect), // Skewport rect. |
+ gfx::Rect(empty_rect), // Soon rect. |
+ gfx::Rect(empty_rect)); // Eventually rect. |
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); |
+ |
+ // Run the decode tasks. Since the first decode is always scheduled, the |
+ // completion for it should be triggered. |
+ FlushDecodeTasks(); |
+ |
+ // Create a new pending tree to invalidate tiles for decoded images and verify |
+ // that only tiles for |image1| are invalidated. |
+ EXPECT_TRUE(host_impl()->client()->did_request_impl_side_invalidation()); |
+ PerformImplSideInvalidation(); |
+ for (int i = 0; i < 2; i++) { |
+ for (int j = 0; j < 2; j++) { |
+ const Tile* tile = pending_tiling->TileAt(i, j); |
+ if (i == 0 && j == 0) |
+ EXPECT_TRUE(tile); |
+ else |
+ EXPECT_FALSE(tile); |
+ } |
+ } |
+ host_impl()->client()->reset_did_request_impl_side_invalidation(); |
+ |
+ // Activating the tree replaces the checker-imaged tile. |
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 3); |
+ ActivateTree(); |
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 2); |
+ |
+ // Set the tile priority rects such that only the tile with the second image |
+ // is scheduled for decodes, since it is checker-imaged. |
+ gfx::Rect rect_to_raster(600, 0, 300, 900); |
+ active_tiling->SetTilePriorityRectsForTesting( |
+ gfx::Rect(rect_to_raster), // Visible rect. |
+ gfx::Rect(rect_to_raster), // Skewport rect. |
+ gfx::Rect(rect_to_raster), // Soon rect. |
+ gfx::Rect(rect_to_raster)); // Eventually rect. |
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); |
+ |
+ // Run decode tasks to trigger completion of any pending decodes. |
+ FlushDecodeTasks(); |
+ |
+ // Create a new pending tree to invalidate tiles for decoded images and verify |
+ // that only tiles for |image2| are invalidated. |
+ EXPECT_TRUE(host_impl()->client()->did_request_impl_side_invalidation()); |
+ PerformImplSideInvalidation(); |
+ for (int i = 0; i < 2; i++) { |
+ for (int j = 0; j < 2; j++) { |
+ const Tile* tile = pending_tiling->TileAt(i, j); |
+ if (i == 1 && j == 0) |
+ EXPECT_TRUE(tile); |
+ else |
+ EXPECT_FALSE(tile); |
+ } |
+ } |
+ host_impl()->client()->reset_did_request_impl_side_invalidation(); |
+ |
+ // Activating the tree replaces the checker-imaged tile. |
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 2); |
+ ActivateTree(); |
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 1); |
+ |
+ // Set the tile priority rects to cover the complete tiling and change the |
+ // visibility. While |image3| has not yet been decoded, since we are |
+ // invisible no decodes should have been scheduled. |
+ active_tiling->SetTilePriorityRectsForTesting( |
+ gfx::Rect(layer_bounds), // Visible rect. |
+ gfx::Rect(layer_bounds), // Skewport rect. |
+ gfx::Rect(layer_bounds), // Soon rect. |
+ gfx::Rect(layer_bounds)); // Eventually rect. |
+ host_impl()->SetVisible(false); |
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); |
+ FlushDecodeTasks(); |
+ EXPECT_FALSE(host_impl()->client()->did_request_impl_side_invalidation()); |
+} |
+ |
+class CheckerImagingTileManagerMemoryTest |
+ : public CheckerImagingTileManagerTest { |
+ public: |
+ std::unique_ptr<FakeLayerTreeHostImpl> CreateHostImpl( |
+ const LayerTreeSettings& settings, |
+ TaskRunnerProvider* task_runner_provider, |
+ TaskGraphRunner* task_graph_runner) override { |
+ LayerTreeSettings new_settings = settings; |
+ new_settings.gpu_memory_policy.num_resources_limit = 4; |
+ return CheckerImagingTileManagerTest::CreateHostImpl( |
+ new_settings, task_runner_provider, task_graph_runner); |
+ } |
+}; |
+ |
+TEST_F(CheckerImagingTileManagerMemoryTest, AddsAllNowTilesToImageDecodeQueue) { |
+ const gfx::Size layer_bounds(900, 1400); |
+ |
+ std::unique_ptr<FakeRecordingSource> recording_source = |
+ FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); |
+ recording_source->set_fill_with_nonsolid_color(true); |
+ recording_source->SetGenerateDiscardableImagesMetadata(true); |
+ |
+ int dimension = 450; |
+ sk_sp<SkImage> image1 = |
+ CreateDiscardableImage(gfx::Size(dimension, dimension)); |
+ sk_sp<SkImage> image2 = |
+ CreateDiscardableImage(gfx::Size(dimension, dimension)); |
+ recording_source->add_draw_image(image1, gfx::Point(0, 515)); |
+ recording_source->add_draw_image(image2, gfx::Point(515, 515)); |
+ |
+ recording_source->Rerecord(); |
+ scoped_refptr<RasterSource> raster_source = |
+ RasterSource::CreateFromRecordingSource(recording_source.get(), false); |
+ |
+ gfx::Size tile_size(500, 500); |
+ Region invalidation((gfx::Rect(layer_bounds))); |
+ SetupPendingTree(raster_source, tile_size, invalidation); |
+ |
+ PictureLayerTilingSet* tiling_set = |
+ pending_layer()->picture_layer_tiling_set(); |
+ PictureLayerTiling* pending_tiling = tiling_set->tiling_at(0); |
+ pending_tiling->set_resolution(HIGH_RESOLUTION); |
+ pending_tiling->CreateAllTilesForTesting(); |
+ |
+ // Use a rect that only rasterizes the bottom 2 rows of tiles. |
+ gfx::Rect rect_to_raster(0, 500, 900, 900); |
+ pending_tiling->SetTilePriorityRectsForTesting( |
+ rect_to_raster, // Visible rect. |
+ rect_to_raster, // Skewport rect. |
+ rect_to_raster, // Soon rect. |
+ rect_to_raster); // Eventually rect. |
+ |
+ // PrepareTiles, rasterize all scheduled tiles and activate while no images |
+ // have been decoded. |
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); |
+ static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle(); |
+ base::RunLoop().RunUntilIdle(); |
+ ActivateTree(); |
+ |
+ // Expand the visible rect to include the complete tiling. The tile iteration |
+ // will not go beyond the first tile since there are no resources with a lower |
+ // priority that can be evicted. But we should still see image decodes |
+ // scheduled for all visible tiles. |
+ gfx::Rect complete_tiling_rect(layer_bounds); |
+ PictureLayerTiling* active_tiling = |
+ active_layer()->picture_layer_tiling_set()->tiling_at(0); |
+ active_tiling->SetTilePriorityRectsForTesting( |
+ complete_tiling_rect, // Visible rect. |
+ complete_tiling_rect, // Skewport rect. |
+ complete_tiling_rect, // Soon rect. |
+ complete_tiling_rect); // Eventually rect. |
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); |
+ |
+ // Flush all decode tasks. The tiles with checkered images should be |
+ // invalidated. |
+ FlushDecodeTasks(); |
+ EXPECT_TRUE(host_impl()->client()->did_request_impl_side_invalidation()); |
+ PerformImplSideInvalidation(); |
+ for (int i = 0; i < 2; i++) { |
+ for (int j = 0; j < 3; j++) { |
+ const Tile* tile = pending_tiling->TileAt(i, j); |
+ if (j == 1) |
+ EXPECT_TRUE(tile); |
+ else |
+ EXPECT_FALSE(tile); |
+ } |
+ } |
+ host_impl()->client()->reset_did_request_impl_side_invalidation(); |
+} |
+ |
} // namespace |
} // namespace cc |