This source file includes following definitions.
- SetupTree
- BeginTest
- DidCommitAndDrawFrame
- PrepareToDrawOnThread
- AfterTest
- SetupTree
- BeginTest
- DidCommitAndDrawFrame
- PrepareToDrawOnThread
- AfterTest
- BeginTest
- SetupTree
- PrepareToDrawOnThread
- SwapBuffersOnThread
- DidCommit
- AfterTest
- BeginTest
- SetupTree
- PrepareToDrawOnThread
- DidCommitAndDrawFrame
- AfterTest
- BeginTest
- SetupTree
- PrepareToDrawOnThread
- DidCommitAndDrawFrame
- AfterTest
- SetupTree
- BeginTest
- PrepareToDrawOnThread
- SwapBuffersOnThread
- AfterTest
- BeginTest
- PrepareToDrawOnThread
- SwapBuffersOnThread
- AfterTest
- InitializeSettings
- BeginTest
- SetupTree
- PrepareToDrawOnThread
- UpdateVisibleTilesOnThread
- SwapBuffersOnThread
- AfterTest
#include "cc/trees/layer_tree_host.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/time/time.h"
#include "cc/test/fake_content_layer.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_painted_scrollbar_layer.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/damage_tracker.h"
#include "cc/trees/layer_tree_impl.h"
namespace cc {
namespace {
class LayerTreeHostDamageTest : public LayerTreeTest {};
class LayerTreeHostDamageTestSetNeedsRedraw
: public LayerTreeHostDamageTest {
virtual void SetupTree() OVERRIDE {
scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
root->SetBounds(gfx::Size(10, 10));
layer_tree_host()->SetRootLayer(root);
LayerTreeHostDamageTest::SetupTree();
}
virtual void BeginTest() OVERRIDE {
draw_count_ = 0;
PostSetNeedsCommitToMainThread();
}
virtual void DidCommitAndDrawFrame() OVERRIDE {
switch (layer_tree_host()->source_frame_number()) {
case 1:
layer_tree_host()->SetNeedsRedraw();
break;
}
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
RenderSurfaceImpl* root_surface =
impl->active_tree()->root_layer()->render_surface();
gfx::RectF root_damage =
root_surface->damage_tracker()->current_damage_rect();
switch (draw_count_) {
case 0:
EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
break;
case 1:
EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
EndTest();
break;
case 2:
NOTREACHED();
}
++draw_count_;
return draw_result;
}
virtual void AfterTest() OVERRIDE {}
int draw_count_;
FakeContentLayerClient client_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetNeedsRedraw);
class LayerTreeHostDamageTestSetViewportSize
: public LayerTreeHostDamageTest {
virtual void SetupTree() OVERRIDE {
scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
root->SetBounds(gfx::Size(10, 10));
layer_tree_host()->SetRootLayer(root);
LayerTreeHostDamageTest::SetupTree();
}
virtual void BeginTest() OVERRIDE {
draw_count_ = 0;
PostSetNeedsCommitToMainThread();
}
virtual void DidCommitAndDrawFrame() OVERRIDE {
switch (layer_tree_host()->source_frame_number()) {
case 1:
layer_tree_host()->SetViewportSize(gfx::Size(15, 15));
break;
}
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
RenderSurfaceImpl* root_surface =
impl->active_tree()->root_layer()->render_surface();
gfx::RectF root_damage =
root_surface->damage_tracker()->current_damage_rect();
switch (draw_count_) {
case 0:
EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
break;
case 1:
EXPECT_EQ(gfx::RectF(15.f, 15.f).ToString(), root_damage.ToString());
EndTest();
break;
case 2:
NOTREACHED();
}
++draw_count_;
return draw_result;
}
virtual void AfterTest() OVERRIDE {}
int draw_count_;
FakeContentLayerClient client_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);
class LayerTreeHostDamageTestNoDamageDoesNotSwap
: public LayerTreeHostDamageTest {
virtual void BeginTest() OVERRIDE {
expect_swap_and_succeed_ = 0;
did_swaps_ = 0;
did_swap_and_succeed_ = 0;
PostSetNeedsCommitToMainThread();
}
virtual void SetupTree() OVERRIDE {
scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
root->SetBounds(gfx::Size(10, 10));
content_ = FakeContentLayer::Create(&client_);
content_->SetBounds(gfx::Size(2000, 100));
root->AddChild(content_);
layer_tree_host()->SetRootLayer(root);
LayerTreeHostDamageTest::SetupTree();
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
int source_frame = host_impl->active_tree()->source_frame_number();
switch (source_frame) {
case 0:
++expect_swap_and_succeed_;
break;
case 1:
break;
case 2:
++expect_swap_and_succeed_;
break;
case 3:
EndTest();
break;
}
return draw_result;
}
virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
bool result) OVERRIDE {
++did_swaps_;
if (result)
++did_swap_and_succeed_;
EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
}
virtual void DidCommit() OVERRIDE {
int next_frame = layer_tree_host()->source_frame_number();
switch (next_frame) {
case 1:
layer_tree_host()->SetNeedsCommit();
break;
case 2:
content_->SetNeedsDisplayRect(
gfx::Rect(layer_tree_host()->device_viewport_size()));
break;
case 3:
content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
layer_tree_host()->SetNeedsCommit();
break;
}
}
virtual void AfterTest() OVERRIDE {
EXPECT_EQ(4, did_swaps_);
EXPECT_EQ(2, expect_swap_and_succeed_);
EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
}
FakeContentLayerClient client_;
scoped_refptr<FakeContentLayer> content_;
int expect_swap_and_succeed_;
int did_swaps_;
int did_swap_and_succeed_;
};
SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
LayerTreeHostDamageTestNoDamageDoesNotSwap);
class LayerTreeHostDamageTestNoDamageReadbackDoesDraw
: public LayerTreeHostDamageTest {
virtual void BeginTest() OVERRIDE {
PostSetNeedsCommitToMainThread();
}
virtual void SetupTree() OVERRIDE {
scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
root->SetBounds(gfx::Size(10, 10));
content_ = FakeContentLayer::Create(&client_);
content_->SetBounds(gfx::Size(100, 100));
root->AddChild(content_);
layer_tree_host()->SetRootLayer(root);
LayerTreeHostDamageTest::SetupTree();
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
int source_frame = host_impl->active_tree()->source_frame_number();
switch (source_frame) {
case 0:
break;
case 1: {
RenderSurfaceImpl* root_surface =
host_impl->active_tree()->root_layer()->render_surface();
gfx::RectF root_damage =
root_surface->damage_tracker()->current_damage_rect();
root_damage.Intersect(root_surface->content_rect());
EXPECT_TRUE(root_damage.Contains(gfx::Rect(3, 3, 1, 1)));
break;
}
case 2:
break;
case 3:
NOTREACHED();
break;
}
return draw_result;
}
virtual void DidCommitAndDrawFrame() OVERRIDE {
int next_frame = layer_tree_host()->source_frame_number();
switch (next_frame) {
case 1: {
char pixels[4];
layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels),
gfx::Rect(3, 3, 1, 1));
EndTest();
break;
}
}
}
virtual void AfterTest() OVERRIDE {}
FakeContentLayerClient client_;
scoped_refptr<FakeContentLayer> content_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageReadbackDoesDraw);
class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
virtual void BeginTest() OVERRIDE {
PostSetNeedsCommitToMainThread();
}
virtual void SetupTree() OVERRIDE {
root_ = FakeContentLayer::Create(&client_);
child_ = FakeContentLayer::Create(&client_);
root_->SetBounds(gfx::Size(500, 500));
child_->SetPosition(gfx::Point(100, 100));
child_->SetBounds(gfx::Size(30, 30));
root_->AddChild(child_);
layer_tree_host()->SetRootLayer(root_);
LayerTreeHostDamageTest::SetupTree();
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
RenderSurfaceImpl* root_surface =
host_impl->active_tree()->root_layer()->render_surface();
gfx::RectF root_damage =
root_surface->damage_tracker()->current_damage_rect();
root_damage.Intersect(root_surface->content_rect());
int source_frame = host_impl->active_tree()->source_frame_number();
switch (source_frame) {
case 0:
EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
root_damage.ToString());
EXPECT_FALSE(frame_data->has_no_damage);
break;
case 1:
EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
EXPECT_TRUE(frame_data->has_no_damage);
host_impl->SetFullRootLayerDamage();
break;
case 2:
EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
root_damage.ToString());
EXPECT_FALSE(frame_data->has_no_damage);
child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
break;
case 3:
EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
root_damage.ToString());
if (delegating_renderer() ||
host_impl->settings().impl_side_painting) {
gfx::RectF paint_rect = child_->LastPaintRect();
paint_rect.set_origin(child_->position());
EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
paint_rect.ToString());
}
EXPECT_FALSE(frame_data->has_no_damage);
child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
host_impl->SetFullRootLayerDamage();
break;
case 4:
EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
root_damage.ToString());
EXPECT_FALSE(frame_data->has_no_damage);
EndTest();
break;
}
return draw_result;
}
virtual void DidCommitAndDrawFrame() OVERRIDE {
if (!TestEnded())
layer_tree_host()->SetNeedsCommit();
if (!child_damage_rect_.IsEmpty()) {
child_->SetNeedsDisplayRect(child_damage_rect_);
child_damage_rect_ = gfx::RectF();
}
}
virtual void AfterTest() OVERRIDE {}
FakeContentLayerClient client_;
scoped_refptr<FakeContentLayer> root_;
scoped_refptr<FakeContentLayer> child_;
gfx::RectF child_damage_rect_;
};
SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
virtual void SetupTree() OVERRIDE {
scoped_refptr<Layer> root_layer = Layer::Create();
root_layer->SetBounds(gfx::Size(400, 400));
root_layer->SetMasksToBounds(true);
layer_tree_host()->SetRootLayer(root_layer);
scoped_refptr<Layer> scroll_clip_layer = Layer::Create();
scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
content_layer->SetScrollOffset(gfx::Vector2d(10, 20));
content_layer->SetBounds(gfx::Size(100, 200));
scroll_clip_layer->SetBounds(
gfx::Size(content_layer->bounds().width() - 30,
content_layer->bounds().height() - 50));
scroll_clip_layer->AddChild(content_layer);
root_layer->AddChild(scroll_clip_layer);
scoped_refptr<Layer> scrollbar_layer =
FakePaintedScrollbarLayer::Create(false, true, content_layer->id());
scrollbar_layer->SetPosition(gfx::Point(300, 300));
scrollbar_layer->SetBounds(gfx::Size(10, 100));
scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
root_layer->AddChild(scrollbar_layer);
gfx::RectF content_rect(content_layer->position(),
content_layer->bounds());
gfx::RectF scrollbar_rect(scrollbar_layer->position(),
scrollbar_layer->bounds());
EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
LayerTreeHostDamageTest::SetupTree();
}
private:
FakeContentLayerClient client_;
};
class LayerTreeHostDamageTestScrollbarDoesDamage
: public LayerTreeHostScrollbarDamageTest {
virtual void BeginTest() OVERRIDE {
did_swaps_ = 0;
PostSetNeedsCommitToMainThread();
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
RenderSurfaceImpl* root_surface =
host_impl->active_tree()->root_layer()->render_surface();
gfx::RectF root_damage =
root_surface->damage_tracker()->current_damage_rect();
root_damage.Intersect(root_surface->content_rect());
switch (did_swaps_) {
case 0:
break;
case 1:
EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
break;
case 2:
EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
break;
case 3:
EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
EndTest();
break;
}
return draw_result;
}
virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
bool result) OVERRIDE {
++did_swaps_;
EXPECT_TRUE(result);
LayerImpl* root = host_impl->active_tree()->root_layer();
LayerImpl* scroll_clip_layer = root->children()[0];
LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
switch (did_swaps_) {
case 1:
scroll_layer->SetPosition(gfx::Point(1, 1));
scroll_layer->SetScrollOffset(scroll_layer->scroll_offset());
host_impl->SetNeedsRedraw();
break;
case 2:
scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
host_impl->SetNeedsRedraw();
break;
case 3:
scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
root->bounds().height() + 100));
host_impl->SetNeedsRedraw();
break;
}
}
virtual void AfterTest() OVERRIDE {
EXPECT_EQ(4, did_swaps_);
}
int did_swaps_;
};
MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
: public LayerTreeHostScrollbarDamageTest {
virtual void BeginTest() OVERRIDE {
did_swaps_ = 0;
PostSetNeedsCommitToMainThread();
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
RenderSurfaceImpl* root_surface =
host_impl->active_tree()->root_layer()->render_surface();
gfx::RectF root_damage =
root_surface->damage_tracker()->current_damage_rect();
root_damage.Intersect(root_surface->content_rect());
int frame = host_impl->active_tree()->source_frame_number();
switch (did_swaps_) {
case 0:
EXPECT_EQ(0, frame);
break;
case 1:
EXPECT_EQ(0, frame);
EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
break;
case 2:
EXPECT_EQ(1, frame);
EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
break;
default:
NOTREACHED();
break;
}
return draw_result;
}
virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
bool result) OVERRIDE {
++did_swaps_;
EXPECT_TRUE(result);
LayerImpl* root = host_impl->active_tree()->root_layer();
LayerImpl* scroll_clip_layer = root->children()[0];
LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
switch (did_swaps_) {
case 1:
scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
host_impl->SetNeedsRedraw();
break;
case 2:
PostSetNeedsCommitToMainThread();
break;
case 3:
EndTest();
break;
default:
NOTREACHED();
break;
}
}
virtual void AfterTest() OVERRIDE {
EXPECT_EQ(3, did_swaps_);
}
int did_swaps_;
};
MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
: public LayerTreeHostDamageTest {
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
settings->impl_side_painting = true;
}
virtual void BeginTest() OVERRIDE {
PostSetNeedsCommitToMainThread();
}
virtual void SetupTree() OVERRIDE {
scoped_refptr<FakePictureLayer> root = FakePictureLayer::Create(&client_);
root->SetBounds(gfx::Size(500, 500));
layer_tree_host()->SetRootLayer(root);
LayerTreeHostDamageTest::SetupTree();
swap_count_ = 0;
prepare_to_draw_count_ = 0;
update_visible_tile_count_ = 0;
}
virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
prepare_to_draw_count_++;
switch (prepare_to_draw_count_) {
case 1:
frame_data->contains_incomplete_tile = true;
DCHECK(!frame_data->has_no_damage);
break;
case 2:
frame_data->contains_incomplete_tile = false;
frame_data->has_no_damage = true;
break;
case 3:
frame_data->contains_incomplete_tile = false;
frame_data->has_no_damage = false;
EndTest();
break;
default:
NOTREACHED();
break;
}
return draw_result;
}
virtual void UpdateVisibleTilesOnThread(
LayerTreeHostImpl* host_impl) OVERRIDE {
update_visible_tile_count_++;
switch (update_visible_tile_count_) {
case 3:
case 6:
host_impl->DidInitializeVisibleTileForTesting();
break;
case 7:
NOTREACHED();
break;
}
}
virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
bool didSwap) OVERRIDE {
if (!didSwap)
return;
++swap_count_;
}
virtual void AfterTest() OVERRIDE {
EXPECT_EQ(update_visible_tile_count_, 6);
EXPECT_EQ(prepare_to_draw_count_, 3);
EXPECT_EQ(swap_count_, 2);
}
FakeContentLayerClient client_;
int swap_count_;
int prepare_to_draw_count_;
int update_visible_tile_count_;
};
MULTI_THREAD_TEST_F(LayerTreeHostDamageTestVisibleTilesStillTriggerDraws);
}
}