Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / ui / compositor / layer_unittest.cc
blob9622b2f1f342a8f9112bfd8f7acfdc6df9d5028b
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/compiler_specific.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/json/json_reader.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/trace_event/trace_event.h"
17 #include "cc/layers/delegated_frame_provider.h"
18 #include "cc/layers/delegated_frame_resource_collection.h"
19 #include "cc/layers/layer.h"
20 #include "cc/output/copy_output_request.h"
21 #include "cc/output/copy_output_result.h"
22 #include "cc/output/delegated_frame_data.h"
23 #include "cc/test/pixel_test_utils.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/compositor/compositor_observer.h"
26 #include "ui/compositor/dip_util.h"
27 #include "ui/compositor/layer.h"
28 #include "ui/compositor/layer_animation_sequence.h"
29 #include "ui/compositor/layer_animator.h"
30 #include "ui/compositor/paint_context.h"
31 #include "ui/compositor/paint_recorder.h"
32 #include "ui/compositor/test/context_factories_for_test.h"
33 #include "ui/compositor/test/draw_waiter_for_test.h"
34 #include "ui/compositor/test/test_compositor_host.h"
35 #include "ui/compositor/test/test_layers.h"
36 #include "ui/gfx/canvas.h"
37 #include "ui/gfx/codec/png_codec.h"
38 #include "ui/gfx/gfx_paths.h"
39 #include "ui/gfx/skia_util.h"
41 using cc::MatchesPNGFile;
43 namespace ui {
45 namespace {
47 // There are three test classes in here that configure the Compositor and
48 // Layer's slightly differently:
49 // - LayerWithNullDelegateTest uses NullLayerDelegate as the LayerDelegate. This
50 // is typically the base class you want to use.
51 // - LayerWithDelegateTest uses LayerDelegate on the delegates.
52 // - LayerWithRealCompositorTest when a real compositor is required for testing.
53 // - Slow because they bring up a window and run the real compositor. This
54 // is typically not what you want.
56 class ColoredLayer : public Layer, public LayerDelegate {
57 public:
58 explicit ColoredLayer(SkColor color)
59 : Layer(LAYER_TEXTURED),
60 color_(color) {
61 set_delegate(this);
64 ~ColoredLayer() override {}
66 // Overridden from LayerDelegate:
67 void OnPaintLayer(const ui::PaintContext& context) override {
68 ui::PaintRecorder recorder(context);
69 recorder.canvas()->DrawColor(color_);
72 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
74 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
76 base::Closure PrepareForLayerBoundsChange() override {
77 return base::Closure();
80 private:
81 SkColor color_;
84 class LayerWithRealCompositorTest : public testing::Test {
85 public:
86 LayerWithRealCompositorTest() {
87 if (PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_)) {
88 test_data_directory_ = test_data_directory_.AppendASCII("compositor");
89 } else {
90 LOG(ERROR) << "Could not open test data directory.";
93 ~LayerWithRealCompositorTest() override {}
95 // Overridden from testing::Test:
96 void SetUp() override {
97 bool enable_pixel_output = true;
98 ui::ContextFactory* context_factory =
99 InitializeContextFactoryForTests(enable_pixel_output);
101 const gfx::Rect host_bounds(10, 10, 500, 500);
102 compositor_host_.reset(
103 TestCompositorHost::Create(host_bounds, context_factory));
104 compositor_host_->Show();
107 void TearDown() override {
108 compositor_host_.reset();
109 TerminateContextFactoryForTests();
112 Compositor* GetCompositor() { return compositor_host_->GetCompositor(); }
114 Layer* CreateLayer(LayerType type) {
115 return new Layer(type);
118 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
119 Layer* layer = new ColoredLayer(color);
120 layer->SetBounds(bounds);
121 return layer;
124 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
125 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
126 layer->SetBounds(bounds);
127 return layer;
130 void DrawTree(Layer* root) {
131 GetCompositor()->SetRootLayer(root);
132 GetCompositor()->ScheduleDraw();
133 WaitForSwap();
136 void ReadPixels(SkBitmap* bitmap) {
137 ReadPixels(bitmap, gfx::Rect(GetCompositor()->size()));
140 void ReadPixels(SkBitmap* bitmap, gfx::Rect source_rect) {
141 scoped_refptr<ReadbackHolder> holder(new ReadbackHolder);
142 scoped_ptr<cc::CopyOutputRequest> request =
143 cc::CopyOutputRequest::CreateBitmapRequest(
144 base::Bind(&ReadbackHolder::OutputRequestCallback, holder));
145 request->set_area(source_rect);
147 GetCompositor()->root_layer()->RequestCopyOfOutput(request.Pass());
149 // Wait for copy response. This needs to wait as the compositor could
150 // be in the middle of a draw right now, and the commit with the
151 // copy output request may not be done on the first draw.
152 for (int i = 0; i < 2; i++) {
153 GetCompositor()->ScheduleFullRedraw();
154 WaitForDraw();
157 // Waits for the callback to finish run and return result.
158 holder->WaitForReadback();
160 *bitmap = holder->result();
163 void WaitForDraw() {
164 ui::DrawWaiterForTest::WaitForCompositingStarted(GetCompositor());
167 void WaitForSwap() {
168 DrawWaiterForTest::WaitForCompositingEnded(GetCompositor());
171 void WaitForCommit() {
172 ui::DrawWaiterForTest::WaitForCommit(GetCompositor());
175 // Invalidates the entire contents of the layer.
176 void SchedulePaintForLayer(Layer* layer) {
177 layer->SchedulePaint(
178 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
181 const base::FilePath& test_data_directory() const {
182 return test_data_directory_;
185 private:
186 class ReadbackHolder : public base::RefCountedThreadSafe<ReadbackHolder> {
187 public:
188 ReadbackHolder() : run_loop_(new base::RunLoop) {}
190 void OutputRequestCallback(scoped_ptr<cc::CopyOutputResult> result) {
191 result_ = result->TakeBitmap();
192 run_loop_->Quit();
195 void WaitForReadback() { run_loop_->Run(); }
197 const SkBitmap& result() const { return *result_; }
199 private:
200 friend class base::RefCountedThreadSafe<ReadbackHolder>;
202 virtual ~ReadbackHolder() {}
204 scoped_ptr<SkBitmap> result_;
205 scoped_ptr<base::RunLoop> run_loop_;
208 scoped_ptr<TestCompositorHost> compositor_host_;
210 // The root directory for test files.
211 base::FilePath test_data_directory_;
213 DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
216 // LayerDelegate that paints colors to the layer.
217 class TestLayerDelegate : public LayerDelegate {
218 public:
219 explicit TestLayerDelegate() { reset(); }
220 ~TestLayerDelegate() override {}
222 void AddColor(SkColor color) {
223 colors_.push_back(color);
226 int color_index() const { return color_index_; }
228 float device_scale_factor() const {
229 return device_scale_factor_;
232 // Overridden from LayerDelegate:
233 void OnPaintLayer(const ui::PaintContext& context) override {
234 ui::PaintRecorder recorder(context);
235 recorder.canvas()->DrawColor(colors_[color_index_]);
236 color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size());
239 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
241 void OnDeviceScaleFactorChanged(float device_scale_factor) override {
242 device_scale_factor_ = device_scale_factor;
245 base::Closure PrepareForLayerBoundsChange() override {
246 return base::Closure();
249 void reset() {
250 color_index_ = 0;
251 device_scale_factor_ = 0.0f;
254 private:
255 std::vector<SkColor> colors_;
256 int color_index_;
257 float device_scale_factor_;
259 DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate);
262 // LayerDelegate that verifies that a layer was asked to update its canvas.
263 class DrawTreeLayerDelegate : public LayerDelegate {
264 public:
265 DrawTreeLayerDelegate() : painted_(false) {}
266 ~DrawTreeLayerDelegate() override {}
268 void Reset() {
269 painted_ = false;
272 bool painted() const { return painted_; }
274 private:
275 // Overridden from LayerDelegate:
276 void OnPaintLayer(const ui::PaintContext& context) override {
277 painted_ = true;
278 ui::PaintRecorder recorder(context);
279 recorder.canvas()->DrawColor(SK_ColorWHITE);
281 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
282 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
283 base::Closure PrepareForLayerBoundsChange() override {
284 return base::Closure();
287 bool painted_;
289 DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate);
292 // The simplest possible layer delegate. Does nothing.
293 class NullLayerDelegate : public LayerDelegate {
294 public:
295 NullLayerDelegate() {}
296 ~NullLayerDelegate() override {}
298 private:
299 // Overridden from LayerDelegate:
300 void OnPaintLayer(const ui::PaintContext& context) override {}
301 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
302 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
303 base::Closure PrepareForLayerBoundsChange() override {
304 return base::Closure();
307 DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate);
310 // Remembers if it has been notified.
311 class TestCompositorObserver : public CompositorObserver {
312 public:
313 TestCompositorObserver()
314 : committed_(false), started_(false), ended_(false), aborted_(false) {}
316 bool committed() const { return committed_; }
317 bool notified() const { return started_ && ended_; }
318 bool aborted() const { return aborted_; }
320 void Reset() {
321 committed_ = false;
322 started_ = false;
323 ended_ = false;
324 aborted_ = false;
327 private:
328 void OnCompositingDidCommit(Compositor* compositor) override {
329 committed_ = true;
332 void OnCompositingStarted(Compositor* compositor,
333 base::TimeTicks start_time) override {
334 started_ = true;
337 void OnCompositingEnded(Compositor* compositor) override { ended_ = true; }
339 void OnCompositingAborted(Compositor* compositor) override {
340 aborted_ = true;
343 void OnCompositingLockStateChanged(Compositor* compositor) override {}
345 void OnCompositingShuttingDown(Compositor* compositor) override {}
347 bool committed_;
348 bool started_;
349 bool ended_;
350 bool aborted_;
352 DISALLOW_COPY_AND_ASSIGN(TestCompositorObserver);
355 } // namespace
357 TEST_F(LayerWithRealCompositorTest, Draw) {
358 scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED,
359 gfx::Rect(20, 20, 50, 50)));
360 DrawTree(layer.get());
363 // Create this hierarchy:
364 // L1 - red
365 // +-- L2 - blue
366 // | +-- L3 - yellow
367 // +-- L4 - magenta
369 TEST_F(LayerWithRealCompositorTest, Hierarchy) {
370 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
371 gfx::Rect(20, 20, 400, 400)));
372 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
373 gfx::Rect(10, 10, 350, 350)));
374 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
375 gfx::Rect(5, 5, 25, 25)));
376 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
377 gfx::Rect(300, 300, 100, 100)));
379 l1->Add(l2.get());
380 l1->Add(l4.get());
381 l2->Add(l3.get());
383 DrawTree(l1.get());
386 class LayerWithDelegateTest : public testing::Test {
387 public:
388 LayerWithDelegateTest() {}
389 ~LayerWithDelegateTest() override {}
391 // Overridden from testing::Test:
392 void SetUp() override {
393 bool enable_pixel_output = false;
394 ui::ContextFactory* context_factory =
395 InitializeContextFactoryForTests(enable_pixel_output);
397 const gfx::Rect host_bounds(1000, 1000);
398 compositor_host_.reset(TestCompositorHost::Create(host_bounds,
399 context_factory));
400 compositor_host_->Show();
403 void TearDown() override {
404 compositor_host_.reset();
405 TerminateContextFactoryForTests();
408 Compositor* compositor() { return compositor_host_->GetCompositor(); }
410 virtual Layer* CreateLayer(LayerType type) {
411 return new Layer(type);
414 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
415 Layer* layer = new ColoredLayer(color);
416 layer->SetBounds(bounds);
417 return layer;
420 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
421 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
422 layer->SetBounds(bounds);
423 return layer;
426 void DrawTree(Layer* root) {
427 compositor()->SetRootLayer(root);
428 Draw();
431 // Invalidates the entire contents of the layer.
432 void SchedulePaintForLayer(Layer* layer) {
433 layer->SchedulePaint(
434 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
437 // Invokes DrawTree on the compositor.
438 void Draw() {
439 compositor()->ScheduleDraw();
440 WaitForDraw();
443 void WaitForDraw() {
444 DrawWaiterForTest::WaitForCompositingStarted(compositor());
447 void WaitForCommit() {
448 DrawWaiterForTest::WaitForCommit(compositor());
451 private:
452 scoped_ptr<TestCompositorHost> compositor_host_;
454 DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
457 // L1
458 // +-- L2
459 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
460 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
461 gfx::Rect(20, 20, 400, 400)));
462 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
463 gfx::Rect(10, 10, 350, 350)));
464 l1->Add(l2.get());
465 DrawTree(l1.get());
467 gfx::Point point1_in_l2_coords(5, 5);
468 Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords);
469 gfx::Point point1_in_l1_coords(15, 15);
470 EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords);
472 gfx::Point point2_in_l1_coords(5, 5);
473 Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords);
474 gfx::Point point2_in_l2_coords(-5, -5);
475 EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords);
478 // L1
479 // +-- L2
480 // +-- L3
481 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
482 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
483 gfx::Rect(20, 20, 400, 400)));
484 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
485 gfx::Rect(10, 10, 350, 350)));
486 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
487 gfx::Rect(10, 10, 100, 100)));
488 l1->Add(l2.get());
489 l2->Add(l3.get());
490 DrawTree(l1.get());
492 gfx::Point point1_in_l3_coords(5, 5);
493 Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords);
494 gfx::Point point1_in_l1_coords(25, 25);
495 EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords);
497 gfx::Point point2_in_l1_coords(5, 5);
498 Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords);
499 gfx::Point point2_in_l3_coords(-15, -15);
500 EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords);
503 TEST_F(LayerWithRealCompositorTest, Delegate) {
504 // This test makes sure that whenever paint happens at a layer, its layer
505 // delegate gets the paint, which in this test update its color and
506 // |color_index|.
507 scoped_ptr<Layer> l1(
508 CreateColorLayer(SK_ColorBLACK, gfx::Rect(20, 20, 400, 400)));
509 GetCompositor()->SetRootLayer(l1.get());
510 WaitForDraw();
512 TestLayerDelegate delegate;
513 l1->set_delegate(&delegate);
514 delegate.AddColor(SK_ColorWHITE);
515 delegate.AddColor(SK_ColorYELLOW);
516 delegate.AddColor(SK_ColorGREEN);
518 l1->SchedulePaint(gfx::Rect(0, 0, 400, 400));
519 WaitForDraw();
520 // Test that paint happened at layer delegate.
521 EXPECT_EQ(1, delegate.color_index());
523 l1->SchedulePaint(gfx::Rect(10, 10, 200, 200));
524 WaitForDraw();
525 // Test that paint happened at layer delegate.
526 EXPECT_EQ(2, delegate.color_index());
528 l1->SchedulePaint(gfx::Rect(5, 5, 50, 50));
529 WaitForDraw();
530 // Test that paint happened at layer delegate.
531 EXPECT_EQ(0, delegate.color_index());
534 TEST_F(LayerWithRealCompositorTest, DrawTree) {
535 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
536 gfx::Rect(20, 20, 400, 400)));
537 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
538 gfx::Rect(10, 10, 350, 350)));
539 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
540 gfx::Rect(10, 10, 100, 100)));
541 l1->Add(l2.get());
542 l2->Add(l3.get());
544 GetCompositor()->SetRootLayer(l1.get());
545 WaitForDraw();
547 DrawTreeLayerDelegate d1;
548 l1->set_delegate(&d1);
549 DrawTreeLayerDelegate d2;
550 l2->set_delegate(&d2);
551 DrawTreeLayerDelegate d3;
552 l3->set_delegate(&d3);
554 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
555 WaitForDraw();
556 EXPECT_FALSE(d1.painted());
557 EXPECT_TRUE(d2.painted());
558 EXPECT_FALSE(d3.painted());
561 // Tests no-texture Layers.
562 // Create this hierarchy:
563 // L1 - red
564 // +-- L2 - NO TEXTURE
565 // | +-- L3 - yellow
566 // +-- L4 - magenta
568 TEST_F(LayerWithRealCompositorTest, HierarchyNoTexture) {
569 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
570 gfx::Rect(20, 20, 400, 400)));
571 scoped_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350)));
572 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
573 gfx::Rect(5, 5, 25, 25)));
574 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
575 gfx::Rect(300, 300, 100, 100)));
577 l1->Add(l2.get());
578 l1->Add(l4.get());
579 l2->Add(l3.get());
581 GetCompositor()->SetRootLayer(l1.get());
582 WaitForDraw();
584 DrawTreeLayerDelegate d2;
585 l2->set_delegate(&d2);
586 DrawTreeLayerDelegate d3;
587 l3->set_delegate(&d3);
589 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
590 l3->SchedulePaint(gfx::Rect(5, 5, 5, 5));
591 WaitForDraw();
593 // |d2| should not have received a paint notification since it has no texture.
594 EXPECT_FALSE(d2.painted());
595 // |d3| should have received a paint notification.
596 EXPECT_TRUE(d3.painted());
599 class LayerWithNullDelegateTest : public LayerWithDelegateTest {
600 public:
601 LayerWithNullDelegateTest() {}
602 ~LayerWithNullDelegateTest() override {}
604 void SetUp() override {
605 LayerWithDelegateTest::SetUp();
606 default_layer_delegate_.reset(new NullLayerDelegate());
609 Layer* CreateLayer(LayerType type) override {
610 Layer* layer = new Layer(type);
611 layer->set_delegate(default_layer_delegate_.get());
612 return layer;
615 Layer* CreateTextureRootLayer(const gfx::Rect& bounds) {
616 Layer* layer = CreateTextureLayer(bounds);
617 compositor()->SetRootLayer(layer);
618 return layer;
621 Layer* CreateTextureLayer(const gfx::Rect& bounds) {
622 Layer* layer = CreateLayer(LAYER_TEXTURED);
623 layer->SetBounds(bounds);
624 return layer;
627 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) override {
628 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
629 layer->SetBounds(bounds);
630 return layer;
633 private:
634 scoped_ptr<NullLayerDelegate> default_layer_delegate_;
636 DISALLOW_COPY_AND_ASSIGN(LayerWithNullDelegateTest);
639 TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) {
640 scoped_ptr<Layer> layer(CreateLayer(LAYER_NOT_DRAWN));
641 std::string name = "\"\'\\/\b\f\n\r\t\n";
642 layer->set_name(name);
643 scoped_refptr<base::trace_event::ConvertableToTraceFormat> debug_info =
644 layer->TakeDebugInfo();
645 EXPECT_TRUE(!!debug_info.get());
646 std::string json;
647 debug_info->AppendAsTraceFormat(&json);
648 base::JSONReader json_reader;
649 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(json));
650 EXPECT_TRUE(!!debug_info_value);
651 EXPECT_TRUE(debug_info_value->IsType(base::Value::TYPE_DICTIONARY));
652 base::DictionaryValue* dictionary = 0;
653 EXPECT_TRUE(debug_info_value->GetAsDictionary(&dictionary));
654 std::string roundtrip;
655 EXPECT_TRUE(dictionary->GetString("layer_name", &roundtrip));
656 EXPECT_EQ(name, roundtrip);
659 void ReturnMailbox(bool* run, uint32 sync_point, bool is_lost) {
660 *run = true;
663 TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
664 scoped_ptr<Layer> l1(CreateLayer(LAYER_SOLID_COLOR));
665 l1->SetFillsBoundsOpaquely(true);
666 l1->SetForceRenderSurface(true);
667 l1->SetVisible(false);
668 l1->SetBounds(gfx::Rect(4, 5));
670 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
671 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
672 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
673 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
674 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
675 EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
677 cc::Layer* before_layer = l1->cc_layer();
679 bool callback1_run = false;
680 cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), 0, 0);
681 l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
682 base::Bind(ReturnMailbox, &callback1_run)),
683 gfx::Size(10, 10));
685 EXPECT_NE(before_layer, l1->cc_layer());
687 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
688 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
689 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
690 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
691 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
692 EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
693 EXPECT_FALSE(callback1_run);
695 bool callback2_run = false;
696 mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0);
697 l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
698 base::Bind(ReturnMailbox, &callback2_run)),
699 gfx::Size(10, 10));
700 EXPECT_TRUE(callback1_run);
701 EXPECT_FALSE(callback2_run);
703 // Show solid color instead.
704 l1->SetShowSolidColorContent();
705 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
706 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
707 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
708 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
709 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
710 EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
711 EXPECT_TRUE(callback2_run);
713 before_layer = l1->cc_layer();
715 // Back to a texture, without changing the bounds of the layer or the texture.
716 bool callback3_run = false;
717 mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0);
718 l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
719 base::Bind(ReturnMailbox, &callback3_run)),
720 gfx::Size(10, 10));
722 EXPECT_NE(before_layer, l1->cc_layer());
724 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
725 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
726 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
727 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
728 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
729 EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
730 EXPECT_FALSE(callback3_run);
732 // Release the on |l1| mailbox to clean up the test.
733 l1->SetShowSolidColorContent();
736 // Various visibile/drawn assertions.
737 TEST_F(LayerWithNullDelegateTest, Visibility) {
738 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
739 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
740 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
741 l1->Add(l2.get());
742 l2->Add(l3.get());
744 NullLayerDelegate delegate;
745 l1->set_delegate(&delegate);
746 l2->set_delegate(&delegate);
747 l3->set_delegate(&delegate);
749 // Layers should initially be drawn.
750 EXPECT_TRUE(l1->IsDrawn());
751 EXPECT_TRUE(l2->IsDrawn());
752 EXPECT_TRUE(l3->IsDrawn());
753 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
754 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
755 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
757 compositor()->SetRootLayer(l1.get());
759 Draw();
761 l1->SetVisible(false);
762 EXPECT_FALSE(l1->IsDrawn());
763 EXPECT_FALSE(l2->IsDrawn());
764 EXPECT_FALSE(l3->IsDrawn());
765 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
766 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
767 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
769 l3->SetVisible(false);
770 EXPECT_FALSE(l1->IsDrawn());
771 EXPECT_FALSE(l2->IsDrawn());
772 EXPECT_FALSE(l3->IsDrawn());
773 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
774 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
775 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
777 l1->SetVisible(true);
778 EXPECT_TRUE(l1->IsDrawn());
779 EXPECT_TRUE(l2->IsDrawn());
780 EXPECT_FALSE(l3->IsDrawn());
781 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
782 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
783 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
786 // Checks that stacking-related methods behave as advertised.
787 TEST_F(LayerWithNullDelegateTest, Stacking) {
788 scoped_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
789 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
790 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
791 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
792 l1->set_name("1");
793 l2->set_name("2");
794 l3->set_name("3");
795 root->Add(l3.get());
796 root->Add(l2.get());
797 root->Add(l1.get());
799 // Layers' children are stored in bottom-to-top order.
800 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
802 root->StackAtTop(l3.get());
803 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
805 root->StackAtTop(l1.get());
806 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
808 root->StackAtTop(l1.get());
809 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
811 root->StackAbove(l2.get(), l3.get());
812 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
814 root->StackAbove(l1.get(), l3.get());
815 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
817 root->StackAbove(l2.get(), l1.get());
818 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
820 root->StackAtBottom(l2.get());
821 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
823 root->StackAtBottom(l3.get());
824 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
826 root->StackAtBottom(l3.get());
827 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
829 root->StackBelow(l2.get(), l3.get());
830 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
832 root->StackBelow(l1.get(), l3.get());
833 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
835 root->StackBelow(l3.get(), l2.get());
836 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
838 root->StackBelow(l3.get(), l2.get());
839 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
841 root->StackBelow(l3.get(), l1.get());
842 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
845 // Verifies SetBounds triggers the appropriate painting/drawing.
846 TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
847 scoped_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
848 compositor()->SetRootLayer(l1.get());
850 Draw();
852 l1->SetBounds(gfx::Rect(5, 5, 200, 200));
854 // The CompositorDelegate (us) should have been told to draw for a move.
855 WaitForDraw();
857 l1->SetBounds(gfx::Rect(5, 5, 100, 100));
859 // The CompositorDelegate (us) should have been told to draw for a resize.
860 WaitForDraw();
863 void ExpectRgba(int x, int y, SkColor expected_color, SkColor actual_color) {
864 EXPECT_EQ(expected_color, actual_color)
865 << "Pixel error at x=" << x << " y=" << y << "; "
866 << "actual RGBA=("
867 << SkColorGetR(actual_color) << ","
868 << SkColorGetG(actual_color) << ","
869 << SkColorGetB(actual_color) << ","
870 << SkColorGetA(actual_color) << "); "
871 << "expected RGBA=("
872 << SkColorGetR(expected_color) << ","
873 << SkColorGetG(expected_color) << ","
874 << SkColorGetB(expected_color) << ","
875 << SkColorGetA(expected_color) << ")";
878 // Checks that pixels are actually drawn to the screen with a read back.
879 TEST_F(LayerWithRealCompositorTest, DrawPixels) {
880 gfx::Size viewport_size = GetCompositor()->size();
882 // The window should be some non-trivial size but may not be exactly
883 // 500x500 on all platforms/bots.
884 EXPECT_GE(viewport_size.width(), 200);
885 EXPECT_GE(viewport_size.height(), 200);
887 int blue_height = 10;
889 scoped_ptr<Layer> layer(
890 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
891 scoped_ptr<Layer> layer2(
892 CreateColorLayer(SK_ColorBLUE,
893 gfx::Rect(0, 0, viewport_size.width(), blue_height)));
895 layer->Add(layer2.get());
897 DrawTree(layer.get());
899 SkBitmap bitmap;
900 ReadPixels(&bitmap, gfx::Rect(viewport_size));
901 ASSERT_FALSE(bitmap.empty());
903 SkAutoLockPixels lock(bitmap);
904 for (int x = 0; x < viewport_size.width(); x++) {
905 for (int y = 0; y < viewport_size.height(); y++) {
906 SkColor actual_color = bitmap.getColor(x, y);
907 SkColor expected_color = y < blue_height ? SK_ColorBLUE : SK_ColorRED;
908 ExpectRgba(x, y, expected_color, actual_color);
913 // Checks that drawing a layer with transparent pixels is blended correctly
914 // with the lower layer.
915 TEST_F(LayerWithRealCompositorTest, DrawAlphaBlendedPixels) {
916 gfx::Size viewport_size = GetCompositor()->size();
918 int test_size = 200;
919 EXPECT_GE(viewport_size.width(), test_size);
920 EXPECT_GE(viewport_size.height(), test_size);
922 // Blue with a wee bit of transparency.
923 SkColor blue_with_alpha = SkColorSetARGBInline(40, 10, 20, 200);
924 SkColor blend_color = SkColorSetARGBInline(255, 216, 3, 32);
926 scoped_ptr<Layer> background_layer(
927 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
928 scoped_ptr<Layer> foreground_layer(
929 CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
931 // This must be set to false for layers with alpha to be blended correctly.
932 foreground_layer->SetFillsBoundsOpaquely(false);
934 background_layer->Add(foreground_layer.get());
935 DrawTree(background_layer.get());
937 SkBitmap bitmap;
938 ReadPixels(&bitmap, gfx::Rect(viewport_size));
939 ASSERT_FALSE(bitmap.empty());
941 SkAutoLockPixels lock(bitmap);
942 for (int x = 0; x < test_size; x++) {
943 for (int y = 0; y < test_size; y++) {
944 SkColor actual_color = bitmap.getColor(x, y);
945 ExpectRgba(x, y, blend_color, actual_color);
950 // Checks that using the AlphaShape filter applied to a layer with
951 // transparency, alpha-blends properly with the layer below.
952 TEST_F(LayerWithRealCompositorTest, DrawAlphaThresholdFilterPixels) {
953 gfx::Size viewport_size = GetCompositor()->size();
955 int test_size = 200;
956 EXPECT_GE(viewport_size.width(), test_size);
957 EXPECT_GE(viewport_size.height(), test_size);
959 int blue_height = 10;
960 SkColor blue_with_alpha = SkColorSetARGBInline(40, 0, 0, 255);
961 SkColor blend_color = SkColorSetARGBInline(255, 215, 0, 40);
963 scoped_ptr<Layer> background_layer(
964 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
965 scoped_ptr<Layer> foreground_layer(
966 CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
968 // Add a shape to restrict the visible part of the layer.
969 SkRegion shape;
970 shape.setRect(0, 0, viewport_size.width(), blue_height);
971 foreground_layer->SetAlphaShape(make_scoped_ptr(new SkRegion(shape)));
973 foreground_layer->SetFillsBoundsOpaquely(false);
975 background_layer->Add(foreground_layer.get());
976 DrawTree(background_layer.get());
978 SkBitmap bitmap;
979 ReadPixels(&bitmap, gfx::Rect(viewport_size));
980 ASSERT_FALSE(bitmap.empty());
982 SkAutoLockPixels lock(bitmap);
983 for (int x = 0; x < test_size; x++) {
984 for (int y = 0; y < test_size; y++) {
985 SkColor actual_color = bitmap.getColor(x, y);
986 ExpectRgba(x, y, actual_color,
987 y < blue_height ? blend_color : SK_ColorRED);
992 // Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
993 TEST_F(LayerWithRealCompositorTest, SetRootLayer) {
994 Compositor* compositor = GetCompositor();
995 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
996 gfx::Rect(20, 20, 400, 400)));
997 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
998 gfx::Rect(10, 10, 350, 350)));
1000 EXPECT_EQ(NULL, l1->GetCompositor());
1001 EXPECT_EQ(NULL, l2->GetCompositor());
1003 compositor->SetRootLayer(l1.get());
1004 EXPECT_EQ(compositor, l1->GetCompositor());
1006 l1->Add(l2.get());
1007 EXPECT_EQ(compositor, l2->GetCompositor());
1009 l1->Remove(l2.get());
1010 EXPECT_EQ(NULL, l2->GetCompositor());
1012 l1->Add(l2.get());
1013 EXPECT_EQ(compositor, l2->GetCompositor());
1015 compositor->SetRootLayer(NULL);
1016 EXPECT_EQ(NULL, l1->GetCompositor());
1017 EXPECT_EQ(NULL, l2->GetCompositor());
1020 // Checks that compositor observers are notified when:
1021 // - DrawTree is called,
1022 // - After ScheduleDraw is called, or
1023 // - Whenever SetBounds, SetOpacity or SetTransform are called.
1024 // TODO(vollick): could be reorganized into compositor_unittest.cc
1025 TEST_F(LayerWithRealCompositorTest, CompositorObservers) {
1026 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
1027 gfx::Rect(20, 20, 400, 400)));
1028 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
1029 gfx::Rect(10, 10, 350, 350)));
1030 l1->Add(l2.get());
1031 TestCompositorObserver observer;
1032 GetCompositor()->AddObserver(&observer);
1034 // Explicitly called DrawTree should cause the observers to be notified.
1035 // NOTE: this call to DrawTree sets l1 to be the compositor's root layer.
1036 DrawTree(l1.get());
1037 EXPECT_TRUE(observer.notified());
1039 // ScheduleDraw without any visible change should cause a commit.
1040 observer.Reset();
1041 l1->ScheduleDraw();
1042 WaitForCommit();
1043 EXPECT_TRUE(observer.committed());
1045 // Moving, but not resizing, a layer should alert the observers.
1046 observer.Reset();
1047 l2->SetBounds(gfx::Rect(0, 0, 350, 350));
1048 WaitForSwap();
1049 EXPECT_TRUE(observer.notified());
1051 // So should resizing a layer.
1052 observer.Reset();
1053 l2->SetBounds(gfx::Rect(0, 0, 400, 400));
1054 WaitForSwap();
1055 EXPECT_TRUE(observer.notified());
1057 // Opacity changes should alert the observers.
1058 observer.Reset();
1059 l2->SetOpacity(0.5f);
1060 WaitForSwap();
1061 EXPECT_TRUE(observer.notified());
1063 // So should setting the opacity back.
1064 observer.Reset();
1065 l2->SetOpacity(1.0f);
1066 WaitForSwap();
1067 EXPECT_TRUE(observer.notified());
1069 // Setting the transform of a layer should alert the observers.
1070 observer.Reset();
1071 gfx::Transform transform;
1072 transform.Translate(200.0, 200.0);
1073 transform.Rotate(90.0);
1074 transform.Translate(-200.0, -200.0);
1075 l2->SetTransform(transform);
1076 WaitForSwap();
1077 EXPECT_TRUE(observer.notified());
1079 // A change resulting in an aborted swap buffer should alert the observer
1080 // and also signal an abort.
1081 observer.Reset();
1082 l2->SetOpacity(0.1f);
1083 GetCompositor()->DidAbortSwapBuffers();
1084 WaitForSwap();
1085 EXPECT_TRUE(observer.notified());
1086 EXPECT_TRUE(observer.aborted());
1088 GetCompositor()->RemoveObserver(&observer);
1090 // Opacity changes should no longer alert the removed observer.
1091 observer.Reset();
1092 l2->SetOpacity(0.5f);
1093 WaitForSwap();
1095 EXPECT_FALSE(observer.notified());
1098 // Checks that modifying the hierarchy correctly affects final composite.
1099 TEST_F(LayerWithRealCompositorTest, ModifyHierarchy) {
1100 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1102 // l0
1103 // +-l11
1104 // | +-l21
1105 // +-l12
1106 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1107 gfx::Rect(0, 0, 50, 50)));
1108 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1109 gfx::Rect(0, 0, 25, 25)));
1110 scoped_ptr<Layer> l21(CreateColorLayer(SK_ColorMAGENTA,
1111 gfx::Rect(0, 0, 15, 15)));
1112 scoped_ptr<Layer> l12(CreateColorLayer(SK_ColorBLUE,
1113 gfx::Rect(10, 10, 25, 25)));
1115 base::FilePath ref_img1 =
1116 test_data_directory().AppendASCII("ModifyHierarchy1.png");
1117 base::FilePath ref_img2 =
1118 test_data_directory().AppendASCII("ModifyHierarchy2.png");
1119 SkBitmap bitmap;
1121 l0->Add(l11.get());
1122 l11->Add(l21.get());
1123 l0->Add(l12.get());
1124 DrawTree(l0.get());
1125 ReadPixels(&bitmap);
1126 ASSERT_FALSE(bitmap.empty());
1127 // WritePNGFile(bitmap, ref_img1);
1128 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1130 l0->StackAtTop(l11.get());
1131 DrawTree(l0.get());
1132 ReadPixels(&bitmap);
1133 ASSERT_FALSE(bitmap.empty());
1134 // WritePNGFile(bitmap, ref_img2);
1135 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1137 // should restore to original configuration
1138 l0->StackAbove(l12.get(), l11.get());
1139 DrawTree(l0.get());
1140 ReadPixels(&bitmap);
1141 ASSERT_FALSE(bitmap.empty());
1142 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1144 // l11 back to front
1145 l0->StackAtTop(l11.get());
1146 DrawTree(l0.get());
1147 ReadPixels(&bitmap);
1148 ASSERT_FALSE(bitmap.empty());
1149 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1151 // should restore to original configuration
1152 l0->StackAbove(l12.get(), l11.get());
1153 DrawTree(l0.get());
1154 ReadPixels(&bitmap);
1155 ASSERT_FALSE(bitmap.empty());
1156 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1158 // l11 back to front
1159 l0->StackAbove(l11.get(), l12.get());
1160 DrawTree(l0.get());
1161 ReadPixels(&bitmap);
1162 ASSERT_FALSE(bitmap.empty());
1163 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1166 // Opacity is rendered correctly.
1167 // Checks that modifying the hierarchy correctly affects final composite.
1168 TEST_F(LayerWithRealCompositorTest, Opacity) {
1169 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1171 // l0
1172 // +-l11
1173 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1174 gfx::Rect(0, 0, 50, 50)));
1175 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1176 gfx::Rect(0, 0, 25, 25)));
1178 base::FilePath ref_img = test_data_directory().AppendASCII("Opacity.png");
1180 l11->SetOpacity(0.75);
1181 l0->Add(l11.get());
1182 DrawTree(l0.get());
1183 SkBitmap bitmap;
1184 ReadPixels(&bitmap);
1185 ASSERT_FALSE(bitmap.empty());
1186 // WritePNGFile(bitmap, ref_img);
1187 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img, cc::ExactPixelComparator(true)));
1190 namespace {
1192 class SchedulePaintLayerDelegate : public LayerDelegate {
1193 public:
1194 SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
1196 ~SchedulePaintLayerDelegate() override {}
1198 void set_layer(Layer* layer) {
1199 layer_ = layer;
1200 layer_->set_delegate(this);
1203 void SetSchedulePaintRect(const gfx::Rect& rect) {
1204 schedule_paint_rect_ = rect;
1207 int GetPaintCountAndClear() {
1208 int value = paint_count_;
1209 paint_count_ = 0;
1210 return value;
1213 const gfx::Rect& last_clip_rect() const { return last_clip_rect_; }
1215 private:
1216 // Overridden from LayerDelegate:
1217 void OnPaintLayer(const ui::PaintContext& context) override {
1218 paint_count_++;
1219 if (!schedule_paint_rect_.IsEmpty()) {
1220 layer_->SchedulePaint(schedule_paint_rect_);
1221 schedule_paint_rect_ = gfx::Rect();
1223 last_clip_rect_ = context.InvalidationForTesting();
1226 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
1228 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
1230 base::Closure PrepareForLayerBoundsChange() override {
1231 return base::Closure();
1234 int paint_count_;
1235 Layer* layer_;
1236 gfx::Rect schedule_paint_rect_;
1237 gfx::Rect last_clip_rect_;
1239 DISALLOW_COPY_AND_ASSIGN(SchedulePaintLayerDelegate);
1242 } // namespace
1244 // Verifies that if SchedulePaint is invoked during painting the layer is still
1245 // marked dirty.
1246 TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
1247 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorRED,
1248 gfx::Rect(0, 0, 500, 500)));
1249 SchedulePaintLayerDelegate child_delegate;
1250 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorBLUE,
1251 gfx::Rect(0, 0, 200, 200)));
1252 child_delegate.set_layer(child.get());
1254 root->Add(child.get());
1256 SchedulePaintForLayer(root.get());
1257 DrawTree(root.get());
1258 child->SchedulePaint(gfx::Rect(0, 0, 20, 20));
1259 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1261 // Set a rect so that when OnPaintLayer() is invoked SchedulePaint is invoked
1262 // again.
1263 child_delegate.SetSchedulePaintRect(gfx::Rect(10, 10, 30, 30));
1264 WaitForCommit();
1265 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1267 // Because SchedulePaint() was invoked from OnPaintLayer() |child| should
1268 // still need to be painted.
1269 WaitForCommit();
1270 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1271 EXPECT_TRUE(child_delegate.last_clip_rect().Contains(
1272 gfx::Rect(10, 10, 30, 30)));
1275 TEST_F(LayerWithRealCompositorTest, ScaleUpDown) {
1276 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1277 gfx::Rect(10, 20, 200, 220)));
1278 TestLayerDelegate root_delegate;
1279 root_delegate.AddColor(SK_ColorWHITE);
1280 root->set_delegate(&root_delegate);
1282 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1283 gfx::Rect(10, 20, 140, 180)));
1284 TestLayerDelegate l1_delegate;
1285 l1_delegate.AddColor(SK_ColorWHITE);
1286 l1->set_delegate(&l1_delegate);
1288 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1289 GetCompositor()->SetRootLayer(root.get());
1290 root->Add(l1.get());
1291 WaitForDraw();
1293 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1294 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1295 gfx::Size cc_bounds_size = root->cc_layer()->bounds();
1296 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1297 cc_bounds_size = l1->cc_layer()->bounds();
1298 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1299 // No scale change, so no scale notification.
1300 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1301 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1303 // Scale up to 2.0. Changing scale doesn't change the bounds in DIP.
1304 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1305 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1306 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1307 // CC layer should still match the UI layer bounds.
1308 cc_bounds_size = root->cc_layer()->bounds();
1309 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1310 cc_bounds_size = l1->cc_layer()->bounds();
1311 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1312 // New scale factor must have been notified. Make sure painting happens at
1313 // right scale.
1314 EXPECT_EQ(2.0f, root_delegate.device_scale_factor());
1315 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1317 // Scale down back to 1.0f.
1318 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1319 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1320 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1321 // CC layer should still match the UI layer bounds.
1322 cc_bounds_size = root->cc_layer()->bounds();
1323 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1324 cc_bounds_size = l1->cc_layer()->bounds();
1325 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1326 // New scale factor must have been notified. Make sure painting happens at
1327 // right scale.
1328 EXPECT_EQ(1.0f, root_delegate.device_scale_factor());
1329 EXPECT_EQ(1.0f, l1_delegate.device_scale_factor());
1331 root_delegate.reset();
1332 l1_delegate.reset();
1333 // Just changing the size shouldn't notify the scale change nor
1334 // trigger repaint.
1335 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(1000, 1000));
1336 // No scale change, so no scale notification.
1337 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1338 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1341 TEST_F(LayerWithRealCompositorTest, ScaleReparent) {
1342 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1343 gfx::Rect(10, 20, 200, 220)));
1344 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1345 gfx::Rect(10, 20, 140, 180)));
1346 TestLayerDelegate l1_delegate;
1347 l1_delegate.AddColor(SK_ColorWHITE);
1348 l1->set_delegate(&l1_delegate);
1350 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1351 GetCompositor()->SetRootLayer(root.get());
1353 root->Add(l1.get());
1354 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1355 gfx::Size cc_bounds_size = l1->cc_layer()->bounds();
1356 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1357 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1359 // Remove l1 from root and change the scale.
1360 root->Remove(l1.get());
1361 EXPECT_EQ(NULL, l1->parent());
1362 EXPECT_EQ(NULL, l1->GetCompositor());
1363 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1364 // Sanity check on root and l1.
1365 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1366 cc_bounds_size = l1->cc_layer()->bounds();
1367 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1369 root->Add(l1.get());
1370 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1371 cc_bounds_size = l1->cc_layer()->bounds();
1372 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1373 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1376 // Verifies that when changing bounds on a layer that is invisible, and then
1377 // made visible, the right thing happens:
1378 // - if just a move, then no painting should happen.
1379 // - if a resize, the layer should be repainted.
1380 TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
1381 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1383 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1384 child->SetBounds(gfx::Rect(0, 0, 500, 500));
1385 DrawTreeLayerDelegate delegate;
1386 child->set_delegate(&delegate);
1387 root->Add(child.get());
1389 // Paint once for initial damage.
1390 child->SetVisible(true);
1391 DrawTree(root.get());
1393 // Reset into invisible state.
1394 child->SetVisible(false);
1395 DrawTree(root.get());
1396 delegate.Reset();
1398 // Move layer.
1399 child->SetBounds(gfx::Rect(200, 200, 500, 500));
1400 child->SetVisible(true);
1401 DrawTree(root.get());
1402 EXPECT_FALSE(delegate.painted());
1404 // Reset into invisible state.
1405 child->SetVisible(false);
1406 DrawTree(root.get());
1407 delegate.Reset();
1409 // Resize layer.
1410 child->SetBounds(gfx::Rect(200, 200, 400, 400));
1411 child->SetVisible(true);
1412 DrawTree(root.get());
1413 EXPECT_TRUE(delegate.painted());
1416 static scoped_ptr<cc::DelegatedFrameData> MakeFrameData(gfx::Size size) {
1417 scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
1418 scoped_ptr<cc::RenderPass> render_pass(cc::RenderPass::Create());
1419 render_pass->SetNew(
1420 cc::RenderPassId(1, 1), gfx::Rect(size), gfx::Rect(), gfx::Transform());
1421 frame_data->render_pass_list.push_back(render_pass.Pass());
1422 return frame_data.Pass();
1425 TEST_F(LayerWithDelegateTest, DelegatedLayer) {
1426 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1428 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1430 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1431 child->SetVisible(true);
1432 root->Add(child.get());
1433 DrawTree(root.get());
1435 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1436 new cc::DelegatedFrameResourceCollection;
1437 scoped_refptr<cc::DelegatedFrameProvider> frame_provider;
1439 // Content matches layer size.
1440 frame_provider = new cc::DelegatedFrameProvider(
1441 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1442 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1443 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1444 gfx::Size(10, 10).ToString());
1446 // Content larger than layer.
1447 child->SetBounds(gfx::Rect(0, 0, 5, 5));
1448 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1449 gfx::Size(5, 5).ToString());
1451 // Content smaller than layer.
1452 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1453 frame_provider = new cc::DelegatedFrameProvider(
1454 resource_collection.get(), MakeFrameData(gfx::Size(5, 5)));
1455 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(5, 5));
1456 EXPECT_EQ(child->cc_layer()->bounds().ToString(), gfx::Size(5, 5).ToString());
1458 // Hi-DPI content on low-DPI layer.
1459 frame_provider = new cc::DelegatedFrameProvider(
1460 resource_collection.get(), MakeFrameData(gfx::Size(20, 20)));
1461 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1462 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1463 gfx::Size(10, 10).ToString());
1465 // Hi-DPI content on hi-DPI layer.
1466 compositor()->SetScaleAndSize(2.f, gfx::Size(1000, 1000));
1467 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1468 gfx::Size(10, 10).ToString());
1470 // Low-DPI content on hi-DPI layer.
1471 frame_provider = new cc::DelegatedFrameProvider(
1472 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1473 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1474 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1475 gfx::Size(10, 10).ToString());
1478 TEST_F(LayerWithDelegateTest, ExternalContent) {
1479 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1480 scoped_ptr<Layer> child(CreateLayer(LAYER_SOLID_COLOR));
1482 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1483 child->SetVisible(true);
1484 root->Add(child.get());
1486 // The layer is already showing solid color content, so the cc layer won't
1487 // change.
1488 scoped_refptr<cc::Layer> before = child->cc_layer();
1489 child->SetShowSolidColorContent();
1490 EXPECT_TRUE(child->cc_layer());
1491 EXPECT_EQ(before.get(), child->cc_layer());
1493 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1494 new cc::DelegatedFrameResourceCollection;
1495 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1496 new cc::DelegatedFrameProvider(resource_collection.get(),
1497 MakeFrameData(gfx::Size(10, 10)));
1499 // Showing delegated content changes the underlying cc layer.
1500 before = child->cc_layer();
1501 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1502 EXPECT_TRUE(child->cc_layer());
1503 EXPECT_NE(before.get(), child->cc_layer());
1505 // Changing to painted content should change the underlying cc layer.
1506 before = child->cc_layer();
1507 child->SetShowSolidColorContent();
1508 EXPECT_TRUE(child->cc_layer());
1509 EXPECT_NE(before.get(), child->cc_layer());
1512 // Verifies that layer filters still attached after changing implementation
1513 // layer.
1514 TEST_F(LayerWithDelegateTest, LayerFiltersSurvival) {
1515 scoped_ptr<Layer> layer(CreateLayer(LAYER_TEXTURED));
1516 layer->SetBounds(gfx::Rect(0, 0, 10, 10));
1517 EXPECT_TRUE(layer->cc_layer());
1518 EXPECT_EQ(0u, layer->cc_layer()->filters().size());
1520 layer->SetLayerGrayscale(0.5f);
1521 EXPECT_EQ(layer->layer_grayscale(), 0.5f);
1522 EXPECT_EQ(1u, layer->cc_layer()->filters().size());
1524 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1525 new cc::DelegatedFrameResourceCollection;
1526 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1527 new cc::DelegatedFrameProvider(resource_collection.get(),
1528 MakeFrameData(gfx::Size(10, 10)));
1530 // Showing delegated content changes the underlying cc layer.
1531 scoped_refptr<cc::Layer> before = layer->cc_layer();
1532 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1533 EXPECT_EQ(layer->layer_grayscale(), 0.5f);
1534 EXPECT_TRUE(layer->cc_layer());
1535 EXPECT_NE(before.get(), layer->cc_layer());
1536 EXPECT_EQ(1u, layer->cc_layer()->filters().size());
1539 // Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation.
1540 TEST_F(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) {
1541 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1542 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1543 scoped_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED));
1545 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1546 l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1548 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1550 // Trigger a threaded animation.
1551 l1->SetOpacity(0.5f);
1553 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1555 // Ensure we can remove a pending threaded animation.
1556 l1->GetAnimator()->StopAnimating();
1558 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1560 // Trigger another threaded animation.
1561 l1->SetOpacity(0.2f);
1563 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1565 root->Add(l1.get());
1566 GetCompositor()->SetRootLayer(root.get());
1568 // Now that l1 is part of a tree, it should have dispatched the pending
1569 // animation.
1570 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1572 // Ensure that l1 no longer holds on to animations.
1573 l1->SetOpacity(0.1f);
1574 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1576 // Ensure that adding a layer to an existing tree causes its pending
1577 // animations to get dispatched.
1578 l2->SetOpacity(0.5f);
1579 EXPECT_TRUE(l2->HasPendingThreadedAnimations());
1581 l1->Add(l2.get());
1582 EXPECT_FALSE(l2->HasPendingThreadedAnimations());
1585 // Tests that in-progress threaded animations complete when a Layer's
1586 // cc::Layer changes.
1587 TEST_F(LayerWithRealCompositorTest, SwitchCCLayerAnimations) {
1588 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1589 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1590 GetCompositor()->SetRootLayer(root.get());
1591 root->Add(l1.get());
1593 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1595 EXPECT_FLOAT_EQ(l1->opacity(), 1.0f);
1597 // Trigger a threaded animation.
1598 l1->SetOpacity(0.5f);
1600 // Change l1's cc::Layer.
1601 l1->SwitchCCLayerForTest();
1603 // Ensure that the opacity animation completed.
1604 EXPECT_FLOAT_EQ(l1->opacity(), 0.5f);
1607 // Tests that the animators in the layer tree is added to the
1608 // animator-collection when the root-layer is set to the compositor.
1609 TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) {
1610 scoped_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
1611 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10)));
1612 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1613 child->SetOpacity(0.5f);
1614 root->Add(child.get());
1616 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1617 compositor()->SetRootLayer(root.get());
1618 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1621 // Tests that adding/removing a layer adds/removes the animator from its entire
1622 // subtree from the compositor's animator-collection.
1623 TEST_F(LayerWithDelegateTest, AddRemoveLayerUpdatesAnimatorsFromSubtree) {
1624 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1625 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1626 scoped_ptr<Layer> grandchild(CreateColorLayer(SK_ColorRED,
1627 gfx::Rect(10, 10)));
1628 root->Add(child.get());
1629 child->Add(grandchild.get());
1630 compositor()->SetRootLayer(root.get());
1632 grandchild->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1633 grandchild->SetOpacity(0.5f);
1634 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1636 root->Remove(child.get());
1637 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1639 root->Add(child.get());
1640 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1643 TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) {
1644 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1645 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1646 root->Add(child.get());
1647 compositor()->SetRootLayer(root.get());
1649 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1650 child->SetOpacity(0.5f);
1651 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1653 child.reset();
1654 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1657 namespace {
1659 std::string Vector2dFTo100thPercisionString(const gfx::Vector2dF& vector) {
1660 return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y());
1663 } // namespace
1665 TEST_F(LayerWithRealCompositorTest, SnapLayerToPixels) {
1666 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1667 scoped_ptr<Layer> c1(CreateLayer(LAYER_TEXTURED));
1668 scoped_ptr<Layer> c11(CreateLayer(LAYER_TEXTURED));
1670 GetCompositor()->SetScaleAndSize(1.25f, gfx::Size(100, 100));
1671 GetCompositor()->SetRootLayer(root.get());
1672 root->Add(c1.get());
1673 c1->Add(c11.get());
1675 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1676 c1->SetBounds(gfx::Rect(1, 1, 10, 10));
1677 c11->SetBounds(gfx::Rect(1, 1, 10, 10));
1678 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1679 // 0.5 at 1.25 scale : (1 - 0.25 + 0.25) / 1.25 = 0.4
1680 EXPECT_EQ("0.40 0.40",
1681 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1683 GetCompositor()->SetScaleAndSize(1.5f, gfx::Size(100, 100));
1684 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1685 // c11 must already be aligned at 1.5 scale.
1686 EXPECT_EQ("0.00 0.00",
1687 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1689 c11->SetBounds(gfx::Rect(2, 2, 10, 10));
1690 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1691 // c11 is now off the pixel.
1692 // 0.5 / 1.5 = 0.333...
1693 EXPECT_EQ("0.33 0.33",
1694 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1697 class FrameDamageCheckingDelegate : public TestLayerDelegate {
1698 public:
1699 FrameDamageCheckingDelegate() : delegated_frame_damage_called_(false) {}
1701 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {
1702 delegated_frame_damage_called_ = true;
1703 delegated_frame_damage_rect_ = damage_rect_in_dip;
1706 const gfx::Rect& delegated_frame_damage_rect() const {
1707 return delegated_frame_damage_rect_;
1709 bool delegated_frame_damage_called() const {
1710 return delegated_frame_damage_called_;
1713 private:
1714 gfx::Rect delegated_frame_damage_rect_;
1715 bool delegated_frame_damage_called_;
1717 DISALLOW_COPY_AND_ASSIGN(FrameDamageCheckingDelegate);
1720 TEST(LayerDelegateTest, DelegatedFrameDamage) {
1721 scoped_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
1722 gfx::Rect damage_rect(2, 1, 5, 3);
1724 FrameDamageCheckingDelegate delegate;
1725 layer->set_delegate(&delegate);
1726 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1727 new cc::DelegatedFrameResourceCollection;
1728 scoped_refptr<cc::DelegatedFrameProvider> frame_provider(
1729 new cc::DelegatedFrameProvider(resource_collection.get(),
1730 MakeFrameData(gfx::Size(10, 10))));
1731 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1733 EXPECT_FALSE(delegate.delegated_frame_damage_called());
1734 layer->OnDelegatedFrameDamage(damage_rect);
1735 EXPECT_TRUE(delegate.delegated_frame_damage_called());
1736 EXPECT_EQ(damage_rect, delegate.delegated_frame_damage_rect());
1739 } // namespace ui