[Telemetry] Reorganize key_mobile_sites pages and update their names
[chromium-blink-merge.git] / ui / compositor / layer_unittest.cc
blob57e1e02d8d0ffb9ebe8339a50f786780fc7e5b5e
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/debug/trace_event.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/json/json_reader.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.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/test/context_factories_for_test.h"
31 #include "ui/compositor/test/draw_waiter_for_test.h"
32 #include "ui/compositor/test/test_compositor_host.h"
33 #include "ui/compositor/test/test_layers.h"
34 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/codec/png_codec.h"
36 #include "ui/gfx/gfx_paths.h"
37 #include "ui/gfx/skia_util.h"
39 using cc::MatchesPNGFile;
41 namespace ui {
43 namespace {
45 // There are three test classes in here that configure the Compositor and
46 // Layer's slightly differently:
47 // - LayerWithNullDelegateTest uses NullLayerDelegate as the LayerDelegate. This
48 // is typically the base class you want to use.
49 // - LayerWithDelegateTest uses LayerDelegate on the delegates.
50 // - LayerWithRealCompositorTest when a real compositor is required for testing.
51 // - Slow because they bring up a window and run the real compositor. This
52 // is typically not what you want.
54 class ColoredLayer : public Layer, public LayerDelegate {
55 public:
56 explicit ColoredLayer(SkColor color)
57 : Layer(LAYER_TEXTURED),
58 color_(color) {
59 set_delegate(this);
62 ~ColoredLayer() override {}
64 // Overridden from LayerDelegate:
65 void OnPaintLayer(gfx::Canvas* canvas) override { canvas->DrawColor(color_); }
67 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
69 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
71 base::Closure PrepareForLayerBoundsChange() override {
72 return base::Closure();
75 private:
76 SkColor color_;
79 class LayerWithRealCompositorTest : public testing::Test {
80 public:
81 LayerWithRealCompositorTest() {
82 if (PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_)) {
83 test_data_directory_ = test_data_directory_.AppendASCII("compositor");
84 } else {
85 LOG(ERROR) << "Could not open test data directory.";
88 ~LayerWithRealCompositorTest() override {}
90 // Overridden from testing::Test:
91 void SetUp() override {
92 bool enable_pixel_output = true;
93 ui::ContextFactory* context_factory =
94 InitializeContextFactoryForTests(enable_pixel_output);
96 const gfx::Rect host_bounds(10, 10, 500, 500);
97 compositor_host_.reset(
98 TestCompositorHost::Create(host_bounds, context_factory));
99 compositor_host_->Show();
102 void TearDown() override {
103 compositor_host_.reset();
104 TerminateContextFactoryForTests();
107 Compositor* GetCompositor() { return compositor_host_->GetCompositor(); }
109 Layer* CreateLayer(LayerType type) {
110 return new Layer(type);
113 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
114 Layer* layer = new ColoredLayer(color);
115 layer->SetBounds(bounds);
116 return layer;
119 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
120 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
121 layer->SetBounds(bounds);
122 return layer;
125 void DrawTree(Layer* root) {
126 GetCompositor()->SetRootLayer(root);
127 GetCompositor()->ScheduleDraw();
128 WaitForDraw();
131 void ReadPixels(SkBitmap* bitmap) {
132 ReadPixels(bitmap, gfx::Rect(GetCompositor()->size()));
135 void ReadPixels(SkBitmap* bitmap, gfx::Rect source_rect) {
136 scoped_refptr<ReadbackHolder> holder(new ReadbackHolder);
137 scoped_ptr<cc::CopyOutputRequest> request =
138 cc::CopyOutputRequest::CreateBitmapRequest(
139 base::Bind(&ReadbackHolder::OutputRequestCallback, holder));
140 request->set_area(source_rect);
142 GetCompositor()->root_layer()->RequestCopyOfOutput(request.Pass());
144 // Wait for copy response. This needs to wait as the compositor could
145 // be in the middle of a draw right now, and the commit with the
146 // copy output request may not be done on the first draw.
147 for (int i = 0; i < 2; i++) {
148 GetCompositor()->ScheduleDraw();
149 WaitForDraw();
152 // Waits for the callback to finish run and return result.
153 holder->WaitForReadback();
155 *bitmap = holder->result();
158 void WaitForDraw() { ui::DrawWaiterForTest::Wait(GetCompositor()); }
160 void WaitForCommit() {
161 ui::DrawWaiterForTest::WaitForCommit(GetCompositor());
164 // Invalidates the entire contents of the layer.
165 void SchedulePaintForLayer(Layer* layer) {
166 layer->SchedulePaint(
167 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
170 const base::FilePath& test_data_directory() const {
171 return test_data_directory_;
174 private:
175 class ReadbackHolder : public base::RefCountedThreadSafe<ReadbackHolder> {
176 public:
177 ReadbackHolder() : run_loop_(new base::RunLoop) {}
179 void OutputRequestCallback(scoped_ptr<cc::CopyOutputResult> result) {
180 result_ = result->TakeBitmap();
181 run_loop_->Quit();
184 void WaitForReadback() { run_loop_->Run(); }
186 const SkBitmap& result() const { return *result_; }
188 private:
189 friend class base::RefCountedThreadSafe<ReadbackHolder>;
191 virtual ~ReadbackHolder() {}
193 scoped_ptr<SkBitmap> result_;
194 scoped_ptr<base::RunLoop> run_loop_;
197 scoped_ptr<TestCompositorHost> compositor_host_;
199 // The root directory for test files.
200 base::FilePath test_data_directory_;
202 DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
205 // LayerDelegate that paints colors to the layer.
206 class TestLayerDelegate : public LayerDelegate {
207 public:
208 explicit TestLayerDelegate() { reset(); }
209 ~TestLayerDelegate() override {}
211 void AddColor(SkColor color) {
212 colors_.push_back(color);
215 const gfx::Size& paint_size() const { return paint_size_; }
216 int color_index() const { return color_index_; }
218 std::string ToScaleString() const {
219 return base::StringPrintf("%.1f %.1f", scale_x_, scale_y_);
222 float device_scale_factor() const {
223 return device_scale_factor_;
226 // Overridden from LayerDelegate:
227 void OnPaintLayer(gfx::Canvas* canvas) override {
228 SkISize size = canvas->sk_canvas()->getBaseLayerSize();
229 paint_size_ = gfx::Size(size.width(), size.height());
230 canvas->DrawColor(colors_[color_index_]);
231 color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size());
232 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
233 scale_x_ = matrix.getScaleX();
234 scale_y_ = matrix.getScaleY();
237 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
239 void OnDeviceScaleFactorChanged(float device_scale_factor) override {
240 device_scale_factor_ = device_scale_factor;
243 base::Closure PrepareForLayerBoundsChange() override {
244 return base::Closure();
247 void reset() {
248 color_index_ = 0;
249 paint_size_.SetSize(0, 0);
250 scale_x_ = scale_y_ = 0.0f;
251 device_scale_factor_ = 0.0f;
254 private:
255 std::vector<SkColor> colors_;
256 int color_index_;
257 gfx::Size paint_size_;
258 float scale_x_;
259 float scale_y_;
260 float device_scale_factor_;
262 DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate);
265 // LayerDelegate that verifies that a layer was asked to update its canvas.
266 class DrawTreeLayerDelegate : public LayerDelegate {
267 public:
268 DrawTreeLayerDelegate() : painted_(false) {}
269 ~DrawTreeLayerDelegate() override {}
271 void Reset() {
272 painted_ = false;
275 bool painted() const { return painted_; }
277 private:
278 // Overridden from LayerDelegate:
279 void OnPaintLayer(gfx::Canvas* canvas) override {
280 painted_ = true;
281 canvas->DrawColor(SK_ColorWHITE);
283 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
284 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
285 base::Closure PrepareForLayerBoundsChange() override {
286 return base::Closure();
289 bool painted_;
291 DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate);
294 // The simplest possible layer delegate. Does nothing.
295 class NullLayerDelegate : public LayerDelegate {
296 public:
297 NullLayerDelegate() {}
298 ~NullLayerDelegate() override {}
300 private:
301 // Overridden from LayerDelegate:
302 void OnPaintLayer(gfx::Canvas* canvas) override {}
303 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
304 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
305 base::Closure PrepareForLayerBoundsChange() override {
306 return base::Closure();
309 DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate);
312 // Remembers if it has been notified.
313 class TestCompositorObserver : public CompositorObserver {
314 public:
315 TestCompositorObserver()
316 : committed_(false), started_(false), ended_(false), aborted_(false) {}
318 bool committed() const { return committed_; }
319 bool notified() const { return started_ && ended_; }
320 bool aborted() const { return aborted_; }
322 void Reset() {
323 committed_ = false;
324 started_ = false;
325 ended_ = false;
326 aborted_ = false;
329 private:
330 void OnCompositingDidCommit(Compositor* compositor) override {
331 committed_ = true;
334 void OnCompositingStarted(Compositor* compositor,
335 base::TimeTicks start_time) override {
336 started_ = true;
339 void OnCompositingEnded(Compositor* compositor) override { ended_ = true; }
341 void OnCompositingAborted(Compositor* compositor) override {
342 aborted_ = true;
345 void OnCompositingLockStateChanged(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() { DrawWaiterForTest::Wait(compositor()); }
445 void WaitForCommit() {
446 DrawWaiterForTest::WaitForCommit(compositor());
449 private:
450 scoped_ptr<TestCompositorHost> compositor_host_;
452 DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
455 // L1
456 // +-- L2
457 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
458 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
459 gfx::Rect(20, 20, 400, 400)));
460 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
461 gfx::Rect(10, 10, 350, 350)));
462 l1->Add(l2.get());
463 DrawTree(l1.get());
465 gfx::Point point1_in_l2_coords(5, 5);
466 Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords);
467 gfx::Point point1_in_l1_coords(15, 15);
468 EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords);
470 gfx::Point point2_in_l1_coords(5, 5);
471 Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords);
472 gfx::Point point2_in_l2_coords(-5, -5);
473 EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords);
476 // L1
477 // +-- L2
478 // +-- L3
479 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
480 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
481 gfx::Rect(20, 20, 400, 400)));
482 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
483 gfx::Rect(10, 10, 350, 350)));
484 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
485 gfx::Rect(10, 10, 100, 100)));
486 l1->Add(l2.get());
487 l2->Add(l3.get());
488 DrawTree(l1.get());
490 gfx::Point point1_in_l3_coords(5, 5);
491 Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords);
492 gfx::Point point1_in_l1_coords(25, 25);
493 EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords);
495 gfx::Point point2_in_l1_coords(5, 5);
496 Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords);
497 gfx::Point point2_in_l3_coords(-15, -15);
498 EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords);
501 TEST_F(LayerWithRealCompositorTest, Delegate) {
502 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorBLACK,
503 gfx::Rect(20, 20, 400, 400)));
504 GetCompositor()->SetRootLayer(l1.get());
505 WaitForDraw();
507 TestLayerDelegate delegate;
508 l1->set_delegate(&delegate);
509 delegate.AddColor(SK_ColorWHITE);
510 delegate.AddColor(SK_ColorYELLOW);
511 delegate.AddColor(SK_ColorGREEN);
513 l1->SchedulePaint(gfx::Rect(0, 0, 400, 400));
514 WaitForDraw();
516 EXPECT_EQ(delegate.color_index(), 1);
517 EXPECT_EQ(delegate.paint_size(), l1->bounds().size());
519 l1->SchedulePaint(gfx::Rect(10, 10, 200, 200));
520 WaitForDraw();
521 EXPECT_EQ(delegate.color_index(), 2);
522 EXPECT_EQ(delegate.paint_size(), gfx::Size(200, 200));
524 l1->SchedulePaint(gfx::Rect(5, 5, 50, 50));
525 WaitForDraw();
526 EXPECT_EQ(delegate.color_index(), 0);
527 EXPECT_EQ(delegate.paint_size(), gfx::Size(50, 50));
530 TEST_F(LayerWithRealCompositorTest, DrawTree) {
531 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
532 gfx::Rect(20, 20, 400, 400)));
533 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
534 gfx::Rect(10, 10, 350, 350)));
535 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
536 gfx::Rect(10, 10, 100, 100)));
537 l1->Add(l2.get());
538 l2->Add(l3.get());
540 GetCompositor()->SetRootLayer(l1.get());
541 WaitForDraw();
543 DrawTreeLayerDelegate d1;
544 l1->set_delegate(&d1);
545 DrawTreeLayerDelegate d2;
546 l2->set_delegate(&d2);
547 DrawTreeLayerDelegate d3;
548 l3->set_delegate(&d3);
550 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
551 WaitForDraw();
552 EXPECT_FALSE(d1.painted());
553 EXPECT_TRUE(d2.painted());
554 EXPECT_FALSE(d3.painted());
557 // Tests no-texture Layers.
558 // Create this hierarchy:
559 // L1 - red
560 // +-- L2 - NO TEXTURE
561 // | +-- L3 - yellow
562 // +-- L4 - magenta
564 TEST_F(LayerWithRealCompositorTest, HierarchyNoTexture) {
565 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
566 gfx::Rect(20, 20, 400, 400)));
567 scoped_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350)));
568 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
569 gfx::Rect(5, 5, 25, 25)));
570 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
571 gfx::Rect(300, 300, 100, 100)));
573 l1->Add(l2.get());
574 l1->Add(l4.get());
575 l2->Add(l3.get());
577 GetCompositor()->SetRootLayer(l1.get());
578 WaitForDraw();
580 DrawTreeLayerDelegate d2;
581 l2->set_delegate(&d2);
582 DrawTreeLayerDelegate d3;
583 l3->set_delegate(&d3);
585 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
586 l3->SchedulePaint(gfx::Rect(5, 5, 5, 5));
587 WaitForDraw();
589 // |d2| should not have received a paint notification since it has no texture.
590 EXPECT_FALSE(d2.painted());
591 // |d3| should have received a paint notification.
592 EXPECT_TRUE(d3.painted());
595 class LayerWithNullDelegateTest : public LayerWithDelegateTest {
596 public:
597 LayerWithNullDelegateTest() {}
598 ~LayerWithNullDelegateTest() override {}
600 void SetUp() override {
601 LayerWithDelegateTest::SetUp();
602 default_layer_delegate_.reset(new NullLayerDelegate());
605 Layer* CreateLayer(LayerType type) override {
606 Layer* layer = new Layer(type);
607 layer->set_delegate(default_layer_delegate_.get());
608 return layer;
611 Layer* CreateTextureRootLayer(const gfx::Rect& bounds) {
612 Layer* layer = CreateTextureLayer(bounds);
613 compositor()->SetRootLayer(layer);
614 return layer;
617 Layer* CreateTextureLayer(const gfx::Rect& bounds) {
618 Layer* layer = CreateLayer(LAYER_TEXTURED);
619 layer->SetBounds(bounds);
620 return layer;
623 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) override {
624 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
625 layer->SetBounds(bounds);
626 return layer;
629 private:
630 scoped_ptr<NullLayerDelegate> default_layer_delegate_;
632 DISALLOW_COPY_AND_ASSIGN(LayerWithNullDelegateTest);
635 TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) {
636 scoped_ptr<Layer> layer(CreateLayer(LAYER_NOT_DRAWN));
637 std::string name = "\"\'\\/\b\f\n\r\t\n";
638 layer->set_name(name);
639 scoped_refptr<base::debug::ConvertableToTraceFormat> debug_info =
640 layer->TakeDebugInfo();
641 EXPECT_TRUE(!!debug_info.get());
642 std::string json;
643 debug_info->AppendAsTraceFormat(&json);
644 base::JSONReader json_reader;
645 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(json));
646 EXPECT_TRUE(!!debug_info_value);
647 EXPECT_TRUE(debug_info_value->IsType(base::Value::TYPE_DICTIONARY));
648 base::DictionaryValue* dictionary = 0;
649 EXPECT_TRUE(debug_info_value->GetAsDictionary(&dictionary));
650 std::string roundtrip;
651 EXPECT_TRUE(dictionary->GetString("layer_name", &roundtrip));
652 EXPECT_EQ(name, roundtrip);
655 void ReturnMailbox(bool* run, uint32 sync_point, bool is_lost) {
656 *run = true;
659 TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
660 scoped_ptr<Layer> l1(CreateLayer(LAYER_SOLID_COLOR));
661 l1->SetFillsBoundsOpaquely(true);
662 l1->SetForceRenderSurface(true);
663 l1->SetVisible(false);
665 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
666 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
667 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
668 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
669 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
671 cc::Layer* before_layer = l1->cc_layer();
673 bool callback1_run = false;
674 cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), 0, 0);
675 l1->SetTextureMailbox(mailbox,
676 cc::SingleReleaseCallback::Create(
677 base::Bind(ReturnMailbox, &callback1_run)),
678 gfx::Size(1, 1));
680 EXPECT_NE(before_layer, l1->cc_layer());
682 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
683 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
684 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
685 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
686 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
687 EXPECT_FALSE(callback1_run);
689 bool callback2_run = false;
690 mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0);
691 l1->SetTextureMailbox(mailbox,
692 cc::SingleReleaseCallback::Create(
693 base::Bind(ReturnMailbox, &callback2_run)),
694 gfx::Size(1, 1));
695 EXPECT_TRUE(callback1_run);
696 EXPECT_FALSE(callback2_run);
698 l1->SetShowSolidColorContent();
699 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
700 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
701 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
702 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
703 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
704 EXPECT_TRUE(callback2_run);
707 // Various visibile/drawn assertions.
708 TEST_F(LayerWithNullDelegateTest, Visibility) {
709 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
710 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
711 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
712 l1->Add(l2.get());
713 l2->Add(l3.get());
715 NullLayerDelegate delegate;
716 l1->set_delegate(&delegate);
717 l2->set_delegate(&delegate);
718 l3->set_delegate(&delegate);
720 // Layers should initially be drawn.
721 EXPECT_TRUE(l1->IsDrawn());
722 EXPECT_TRUE(l2->IsDrawn());
723 EXPECT_TRUE(l3->IsDrawn());
724 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
725 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
726 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
728 compositor()->SetRootLayer(l1.get());
730 Draw();
732 l1->SetVisible(false);
733 EXPECT_FALSE(l1->IsDrawn());
734 EXPECT_FALSE(l2->IsDrawn());
735 EXPECT_FALSE(l3->IsDrawn());
736 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
737 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
738 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
740 l3->SetVisible(false);
741 EXPECT_FALSE(l1->IsDrawn());
742 EXPECT_FALSE(l2->IsDrawn());
743 EXPECT_FALSE(l3->IsDrawn());
744 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
745 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
746 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
748 l1->SetVisible(true);
749 EXPECT_TRUE(l1->IsDrawn());
750 EXPECT_TRUE(l2->IsDrawn());
751 EXPECT_FALSE(l3->IsDrawn());
752 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
753 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
754 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
757 // Checks that stacking-related methods behave as advertised.
758 TEST_F(LayerWithNullDelegateTest, Stacking) {
759 scoped_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
760 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
761 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
762 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
763 l1->set_name("1");
764 l2->set_name("2");
765 l3->set_name("3");
766 root->Add(l3.get());
767 root->Add(l2.get());
768 root->Add(l1.get());
770 // Layers' children are stored in bottom-to-top order.
771 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
773 root->StackAtTop(l3.get());
774 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
776 root->StackAtTop(l1.get());
777 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
779 root->StackAtTop(l1.get());
780 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
782 root->StackAbove(l2.get(), l3.get());
783 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
785 root->StackAbove(l1.get(), l3.get());
786 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
788 root->StackAbove(l2.get(), l1.get());
789 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
791 root->StackAtBottom(l2.get());
792 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
794 root->StackAtBottom(l3.get());
795 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
797 root->StackAtBottom(l3.get());
798 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
800 root->StackBelow(l2.get(), l3.get());
801 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
803 root->StackBelow(l1.get(), l3.get());
804 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
806 root->StackBelow(l3.get(), l2.get());
807 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
809 root->StackBelow(l3.get(), l2.get());
810 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
812 root->StackBelow(l3.get(), l1.get());
813 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
816 // Verifies SetBounds triggers the appropriate painting/drawing.
817 TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
818 scoped_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
819 compositor()->SetRootLayer(l1.get());
821 Draw();
823 l1->SetBounds(gfx::Rect(5, 5, 200, 200));
825 // The CompositorDelegate (us) should have been told to draw for a move.
826 WaitForDraw();
828 l1->SetBounds(gfx::Rect(5, 5, 100, 100));
830 // The CompositorDelegate (us) should have been told to draw for a resize.
831 WaitForDraw();
834 void ExpectRgba(int x, int y, SkColor expected_color, SkColor actual_color) {
835 EXPECT_EQ(expected_color, actual_color)
836 << "Pixel error at x=" << x << " y=" << y << "; "
837 << "actual RGBA=("
838 << SkColorGetR(actual_color) << ","
839 << SkColorGetG(actual_color) << ","
840 << SkColorGetB(actual_color) << ","
841 << SkColorGetA(actual_color) << "); "
842 << "expected RGBA=("
843 << SkColorGetR(expected_color) << ","
844 << SkColorGetG(expected_color) << ","
845 << SkColorGetB(expected_color) << ","
846 << SkColorGetA(expected_color) << ")";
849 // Checks that pixels are actually drawn to the screen with a read back.
850 TEST_F(LayerWithRealCompositorTest, DrawPixels) {
851 gfx::Size viewport_size = GetCompositor()->size();
853 // The window should be some non-trivial size but may not be exactly
854 // 500x500 on all platforms/bots.
855 EXPECT_GE(viewport_size.width(), 200);
856 EXPECT_GE(viewport_size.height(), 200);
858 int blue_height = 10;
860 scoped_ptr<Layer> layer(
861 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
862 scoped_ptr<Layer> layer2(
863 CreateColorLayer(SK_ColorBLUE,
864 gfx::Rect(0, 0, viewport_size.width(), blue_height)));
866 layer->Add(layer2.get());
868 DrawTree(layer.get());
870 SkBitmap bitmap;
871 ReadPixels(&bitmap, gfx::Rect(viewport_size));
872 ASSERT_FALSE(bitmap.empty());
874 SkAutoLockPixels lock(bitmap);
875 for (int x = 0; x < viewport_size.width(); x++) {
876 for (int y = 0; y < viewport_size.height(); y++) {
877 SkColor actual_color = bitmap.getColor(x, y);
878 SkColor expected_color = y < blue_height ? SK_ColorBLUE : SK_ColorRED;
879 ExpectRgba(x, y, expected_color, actual_color);
884 // Checks that drawing a layer with transparent pixels is blended correctly
885 // with the lower layer.
886 TEST_F(LayerWithRealCompositorTest, DrawAlphaBlendedPixels) {
887 gfx::Size viewport_size = GetCompositor()->size();
889 int test_size = 200;
890 EXPECT_GE(viewport_size.width(), test_size);
891 EXPECT_GE(viewport_size.height(), test_size);
893 // Blue with a wee bit of transparency.
894 SkColor blue_with_alpha = SkColorSetARGBInline(40, 10, 20, 200);
895 SkColor blend_color = SkColorSetARGBInline(255, 216, 3, 32);
897 scoped_ptr<Layer> background_layer(
898 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
899 scoped_ptr<Layer> foreground_layer(
900 CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
902 // This must be set to false for layers with alpha to be blended correctly.
903 foreground_layer->SetFillsBoundsOpaquely(false);
905 background_layer->Add(foreground_layer.get());
906 DrawTree(background_layer.get());
908 SkBitmap bitmap;
909 ReadPixels(&bitmap, gfx::Rect(viewport_size));
910 ASSERT_FALSE(bitmap.empty());
912 SkAutoLockPixels lock(bitmap);
913 for (int x = 0; x < test_size; x++) {
914 for (int y = 0; y < test_size; y++) {
915 SkColor actual_color = bitmap.getColor(x, y);
916 ExpectRgba(x, y, blend_color, actual_color);
921 // Checks that using the AlphaShape filter applied to a layer with
922 // transparency, alpha-blends properly with the layer below.
923 TEST_F(LayerWithRealCompositorTest, DrawAlphaThresholdFilterPixels) {
924 gfx::Size viewport_size = GetCompositor()->size();
926 int test_size = 200;
927 EXPECT_GE(viewport_size.width(), test_size);
928 EXPECT_GE(viewport_size.height(), test_size);
930 int blue_height = 10;
931 SkColor blue_with_alpha = SkColorSetARGBInline(40, 0, 0, 255);
932 SkColor blend_color = SkColorSetARGBInline(255, 215, 0, 40);
934 scoped_ptr<Layer> background_layer(
935 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
936 scoped_ptr<Layer> foreground_layer(
937 CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
939 // Add a shape to restrict the visible part of the layer.
940 SkRegion shape;
941 shape.setRect(0, 0, viewport_size.width(), blue_height);
942 foreground_layer->SetAlphaShape(make_scoped_ptr(new SkRegion(shape)));
944 foreground_layer->SetFillsBoundsOpaquely(false);
946 background_layer->Add(foreground_layer.get());
947 DrawTree(background_layer.get());
949 SkBitmap bitmap;
950 ReadPixels(&bitmap, gfx::Rect(viewport_size));
951 ASSERT_FALSE(bitmap.empty());
953 SkAutoLockPixels lock(bitmap);
954 for (int x = 0; x < test_size; x++) {
955 for (int y = 0; y < test_size; y++) {
956 SkColor actual_color = bitmap.getColor(x, y);
957 ExpectRgba(x, y, actual_color,
958 y < blue_height ? blend_color : SK_ColorRED);
963 // Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
964 TEST_F(LayerWithRealCompositorTest, SetRootLayer) {
965 Compositor* compositor = GetCompositor();
966 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
967 gfx::Rect(20, 20, 400, 400)));
968 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
969 gfx::Rect(10, 10, 350, 350)));
971 EXPECT_EQ(NULL, l1->GetCompositor());
972 EXPECT_EQ(NULL, l2->GetCompositor());
974 compositor->SetRootLayer(l1.get());
975 EXPECT_EQ(compositor, l1->GetCompositor());
977 l1->Add(l2.get());
978 EXPECT_EQ(compositor, l2->GetCompositor());
980 l1->Remove(l2.get());
981 EXPECT_EQ(NULL, l2->GetCompositor());
983 l1->Add(l2.get());
984 EXPECT_EQ(compositor, l2->GetCompositor());
986 compositor->SetRootLayer(NULL);
987 EXPECT_EQ(NULL, l1->GetCompositor());
988 EXPECT_EQ(NULL, l2->GetCompositor());
991 // Checks that compositor observers are notified when:
992 // - DrawTree is called,
993 // - After ScheduleDraw is called, or
994 // - Whenever SetBounds, SetOpacity or SetTransform are called.
995 // TODO(vollick): could be reorganized into compositor_unittest.cc
996 TEST_F(LayerWithRealCompositorTest, CompositorObservers) {
997 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
998 gfx::Rect(20, 20, 400, 400)));
999 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
1000 gfx::Rect(10, 10, 350, 350)));
1001 l1->Add(l2.get());
1002 TestCompositorObserver observer;
1003 GetCompositor()->AddObserver(&observer);
1005 // Explicitly called DrawTree should cause the observers to be notified.
1006 // NOTE: this call to DrawTree sets l1 to be the compositor's root layer.
1007 DrawTree(l1.get());
1008 EXPECT_TRUE(observer.notified());
1010 // ScheduleDraw without any visible change should cause a commit.
1011 observer.Reset();
1012 l1->ScheduleDraw();
1013 WaitForCommit();
1014 EXPECT_TRUE(observer.committed());
1016 // Moving, but not resizing, a layer should alert the observers.
1017 observer.Reset();
1018 l2->SetBounds(gfx::Rect(0, 0, 350, 350));
1019 WaitForDraw();
1020 EXPECT_TRUE(observer.notified());
1022 // So should resizing a layer.
1023 observer.Reset();
1024 l2->SetBounds(gfx::Rect(0, 0, 400, 400));
1025 WaitForDraw();
1026 EXPECT_TRUE(observer.notified());
1028 // Opacity changes should alert the observers.
1029 observer.Reset();
1030 l2->SetOpacity(0.5f);
1031 WaitForDraw();
1032 EXPECT_TRUE(observer.notified());
1034 // So should setting the opacity back.
1035 observer.Reset();
1036 l2->SetOpacity(1.0f);
1037 WaitForDraw();
1038 EXPECT_TRUE(observer.notified());
1040 // Setting the transform of a layer should alert the observers.
1041 observer.Reset();
1042 gfx::Transform transform;
1043 transform.Translate(200.0, 200.0);
1044 transform.Rotate(90.0);
1045 transform.Translate(-200.0, -200.0);
1046 l2->SetTransform(transform);
1047 WaitForDraw();
1048 EXPECT_TRUE(observer.notified());
1050 // A change resulting in an aborted swap buffer should alert the observer
1051 // and also signal an abort.
1052 observer.Reset();
1053 l2->SetOpacity(0.1f);
1054 GetCompositor()->DidAbortSwapBuffers();
1055 WaitForDraw();
1056 EXPECT_TRUE(observer.notified());
1057 EXPECT_TRUE(observer.aborted());
1059 GetCompositor()->RemoveObserver(&observer);
1061 // Opacity changes should no longer alert the removed observer.
1062 observer.Reset();
1063 l2->SetOpacity(0.5f);
1064 WaitForDraw();
1066 EXPECT_FALSE(observer.notified());
1069 // Checks that modifying the hierarchy correctly affects final composite.
1070 TEST_F(LayerWithRealCompositorTest, ModifyHierarchy) {
1071 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1073 // l0
1074 // +-l11
1075 // | +-l21
1076 // +-l12
1077 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1078 gfx::Rect(0, 0, 50, 50)));
1079 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1080 gfx::Rect(0, 0, 25, 25)));
1081 scoped_ptr<Layer> l21(CreateColorLayer(SK_ColorMAGENTA,
1082 gfx::Rect(0, 0, 15, 15)));
1083 scoped_ptr<Layer> l12(CreateColorLayer(SK_ColorBLUE,
1084 gfx::Rect(10, 10, 25, 25)));
1086 base::FilePath ref_img1 =
1087 test_data_directory().AppendASCII("ModifyHierarchy1.png");
1088 base::FilePath ref_img2 =
1089 test_data_directory().AppendASCII("ModifyHierarchy2.png");
1090 SkBitmap bitmap;
1092 l0->Add(l11.get());
1093 l11->Add(l21.get());
1094 l0->Add(l12.get());
1095 DrawTree(l0.get());
1096 ReadPixels(&bitmap);
1097 ASSERT_FALSE(bitmap.empty());
1098 // WritePNGFile(bitmap, ref_img1);
1099 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1101 l0->StackAtTop(l11.get());
1102 DrawTree(l0.get());
1103 ReadPixels(&bitmap);
1104 ASSERT_FALSE(bitmap.empty());
1105 // WritePNGFile(bitmap, ref_img2);
1106 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1108 // should restore to original configuration
1109 l0->StackAbove(l12.get(), l11.get());
1110 DrawTree(l0.get());
1111 ReadPixels(&bitmap);
1112 ASSERT_FALSE(bitmap.empty());
1113 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1115 // l11 back to front
1116 l0->StackAtTop(l11.get());
1117 DrawTree(l0.get());
1118 ReadPixels(&bitmap);
1119 ASSERT_FALSE(bitmap.empty());
1120 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1122 // should restore to original configuration
1123 l0->StackAbove(l12.get(), l11.get());
1124 DrawTree(l0.get());
1125 ReadPixels(&bitmap);
1126 ASSERT_FALSE(bitmap.empty());
1127 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1129 // l11 back to front
1130 l0->StackAbove(l11.get(), l12.get());
1131 DrawTree(l0.get());
1132 ReadPixels(&bitmap);
1133 ASSERT_FALSE(bitmap.empty());
1134 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1137 // Opacity is rendered correctly.
1138 // Checks that modifying the hierarchy correctly affects final composite.
1139 TEST_F(LayerWithRealCompositorTest, Opacity) {
1140 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1142 // l0
1143 // +-l11
1144 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1145 gfx::Rect(0, 0, 50, 50)));
1146 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1147 gfx::Rect(0, 0, 25, 25)));
1149 base::FilePath ref_img = test_data_directory().AppendASCII("Opacity.png");
1151 l11->SetOpacity(0.75);
1152 l0->Add(l11.get());
1153 DrawTree(l0.get());
1154 SkBitmap bitmap;
1155 ReadPixels(&bitmap);
1156 ASSERT_FALSE(bitmap.empty());
1157 // WritePNGFile(bitmap, ref_img);
1158 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img, cc::ExactPixelComparator(true)));
1161 namespace {
1163 class SchedulePaintLayerDelegate : public LayerDelegate {
1164 public:
1165 SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
1167 ~SchedulePaintLayerDelegate() override {}
1169 void set_layer(Layer* layer) {
1170 layer_ = layer;
1171 layer_->set_delegate(this);
1174 void SetSchedulePaintRect(const gfx::Rect& rect) {
1175 schedule_paint_rect_ = rect;
1178 int GetPaintCountAndClear() {
1179 int value = paint_count_;
1180 paint_count_ = 0;
1181 return value;
1184 const gfx::RectF& last_clip_rect() const { return last_clip_rect_; }
1186 private:
1187 // Overridden from LayerDelegate:
1188 void OnPaintLayer(gfx::Canvas* canvas) override {
1189 paint_count_++;
1190 if (!schedule_paint_rect_.IsEmpty()) {
1191 layer_->SchedulePaint(schedule_paint_rect_);
1192 schedule_paint_rect_ = gfx::Rect();
1194 SkRect sk_clip_rect;
1195 if (canvas->sk_canvas()->getClipBounds(&sk_clip_rect))
1196 last_clip_rect_ = gfx::SkRectToRectF(sk_clip_rect);
1199 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
1201 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
1203 base::Closure PrepareForLayerBoundsChange() override {
1204 return base::Closure();
1207 int paint_count_;
1208 Layer* layer_;
1209 gfx::Rect schedule_paint_rect_;
1210 gfx::RectF last_clip_rect_;
1212 DISALLOW_COPY_AND_ASSIGN(SchedulePaintLayerDelegate);
1215 } // namespace
1217 // Verifies that if SchedulePaint is invoked during painting the layer is still
1218 // marked dirty.
1219 TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
1220 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorRED,
1221 gfx::Rect(0, 0, 500, 500)));
1222 SchedulePaintLayerDelegate child_delegate;
1223 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorBLUE,
1224 gfx::Rect(0, 0, 200, 200)));
1225 child_delegate.set_layer(child.get());
1227 root->Add(child.get());
1229 SchedulePaintForLayer(root.get());
1230 DrawTree(root.get());
1231 child->SchedulePaint(gfx::Rect(0, 0, 20, 20));
1232 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1234 // Set a rect so that when OnPaintLayer() is invoked SchedulePaint is invoked
1235 // again.
1236 child_delegate.SetSchedulePaintRect(gfx::Rect(10, 10, 30, 30));
1237 WaitForCommit();
1238 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1240 // Because SchedulePaint() was invoked from OnPaintLayer() |child| should
1241 // still need to be painted.
1242 WaitForCommit();
1243 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1244 EXPECT_TRUE(child_delegate.last_clip_rect().Contains(
1245 gfx::Rect(10, 10, 30, 30)));
1248 TEST_F(LayerWithRealCompositorTest, ScaleUpDown) {
1249 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1250 gfx::Rect(10, 20, 200, 220)));
1251 TestLayerDelegate root_delegate;
1252 root_delegate.AddColor(SK_ColorWHITE);
1253 root->set_delegate(&root_delegate);
1255 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1256 gfx::Rect(10, 20, 140, 180)));
1257 TestLayerDelegate l1_delegate;
1258 l1_delegate.AddColor(SK_ColorWHITE);
1259 l1->set_delegate(&l1_delegate);
1261 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1262 GetCompositor()->SetRootLayer(root.get());
1263 root->Add(l1.get());
1264 WaitForDraw();
1266 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1267 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1268 gfx::Size cc_bounds_size = root->cc_layer()->bounds();
1269 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1270 cc_bounds_size = l1->cc_layer()->bounds();
1271 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1272 // No scale change, so no scale notification.
1273 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1274 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1276 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1277 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1279 // Scale up to 2.0. Changing scale doesn't change the bounds in DIP.
1280 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1281 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1282 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1283 // CC layer should still match the UI layer bounds.
1284 cc_bounds_size = root->cc_layer()->bounds();
1285 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1286 cc_bounds_size = l1->cc_layer()->bounds();
1287 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1288 // New scale factor must have been notified.
1289 EXPECT_EQ(2.0f, root_delegate.device_scale_factor());
1290 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1292 // Canvas size must have been scaled down up.
1293 WaitForDraw();
1294 EXPECT_EQ("400x440", root_delegate.paint_size().ToString());
1295 EXPECT_EQ("2.0 2.0", root_delegate.ToScaleString());
1296 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1297 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1299 // Scale down back to 1.0f.
1300 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1301 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1302 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1303 // CC layer should still match the UI layer bounds.
1304 cc_bounds_size = root->cc_layer()->bounds();
1305 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1306 cc_bounds_size = l1->cc_layer()->bounds();
1307 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1308 // New scale factor must have been notified.
1309 EXPECT_EQ(1.0f, root_delegate.device_scale_factor());
1310 EXPECT_EQ(1.0f, l1_delegate.device_scale_factor());
1312 // Canvas size must have been scaled down too.
1313 WaitForDraw();
1314 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1315 EXPECT_EQ("1.0 1.0", root_delegate.ToScaleString());
1316 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1317 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1319 root_delegate.reset();
1320 l1_delegate.reset();
1321 // Just changing the size shouldn't notify the scale change nor
1322 // trigger repaint.
1323 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(1000, 1000));
1324 // No scale change, so no scale notification.
1325 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1326 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1327 WaitForDraw();
1328 EXPECT_EQ("0x0", root_delegate.paint_size().ToString());
1329 EXPECT_EQ("0.0 0.0", root_delegate.ToScaleString());
1330 EXPECT_EQ("0x0", l1_delegate.paint_size().ToString());
1331 EXPECT_EQ("0.0 0.0", l1_delegate.ToScaleString());
1334 TEST_F(LayerWithRealCompositorTest, ScaleReparent) {
1335 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1336 gfx::Rect(10, 20, 200, 220)));
1337 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1338 gfx::Rect(10, 20, 140, 180)));
1339 TestLayerDelegate l1_delegate;
1340 l1_delegate.AddColor(SK_ColorWHITE);
1341 l1->set_delegate(&l1_delegate);
1343 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1344 GetCompositor()->SetRootLayer(root.get());
1345 WaitForDraw();
1347 root->Add(l1.get());
1348 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1349 gfx::Size cc_bounds_size = l1->cc_layer()->bounds();
1350 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1351 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1353 WaitForDraw();
1354 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1355 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1357 // Remove l1 from root and change the scale.
1358 root->Remove(l1.get());
1359 EXPECT_EQ(NULL, l1->parent());
1360 EXPECT_EQ(NULL, l1->GetCompositor());
1361 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1362 // Sanity check on root and l1.
1363 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1364 cc_bounds_size = l1->cc_layer()->bounds();
1365 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1367 root->Add(l1.get());
1368 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1369 cc_bounds_size = l1->cc_layer()->bounds();
1370 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1371 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1372 WaitForDraw();
1373 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1374 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1377 // Verifies that when changing bounds on a layer that is invisible, and then
1378 // made visible, the right thing happens:
1379 // - if just a move, then no painting should happen.
1380 // - if a resize, the layer should be repainted.
1381 TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
1382 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1384 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1385 child->SetBounds(gfx::Rect(0, 0, 500, 500));
1386 DrawTreeLayerDelegate delegate;
1387 child->set_delegate(&delegate);
1388 root->Add(child.get());
1390 // Paint once for initial damage.
1391 child->SetVisible(true);
1392 DrawTree(root.get());
1394 // Reset into invisible state.
1395 child->SetVisible(false);
1396 DrawTree(root.get());
1397 delegate.Reset();
1399 // Move layer.
1400 child->SetBounds(gfx::Rect(200, 200, 500, 500));
1401 child->SetVisible(true);
1402 DrawTree(root.get());
1403 EXPECT_FALSE(delegate.painted());
1405 // Reset into invisible state.
1406 child->SetVisible(false);
1407 DrawTree(root.get());
1408 delegate.Reset();
1410 // Resize layer.
1411 child->SetBounds(gfx::Rect(200, 200, 400, 400));
1412 child->SetVisible(true);
1413 DrawTree(root.get());
1414 EXPECT_TRUE(delegate.painted());
1417 static scoped_ptr<cc::DelegatedFrameData> MakeFrameData(gfx::Size size) {
1418 scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
1419 scoped_ptr<cc::RenderPass> render_pass(cc::RenderPass::Create());
1420 render_pass->SetNew(
1421 cc::RenderPassId(1, 1), gfx::Rect(size), gfx::Rect(), gfx::Transform());
1422 frame_data->render_pass_list.push_back(render_pass.Pass());
1423 return frame_data.Pass();
1426 TEST_F(LayerWithDelegateTest, DelegatedLayer) {
1427 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1429 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1431 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1432 child->SetVisible(true);
1433 root->Add(child.get());
1434 DrawTree(root.get());
1436 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1437 new cc::DelegatedFrameResourceCollection;
1438 scoped_refptr<cc::DelegatedFrameProvider> frame_provider;
1440 // Content matches layer size.
1441 frame_provider = new cc::DelegatedFrameProvider(
1442 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1443 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1444 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1445 gfx::Size(10, 10).ToString());
1447 // Content larger than layer.
1448 child->SetBounds(gfx::Rect(0, 0, 5, 5));
1449 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1450 gfx::Size(5, 5).ToString());
1452 // Content smaller than layer.
1453 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1454 frame_provider = new cc::DelegatedFrameProvider(
1455 resource_collection.get(), MakeFrameData(gfx::Size(5, 5)));
1456 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(5, 5));
1457 EXPECT_EQ(child->cc_layer()->bounds().ToString(), gfx::Size(5, 5).ToString());
1459 // Hi-DPI content on low-DPI layer.
1460 frame_provider = new cc::DelegatedFrameProvider(
1461 resource_collection.get(), MakeFrameData(gfx::Size(20, 20)));
1462 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1463 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1464 gfx::Size(10, 10).ToString());
1466 // Hi-DPI content on hi-DPI layer.
1467 compositor()->SetScaleAndSize(2.f, gfx::Size(1000, 1000));
1468 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1469 gfx::Size(10, 10).ToString());
1471 // Low-DPI content on hi-DPI layer.
1472 frame_provider = new cc::DelegatedFrameProvider(
1473 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1474 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1475 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1476 gfx::Size(10, 10).ToString());
1479 TEST_F(LayerWithDelegateTest, ExternalContent) {
1480 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1481 scoped_ptr<Layer> child(CreateLayer(LAYER_SOLID_COLOR));
1483 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1484 child->SetVisible(true);
1485 root->Add(child.get());
1487 // The layer is already showing solid color content, so the cc layer won't
1488 // change.
1489 scoped_refptr<cc::Layer> before = child->cc_layer();
1490 child->SetShowSolidColorContent();
1491 EXPECT_TRUE(child->cc_layer());
1492 EXPECT_EQ(before.get(), child->cc_layer());
1494 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1495 new cc::DelegatedFrameResourceCollection;
1496 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1497 new cc::DelegatedFrameProvider(resource_collection.get(),
1498 MakeFrameData(gfx::Size(10, 10)));
1500 // Showing delegated content changes the underlying cc layer.
1501 before = child->cc_layer();
1502 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1503 EXPECT_TRUE(child->cc_layer());
1504 EXPECT_NE(before.get(), child->cc_layer());
1506 // Changing to painted content should change the underlying cc layer.
1507 before = child->cc_layer();
1508 child->SetShowSolidColorContent();
1509 EXPECT_TRUE(child->cc_layer());
1510 EXPECT_NE(before.get(), child->cc_layer());
1513 // Verifies that layer filters still attached after changing implementation
1514 // layer.
1515 TEST_F(LayerWithDelegateTest, LayerFiltersSurvival) {
1516 scoped_ptr<Layer> layer(CreateLayer(LAYER_TEXTURED));
1517 layer->SetBounds(gfx::Rect(0, 0, 10, 10));
1518 EXPECT_TRUE(layer->cc_layer());
1519 EXPECT_EQ(0u, layer->cc_layer()->filters().size());
1521 layer->SetLayerGrayscale(0.5f);
1522 EXPECT_EQ(layer->layer_grayscale(), 0.5f);
1523 EXPECT_EQ(1u, layer->cc_layer()->filters().size());
1525 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1526 new cc::DelegatedFrameResourceCollection;
1527 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1528 new cc::DelegatedFrameProvider(resource_collection.get(),
1529 MakeFrameData(gfx::Size(10, 10)));
1531 // Showing delegated content changes the underlying cc layer.
1532 scoped_refptr<cc::Layer> before = layer->cc_layer();
1533 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1534 EXPECT_EQ(layer->layer_grayscale(), 0.5f);
1535 EXPECT_TRUE(layer->cc_layer());
1536 EXPECT_NE(before.get(), layer->cc_layer());
1537 EXPECT_EQ(1u, layer->cc_layer()->filters().size());
1540 // Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation.
1541 TEST_F(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) {
1542 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1543 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1544 scoped_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED));
1546 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1547 l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1549 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1551 // Trigger a threaded animation.
1552 l1->SetOpacity(0.5f);
1554 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1556 // Ensure we can remove a pending threaded animation.
1557 l1->GetAnimator()->StopAnimating();
1559 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1561 // Trigger another threaded animation.
1562 l1->SetOpacity(0.2f);
1564 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1566 root->Add(l1.get());
1567 GetCompositor()->SetRootLayer(root.get());
1569 // Now that l1 is part of a tree, it should have dispatched the pending
1570 // animation.
1571 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1573 // Ensure that l1 no longer holds on to animations.
1574 l1->SetOpacity(0.1f);
1575 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1577 // Ensure that adding a layer to an existing tree causes its pending
1578 // animations to get dispatched.
1579 l2->SetOpacity(0.5f);
1580 EXPECT_TRUE(l2->HasPendingThreadedAnimations());
1582 l1->Add(l2.get());
1583 EXPECT_FALSE(l2->HasPendingThreadedAnimations());
1586 // Tests that in-progress threaded animations complete when a Layer's
1587 // cc::Layer changes.
1588 TEST_F(LayerWithRealCompositorTest, SwitchCCLayerAnimations) {
1589 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1590 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1591 GetCompositor()->SetRootLayer(root.get());
1592 root->Add(l1.get());
1594 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1596 EXPECT_FLOAT_EQ(l1->opacity(), 1.0f);
1598 // Trigger a threaded animation.
1599 l1->SetOpacity(0.5f);
1601 // Change l1's cc::Layer.
1602 l1->SwitchCCLayerForTest();
1604 // Ensure that the opacity animation completed.
1605 EXPECT_FLOAT_EQ(l1->opacity(), 0.5f);
1608 // Tests that the animators in the layer tree is added to the
1609 // animator-collection when the root-layer is set to the compositor.
1610 TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) {
1611 scoped_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
1612 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10)));
1613 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1614 child->SetOpacity(0.5f);
1615 root->Add(child.get());
1617 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1618 compositor()->SetRootLayer(root.get());
1619 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1622 // Tests that adding/removing a layer adds/removes the animator from its entire
1623 // subtree from the compositor's animator-collection.
1624 TEST_F(LayerWithDelegateTest, AddRemoveLayerUpdatesAnimatorsFromSubtree) {
1625 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1626 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1627 scoped_ptr<Layer> grandchild(CreateColorLayer(SK_ColorRED,
1628 gfx::Rect(10, 10)));
1629 root->Add(child.get());
1630 child->Add(grandchild.get());
1631 compositor()->SetRootLayer(root.get());
1633 grandchild->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1634 grandchild->SetOpacity(0.5f);
1635 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1637 root->Remove(child.get());
1638 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1640 root->Add(child.get());
1641 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1644 TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) {
1645 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1646 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1647 root->Add(child.get());
1648 compositor()->SetRootLayer(root.get());
1650 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1651 child->SetOpacity(0.5f);
1652 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1654 child.reset();
1655 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1658 namespace {
1660 std::string Vector2dFTo100thPercisionString(const gfx::Vector2dF& vector) {
1661 return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y());
1664 } // namespace
1666 TEST_F(LayerWithRealCompositorTest, SnapLayerToPixels) {
1667 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1668 scoped_ptr<Layer> c1(CreateLayer(LAYER_TEXTURED));
1669 scoped_ptr<Layer> c11(CreateLayer(LAYER_TEXTURED));
1671 GetCompositor()->SetScaleAndSize(1.25f, gfx::Size(100, 100));
1672 GetCompositor()->SetRootLayer(root.get());
1673 root->Add(c1.get());
1674 c1->Add(c11.get());
1676 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1677 c1->SetBounds(gfx::Rect(1, 1, 10, 10));
1678 c11->SetBounds(gfx::Rect(1, 1, 10, 10));
1679 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1680 // 0.5 at 1.25 scale : (1 - 0.25 + 0.25) / 1.25 = 0.4
1681 EXPECT_EQ("0.40 0.40",
1682 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1684 GetCompositor()->SetScaleAndSize(1.5f, gfx::Size(100, 100));
1685 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1686 // c11 must already be aligned at 1.5 scale.
1687 EXPECT_EQ("0.00 0.00",
1688 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1690 c11->SetBounds(gfx::Rect(2, 2, 10, 10));
1691 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1692 // c11 is now off the pixel.
1693 // 0.5 / 1.5 = 0.333...
1694 EXPECT_EQ("0.33 0.33",
1695 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1698 class FrameDamageCheckingDelegate : public TestLayerDelegate {
1699 public:
1700 FrameDamageCheckingDelegate() : delegated_frame_damage_called_(false) {}
1702 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {
1703 delegated_frame_damage_called_ = true;
1704 delegated_frame_damage_rect_ = damage_rect_in_dip;
1707 const gfx::Rect& delegated_frame_damage_rect() const {
1708 return delegated_frame_damage_rect_;
1710 bool delegated_frame_damage_called() const {
1711 return delegated_frame_damage_called_;
1714 private:
1715 gfx::Rect delegated_frame_damage_rect_;
1716 bool delegated_frame_damage_called_;
1718 DISALLOW_COPY_AND_ASSIGN(FrameDamageCheckingDelegate);
1721 TEST(LayerDelegateTest, DelegatedFrameDamage) {
1722 scoped_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
1723 gfx::Rect damage_rect(2, 1, 5, 3);
1725 FrameDamageCheckingDelegate delegate;
1726 layer->set_delegate(&delegate);
1727 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1728 new cc::DelegatedFrameResourceCollection;
1729 scoped_refptr<cc::DelegatedFrameProvider> frame_provider(
1730 new cc::DelegatedFrameProvider(resource_collection.get(),
1731 MakeFrameData(gfx::Size(10, 10))));
1732 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1734 EXPECT_FALSE(delegate.delegated_frame_damage_called());
1735 layer->OnDelegatedFrameDamage(damage_rect);
1736 EXPECT_TRUE(delegate.delegated_frame_damage_called());
1737 EXPECT_EQ(damage_rect, delegate.delegated_frame_damage_rect());
1740 } // namespace ui