This source file includes following definitions.
- SetRenderTarget
- SetOcclusion
- Create
- EnsureOutputSurfaceCreated
- OnCreateAndInitializeOutputSurfaceAttempted
- output_surface_created_
- occlusion_
- SetUp
- ResourceManagerClearAllMemory
- UpdateTextures
- LayerPushPropertiesTo
- LayerUpdate
- CalcDrawProps
- UpdateAndPush
- UpdateAndPush
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- Create
- Paint
- PaintedRect
- ResetPaintedRect
- tracking_layer_painter
- TEST_F
- TEST_F
#include "cc/layers/tiled_layer.h"
#include <limits>
#include <vector>
#include "base/run_loop.h"
#include "cc/resources/bitmap_content_layer_updater.h"
#include "cc/resources/layer_painter.h"
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/resources/resource_update_controller.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_proxy.h"
#include "cc/test/fake_rendering_stats_instrumentation.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/tiled_layer_test_common.h"
#include "cc/trees/occlusion_tracker.h"
#include "cc/trees/single_thread_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/transform.h"
namespace cc {
namespace {
class TestOcclusionTracker : public OcclusionTracker<Layer> {
public:
TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) {
stack_.push_back(StackObject());
}
void SetRenderTarget(Layer* render_target) {
stack_.back().target = render_target;
}
void SetOcclusion(const Region& occlusion) {
stack_.back().occlusion_from_inside_target = occlusion;
}
};
class SynchronousOutputSurfaceLayerTreeHost : public LayerTreeHost {
public:
static scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> Create(
LayerTreeHostClient* client,
SharedBitmapManager* manager,
const LayerTreeSettings& settings,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost(
client, manager, settings, impl_task_runner));
}
virtual ~SynchronousOutputSurfaceLayerTreeHost() {}
bool EnsureOutputSurfaceCreated() {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
run_loop_.QuitClosure(),
base::TimeDelta::FromSeconds(5));
run_loop_.Run();
return output_surface_created_;
}
virtual CreateResult OnCreateAndInitializeOutputSurfaceAttempted(
bool success) OVERRIDE {
CreateResult result =
LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success);
output_surface_created_ = success;
run_loop_.Quit();
return result;
}
private:
SynchronousOutputSurfaceLayerTreeHost(
LayerTreeHostClient* client,
SharedBitmapManager* manager,
const LayerTreeSettings& settings,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
: LayerTreeHost(client, manager, settings),
output_surface_created_(false) {
LayerTreeHost::InitializeThreaded(impl_task_runner);
}
bool output_surface_created_;
base::RunLoop run_loop_;
};
class TiledLayerTest : public testing::Test {
public:
TiledLayerTest()
: proxy_(NULL),
output_surface_(FakeOutputSurface::Create3d()),
queue_(make_scoped_ptr(new ResourceUpdateQueue)),
impl_thread_("ImplThread"),
fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D),
occlusion_(NULL) {
settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max();
settings_.layer_transforms_should_scale_layer_contents = true;
}
virtual void SetUp() {
impl_thread_.Start();
shared_bitmap_manager_.reset(new TestSharedBitmapManager());
layer_tree_host_ = SynchronousOutputSurfaceLayerTreeHost::Create(
&fake_layer_tree_host_client_,
shared_bitmap_manager_.get(),
settings_,
impl_thread_.message_loop_proxy());
proxy_ = layer_tree_host_->proxy();
resource_manager_ = PrioritizedResourceManager::Create(proxy_);
layer_tree_host_->SetLayerTreeHostClientReady();
CHECK(layer_tree_host_->EnsureOutputSurfaceCreated());
layer_tree_host_->SetRootLayer(Layer::Create());
CHECK(output_surface_->BindToClient(&output_surface_client_));
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(proxy_);
resource_provider_ = ResourceProvider::Create(
output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1);
host_impl_ = make_scoped_ptr(
new FakeLayerTreeHostImpl(proxy_, shared_bitmap_manager_.get()));
}
virtual ~TiledLayerTest() {
ResourceManagerClearAllMemory(resource_manager_.get(),
resource_provider_.get());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(proxy_);
resource_provider_.reset();
host_impl_.reset();
}
void ResourceManagerClearAllMemory(
PrioritizedResourceManager* resource_manager,
ResourceProvider* resource_provider) {
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(proxy_);
resource_manager->ClearAllMemory(resource_provider);
resource_manager->ReduceMemory(resource_provider);
}
resource_manager->UnlinkAndClearEvictedBackings();
}
void UpdateTextures() {
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(proxy_);
DCHECK(queue_);
scoped_ptr<ResourceUpdateController> update_controller =
ResourceUpdateController::Create(NULL,
proxy_->ImplThreadTaskRunner(),
queue_.Pass(),
resource_provider_.get());
update_controller->Finalize();
queue_ = make_scoped_ptr(new ResourceUpdateQueue);
}
void LayerPushPropertiesTo(FakeTiledLayer* layer,
FakeTiledLayerImpl* layer_impl) {
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(proxy_);
layer->PushPropertiesTo(layer_impl);
layer->ResetNumDependentsNeedPushProperties();
}
void LayerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded) {
DebugScopedSetMainThread main_thread(proxy_);
layer->Update(queue_.get(), occluded);
}
void CalcDrawProps(RenderSurfaceLayerList* render_surface_layer_list) {
if (occlusion_)
occlusion_->SetRenderTarget(layer_tree_host_->root_layer());
LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
layer_tree_host_->root_layer(),
layer_tree_host_->device_viewport_size(),
render_surface_layer_list);
inputs.device_scale_factor = layer_tree_host_->device_scale_factor();
inputs.max_texture_size =
layer_tree_host_->GetRendererCapabilities().max_texture_size;
inputs.can_adjust_raster_scales = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
}
bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
const scoped_ptr<FakeTiledLayerImpl>& layer_impl1) {
scoped_refptr<FakeTiledLayer> layer2;
scoped_ptr<FakeTiledLayerImpl> layer_impl2;
return UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
}
bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
const scoped_ptr<FakeTiledLayerImpl>& layer_impl1,
const scoped_refptr<FakeTiledLayer>& layer2,
const scoped_ptr<FakeTiledLayerImpl>& layer_impl2) {
resource_manager_->ClearPriorities();
if (layer1.get())
layer1->SetTexturePriorities(priority_calculator_);
if (layer2.get())
layer2->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
if (layer1.get())
layer1->SavePaintProperties();
if (layer2.get())
layer2->SavePaintProperties();
if (layer1.get())
layer1->Update(queue_.get(), occlusion_);
if (layer2.get())
layer2->Update(queue_.get(), occlusion_);
bool needs_update = false;
if (layer1.get())
needs_update |= layer1->NeedsIdlePaint();
if (layer2.get())
needs_update |= layer2->NeedsIdlePaint();
UpdateTextures();
if (layer1.get())
LayerPushPropertiesTo(layer1.get(), layer_impl1.get());
if (layer2.get())
LayerPushPropertiesTo(layer2.get(), layer_impl2.get());
return needs_update;
}
public:
Proxy* proxy_;
LayerTreeSettings settings_;
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
scoped_ptr<ResourceProvider> resource_provider_;
scoped_ptr<ResourceUpdateQueue> queue_;
PriorityCalculator priority_calculator_;
base::Thread impl_thread_;
FakeLayerTreeHostClient fake_layer_tree_host_client_;
scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> layer_tree_host_;
scoped_ptr<FakeLayerTreeHostImpl> host_impl_;
scoped_ptr<PrioritizedResourceManager> resource_manager_;
TestOcclusionTracker* occlusion_;
};
TEST_F(TiledLayerTest, PushDirtyTiles) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
}
TEST_F(TiledLayerTest, PushOccludedDirtyTiles) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
TestOcclusionTracker occluded;
occlusion_ = &occluded;
layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
layer_tree_host_->root_layer()->AddChild(layer);
{
RenderSurfaceLayerList render_surface_layer_list;
layer->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
}
{
RenderSurfaceLayerList render_surface_layer_list;
layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
occluded.SetOcclusion(gfx::Rect(0, 0, 50, 50));
CalcDrawProps(&render_surface_layer_list);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
}
}
TEST_F(TiledLayerTest, PushDeletedTiles) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
resource_manager_->ClearPriorities();
ResourceManagerClearAllMemory(resource_manager_.get(),
resource_provider_.get());
resource_manager_->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
LayerPushPropertiesTo(layer.get(), layer_impl.get());
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
}
TEST_F(TiledLayerTest, PushIdlePaintTiles) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(500, 500));
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = gfx::Rect(200, 200, 100, 100);
bool needs_update = UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(needs_update);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(2, 2));
for (int i = 0; i < 4; i++) {
needs_update = UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(needs_update);
}
for (int i = 0; i < 20; i++)
needs_update = UpdateAndPush(layer, layer_impl);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++)
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j));
}
EXPECT_FALSE(needs_update);
}
TEST_F(TiledLayerTest, PredictivePainting) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
layer_tree_host_->root_layer()->AddChild(layer);
gfx::Vector2d directions[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
gfx::Vector2d(10, 20),
gfx::Vector2d(-20, 10) };
gfx::Rect pushed_visible_tiles[6] = {
gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
};
gfx::Rect pushed_prepaint_tiles[6] = {
gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
};
for (int k = 0; k < 6; k++) {
gfx::Size bounds = gfx::Size(500, 500);
gfx::Rect visible_rect = gfx::Rect(200, 200, 100, 100);
gfx::Rect previous_visible_rect =
gfx::Rect(visible_rect.origin() + directions[k], visible_rect.size());
gfx::Rect next_visible_rect =
gfx::Rect(visible_rect.origin() - directions[k], visible_rect.size());
layer->SetBounds(bounds);
RenderSurfaceLayerList render_surface_layer_list;
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = previous_visible_rect;
bool needs_update = UpdateAndPush(layer, layer_impl);
layer->SetNeedsDisplay();
layer->draw_properties().visible_content_rect = visible_rect;
needs_update = UpdateAndPush(layer, layer_impl);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++)
EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j),
pushed_visible_tiles[k].Contains(i, j));
}
if (k <= 3) {
layer->draw_properties().visible_content_rect = next_visible_rect;
needs_update = UpdateAndPush(layer, layer_impl);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++)
EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j),
pushed_prepaint_tiles[k].Contains(i, j));
}
}
for (int i = 0; i < 20; i++)
needs_update = UpdateAndPush(layer, layer_impl);
EXPECT_FALSE(needs_update);
}
}
TEST_F(TiledLayerTest, PushTilesAfterIdlePaintFailed) {
resource_manager_->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
scoped_refptr<FakeTiledLayer> layer1 =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl1 =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
scoped_refptr<FakeTiledLayer> layer2 =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl2 =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer1);
layer_tree_host_->root_layer()->AddChild(layer2);
gfx::Rect layer1_rect(0, 0, 100, 2400);
gfx::Rect layer2_rect(0, 0, 100, 300);
layer1->SetBounds(layer1_rect.size());
layer2->SetBounds(layer2_rect.size());
CalcDrawProps(&render_surface_layer_list);
layer1->draw_properties().visible_content_rect = layer1_rect;
layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
bool needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
EXPECT_TRUE(needs_update);
resource_manager_->SetMaxMemoryLimitBytes(1024 * 1024);
for (int i = 0; i < 4; i++) {
needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
}
EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 23));
EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1));
EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1));
EXPECT_FALSE(needs_update);
EXPECT_FALSE(layer_impl2->HasResourceIdForTileAt(0, 2));
}
TEST_F(TiledLayerTest, PushIdlePaintedOccludedTiles) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
TestOcclusionTracker occluded;
occlusion_ = &occluded;
layer_tree_host_->root_layer()->AddChild(layer);
occluded.SetOcclusion(gfx::Rect(0, 0, 100, 100));
layer->SetBounds(gfx::Size(100, 100));
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
}
TEST_F(TiledLayerTest, PushTilesMarkedDirtyDuringPaint) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->fake_layer_updater()->SetRectToInvalidate(
gfx::Rect(0, 50, 100, 50), layer.get());
layer->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
}
TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer) {
scoped_refptr<FakeTiledLayer> layer1 =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_refptr<FakeTiledLayer> layer2 =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer1_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
scoped_ptr<FakeTiledLayerImpl> layer2_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer1);
layer_tree_host_->root_layer()->AddChild(layer2);
layer2->fake_layer_updater()->SetRectToInvalidate(
gfx::Rect(0, 50, 100, 50), layer1.get());
layer1->SetBounds(gfx::Size(100, 200));
layer2->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl);
EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1));
EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1));
}
TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer) {
scoped_refptr<FakeTiledLayer> layer1 =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_refptr<FakeTiledLayer> layer2 =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer1_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
scoped_ptr<FakeTiledLayerImpl> layer2_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer1);
layer_tree_host_->root_layer()->AddChild(layer2);
layer1->fake_layer_updater()->SetRectToInvalidate(
gfx::Rect(0, 50, 100, 50), layer2.get());
layer1->SetBounds(gfx::Size(100, 200));
layer2->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl);
EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1));
EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1));
}
TEST_F(TiledLayerTest, PaintSmallAnimatedLayersImmediately) {
bool run_out_of_memory[2] = { false, true };
for (int i = 0; i < 2; i++) {
int viewport_width = 4 * FakeTiledLayer::tile_size().width();
int viewport_height = 4 * FakeTiledLayer::tile_size().width();
int layer_width = 5 * FakeTiledLayer::tile_size().width();
int layer_height = 5 * FakeTiledLayer::tile_size().height();
int memory_for_layer = layer_width * layer_height * 4;
layer_tree_host_->SetViewportSize(
gfx::Size(viewport_width, viewport_height));
if (run_out_of_memory[i])
layer_width *= 2;
resource_manager_->SetMaxMemoryLimitBytes(memory_for_layer);
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(layer_width, layer_height));
gfx::Rect visible_rect(0, 0, layer_width / 2, layer_height);
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().target_space_transform_is_animating = true;
layer->draw_properties().visible_content_rect = visible_rect;
layer->SetLayerTreeHost(layer_tree_host_.get());
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
UpdateTextures();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
if (!run_out_of_memory[i]) {
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j)
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j));
}
} else {
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 5; ++j)
EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), i < 5);
}
}
layer->RemoveFromParent();
}
}
TEST_F(TiledLayerTest, IdlePaintOutOfMemory) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
int memory_limit = 4 * 100 * 100;
resource_manager_->SetMaxMemoryLimitBytes(memory_limit);
bool needs_update = false;
layer->SetBounds(gfx::Size(300, 300));
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = gfx::Rect(100, 100, 100, 100);
for (int i = 0; i < 2; i++)
needs_update = UpdateAndPush(layer, layer_impl);
EXPECT_FALSE(needs_update);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1));
}
TEST_F(TiledLayerTest, IdlePaintZeroSizedLayer) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
layer_tree_host_->root_layer()->AddChild(layer);
bool animating[2] = { false, true };
for (int i = 0; i < 2; i++) {
layer->draw_properties().target_space_transform_is_animating = animating[i];
layer->SetBounds(gfx::Size());
RenderSurfaceLayerList render_surface_layer_list;
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = gfx::Rect();
bool needs_update = UpdateAndPush(layer, layer_impl);
EXPECT_EQ(0u, layer->NumPaintedTiles());
EXPECT_FALSE(needs_update);
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
}
}
TEST_F(TiledLayerTest, IdlePaintNonVisibleLayers) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
gfx::Rect v(0, 0, 100, 100);
gfx::Rect nv(0, 0, 0, 0);
gfx::Rect visible_rect[10] = { nv, nv, v, v, nv, nv, v, v, nv, nv };
bool invalidate[10] = { true, true, true, true, true, true, true, true, false,
false };
bool have_tile[10] = { false, false, true, true, false, false, true, true,
true, true };
layer_tree_host_->root_layer()->AddChild(layer);
for (int i = 0; i < 10; i++) {
layer->SetBounds(gfx::Size(100, 100));
RenderSurfaceLayerList render_surface_layer_list;
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = visible_rect[i];
if (invalidate[i])
layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
bool needs_update = UpdateAndPush(layer, layer_impl);
EXPECT_FALSE(needs_update);
EXPECT_EQ(layer_impl->HasResourceIdForTileAt(0, 0), have_tile[i]);
}
}
TEST_F(TiledLayerTest, InvalidateFromPrepare) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
UpdateAndPush(layer, layer_impl);
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
layer->fake_layer_updater()->ClearPrepareCount();
UpdateAndPush(layer, layer_impl);
EXPECT_EQ(0, layer->fake_layer_updater()->prepare_count());
layer->fake_layer_updater()->SetRectToInvalidate(
gfx::Rect(25, 25, 50, 50), layer.get());
layer->fake_layer_updater()->ClearPrepareCount();
layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
UpdateAndPush(layer, layer_impl);
EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count());
layer->fake_layer_updater()->ClearPrepareCount();
UpdateAndPush(layer, layer_impl);
EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count());
}
TEST_F(TiledLayerTest, VerifyUpdateRectWhenContentBoundsAreScaled) {
scoped_refptr<FakeTiledLayerWithScaledBounds> layer = make_scoped_refptr(
new FakeTiledLayerWithScaledBounds(resource_manager_.get()));
layer_tree_host_->root_layer()->AddChild(layer);
gfx::Rect layer_bounds(0, 0, 300, 200);
gfx::Rect content_bounds(0, 0, 200, 250);
layer->SetBounds(layer_bounds.size());
layer->SetContentBounds(content_bounds.size());
layer->draw_properties().visible_content_rect = content_bounds;
layer->InvalidateContentRect(content_bounds);
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 300, 300 * 0.8), layer->update_rect());
UpdateTextures();
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->InvalidateContentRect(content_bounds);
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds), layer->update_rect());
UpdateTextures();
gfx::Rect partial_damage(30, 100, 10, 10);
layer->InvalidateContentRect(partial_damage);
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
EXPECT_FLOAT_RECT_EQ(gfx::RectF(45, 80, 15, 8), layer->update_rect());
}
TEST_F(TiledLayerTest, VerifyInvalidationWhenContentsScaleChanges) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(100, 100));
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
layer->Update(queue_.get(), NULL);
UpdateTextures();
EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
layer->last_needs_display_rect());
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
UpdateTextures();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1));
layer->SetNeedsDisplayRect(gfx::Rect());
EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->last_needs_display_rect());
layer->UpdateContentsScale(2.f);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200);
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
UpdateTextures();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 0));
EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1));
EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
layer->last_needs_display_rect());
layer->SetNeedsDisplay();
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0));
EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1));
}
TEST_F(TiledLayerTest, SkipsDrawGetsReset) {
gfx::Size content_bounds(300, 300);
gfx::Rect content_rect(content_bounds);
int memory_limit = 4 * 300 * 300;
scoped_refptr<FakeTiledLayer> root_layer = make_scoped_refptr(
new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
scoped_refptr<FakeTiledLayer> child_layer = make_scoped_refptr(
new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
root_layer->AddChild(child_layer);
root_layer->SetBounds(content_bounds);
root_layer->draw_properties().visible_content_rect = content_rect;
root_layer->SetPosition(gfx::PointF(0, 0));
child_layer->SetBounds(content_bounds);
child_layer->draw_properties().visible_content_rect = content_rect;
child_layer->SetPosition(gfx::PointF(0, 0));
root_layer->InvalidateContentRect(content_rect);
child_layer->InvalidateContentRect(content_rect);
layer_tree_host_->SetRootLayer(root_layer);
layer_tree_host_->SetViewportSize(gfx::Size(300, 300));
layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
memory_limit);
layer_tree_host_->UpdateLayers(queue_.get());
EXPECT_TRUE(root_layer->SkipsDraw());
EXPECT_FALSE(child_layer->SkipsDraw());
layer_tree_host_->CommitComplete();
root_layer->RemoveAllChildren();
layer_tree_host_->UpdateLayers(queue_.get());
EXPECT_FALSE(root_layer->SkipsDraw());
ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
resource_provider_.get());
layer_tree_host_->SetRootLayer(NULL);
}
TEST_F(TiledLayerTest, ResizeToSmaller) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(700, 700));
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
layer->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
layer->SetBounds(gfx::Size(200, 200));
layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
}
TEST_F(TiledLayerTest, HugeLayerUpdateCrash) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
layer_tree_host_->root_layer()->AddChild(layer);
int size = 1 << 30;
layer->SetBounds(gfx::Size(size, size));
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
layer->InvalidateContentRect(gfx::Rect(0, 0, size, size));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
}
class TiledLayerPartialUpdateTest : public TiledLayerTest {
public:
TiledLayerPartialUpdateTest() { settings_.max_partial_texture_updates = 4; }
};
TEST_F(TiledLayerPartialUpdateTest, PartialUpdates) {
gfx::Size content_bounds(300, 200);
gfx::Rect content_rect(content_bounds);
scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(
new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
layer->SetBounds(content_bounds);
layer->SetPosition(gfx::PointF(0, 0));
layer->draw_properties().visible_content_rect = content_rect;
layer->InvalidateContentRect(content_rect);
layer_tree_host_->SetRootLayer(layer);
layer_tree_host_->SetViewportSize(gfx::Size(300, 200));
layer_tree_host_->UpdateLayers(queue_.get());
{
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
EXPECT_EQ(6u, queue_->FullUploadSize());
EXPECT_EQ(0u, queue_->PartialUploadSize());
UpdateTextures();
EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
layer->fake_layer_updater()->ClearUpdateCount();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
}
layer_tree_host_->CommitComplete();
layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
layer_tree_host_->UpdateLayers(queue_.get());
{
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
EXPECT_EQ(3u, queue_->FullUploadSize());
EXPECT_EQ(3u, queue_->PartialUploadSize());
UpdateTextures();
EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
layer->fake_layer_updater()->ClearUpdateCount();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
}
layer_tree_host_->CommitComplete();
layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
{
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
layer_tree_host_->UpdateLayers(queue_.get());
EXPECT_EQ(2u, queue_->FullUploadSize());
EXPECT_EQ(4u, queue_->PartialUploadSize());
UpdateTextures();
EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
layer->fake_layer_updater()->ClearUpdateCount();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
}
layer_tree_host_->CommitComplete();
layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
{
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
LayerPushPropertiesTo(layer.get(), layer_impl.get());
}
layer_tree_host_->CommitComplete();
layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
{
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
layer_tree_host_->UpdateLayers(queue_.get());
EXPECT_EQ(6u, queue_->FullUploadSize());
EXPECT_EQ(0u, queue_->PartialUploadSize());
UpdateTextures();
EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
layer->fake_layer_updater()->ClearUpdateCount();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
}
layer_tree_host_->CommitComplete();
layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
{
scoped_ptr<FakeTiledLayerImpl> layer_impl =
make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
layer_tree_host_->UpdateLayers(queue_.get());
EXPECT_EQ(0u, queue_->FullUploadSize());
EXPECT_EQ(4u, queue_->PartialUploadSize());
UpdateTextures();
EXPECT_EQ(4, layer->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
layer->fake_layer_updater()->ClearUpdateCount();
LayerPushPropertiesTo(layer.get(), layer_impl.get());
}
layer_tree_host_->CommitComplete();
ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
resource_provider_.get());
layer_tree_host_->SetRootLayer(NULL);
}
TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
RenderSurfaceLayerList render_surface_layer_list;
layer_tree_host_->root_layer()->AddChild(layer);
layer->SetBounds(gfx::Size(100, 200));
CalcDrawProps(&render_surface_layer_list);
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
EXPECT_EQ(2, layer->fake_layer_updater()->update_count());
}
TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
RenderSurfaceLayerList render_surface_layer_list;
TestOcclusionTracker occluded;
occlusion_ = &occluded;
layer_tree_host_->root_layer()->AddChild(layer);
layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
layer->SetBounds(gfx::Size(600, 600));
CalcDrawProps(&render_surface_layer_list);
occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100));
layer->draw_properties().drawable_content_rect =
gfx::Rect(layer->content_bounds());
layer->draw_properties().visible_content_rect =
gfx::Rect(layer->content_bounds());
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
layer->fake_layer_updater()->ClearUpdateCount();
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
occluded.SetOcclusion(gfx::Rect(250, 200, 300, 100));
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(36 - 2, layer->fake_layer_updater()->update_count());
layer->fake_layer_updater()->ClearUpdateCount();
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
occluded.SetOcclusion(gfx::Rect(250, 250, 300, 100));
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(36, layer->fake_layer_updater()->update_count());
}
TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
RenderSurfaceLayerList render_surface_layer_list;
TestOcclusionTracker occluded;
occlusion_ = &occluded;
layer_tree_host_->root_layer()->AddChild(layer);
layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
layer->SetBounds(gfx::Size(600, 600));
CalcDrawProps(&render_surface_layer_list);
occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150));
layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360);
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(24 - 3, layer->fake_layer_updater()->update_count());
layer->fake_layer_updater()->ClearUpdateCount();
occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150));
layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350);
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count());
layer->fake_layer_updater()->ClearUpdateCount();
occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150));
layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340);
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count());
}
TEST_F(TiledLayerTest, TilesNotPaintedWithoutInvalidation) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
RenderSurfaceLayerList render_surface_layer_list;
TestOcclusionTracker occluded;
occlusion_ = &occluded;
layer_tree_host_->root_layer()->AddChild(layer);
layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
layer->SetBounds(gfx::Size(600, 600));
CalcDrawProps(&render_surface_layer_list);
occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100));
layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600);
layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600);
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
UpdateTextures();
layer->fake_layer_updater()->ClearUpdateCount();
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(3, layer->fake_layer_updater()->update_count());
}
TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndTransforms) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
RenderSurfaceLayerList render_surface_layer_list;
TestOcclusionTracker occluded;
occlusion_ = &occluded;
layer_tree_host_->root_layer()->AddChild(layer);
layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
layer->SetBounds(gfx::Size(600, 600));
CalcDrawProps(&render_surface_layer_list);
gfx::Transform screen_transform;
screen_transform.Scale(0.5, 0.5);
layer->draw_properties().screen_space_transform = screen_transform;
layer->draw_properties().target_space_transform = screen_transform;
occluded.SetOcclusion(gfx::Rect(100, 100, 150, 50));
layer->draw_properties().drawable_content_rect =
gfx::Rect(layer->content_bounds());
layer->draw_properties().visible_content_rect =
gfx::Rect(layer->content_bounds());
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
}
TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) {
scoped_refptr<FakeTiledLayer> layer =
new FakeTiledLayer(resource_manager_.get());
RenderSurfaceLayerList render_surface_layer_list;
TestOcclusionTracker occluded;
occlusion_ = &occluded;
scoped_refptr<FakeTiledLayer> scale_layer =
new FakeTiledLayer(resource_manager_.get());
gfx::Transform scale_transform;
scale_transform.Scale(2.0, 2.0);
scale_layer->SetTransform(scale_transform);
layer_tree_host_->root_layer()->AddChild(scale_layer);
layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
layer->SetAnchorPoint(gfx::PointF());
layer->SetBounds(gfx::Size(300, 300));
scale_layer->AddChild(layer);
CalcDrawProps(&render_surface_layer_list);
EXPECT_FLOAT_EQ(2.f, layer->contents_scale_x());
EXPECT_FLOAT_EQ(2.f, layer->contents_scale_y());
EXPECT_EQ(gfx::Size(600, 600).ToString(),
layer->content_bounds().ToString());
occluded.SetOcclusion(gfx::Rect(200, 200, 300, 50));
layer->draw_properties().drawable_content_rect =
gfx::Rect(layer->bounds());
layer->draw_properties().visible_content_rect =
gfx::Rect(layer->content_bounds());
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
int visible_tiles1 = 6 * 6;
EXPECT_EQ(visible_tiles1, layer->fake_layer_updater()->update_count());
layer->fake_layer_updater()->ClearUpdateCount();
occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100));
layer->draw_properties().drawable_content_rect =
gfx::Rect(layer->bounds());
layer->draw_properties().visible_content_rect =
gfx::Rect(layer->content_bounds());
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
int visible_tiles2 = 6 * 6 - 3;
EXPECT_EQ(visible_tiles2, layer->fake_layer_updater()->update_count());
layer->fake_layer_updater()->ClearUpdateCount();
gfx::Transform screen_transform;
screen_transform.Scale(0.5, 0.5);
layer->draw_properties().screen_space_transform = screen_transform;
layer->draw_properties().target_space_transform = screen_transform;
occluded.SetOcclusion(gfx::Rect(100, 100, 150, 100));
gfx::Rect layer_bounds_rect(layer->bounds());
layer->draw_properties().drawable_content_rect =
gfx::ScaleToEnclosingRect(layer_bounds_rect, 0.5f);
layer->draw_properties().visible_content_rect =
gfx::Rect(layer->content_bounds());
layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
int visible_tiles3 = 6 * 6 - 6;
EXPECT_EQ(visible_tiles3, layer->fake_layer_updater()->update_count());
}
TEST_F(TiledLayerTest, VisibleContentOpaqueRegion) {
scoped_refptr<FakeTiledLayer> layer =
make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
RenderSurfaceLayerList render_surface_layer_list;
TestOcclusionTracker occluded;
occlusion_ = &occluded;
layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
layer_tree_host_->root_layer()->AddChild(layer);
gfx::Rect opaque_paint_rect;
Region opaque_contents;
gfx::Rect content_bounds = gfx::Rect(0, 0, 100, 200);
gfx::Rect visible_bounds = gfx::Rect(0, 0, 100, 150);
layer->SetBounds(content_bounds.size());
CalcDrawProps(&render_surface_layer_list);
layer->draw_properties().drawable_content_rect = visible_bounds;
layer->draw_properties().visible_content_rect = visible_bounds;
layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
layer->InvalidateContentRect(content_bounds);
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
opaque_contents = layer->VisibleContentOpaqueRegion();
EXPECT_TRUE(opaque_contents.IsEmpty());
opaque_paint_rect = gfx::Rect(10, 10, 90, 190);
layer->fake_layer_updater()->SetOpaquePaintRect(opaque_paint_rect);
layer->InvalidateContentRect(content_bounds);
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
UpdateTextures();
opaque_contents = layer->VisibleContentOpaqueRegion();
EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
opaque_contents.ToString());
layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
UpdateTextures();
opaque_contents = layer->VisibleContentOpaqueRegion();
EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
opaque_contents.ToString());
layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
layer->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
UpdateTextures();
opaque_contents = layer->VisibleContentOpaqueRegion();
EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
opaque_contents.ToString());
layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
layer->InvalidateContentRect(gfx::Rect(10, 10, 1, 1));
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), &occluded);
UpdateTextures();
opaque_contents = layer->VisibleContentOpaqueRegion();
EXPECT_EQ(gfx::IntersectRects(gfx::Rect(10, 100, 90, 100),
visible_bounds).ToString(),
opaque_contents.ToString());
}
TEST_F(TiledLayerTest, DontAllocateContentsWhenTargetSurfaceCantBeAllocated) {
gfx::Rect root_rect(0, 0, 300, 200);
gfx::Rect child_rect(0, 0, 300, 100);
gfx::Rect child2_rect(0, 100, 300, 100);
scoped_refptr<FakeTiledLayer> root = make_scoped_refptr(
new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
scoped_refptr<Layer> surface = Layer::Create();
scoped_refptr<FakeTiledLayer> child = make_scoped_refptr(
new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr(
new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
root->SetBounds(root_rect.size());
root->SetAnchorPoint(gfx::PointF());
root->draw_properties().drawable_content_rect = root_rect;
root->draw_properties().visible_content_rect = root_rect;
root->AddChild(surface);
surface->SetForceRenderSurface(true);
surface->SetAnchorPoint(gfx::PointF());
surface->SetOpacity(0.5);
surface->AddChild(child);
surface->AddChild(child2);
child->SetBounds(child_rect.size());
child->SetAnchorPoint(gfx::PointF());
child->SetPosition(child_rect.origin());
child->draw_properties().visible_content_rect = child_rect;
child->draw_properties().drawable_content_rect = root_rect;
child2->SetBounds(child2_rect.size());
child2->SetAnchorPoint(gfx::PointF());
child2->SetPosition(child2_rect.origin());
child2->draw_properties().visible_content_rect = child2_rect;
child2->draw_properties().drawable_content_rect = root_rect;
layer_tree_host_->SetRootLayer(root);
layer_tree_host_->SetViewportSize(root_rect.size());
root->InvalidateContentRect(root_rect);
child->InvalidateContentRect(child_rect);
child2->InvalidateContentRect(child2_rect);
layer_tree_host_->UpdateLayers(queue_.get());
{
UpdateTextures();
EXPECT_EQ(6, root->fake_layer_updater()->update_count());
EXPECT_EQ(3, child->fake_layer_updater()->update_count());
EXPECT_EQ(3, child2->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
root->fake_layer_updater()->ClearUpdateCount();
child->fake_layer_updater()->ClearUpdateCount();
child2->fake_layer_updater()->ClearUpdateCount();
scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
LayerPushPropertiesTo(child2.get(), child2_impl.get());
LayerPushPropertiesTo(child.get(), child_impl.get());
LayerPushPropertiesTo(root.get(), root_impl.get());
for (unsigned i = 0; i < 3; ++i) {
for (unsigned j = 0; j < 2; ++j)
EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
EXPECT_TRUE(child_impl->HasResourceIdForTileAt(i, 0));
EXPECT_TRUE(child2_impl->HasResourceIdForTileAt(i, 0));
}
}
layer_tree_host_->CommitComplete();
root->InvalidateContentRect(root_rect);
child->InvalidateContentRect(child_rect);
child2->InvalidateContentRect(child2_rect);
size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4;
layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
memory_limit);
layer_tree_host_->UpdateLayers(queue_.get());
{
UpdateTextures();
EXPECT_EQ(6, root->fake_layer_updater()->update_count());
EXPECT_EQ(0, child->fake_layer_updater()->update_count());
EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
root->fake_layer_updater()->ClearUpdateCount();
child->fake_layer_updater()->ClearUpdateCount();
child2->fake_layer_updater()->ClearUpdateCount();
scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
LayerPushPropertiesTo(child2.get(), child2_impl.get());
LayerPushPropertiesTo(child.get(), child_impl.get());
LayerPushPropertiesTo(root.get(), root_impl.get());
for (unsigned i = 0; i < 3; ++i) {
for (unsigned j = 0; j < 2; ++j)
EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
}
}
layer_tree_host_->CommitComplete();
root->InvalidateContentRect(root_rect);
child->InvalidateContentRect(child_rect);
child2->InvalidateContentRect(child2_rect);
memory_limit = (3 * 1) * (100 * 100) * 4;
layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
memory_limit);
layer_tree_host_->UpdateLayers(queue_.get());
{
UpdateTextures();
EXPECT_EQ(0, root->fake_layer_updater()->update_count());
EXPECT_EQ(0, child->fake_layer_updater()->update_count());
EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
EXPECT_FALSE(queue_->HasMoreUpdates());
root->fake_layer_updater()->ClearUpdateCount();
child->fake_layer_updater()->ClearUpdateCount();
child2->fake_layer_updater()->ClearUpdateCount();
scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
LayerPushPropertiesTo(child2.get(), child2_impl.get());
LayerPushPropertiesTo(child.get(), child_impl.get());
LayerPushPropertiesTo(root.get(), root_impl.get());
for (unsigned i = 0; i < 3; ++i) {
for (unsigned j = 0; j < 2; ++j)
EXPECT_FALSE(root_impl->HasResourceIdForTileAt(i, j));
EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
}
}
layer_tree_host_->CommitComplete();
ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
resource_provider_.get());
layer_tree_host_->SetRootLayer(NULL);
}
class TrackingLayerPainter : public LayerPainter {
public:
static scoped_ptr<TrackingLayerPainter> Create() {
return make_scoped_ptr(new TrackingLayerPainter());
}
virtual void Paint(SkCanvas* canvas,
const gfx::Rect& content_rect,
gfx::RectF* opaque) OVERRIDE {
painted_rect_ = content_rect;
}
gfx::Rect PaintedRect() const { return painted_rect_; }
void ResetPaintedRect() { painted_rect_ = gfx::Rect(); }
private:
gfx::Rect painted_rect_;
};
class UpdateTrackingTiledLayer : public FakeTiledLayer {
public:
explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager)
: FakeTiledLayer(manager) {
scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create());
tracking_layer_painter_ = painter.get();
layer_updater_ =
BitmapContentLayerUpdater::Create(painter.PassAs<LayerPainter>(),
&stats_instrumentation_,
0);
}
TrackingLayerPainter* tracking_layer_painter() const {
return tracking_layer_painter_;
}
private:
virtual LayerUpdater* Updater() const OVERRIDE {
return layer_updater_.get();
}
virtual ~UpdateTrackingTiledLayer() {}
TrackingLayerPainter* tracking_layer_painter_;
scoped_refptr<BitmapContentLayerUpdater> layer_updater_;
FakeRenderingStatsInstrumentation stats_instrumentation_;
};
TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) {
scoped_refptr<UpdateTrackingTiledLayer> layer =
make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
layer_tree_host_->root_layer()->AddChild(layer);
gfx::Rect layer_rect(0, 0, 30, 31);
layer->SetPosition(layer_rect.origin());
layer->SetBounds(layer_rect.size());
layer->UpdateContentsScale(1.5f);
gfx::Rect content_rect(0, 0, 45, 47);
EXPECT_EQ(content_rect.size(), layer->content_bounds());
layer->draw_properties().visible_content_rect = content_rect;
layer->draw_properties().drawable_content_rect = content_rect;
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
layer->tracking_layer_painter()->ResetPaintedRect();
EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
UpdateTextures();
layer->InvalidateContentRect(content_rect);
layer->Update(queue_.get(), NULL);
EXPECT_RECT_EQ(layer_rect, layer->tracking_layer_painter()->PaintedRect());
}
TEST_F(TiledLayerTest,
NonIntegerContentsScaleIsNotDistortedDuringInvalidation) {
scoped_refptr<UpdateTrackingTiledLayer> layer =
make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
layer_tree_host_->root_layer()->AddChild(layer);
gfx::Rect layer_rect(0, 0, 30, 31);
layer->SetPosition(layer_rect.origin());
layer->SetBounds(layer_rect.size());
layer->UpdateContentsScale(1.3f);
gfx::Rect content_rect(layer->content_bounds());
layer->draw_properties().visible_content_rect = content_rect;
layer->draw_properties().drawable_content_rect = content_rect;
layer->SetTexturePriorities(priority_calculator_);
resource_manager_->PrioritizeTextures();
layer->SavePaintProperties();
layer->Update(queue_.get(), NULL);
layer->tracking_layer_painter()->ResetPaintedRect();
EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
UpdateTextures();
layer->SetNeedsDisplayRect(layer_rect);
layer->Update(queue_.get(), NULL);
EXPECT_RECT_EQ(layer_rect, layer->tracking_layer_painter()->PaintedRect());
}
}
}