Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / compositor / layer_unittest.cc
blobdefb4a24020a541e5fabb83aa47800dceaab5ad4
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/file_util.h"
10 #include "base/files/file_path.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 virtual ~ColoredLayer() { }
64 // Overridden from LayerDelegate:
65 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
66 canvas->DrawColor(color_);
69 virtual void OnDelegatedFrameDamage(
70 const gfx::Rect& damage_rect_in_dip) OVERRIDE {}
72 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
75 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
76 return base::Closure();
79 private:
80 SkColor color_;
83 class LayerWithRealCompositorTest : public testing::Test {
84 public:
85 LayerWithRealCompositorTest() {
86 if (PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_)) {
87 test_data_directory_ = test_data_directory_.AppendASCII("compositor");
88 } else {
89 LOG(ERROR) << "Could not open test data directory.";
92 virtual ~LayerWithRealCompositorTest() {}
94 // Overridden from testing::Test:
95 virtual void SetUp() OVERRIDE {
96 bool enable_pixel_output = true;
97 ui::ContextFactory* context_factory =
98 InitializeContextFactoryForTests(enable_pixel_output);
100 const gfx::Rect host_bounds(10, 10, 500, 500);
101 compositor_host_.reset(
102 TestCompositorHost::Create(host_bounds, context_factory));
103 compositor_host_->Show();
106 virtual void TearDown() OVERRIDE {
107 compositor_host_.reset();
108 TerminateContextFactoryForTests();
111 Compositor* GetCompositor() { return compositor_host_->GetCompositor(); }
113 Layer* CreateLayer(LayerType type) {
114 return new Layer(type);
117 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
118 Layer* layer = new ColoredLayer(color);
119 layer->SetBounds(bounds);
120 return layer;
123 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
124 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
125 layer->SetBounds(bounds);
126 return layer;
129 void DrawTree(Layer* root) {
130 GetCompositor()->SetRootLayer(root);
131 GetCompositor()->ScheduleDraw();
132 WaitForDraw();
135 bool ReadPixels(SkBitmap* bitmap) {
136 return ReadPixels(bitmap, gfx::Rect(GetCompositor()->size()));
139 bool ReadPixels(SkBitmap* bitmap, gfx::Rect source_rect) {
140 scoped_refptr<ReadbackHolder> holder(new ReadbackHolder);
141 scoped_ptr<cc::CopyOutputRequest> request =
142 cc::CopyOutputRequest::CreateBitmapRequest(
143 base::Bind(&ReadbackHolder::OutputRequestCallback, holder));
144 request->set_area(source_rect);
146 GetCompositor()->root_layer()->RequestCopyOfOutput(request.Pass());
148 // Wait for copy response. This needs to wait as the compositor could
149 // be in the middle of a draw right now, and the commit with the
150 // copy output request may not be done on the first draw.
151 for (int i = 0; i < 2; i++) {
152 GetCompositor()->ScheduleDraw();
153 WaitForDraw();
156 if (holder->completed()) {
157 *bitmap = holder->result();
158 return true;
161 // Callback never called.
162 NOTREACHED();
163 return false;
166 void WaitForDraw() { ui::DrawWaiterForTest::Wait(GetCompositor()); }
168 void WaitForCommit() {
169 ui::DrawWaiterForTest::WaitForCommit(GetCompositor());
172 // Invalidates the entire contents of the layer.
173 void SchedulePaintForLayer(Layer* layer) {
174 layer->SchedulePaint(
175 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
178 const base::FilePath& test_data_directory() const {
179 return test_data_directory_;
182 private:
183 class ReadbackHolder : public base::RefCountedThreadSafe<ReadbackHolder> {
184 public:
185 ReadbackHolder() : completed_(false) {}
187 void OutputRequestCallback(scoped_ptr<cc::CopyOutputResult> result) {
188 DCHECK(!completed_);
189 result_ = result->TakeBitmap();
190 completed_ = true;
192 bool completed() const {
193 return completed_;
195 const SkBitmap& result() const { return *result_; }
197 private:
198 friend class base::RefCountedThreadSafe<ReadbackHolder>;
200 virtual ~ReadbackHolder() {}
202 scoped_ptr<SkBitmap> result_;
203 bool completed_;
206 scoped_ptr<TestCompositorHost> compositor_host_;
208 // The root directory for test files.
209 base::FilePath test_data_directory_;
211 DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
214 // LayerDelegate that paints colors to the layer.
215 class TestLayerDelegate : public LayerDelegate {
216 public:
217 explicit TestLayerDelegate() { reset(); }
218 virtual ~TestLayerDelegate() {}
220 void AddColor(SkColor color) {
221 colors_.push_back(color);
224 const gfx::Size& paint_size() const { return paint_size_; }
225 int color_index() const { return color_index_; }
227 std::string ToScaleString() const {
228 return base::StringPrintf("%.1f %.1f", scale_x_, scale_y_);
231 float device_scale_factor() const {
232 return device_scale_factor_;
235 // Overridden from LayerDelegate:
236 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
237 SkISize size = canvas->sk_canvas()->getBaseLayerSize();
238 paint_size_ = gfx::Size(size.width(), size.height());
239 canvas->FillRect(gfx::Rect(paint_size_), colors_[color_index_]);
240 color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size());
241 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
242 scale_x_ = matrix.getScaleX();
243 scale_y_ = matrix.getScaleY();
246 virtual void OnDelegatedFrameDamage(
247 const gfx::Rect& damage_rect_in_dip) OVERRIDE {}
249 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
250 device_scale_factor_ = device_scale_factor;
253 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
254 return base::Closure();
257 void reset() {
258 color_index_ = 0;
259 paint_size_.SetSize(0, 0);
260 scale_x_ = scale_y_ = 0.0f;
261 device_scale_factor_ = 0.0f;
264 private:
265 std::vector<SkColor> colors_;
266 int color_index_;
267 gfx::Size paint_size_;
268 float scale_x_;
269 float scale_y_;
270 float device_scale_factor_;
272 DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate);
275 // LayerDelegate that verifies that a layer was asked to update its canvas.
276 class DrawTreeLayerDelegate : public LayerDelegate {
277 public:
278 DrawTreeLayerDelegate() : painted_(false) {}
279 virtual ~DrawTreeLayerDelegate() {}
281 void Reset() {
282 painted_ = false;
285 bool painted() const { return painted_; }
287 private:
288 // Overridden from LayerDelegate:
289 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
290 painted_ = true;
292 virtual void OnDelegatedFrameDamage(
293 const gfx::Rect& damage_rect_in_dip) OVERRIDE {}
294 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
296 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
297 return base::Closure();
300 bool painted_;
302 DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate);
305 // The simplest possible layer delegate. Does nothing.
306 class NullLayerDelegate : public LayerDelegate {
307 public:
308 NullLayerDelegate() {}
309 virtual ~NullLayerDelegate() {}
311 private:
312 // Overridden from LayerDelegate:
313 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {}
314 virtual void OnDelegatedFrameDamage(
315 const gfx::Rect& damage_rect_in_dip) OVERRIDE {}
316 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
317 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
318 return base::Closure();
321 DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate);
324 // Remembers if it has been notified.
325 class TestCompositorObserver : public CompositorObserver {
326 public:
327 TestCompositorObserver()
328 : committed_(false), started_(false), ended_(false), aborted_(false) {}
330 bool committed() const { return committed_; }
331 bool notified() const { return started_ && ended_; }
332 bool aborted() const { return aborted_; }
334 void Reset() {
335 committed_ = false;
336 started_ = false;
337 ended_ = false;
338 aborted_ = false;
341 private:
342 virtual void OnCompositingDidCommit(Compositor* compositor) OVERRIDE {
343 committed_ = true;
346 virtual void OnCompositingStarted(Compositor* compositor,
347 base::TimeTicks start_time) OVERRIDE {
348 started_ = true;
351 virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE {
352 ended_ = true;
355 virtual void OnCompositingAborted(Compositor* compositor) OVERRIDE {
356 aborted_ = true;
359 virtual void OnCompositingLockStateChanged(Compositor* compositor) OVERRIDE {
362 bool committed_;
363 bool started_;
364 bool ended_;
365 bool aborted_;
367 DISALLOW_COPY_AND_ASSIGN(TestCompositorObserver);
370 } // namespace
372 TEST_F(LayerWithRealCompositorTest, Draw) {
373 scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED,
374 gfx::Rect(20, 20, 50, 50)));
375 DrawTree(layer.get());
378 // Create this hierarchy:
379 // L1 - red
380 // +-- L2 - blue
381 // | +-- L3 - yellow
382 // +-- L4 - magenta
384 TEST_F(LayerWithRealCompositorTest, Hierarchy) {
385 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
386 gfx::Rect(20, 20, 400, 400)));
387 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
388 gfx::Rect(10, 10, 350, 350)));
389 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
390 gfx::Rect(5, 5, 25, 25)));
391 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
392 gfx::Rect(300, 300, 100, 100)));
394 l1->Add(l2.get());
395 l1->Add(l4.get());
396 l2->Add(l3.get());
398 DrawTree(l1.get());
401 class LayerWithDelegateTest : public testing::Test {
402 public:
403 LayerWithDelegateTest() {}
404 virtual ~LayerWithDelegateTest() {}
406 // Overridden from testing::Test:
407 virtual void SetUp() OVERRIDE {
408 bool enable_pixel_output = false;
409 ui::ContextFactory* context_factory =
410 InitializeContextFactoryForTests(enable_pixel_output);
412 const gfx::Rect host_bounds(1000, 1000);
413 compositor_host_.reset(TestCompositorHost::Create(host_bounds,
414 context_factory));
415 compositor_host_->Show();
418 virtual void TearDown() OVERRIDE {
419 compositor_host_.reset();
420 TerminateContextFactoryForTests();
423 Compositor* compositor() { return compositor_host_->GetCompositor(); }
425 virtual Layer* CreateLayer(LayerType type) {
426 return new Layer(type);
429 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
430 Layer* layer = new ColoredLayer(color);
431 layer->SetBounds(bounds);
432 return layer;
435 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
436 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
437 layer->SetBounds(bounds);
438 return layer;
441 void DrawTree(Layer* root) {
442 compositor()->SetRootLayer(root);
443 Draw();
446 // Invalidates the entire contents of the layer.
447 void SchedulePaintForLayer(Layer* layer) {
448 layer->SchedulePaint(
449 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
452 // Invokes DrawTree on the compositor.
453 void Draw() {
454 compositor()->ScheduleDraw();
455 WaitForDraw();
458 void WaitForDraw() { DrawWaiterForTest::Wait(compositor()); }
460 void WaitForCommit() {
461 DrawWaiterForTest::WaitForCommit(compositor());
464 private:
465 scoped_ptr<TestCompositorHost> compositor_host_;
467 DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
470 // L1
471 // +-- L2
472 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
473 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
474 gfx::Rect(20, 20, 400, 400)));
475 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
476 gfx::Rect(10, 10, 350, 350)));
477 l1->Add(l2.get());
478 DrawTree(l1.get());
480 gfx::Point point1_in_l2_coords(5, 5);
481 Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords);
482 gfx::Point point1_in_l1_coords(15, 15);
483 EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords);
485 gfx::Point point2_in_l1_coords(5, 5);
486 Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords);
487 gfx::Point point2_in_l2_coords(-5, -5);
488 EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords);
491 // L1
492 // +-- L2
493 // +-- L3
494 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
495 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
496 gfx::Rect(20, 20, 400, 400)));
497 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
498 gfx::Rect(10, 10, 350, 350)));
499 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
500 gfx::Rect(10, 10, 100, 100)));
501 l1->Add(l2.get());
502 l2->Add(l3.get());
503 DrawTree(l1.get());
505 gfx::Point point1_in_l3_coords(5, 5);
506 Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords);
507 gfx::Point point1_in_l1_coords(25, 25);
508 EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords);
510 gfx::Point point2_in_l1_coords(5, 5);
511 Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords);
512 gfx::Point point2_in_l3_coords(-15, -15);
513 EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords);
516 TEST_F(LayerWithRealCompositorTest, Delegate) {
517 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorBLACK,
518 gfx::Rect(20, 20, 400, 400)));
519 GetCompositor()->SetRootLayer(l1.get());
520 WaitForDraw();
522 TestLayerDelegate delegate;
523 l1->set_delegate(&delegate);
524 delegate.AddColor(SK_ColorWHITE);
525 delegate.AddColor(SK_ColorYELLOW);
526 delegate.AddColor(SK_ColorGREEN);
528 l1->SchedulePaint(gfx::Rect(0, 0, 400, 400));
529 WaitForDraw();
531 EXPECT_EQ(delegate.color_index(), 1);
532 EXPECT_EQ(delegate.paint_size(), l1->bounds().size());
534 l1->SchedulePaint(gfx::Rect(10, 10, 200, 200));
535 WaitForDraw();
536 EXPECT_EQ(delegate.color_index(), 2);
537 EXPECT_EQ(delegate.paint_size(), gfx::Size(200, 200));
539 l1->SchedulePaint(gfx::Rect(5, 5, 50, 50));
540 WaitForDraw();
541 EXPECT_EQ(delegate.color_index(), 0);
542 EXPECT_EQ(delegate.paint_size(), gfx::Size(50, 50));
545 TEST_F(LayerWithRealCompositorTest, DrawTree) {
546 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
547 gfx::Rect(20, 20, 400, 400)));
548 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
549 gfx::Rect(10, 10, 350, 350)));
550 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
551 gfx::Rect(10, 10, 100, 100)));
552 l1->Add(l2.get());
553 l2->Add(l3.get());
555 GetCompositor()->SetRootLayer(l1.get());
556 WaitForDraw();
558 DrawTreeLayerDelegate d1;
559 l1->set_delegate(&d1);
560 DrawTreeLayerDelegate d2;
561 l2->set_delegate(&d2);
562 DrawTreeLayerDelegate d3;
563 l3->set_delegate(&d3);
565 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
566 WaitForDraw();
567 EXPECT_FALSE(d1.painted());
568 EXPECT_TRUE(d2.painted());
569 EXPECT_FALSE(d3.painted());
572 // Tests no-texture Layers.
573 // Create this hierarchy:
574 // L1 - red
575 // +-- L2 - NO TEXTURE
576 // | +-- L3 - yellow
577 // +-- L4 - magenta
579 TEST_F(LayerWithRealCompositorTest, HierarchyNoTexture) {
580 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
581 gfx::Rect(20, 20, 400, 400)));
582 scoped_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350)));
583 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
584 gfx::Rect(5, 5, 25, 25)));
585 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
586 gfx::Rect(300, 300, 100, 100)));
588 l1->Add(l2.get());
589 l1->Add(l4.get());
590 l2->Add(l3.get());
592 GetCompositor()->SetRootLayer(l1.get());
593 WaitForDraw();
595 DrawTreeLayerDelegate d2;
596 l2->set_delegate(&d2);
597 DrawTreeLayerDelegate d3;
598 l3->set_delegate(&d3);
600 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
601 l3->SchedulePaint(gfx::Rect(5, 5, 5, 5));
602 WaitForDraw();
604 // |d2| should not have received a paint notification since it has no texture.
605 EXPECT_FALSE(d2.painted());
606 // |d3| should have received a paint notification.
607 EXPECT_TRUE(d3.painted());
610 class LayerWithNullDelegateTest : public LayerWithDelegateTest {
611 public:
612 LayerWithNullDelegateTest() {}
613 virtual ~LayerWithNullDelegateTest() {}
615 virtual void SetUp() OVERRIDE {
616 LayerWithDelegateTest::SetUp();
617 default_layer_delegate_.reset(new NullLayerDelegate());
620 virtual Layer* CreateLayer(LayerType type) OVERRIDE {
621 Layer* layer = new Layer(type);
622 layer->set_delegate(default_layer_delegate_.get());
623 return layer;
626 Layer* CreateTextureRootLayer(const gfx::Rect& bounds) {
627 Layer* layer = CreateTextureLayer(bounds);
628 compositor()->SetRootLayer(layer);
629 return layer;
632 Layer* CreateTextureLayer(const gfx::Rect& bounds) {
633 Layer* layer = CreateLayer(LAYER_TEXTURED);
634 layer->SetBounds(bounds);
635 return layer;
638 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) OVERRIDE {
639 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
640 layer->SetBounds(bounds);
641 return layer;
644 private:
645 scoped_ptr<NullLayerDelegate> default_layer_delegate_;
647 DISALLOW_COPY_AND_ASSIGN(LayerWithNullDelegateTest);
650 TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) {
651 scoped_ptr<Layer> layer(CreateLayer(LAYER_NOT_DRAWN));
652 std::string name = "\"\'\\/\b\f\n\r\t\n";
653 layer->set_name(name);
654 scoped_refptr<base::debug::ConvertableToTraceFormat> debug_info =
655 layer->TakeDebugInfo();
656 EXPECT_TRUE(!!debug_info.get());
657 std::string json;
658 debug_info->AppendAsTraceFormat(&json);
659 base::JSONReader json_reader;
660 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(json));
661 EXPECT_TRUE(!!debug_info_value);
662 EXPECT_TRUE(debug_info_value->IsType(base::Value::TYPE_DICTIONARY));
663 base::DictionaryValue* dictionary = 0;
664 EXPECT_TRUE(debug_info_value->GetAsDictionary(&dictionary));
665 std::string roundtrip;
666 EXPECT_TRUE(dictionary->GetString("layer_name", &roundtrip));
667 EXPECT_EQ(name, roundtrip);
670 void ReturnMailbox(bool* run, uint32 sync_point, bool is_lost) {
671 *run = true;
674 TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
675 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
676 gfx::Rect(20, 20, 400, 400)));
677 l1->SetFillsBoundsOpaquely(true);
678 l1->SetForceRenderSurface(true);
679 l1->SetVisible(false);
681 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
682 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
683 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
684 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
685 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
687 cc::Layer* before_layer = l1->cc_layer();
689 bool callback1_run = false;
690 cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), 0, 0);
691 l1->SetTextureMailbox(mailbox,
692 cc::SingleReleaseCallback::Create(
693 base::Bind(ReturnMailbox, &callback1_run)),
694 gfx::Size(1, 1));
696 EXPECT_NE(before_layer, l1->cc_layer());
698 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
699 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
700 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
701 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
702 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
703 EXPECT_FALSE(callback1_run);
705 bool callback2_run = false;
706 mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0);
707 l1->SetTextureMailbox(mailbox,
708 cc::SingleReleaseCallback::Create(
709 base::Bind(ReturnMailbox, &callback2_run)),
710 gfx::Size(1, 1));
711 EXPECT_TRUE(callback1_run);
712 EXPECT_FALSE(callback2_run);
714 l1->SetShowPaintedContent();
715 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
716 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
717 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
718 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
719 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
720 EXPECT_TRUE(callback2_run);
723 // Various visibile/drawn assertions.
724 TEST_F(LayerWithNullDelegateTest, Visibility) {
725 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
726 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
727 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
728 l1->Add(l2.get());
729 l2->Add(l3.get());
731 NullLayerDelegate delegate;
732 l1->set_delegate(&delegate);
733 l2->set_delegate(&delegate);
734 l3->set_delegate(&delegate);
736 // Layers should initially be drawn.
737 EXPECT_TRUE(l1->IsDrawn());
738 EXPECT_TRUE(l2->IsDrawn());
739 EXPECT_TRUE(l3->IsDrawn());
740 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
741 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
742 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
744 compositor()->SetRootLayer(l1.get());
746 Draw();
748 l1->SetVisible(false);
749 EXPECT_FALSE(l1->IsDrawn());
750 EXPECT_FALSE(l2->IsDrawn());
751 EXPECT_FALSE(l3->IsDrawn());
752 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
753 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
754 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
756 l3->SetVisible(false);
757 EXPECT_FALSE(l1->IsDrawn());
758 EXPECT_FALSE(l2->IsDrawn());
759 EXPECT_FALSE(l3->IsDrawn());
760 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
761 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
762 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
764 l1->SetVisible(true);
765 EXPECT_TRUE(l1->IsDrawn());
766 EXPECT_TRUE(l2->IsDrawn());
767 EXPECT_FALSE(l3->IsDrawn());
768 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
769 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
770 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
773 // Checks that stacking-related methods behave as advertised.
774 TEST_F(LayerWithNullDelegateTest, Stacking) {
775 scoped_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
776 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
777 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
778 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
779 l1->set_name("1");
780 l2->set_name("2");
781 l3->set_name("3");
782 root->Add(l3.get());
783 root->Add(l2.get());
784 root->Add(l1.get());
786 // Layers' children are stored in bottom-to-top order.
787 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
789 root->StackAtTop(l3.get());
790 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
792 root->StackAtTop(l1.get());
793 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
795 root->StackAtTop(l1.get());
796 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
798 root->StackAbove(l2.get(), l3.get());
799 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
801 root->StackAbove(l1.get(), l3.get());
802 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
804 root->StackAbove(l2.get(), l1.get());
805 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
807 root->StackAtBottom(l2.get());
808 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
810 root->StackAtBottom(l3.get());
811 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
813 root->StackAtBottom(l3.get());
814 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
816 root->StackBelow(l2.get(), l3.get());
817 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
819 root->StackBelow(l1.get(), l3.get());
820 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
822 root->StackBelow(l3.get(), l2.get());
823 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
825 root->StackBelow(l3.get(), l2.get());
826 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
828 root->StackBelow(l3.get(), l1.get());
829 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
832 // Verifies SetBounds triggers the appropriate painting/drawing.
833 TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
834 scoped_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
835 compositor()->SetRootLayer(l1.get());
837 Draw();
839 l1->SetBounds(gfx::Rect(5, 5, 200, 200));
841 // The CompositorDelegate (us) should have been told to draw for a move.
842 WaitForDraw();
844 l1->SetBounds(gfx::Rect(5, 5, 100, 100));
846 // The CompositorDelegate (us) should have been told to draw for a resize.
847 WaitForDraw();
850 // Checks that pixels are actually drawn to the screen with a read back.
851 TEST_F(LayerWithRealCompositorTest, DrawPixels) {
852 gfx::Size viewport_size = GetCompositor()->size();
854 // The window should be some non-trivial size but may not be exactly
855 // 500x500 on all platforms/bots.
856 EXPECT_GE(viewport_size.width(), 200);
857 EXPECT_GE(viewport_size.height(), 200);
859 int blue_height = 10;
861 scoped_ptr<Layer> layer(
862 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
863 scoped_ptr<Layer> layer2(
864 CreateColorLayer(SK_ColorBLUE,
865 gfx::Rect(0, 0, viewport_size.width(), blue_height)));
867 layer->Add(layer2.get());
869 DrawTree(layer.get());
871 SkBitmap bitmap;
872 ASSERT_TRUE(ReadPixels(&bitmap, gfx::Rect(viewport_size)));
873 ASSERT_FALSE(bitmap.empty());
875 SkAutoLockPixels lock(bitmap);
876 for (int x = 0; x < viewport_size.width(); x++) {
877 for (int y = 0; y < viewport_size.height(); y++) {
878 SkColor actual_color = bitmap.getColor(x, y);
879 SkColor expected_color = y < blue_height ? SK_ColorBLUE : SK_ColorRED;
880 EXPECT_EQ(expected_color, actual_color)
881 << "Pixel error at x=" << x << " y=" << y << "; "
882 << "actual RGBA=("
883 << SkColorGetR(actual_color) << ","
884 << SkColorGetG(actual_color) << ","
885 << SkColorGetB(actual_color) << ","
886 << SkColorGetA(actual_color) << "); "
887 << "expected RGBA=("
888 << SkColorGetR(expected_color) << ","
889 << SkColorGetG(expected_color) << ","
890 << SkColorGetB(expected_color) << ","
891 << SkColorGetA(expected_color) << ")";
896 // Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
897 TEST_F(LayerWithRealCompositorTest, SetRootLayer) {
898 Compositor* compositor = GetCompositor();
899 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
900 gfx::Rect(20, 20, 400, 400)));
901 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
902 gfx::Rect(10, 10, 350, 350)));
904 EXPECT_EQ(NULL, l1->GetCompositor());
905 EXPECT_EQ(NULL, l2->GetCompositor());
907 compositor->SetRootLayer(l1.get());
908 EXPECT_EQ(compositor, l1->GetCompositor());
910 l1->Add(l2.get());
911 EXPECT_EQ(compositor, l2->GetCompositor());
913 l1->Remove(l2.get());
914 EXPECT_EQ(NULL, l2->GetCompositor());
916 l1->Add(l2.get());
917 EXPECT_EQ(compositor, l2->GetCompositor());
919 compositor->SetRootLayer(NULL);
920 EXPECT_EQ(NULL, l1->GetCompositor());
921 EXPECT_EQ(NULL, l2->GetCompositor());
924 // Checks that compositor observers are notified when:
925 // - DrawTree is called,
926 // - After ScheduleDraw is called, or
927 // - Whenever SetBounds, SetOpacity or SetTransform are called.
928 // TODO(vollick): could be reorganized into compositor_unittest.cc
929 TEST_F(LayerWithRealCompositorTest, CompositorObservers) {
930 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
931 gfx::Rect(20, 20, 400, 400)));
932 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
933 gfx::Rect(10, 10, 350, 350)));
934 l1->Add(l2.get());
935 TestCompositorObserver observer;
936 GetCompositor()->AddObserver(&observer);
938 // Explicitly called DrawTree should cause the observers to be notified.
939 // NOTE: this call to DrawTree sets l1 to be the compositor's root layer.
940 DrawTree(l1.get());
941 EXPECT_TRUE(observer.notified());
943 // ScheduleDraw without any visible change should cause a commit.
944 observer.Reset();
945 l1->ScheduleDraw();
946 WaitForCommit();
947 EXPECT_TRUE(observer.committed());
949 // Moving, but not resizing, a layer should alert the observers.
950 observer.Reset();
951 l2->SetBounds(gfx::Rect(0, 0, 350, 350));
952 WaitForDraw();
953 EXPECT_TRUE(observer.notified());
955 // So should resizing a layer.
956 observer.Reset();
957 l2->SetBounds(gfx::Rect(0, 0, 400, 400));
958 WaitForDraw();
959 EXPECT_TRUE(observer.notified());
961 // Opacity changes should alert the observers.
962 observer.Reset();
963 l2->SetOpacity(0.5f);
964 WaitForDraw();
965 EXPECT_TRUE(observer.notified());
967 // So should setting the opacity back.
968 observer.Reset();
969 l2->SetOpacity(1.0f);
970 WaitForDraw();
971 EXPECT_TRUE(observer.notified());
973 // Setting the transform of a layer should alert the observers.
974 observer.Reset();
975 gfx::Transform transform;
976 transform.Translate(200.0, 200.0);
977 transform.Rotate(90.0);
978 transform.Translate(-200.0, -200.0);
979 l2->SetTransform(transform);
980 WaitForDraw();
981 EXPECT_TRUE(observer.notified());
983 // A change resulting in an aborted swap buffer should alert the observer
984 // and also signal an abort.
985 observer.Reset();
986 l2->SetOpacity(0.1f);
987 GetCompositor()->DidAbortSwapBuffers();
988 WaitForDraw();
989 EXPECT_TRUE(observer.notified());
990 EXPECT_TRUE(observer.aborted());
992 GetCompositor()->RemoveObserver(&observer);
994 // Opacity changes should no longer alert the removed observer.
995 observer.Reset();
996 l2->SetOpacity(0.5f);
997 WaitForDraw();
999 EXPECT_FALSE(observer.notified());
1002 // Checks that modifying the hierarchy correctly affects final composite.
1003 TEST_F(LayerWithRealCompositorTest, ModifyHierarchy) {
1004 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1006 // l0
1007 // +-l11
1008 // | +-l21
1009 // +-l12
1010 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1011 gfx::Rect(0, 0, 50, 50)));
1012 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1013 gfx::Rect(0, 0, 25, 25)));
1014 scoped_ptr<Layer> l21(CreateColorLayer(SK_ColorMAGENTA,
1015 gfx::Rect(0, 0, 15, 15)));
1016 scoped_ptr<Layer> l12(CreateColorLayer(SK_ColorBLUE,
1017 gfx::Rect(10, 10, 25, 25)));
1019 base::FilePath ref_img1 =
1020 test_data_directory().AppendASCII("ModifyHierarchy1.png");
1021 base::FilePath ref_img2 =
1022 test_data_directory().AppendASCII("ModifyHierarchy2.png");
1023 SkBitmap bitmap;
1025 l0->Add(l11.get());
1026 l11->Add(l21.get());
1027 l0->Add(l12.get());
1028 DrawTree(l0.get());
1029 ASSERT_TRUE(ReadPixels(&bitmap));
1030 ASSERT_FALSE(bitmap.empty());
1031 // WritePNGFile(bitmap, ref_img1);
1032 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1034 l0->StackAtTop(l11.get());
1035 DrawTree(l0.get());
1036 ASSERT_TRUE(ReadPixels(&bitmap));
1037 ASSERT_FALSE(bitmap.empty());
1038 // WritePNGFile(bitmap, ref_img2);
1039 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1041 // should restore to original configuration
1042 l0->StackAbove(l12.get(), l11.get());
1043 DrawTree(l0.get());
1044 ASSERT_TRUE(ReadPixels(&bitmap));
1045 ASSERT_FALSE(bitmap.empty());
1046 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1048 // l11 back to front
1049 l0->StackAtTop(l11.get());
1050 DrawTree(l0.get());
1051 ASSERT_TRUE(ReadPixels(&bitmap));
1052 ASSERT_FALSE(bitmap.empty());
1053 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1055 // should restore to original configuration
1056 l0->StackAbove(l12.get(), l11.get());
1057 DrawTree(l0.get());
1058 ASSERT_TRUE(ReadPixels(&bitmap));
1059 ASSERT_FALSE(bitmap.empty());
1060 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1062 // l11 back to front
1063 l0->StackAbove(l11.get(), l12.get());
1064 DrawTree(l0.get());
1065 ASSERT_TRUE(ReadPixels(&bitmap));
1066 ASSERT_FALSE(bitmap.empty());
1067 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1070 // Opacity is rendered correctly.
1071 // Checks that modifying the hierarchy correctly affects final composite.
1072 TEST_F(LayerWithRealCompositorTest, Opacity) {
1073 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1075 // l0
1076 // +-l11
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)));
1082 base::FilePath ref_img = test_data_directory().AppendASCII("Opacity.png");
1084 l11->SetOpacity(0.75);
1085 l0->Add(l11.get());
1086 DrawTree(l0.get());
1087 SkBitmap bitmap;
1088 ASSERT_TRUE(ReadPixels(&bitmap));
1089 ASSERT_FALSE(bitmap.empty());
1090 // WritePNGFile(bitmap, ref_img);
1091 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img, cc::ExactPixelComparator(true)));
1094 namespace {
1096 class SchedulePaintLayerDelegate : public LayerDelegate {
1097 public:
1098 SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
1100 virtual ~SchedulePaintLayerDelegate() {}
1102 void set_layer(Layer* layer) {
1103 layer_ = layer;
1104 layer_->set_delegate(this);
1107 void SetSchedulePaintRect(const gfx::Rect& rect) {
1108 schedule_paint_rect_ = rect;
1111 int GetPaintCountAndClear() {
1112 int value = paint_count_;
1113 paint_count_ = 0;
1114 return value;
1117 const gfx::RectF& last_clip_rect() const { return last_clip_rect_; }
1119 private:
1120 // Overridden from LayerDelegate:
1121 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
1122 paint_count_++;
1123 if (!schedule_paint_rect_.IsEmpty()) {
1124 layer_->SchedulePaint(schedule_paint_rect_);
1125 schedule_paint_rect_ = gfx::Rect();
1127 SkRect sk_clip_rect;
1128 if (canvas->sk_canvas()->getClipBounds(&sk_clip_rect))
1129 last_clip_rect_ = gfx::SkRectToRectF(sk_clip_rect);
1132 virtual void OnDelegatedFrameDamage(
1133 const gfx::Rect& damage_rect_in_dip) OVERRIDE {}
1135 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
1138 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
1139 return base::Closure();
1142 int paint_count_;
1143 Layer* layer_;
1144 gfx::Rect schedule_paint_rect_;
1145 gfx::RectF last_clip_rect_;
1147 DISALLOW_COPY_AND_ASSIGN(SchedulePaintLayerDelegate);
1150 } // namespace
1152 // Verifies that if SchedulePaint is invoked during painting the layer is still
1153 // marked dirty.
1154 TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
1155 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorRED,
1156 gfx::Rect(0, 0, 500, 500)));
1157 SchedulePaintLayerDelegate child_delegate;
1158 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorBLUE,
1159 gfx::Rect(0, 0, 200, 200)));
1160 child_delegate.set_layer(child.get());
1162 root->Add(child.get());
1164 SchedulePaintForLayer(root.get());
1165 DrawTree(root.get());
1166 child->SchedulePaint(gfx::Rect(0, 0, 20, 20));
1167 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1169 // Set a rect so that when OnPaintLayer() is invoked SchedulePaint is invoked
1170 // again.
1171 child_delegate.SetSchedulePaintRect(gfx::Rect(10, 10, 30, 30));
1172 WaitForCommit();
1173 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1175 // Because SchedulePaint() was invoked from OnPaintLayer() |child| should
1176 // still need to be painted.
1177 WaitForCommit();
1178 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1179 EXPECT_TRUE(child_delegate.last_clip_rect().Contains(
1180 gfx::Rect(10, 10, 30, 30)));
1183 TEST_F(LayerWithRealCompositorTest, ScaleUpDown) {
1184 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1185 gfx::Rect(10, 20, 200, 220)));
1186 TestLayerDelegate root_delegate;
1187 root_delegate.AddColor(SK_ColorWHITE);
1188 root->set_delegate(&root_delegate);
1190 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1191 gfx::Rect(10, 20, 140, 180)));
1192 TestLayerDelegate l1_delegate;
1193 l1_delegate.AddColor(SK_ColorWHITE);
1194 l1->set_delegate(&l1_delegate);
1196 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1197 GetCompositor()->SetRootLayer(root.get());
1198 root->Add(l1.get());
1199 WaitForDraw();
1201 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1202 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1203 gfx::Size cc_bounds_size = root->cc_layer()->bounds();
1204 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1205 cc_bounds_size = l1->cc_layer()->bounds();
1206 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1207 // No scale change, so no scale notification.
1208 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1209 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1211 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1212 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1214 // Scale up to 2.0. Changing scale doesn't change the bounds in DIP.
1215 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1216 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1217 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1218 // CC layer should still match the UI layer bounds.
1219 cc_bounds_size = root->cc_layer()->bounds();
1220 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1221 cc_bounds_size = l1->cc_layer()->bounds();
1222 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1223 // New scale factor must have been notified.
1224 EXPECT_EQ(2.0f, root_delegate.device_scale_factor());
1225 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1227 // Canvas size must have been scaled down up.
1228 WaitForDraw();
1229 EXPECT_EQ("400x440", root_delegate.paint_size().ToString());
1230 EXPECT_EQ("2.0 2.0", root_delegate.ToScaleString());
1231 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1232 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1234 // Scale down back to 1.0f.
1235 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1236 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1237 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1238 // CC layer should still match the UI layer bounds.
1239 cc_bounds_size = root->cc_layer()->bounds();
1240 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1241 cc_bounds_size = l1->cc_layer()->bounds();
1242 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1243 // New scale factor must have been notified.
1244 EXPECT_EQ(1.0f, root_delegate.device_scale_factor());
1245 EXPECT_EQ(1.0f, l1_delegate.device_scale_factor());
1247 // Canvas size must have been scaled down too.
1248 WaitForDraw();
1249 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1250 EXPECT_EQ("1.0 1.0", root_delegate.ToScaleString());
1251 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1252 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1254 root_delegate.reset();
1255 l1_delegate.reset();
1256 // Just changing the size shouldn't notify the scale change nor
1257 // trigger repaint.
1258 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(1000, 1000));
1259 // No scale change, so no scale notification.
1260 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1261 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1262 WaitForDraw();
1263 EXPECT_EQ("0x0", root_delegate.paint_size().ToString());
1264 EXPECT_EQ("0.0 0.0", root_delegate.ToScaleString());
1265 EXPECT_EQ("0x0", l1_delegate.paint_size().ToString());
1266 EXPECT_EQ("0.0 0.0", l1_delegate.ToScaleString());
1269 TEST_F(LayerWithRealCompositorTest, ScaleReparent) {
1270 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1271 gfx::Rect(10, 20, 200, 220)));
1272 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1273 gfx::Rect(10, 20, 140, 180)));
1274 TestLayerDelegate l1_delegate;
1275 l1_delegate.AddColor(SK_ColorWHITE);
1276 l1->set_delegate(&l1_delegate);
1278 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1279 GetCompositor()->SetRootLayer(root.get());
1280 WaitForDraw();
1282 root->Add(l1.get());
1283 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1284 gfx::Size cc_bounds_size = l1->cc_layer()->bounds();
1285 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1286 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1288 WaitForDraw();
1289 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1290 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1292 // Remove l1 from root and change the scale.
1293 root->Remove(l1.get());
1294 EXPECT_EQ(NULL, l1->parent());
1295 EXPECT_EQ(NULL, l1->GetCompositor());
1296 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1297 // Sanity check on root and l1.
1298 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1299 cc_bounds_size = l1->cc_layer()->bounds();
1300 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1302 root->Add(l1.get());
1303 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1304 cc_bounds_size = l1->cc_layer()->bounds();
1305 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1306 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1307 WaitForDraw();
1308 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1309 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1312 // Verifies that when changing bounds on a layer that is invisible, and then
1313 // made visible, the right thing happens:
1314 // - if just a move, then no painting should happen.
1315 // - if a resize, the layer should be repainted.
1316 TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
1317 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1319 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1320 child->SetBounds(gfx::Rect(0, 0, 500, 500));
1321 DrawTreeLayerDelegate delegate;
1322 child->set_delegate(&delegate);
1323 root->Add(child.get());
1325 // Paint once for initial damage.
1326 child->SetVisible(true);
1327 DrawTree(root.get());
1329 // Reset into invisible state.
1330 child->SetVisible(false);
1331 DrawTree(root.get());
1332 delegate.Reset();
1334 // Move layer.
1335 child->SetBounds(gfx::Rect(200, 200, 500, 500));
1336 child->SetVisible(true);
1337 DrawTree(root.get());
1338 EXPECT_FALSE(delegate.painted());
1340 // Reset into invisible state.
1341 child->SetVisible(false);
1342 DrawTree(root.get());
1343 delegate.Reset();
1345 // Resize layer.
1346 child->SetBounds(gfx::Rect(200, 200, 400, 400));
1347 child->SetVisible(true);
1348 DrawTree(root.get());
1349 EXPECT_TRUE(delegate.painted());
1352 static scoped_ptr<cc::DelegatedFrameData> MakeFrameData(gfx::Size size) {
1353 scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
1354 scoped_ptr<cc::RenderPass> render_pass(cc::RenderPass::Create());
1355 render_pass->SetNew(
1356 cc::RenderPassId(1, 1), gfx::Rect(size), gfx::Rect(), gfx::Transform());
1357 frame_data->render_pass_list.push_back(render_pass.Pass());
1358 return frame_data.Pass();
1361 TEST_F(LayerWithDelegateTest, DelegatedLayer) {
1362 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1364 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1366 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1367 child->SetVisible(true);
1368 root->Add(child.get());
1369 DrawTree(root.get());
1371 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1372 new cc::DelegatedFrameResourceCollection;
1373 scoped_refptr<cc::DelegatedFrameProvider> frame_provider;
1375 // Content matches layer size.
1376 frame_provider = new cc::DelegatedFrameProvider(
1377 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1378 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1379 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1380 gfx::Size(10, 10).ToString());
1382 // Content larger than layer.
1383 child->SetBounds(gfx::Rect(0, 0, 5, 5));
1384 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1385 gfx::Size(5, 5).ToString());
1387 // Content smaller than layer.
1388 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1389 frame_provider = new cc::DelegatedFrameProvider(
1390 resource_collection.get(), MakeFrameData(gfx::Size(5, 5)));
1391 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(5, 5));
1392 EXPECT_EQ(child->cc_layer()->bounds().ToString(), gfx::Size(5, 5).ToString());
1394 // Hi-DPI content on low-DPI layer.
1395 frame_provider = new cc::DelegatedFrameProvider(
1396 resource_collection.get(), MakeFrameData(gfx::Size(20, 20)));
1397 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1398 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1399 gfx::Size(10, 10).ToString());
1401 // Hi-DPI content on hi-DPI layer.
1402 compositor()->SetScaleAndSize(2.f, gfx::Size(1000, 1000));
1403 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1404 gfx::Size(10, 10).ToString());
1406 // Low-DPI content on hi-DPI layer.
1407 frame_provider = new cc::DelegatedFrameProvider(
1408 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1409 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1410 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1411 gfx::Size(10, 10).ToString());
1414 TEST_F(LayerWithDelegateTest, ExternalContent) {
1415 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1416 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1418 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1419 child->SetVisible(true);
1420 root->Add(child.get());
1422 // The layer is already showing painted content, so the cc layer won't change.
1423 scoped_refptr<cc::Layer> before = child->cc_layer();
1424 child->SetShowPaintedContent();
1425 EXPECT_TRUE(child->cc_layer());
1426 EXPECT_EQ(before.get(), child->cc_layer());
1428 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1429 new cc::DelegatedFrameResourceCollection;
1430 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1431 new cc::DelegatedFrameProvider(resource_collection.get(),
1432 MakeFrameData(gfx::Size(10, 10)));
1434 // Showing delegated content changes the underlying cc layer.
1435 before = child->cc_layer();
1436 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1437 EXPECT_TRUE(child->cc_layer());
1438 EXPECT_NE(before.get(), child->cc_layer());
1440 // Changing to painted content should change the underlying cc layer.
1441 before = child->cc_layer();
1442 child->SetShowPaintedContent();
1443 EXPECT_TRUE(child->cc_layer());
1444 EXPECT_NE(before.get(), child->cc_layer());
1447 // Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation.
1448 TEST_F(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) {
1449 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1450 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1451 scoped_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED));
1453 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1454 l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1456 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1458 // Trigger a threaded animation.
1459 l1->SetOpacity(0.5f);
1461 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1463 // Ensure we can remove a pending threaded animation.
1464 l1->GetAnimator()->StopAnimating();
1466 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1468 // Trigger another threaded animation.
1469 l1->SetOpacity(0.2f);
1471 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1473 root->Add(l1.get());
1474 GetCompositor()->SetRootLayer(root.get());
1476 // Now that l1 is part of a tree, it should have dispatched the pending
1477 // animation.
1478 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1480 // Ensure that l1 no longer holds on to animations.
1481 l1->SetOpacity(0.1f);
1482 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1484 // Ensure that adding a layer to an existing tree causes its pending
1485 // animations to get dispatched.
1486 l2->SetOpacity(0.5f);
1487 EXPECT_TRUE(l2->HasPendingThreadedAnimations());
1489 l1->Add(l2.get());
1490 EXPECT_FALSE(l2->HasPendingThreadedAnimations());
1493 // Tests that in-progress threaded animations complete when a Layer's
1494 // cc::Layer changes.
1495 TEST_F(LayerWithRealCompositorTest, SwitchCCLayerAnimations) {
1496 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1497 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1498 GetCompositor()->SetRootLayer(root.get());
1499 root->Add(l1.get());
1501 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1503 EXPECT_FLOAT_EQ(l1->opacity(), 1.0f);
1505 // Trigger a threaded animation.
1506 l1->SetOpacity(0.5f);
1508 // Change l1's cc::Layer.
1509 l1->SwitchCCLayerForTest();
1511 // Ensure that the opacity animation completed.
1512 EXPECT_FLOAT_EQ(l1->opacity(), 0.5f);
1515 // Tests that the animators in the layer tree is added to the
1516 // animator-collection when the root-layer is set to the compositor.
1517 TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) {
1518 scoped_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
1519 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10)));
1520 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1521 child->SetOpacity(0.5f);
1522 root->Add(child.get());
1524 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1525 compositor()->SetRootLayer(root.get());
1526 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1529 // Tests that adding/removing a layer adds/removes the animator from its entire
1530 // subtree from the compositor's animator-collection.
1531 TEST_F(LayerWithDelegateTest, AddRemoveLayerUpdatesAnimatorsFromSubtree) {
1532 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1533 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1534 scoped_ptr<Layer> grandchild(CreateColorLayer(SK_ColorRED,
1535 gfx::Rect(10, 10)));
1536 root->Add(child.get());
1537 child->Add(grandchild.get());
1538 compositor()->SetRootLayer(root.get());
1540 grandchild->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1541 grandchild->SetOpacity(0.5f);
1542 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1544 root->Remove(child.get());
1545 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1547 root->Add(child.get());
1548 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1551 TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) {
1552 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1553 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1554 root->Add(child.get());
1555 compositor()->SetRootLayer(root.get());
1557 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1558 child->SetOpacity(0.5f);
1559 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1561 child.reset();
1562 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1565 namespace {
1567 std::string Vector2dFTo100thPercisionString(const gfx::Vector2dF& vector) {
1568 return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y());
1571 } // namespace
1573 TEST_F(LayerWithRealCompositorTest, SnapLayerToPixels) {
1574 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1575 scoped_ptr<Layer> c1(CreateLayer(LAYER_TEXTURED));
1576 scoped_ptr<Layer> c11(CreateLayer(LAYER_TEXTURED));
1578 GetCompositor()->SetScaleAndSize(1.25f, gfx::Size(100, 100));
1579 GetCompositor()->SetRootLayer(root.get());
1580 root->Add(c1.get());
1581 c1->Add(c11.get());
1583 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1584 c1->SetBounds(gfx::Rect(1, 1, 10, 10));
1585 c11->SetBounds(gfx::Rect(1, 1, 10, 10));
1586 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1587 // 0.5 at 1.25 scale : (1 - 0.25 + 0.25) / 1.25 = 0.4
1588 EXPECT_EQ("0.40 0.40",
1589 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1591 GetCompositor()->SetScaleAndSize(1.5f, gfx::Size(100, 100));
1592 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1593 // c11 must already be aligned at 1.5 scale.
1594 EXPECT_EQ("0.00 0.00",
1595 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1597 c11->SetBounds(gfx::Rect(2, 2, 10, 10));
1598 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1599 // c11 is now off the pixel.
1600 // 0.5 / 1.5 = 0.333...
1601 EXPECT_EQ("0.33 0.33",
1602 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1605 class FrameDamageCheckingDelegate : public TestLayerDelegate {
1606 public:
1607 FrameDamageCheckingDelegate() : delegated_frame_damage_called_(false) {}
1609 virtual void OnDelegatedFrameDamage(
1610 const gfx::Rect& damage_rect_in_dip) OVERRIDE {
1611 delegated_frame_damage_called_ = true;
1612 delegated_frame_damage_rect_ = damage_rect_in_dip;
1615 const gfx::Rect& delegated_frame_damage_rect() const {
1616 return delegated_frame_damage_rect_;
1618 bool delegated_frame_damage_called() const {
1619 return delegated_frame_damage_called_;
1622 private:
1623 gfx::Rect delegated_frame_damage_rect_;
1624 bool delegated_frame_damage_called_;
1626 DISALLOW_COPY_AND_ASSIGN(FrameDamageCheckingDelegate);
1629 TEST(LayerDelegateTest, DelegatedFrameDamage) {
1630 scoped_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
1631 gfx::Rect damage_rect(2, 1, 5, 3);
1633 FrameDamageCheckingDelegate delegate;
1634 layer->set_delegate(&delegate);
1635 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1636 new cc::DelegatedFrameResourceCollection;
1637 scoped_refptr<cc::DelegatedFrameProvider> frame_provider(
1638 new cc::DelegatedFrameProvider(resource_collection.get(),
1639 MakeFrameData(gfx::Size(10, 10))));
1640 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1642 EXPECT_FALSE(delegate.delegated_frame_damage_called());
1643 layer->OnDelegatedFrameDamage(damage_rect);
1644 EXPECT_TRUE(delegate.delegated_frame_damage_called());
1645 EXPECT_EQ(damage_rect, delegate.delegated_frame_damage_rect());
1648 } // namespace ui