Commit 7fceb779 authored by vmpstr's avatar vmpstr Committed by Commit bot

cc: Remove tiles from recycle tree that were deleted on active.

This patch removes tiles from the recycle tree that were deleted from
the active tree as a result of a shifting live tiles rect. It is
important to do this, since if the active tree then would recreate
the deleted tile (ie, live tiles rect shift back), we have to ensure
that this tile will be shared when the next pending tree is created.
If we don't do it, we can run into a situation in which we will
continuously raster the same tile.

The patch does the following:
- Adds a way to get a recycled tree twin tiling.
- During LiveTilesRect tile deletion, deletes tiles from the same
  location from the recycle twin (if one exists).

R=danakj, enne

Review URL: https://codereview.chromium.org/502453003

Cr-Commit-Position: refs/heads/master@{#291949}
parent aa7e9b61
...@@ -118,6 +118,11 @@ class FixedInvalidationPictureLayerTilingClient ...@@ -118,6 +118,11 @@ class FixedInvalidationPictureLayerTilingClient
return base_client_->GetTwinTiling(tiling); return base_client_->GetTwinTiling(tiling);
} }
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) OVERRIDE {
return base_client_->GetRecycledTwinTiling(tiling);
}
virtual size_t GetMaxTilesForInterestArea() const OVERRIDE { virtual size_t GetMaxTilesForInterestArea() const OVERRIDE {
return base_client_->GetMaxTilesForInterestArea(); return base_client_->GetMaxTilesForInterestArea();
} }
......
...@@ -109,7 +109,7 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { ...@@ -109,7 +109,7 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
LayerImpl::PushPropertiesTo(base_layer); LayerImpl::PushPropertiesTo(base_layer);
// When the pending tree pushes to the active tree, the pending twin // When the pending tree pushes to the active tree, the pending twin
// disappears. // becomes recycled.
layer_impl->twin_layer_ = NULL; layer_impl->twin_layer_ = NULL;
twin_layer_ = NULL; twin_layer_ = NULL;
...@@ -541,6 +541,12 @@ gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const { ...@@ -541,6 +541,12 @@ gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
return visible_rect_in_content_space; return visible_rect_in_content_space;
} }
PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() {
// TODO(vmpstr): Maintain recycled twin as a member. crbug.com/407418
return static_cast<PictureLayerImpl*>(
layer_tree_impl()->FindRecycleTreeLayerById(id()));
}
void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
if (layer_tree_impl()->IsActiveTree()) { if (layer_tree_impl()->IsActiveTree()) {
gfx::RectF layer_damage_rect = gfx::RectF layer_damage_rect =
...@@ -613,6 +619,14 @@ const PictureLayerTiling* PictureLayerImpl::GetTwinTiling( ...@@ -613,6 +619,14 @@ const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
return twin_layer_->tilings_->TilingAtScale(tiling->contents_scale()); return twin_layer_->tilings_->TilingAtScale(tiling->contents_scale());
} }
PictureLayerTiling* PictureLayerImpl::GetRecycledTwinTiling(
const PictureLayerTiling* tiling) {
PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
if (!recycled_twin || !recycled_twin->tilings_)
return NULL;
return recycled_twin->tilings_->TilingAtScale(tiling->contents_scale());
}
size_t PictureLayerImpl::GetMaxTilesForInterestArea() const { size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
return layer_tree_impl()->settings().max_tiles_for_interest_area; return layer_tree_impl()->settings().max_tiles_for_interest_area;
} }
...@@ -1253,8 +1267,7 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer( ...@@ -1253,8 +1267,7 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
if (to_remove.empty()) if (to_remove.empty())
return; return;
PictureLayerImpl* recycled_twin = static_cast<PictureLayerImpl*>( PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
layer_tree_impl()->FindRecycleTreeLayerById(id()));
// Remove tilings on this tree and the twin tree. // Remove tilings on this tree and the twin tree.
for (size_t i = 0; i < to_remove.size(); ++i) { for (size_t i = 0; i < to_remove.size(); ++i) {
const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]); const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
......
...@@ -124,6 +124,8 @@ class CC_EXPORT PictureLayerImpl ...@@ -124,6 +124,8 @@ class CC_EXPORT PictureLayerImpl
virtual const Region* GetInvalidation() OVERRIDE; virtual const Region* GetInvalidation() OVERRIDE;
virtual const PictureLayerTiling* GetTwinTiling( virtual const PictureLayerTiling* GetTwinTiling(
const PictureLayerTiling* tiling) const OVERRIDE; const PictureLayerTiling* tiling) const OVERRIDE;
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) OVERRIDE;
virtual size_t GetMaxTilesForInterestArea() const OVERRIDE; virtual size_t GetMaxTilesForInterestArea() const OVERRIDE;
virtual float GetSkewportTargetTimeInSeconds() const OVERRIDE; virtual float GetSkewportTargetTimeInSeconds() const OVERRIDE;
virtual int GetSkewportExtrapolationLimitInContentPixels() const OVERRIDE; virtual int GetSkewportExtrapolationLimitInContentPixels() const OVERRIDE;
...@@ -173,6 +175,7 @@ class CC_EXPORT PictureLayerImpl ...@@ -173,6 +175,7 @@ class CC_EXPORT PictureLayerImpl
const gfx::Rect& rect, const gfx::Rect& rect,
const Region& missing_region) const; const Region& missing_region) const;
gfx::Rect GetViewportForTilePriorityInContentSpace() const; gfx::Rect GetViewportForTilePriorityInContentSpace() const;
PictureLayerImpl* GetRecycledTwinLayer();
void DoPostCommitInitializationIfNeeded() { void DoPostCommitInitializationIfNeeded() {
if (needs_post_commit_initialization_) if (needs_post_commit_initialization_)
......
...@@ -53,7 +53,10 @@ class PictureLayerImplTest : public testing::Test { ...@@ -53,7 +53,10 @@ class PictureLayerImplTest : public testing::Test {
host_impl_(ImplSidePaintingSettings(), host_impl_(ImplSidePaintingSettings(),
&proxy_, &proxy_,
&shared_bitmap_manager_), &shared_bitmap_manager_),
id_(7) {} id_(7),
pending_layer_(NULL),
old_pending_layer_(NULL),
active_layer_(NULL) {}
explicit PictureLayerImplTest(const LayerTreeSettings& settings) explicit PictureLayerImplTest(const LayerTreeSettings& settings)
: proxy_(base::MessageLoopProxy::current()), : proxy_(base::MessageLoopProxy::current()),
...@@ -86,6 +89,8 @@ class PictureLayerImplTest : public testing::Test { ...@@ -86,6 +89,8 @@ class PictureLayerImplTest : public testing::Test {
void ActivateTree() { void ActivateTree() {
host_impl_.ActivateSyncTree(); host_impl_.ActivateSyncTree();
CHECK(!host_impl_.pending_tree()); CHECK(!host_impl_.pending_tree());
CHECK(host_impl_.recycle_tree());
old_pending_layer_ = pending_layer_;
pending_layer_ = NULL; pending_layer_ = NULL;
active_layer_ = static_cast<FakePictureLayerImpl*>( active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_)); host_impl_.active_tree()->LayerById(id_));
...@@ -266,6 +271,7 @@ class PictureLayerImplTest : public testing::Test { ...@@ -266,6 +271,7 @@ class PictureLayerImplTest : public testing::Test {
FakeLayerTreeHostImpl host_impl_; FakeLayerTreeHostImpl host_impl_;
int id_; int id_;
FakePictureLayerImpl* pending_layer_; FakePictureLayerImpl* pending_layer_;
FakePictureLayerImpl* old_pending_layer_;
FakePictureLayerImpl* active_layer_; FakePictureLayerImpl* active_layer_;
private: private:
...@@ -4145,5 +4151,31 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, ...@@ -4145,5 +4151,31 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
VerifyEvictionConsidersOcclusion(active_layer_, VerifyEvictionConsidersOcclusion(active_layer_,
total_expected_occluded_tile_count); total_expected_occluded_tile_count);
} }
TEST_F(PictureLayerImplTest, RecycledTwinLayer) {
gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
scoped_refptr<FakePicturePileImpl> pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
SetupPendingTree(pile);
EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer());
ActivateTree();
EXPECT_TRUE(active_layer_->GetRecycledTwinLayer());
EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer());
SetupPendingTree(pile);
EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer());
EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
ActivateTree();
EXPECT_TRUE(active_layer_->GetRecycledTwinLayer());
EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer());
host_impl_.ResetRecycleTreeForTesting();
EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
}
} // namespace } // namespace
} // namespace cc } // namespace cc
...@@ -607,6 +607,15 @@ void PictureLayerTiling::UpdateTilePriorities( ...@@ -607,6 +607,15 @@ void PictureLayerTiling::UpdateTilePriorities(
current_eventually_rect_ = eventually_rect; current_eventually_rect_ = eventually_rect;
} }
void PictureLayerTiling::RemoveTileAt(int i, int j) {
TileMapKey key(i, j);
TileMap::iterator found = tiles_.find(key);
if (found == tiles_.end())
return;
ReleaseTile(found->second.get(), client_->GetTree());
tiles_.erase(found);
}
void PictureLayerTiling::SetLiveTilesRect( void PictureLayerTiling::SetLiveTilesRect(
const gfx::Rect& new_live_tiles_rect) { const gfx::Rect& new_live_tiles_rect) {
DCHECK(new_live_tiles_rect.IsEmpty() || DCHECK(new_live_tiles_rect.IsEmpty() ||
...@@ -617,6 +626,7 @@ void PictureLayerTiling::SetLiveTilesRect( ...@@ -617,6 +626,7 @@ void PictureLayerTiling::SetLiveTilesRect(
return; return;
// Iterate to delete all tiles outside of our new live_tiles rect. // Iterate to delete all tiles outside of our new live_tiles rect.
PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this);
for (TilingData::DifferenceIterator iter(&tiling_data_, for (TilingData::DifferenceIterator iter(&tiling_data_,
live_tiles_rect_, live_tiles_rect_,
new_live_tiles_rect); new_live_tiles_rect);
...@@ -629,6 +639,8 @@ void PictureLayerTiling::SetLiveTilesRect( ...@@ -629,6 +639,8 @@ void PictureLayerTiling::SetLiveTilesRect(
if (found != tiles_.end()) { if (found != tiles_.end()) {
ReleaseTile(found->second.get(), client_->GetTree()); ReleaseTile(found->second.get(), client_->GetTree());
tiles_.erase(found); tiles_.erase(found);
if (recycled_twin)
recycled_twin->RemoveTileAt(iter.index_x(), iter.index_y());
} }
} }
......
...@@ -44,6 +44,8 @@ class CC_EXPORT PictureLayerTilingClient { ...@@ -44,6 +44,8 @@ class CC_EXPORT PictureLayerTilingClient {
virtual const Region* GetInvalidation() = 0; virtual const Region* GetInvalidation() = 0;
virtual const PictureLayerTiling* GetTwinTiling( virtual const PictureLayerTiling* GetTwinTiling(
const PictureLayerTiling* tiling) const = 0; const PictureLayerTiling* tiling) const = 0;
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) = 0;
virtual size_t GetMaxTilesForInterestArea() const = 0; virtual size_t GetMaxTilesForInterestArea() const = 0;
virtual float GetSkewportTargetTimeInSeconds() const = 0; virtual float GetSkewportTargetTimeInSeconds() const = 0;
virtual int GetSkewportExtrapolationLimitInContentPixels() const = 0; virtual int GetSkewportExtrapolationLimitInContentPixels() const = 0;
...@@ -295,6 +297,7 @@ class CC_EXPORT PictureLayerTiling { ...@@ -295,6 +297,7 @@ class CC_EXPORT PictureLayerTiling {
PictureLayerTilingClient* client); PictureLayerTilingClient* client);
void SetLiveTilesRect(const gfx::Rect& live_tiles_rect); void SetLiveTilesRect(const gfx::Rect& live_tiles_rect);
Tile* CreateTile(int i, int j, const PictureLayerTiling* twin_tiling); Tile* CreateTile(int i, int j, const PictureLayerTiling* twin_tiling);
void RemoveTileAt(int i, int j);
// Computes a skewport. The calculation extrapolates the last visible // Computes a skewport. The calculation extrapolates the last visible
// rect and the current visible rect to expand the skewport to where it // rect and the current visible rect to expand the skewport to where it
......
...@@ -1948,5 +1948,88 @@ TEST(PictureLayerTilingTest, ResetClearsPriorities) { ...@@ -1948,5 +1948,88 @@ TEST(PictureLayerTilingTest, ResetClearsPriorities) {
tiles.clear(); tiles.clear();
} }
TEST(PictureLayerTilingTest, RecycledTilesCleared) {
// This test performs the following:
// Setup:
// - Two tilings, one active one recycled with all tiles shared.
// Procedure:
// - Viewport moves somewhere far away and active tiling clears tiles.
// - Viewport moves back and a new active tiling tile is created.
// Result:
// - Recycle tiling does _not_ have the tile in the same location (thus it
// will be shared next time a pending tiling is created).
FakePictureLayerTilingClient client;
scoped_ptr<TestablePictureLayerTiling> tiling;
client.SetTileSize(gfx::Size(100, 100));
client.set_tree(ACTIVE_TREE);
client.set_max_tiles_for_interest_area(10);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
gfx::Size(10000, 10000),
&client);
// Create all tiles on this tiling.
tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(0, 0, 100, 100),
1.0f,
1.0f,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
FakePictureLayerTilingClient second_client;
second_client.SetTileSize(gfx::Size(100, 100));
second_client.set_tree(PENDING_TREE);
second_client.set_twin_tiling(tiling.get());
second_client.set_max_tiles_for_interest_area(10);
scoped_ptr<TestablePictureLayerTiling> second_tiling;
second_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
gfx::Size(10000, 10000),
&second_client);
// Create all tiles on the second tiling. All tiles should be shared.
second_tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(0, 0, 100, 100),
1.0f,
1.0f,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
// Verify that tiles exist and are shared.
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_EQ(tiling->TileAt(0, 0), second_tiling->TileAt(0, 0));
// Set the second tiling as recycled.
client.set_twin_tiling(NULL);
client.set_recycled_twin_tiling(second_tiling.get());
second_client.set_twin_tiling(NULL);
// Move the viewport far away from the (0, 0) tile.
tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(9000, 9000, 100, 100),
1.0f,
2.0,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
// Ensure the tile was deleted.
EXPECT_FALSE(tiling->TileAt(0, 0));
// Move the viewport back to (0, 0) tile.
tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(0, 0, 100, 100),
1.0f,
3.0,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
// Ensure that we now have a tile here, but the recycle tiling does not.
EXPECT_TRUE(tiling->TileAt(0, 0));
EXPECT_FALSE(second_tiling->TileAt(0, 0));
}
} // namespace } // namespace
} // namespace cc } // namespace cc
...@@ -60,6 +60,7 @@ class FakePictureLayerImpl : public PictureLayerImpl { ...@@ -60,6 +60,7 @@ class FakePictureLayerImpl : public PictureLayerImpl {
using PictureLayerImpl::MinimumContentsScale; using PictureLayerImpl::MinimumContentsScale;
using PictureLayerImpl::GetViewportForTilePriorityInContentSpace; using PictureLayerImpl::GetViewportForTilePriorityInContentSpace;
using PictureLayerImpl::SanityCheckTilingState; using PictureLayerImpl::SanityCheckTilingState;
using PictureLayerImpl::GetRecycledTwinLayer;
using PictureLayerImpl::UpdateIdealScales; using PictureLayerImpl::UpdateIdealScales;
using PictureLayerImpl::MaximumTilingContentsScale; using PictureLayerImpl::MaximumTilingContentsScale;
......
...@@ -15,10 +15,12 @@ FakePictureLayerTilingClient::FakePictureLayerTilingClient() ...@@ -15,10 +15,12 @@ FakePictureLayerTilingClient::FakePictureLayerTilingClient()
: tile_manager_(new FakeTileManager(&tile_manager_client_)), : tile_manager_(new FakeTileManager(&tile_manager_client_)),
pile_(FakePicturePileImpl::CreateInfiniteFilledPile()), pile_(FakePicturePileImpl::CreateInfiniteFilledPile()),
twin_tiling_(NULL), twin_tiling_(NULL),
recycled_twin_tiling_(NULL),
allow_create_tile_(true), allow_create_tile_(true),
max_tiles_for_interest_area_(10000), max_tiles_for_interest_area_(10000),
skewport_target_time_in_seconds_(1.0f), skewport_target_time_in_seconds_(1.0f),
skewport_extrapolation_limit_in_content_pixels_(2000) {} skewport_extrapolation_limit_in_content_pixels_(2000) {
}
FakePictureLayerTilingClient::FakePictureLayerTilingClient( FakePictureLayerTilingClient::FakePictureLayerTilingClient(
ResourceProvider* resource_provider) ResourceProvider* resource_provider)
...@@ -28,9 +30,11 @@ FakePictureLayerTilingClient::FakePictureLayerTilingClient( ...@@ -28,9 +30,11 @@ FakePictureLayerTilingClient::FakePictureLayerTilingClient(
new FakeTileManager(&tile_manager_client_, resource_pool_.get())), new FakeTileManager(&tile_manager_client_, resource_pool_.get())),
pile_(FakePicturePileImpl::CreateInfiniteFilledPile()), pile_(FakePicturePileImpl::CreateInfiniteFilledPile()),
twin_tiling_(NULL), twin_tiling_(NULL),
recycled_twin_tiling_(NULL),
allow_create_tile_(true), allow_create_tile_(true),
max_tiles_for_interest_area_(10000), max_tiles_for_interest_area_(10000),
skewport_target_time_in_seconds_(1.0f) {} skewport_target_time_in_seconds_(1.0f) {
}
FakePictureLayerTilingClient::~FakePictureLayerTilingClient() { FakePictureLayerTilingClient::~FakePictureLayerTilingClient() {
} }
...@@ -79,6 +83,11 @@ const PictureLayerTiling* FakePictureLayerTilingClient::GetTwinTiling( ...@@ -79,6 +83,11 @@ const PictureLayerTiling* FakePictureLayerTilingClient::GetTwinTiling(
return twin_tiling_; return twin_tiling_;
} }
PictureLayerTiling* FakePictureLayerTilingClient::GetRecycledTwinTiling(
const PictureLayerTiling* tiling) {
return recycled_twin_tiling_;
}
WhichTree FakePictureLayerTilingClient::GetTree() const { WhichTree FakePictureLayerTilingClient::GetTree() const {
return tree_; return tree_;
} }
......
...@@ -36,9 +36,14 @@ class FakePictureLayerTilingClient : public PictureLayerTilingClient { ...@@ -36,9 +36,14 @@ class FakePictureLayerTilingClient : public PictureLayerTilingClient {
virtual const Region* GetInvalidation() OVERRIDE; virtual const Region* GetInvalidation() OVERRIDE;
virtual const PictureLayerTiling* GetTwinTiling( virtual const PictureLayerTiling* GetTwinTiling(
const PictureLayerTiling* tiling) const OVERRIDE; const PictureLayerTiling* tiling) const OVERRIDE;
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) OVERRIDE;
virtual WhichTree GetTree() const OVERRIDE; virtual WhichTree GetTree() const OVERRIDE;
void set_twin_tiling(PictureLayerTiling* tiling) { twin_tiling_ = tiling; } void set_twin_tiling(PictureLayerTiling* tiling) { twin_tiling_ = tiling; }
void set_recycled_twin_tiling(PictureLayerTiling* tiling) {
recycled_twin_tiling_ = tiling;
}
void set_text_rect(const gfx::Rect& rect) { text_rect_ = rect; } void set_text_rect(const gfx::Rect& rect) { text_rect_ = rect; }
void set_allow_create_tile(bool allow) { allow_create_tile_ = allow; } void set_allow_create_tile(bool allow) { allow_create_tile_ = allow; }
void set_invalidation(const Region& region) { invalidation_ = region; } void set_invalidation(const Region& region) { invalidation_ = region; }
...@@ -64,6 +69,7 @@ class FakePictureLayerTilingClient : public PictureLayerTilingClient { ...@@ -64,6 +69,7 @@ class FakePictureLayerTilingClient : public PictureLayerTilingClient {
scoped_refptr<PicturePileImpl> pile_; scoped_refptr<PicturePileImpl> pile_;
gfx::Size tile_size_; gfx::Size tile_size_;
PictureLayerTiling* twin_tiling_; PictureLayerTiling* twin_tiling_;
PictureLayerTiling* recycled_twin_tiling_;
gfx::Rect text_rect_; gfx::Rect text_rect_;
bool allow_create_tile_; bool allow_create_tile_;
Region invalidation_; Region invalidation_;
......
...@@ -1167,6 +1167,12 @@ void LayerTreeHostImpl::ResetTreesForTesting() { ...@@ -1167,6 +1167,12 @@ void LayerTreeHostImpl::ResetTreesForTesting() {
recycle_tree_.reset(); recycle_tree_.reset();
} }
void LayerTreeHostImpl::ResetRecycleTreeForTesting() {
if (recycle_tree_)
recycle_tree_->DetachLayerTree();
recycle_tree_.reset();
}
void LayerTreeHostImpl::EnforceManagedMemoryPolicy( void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
const ManagedMemoryPolicy& policy) { const ManagedMemoryPolicy& policy) {
......
...@@ -217,6 +217,7 @@ class CC_EXPORT LayerTreeHostImpl ...@@ -217,6 +217,7 @@ class CC_EXPORT LayerTreeHostImpl
// Resets all of the trees to an empty state. // Resets all of the trees to an empty state.
void ResetTreesForTesting(); void ResetTreesForTesting();
void ResetRecycleTreeForTesting();
DrawMode GetDrawMode() const; DrawMode GetDrawMode() const;
......
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