layer_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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.
4
5#include "base/basictypes.h"
6#include "base/bind.h"
7#include "base/compiler_specific.h"
8#include "base/file_util.h"
9#include "base/files/file_path.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/message_loop.h"
12#include "base/path_service.h"
13#include "base/string_util.h"
14#include "base/stringprintf.h"
15#include "cc/layers/layer.h"
16#include "cc/output/delegated_frame_data.h"
17#include "cc/test/pixel_test_utils.h"
18#include "testing/gtest/include/gtest/gtest.h"
19#include "ui/compositor/compositor_observer.h"
20#include "ui/compositor/compositor_setup.h"
21#include "ui/compositor/layer.h"
22#include "ui/compositor/layer_animation_sequence.h"
23#include "ui/compositor/layer_animator.h"
24#include "ui/compositor/test/test_compositor_host.h"
25#include "ui/compositor/test/test_layers.h"
26#include "ui/gfx/canvas.h"
27#include "ui/gfx/codec/png_codec.h"
28#include "ui/gfx/gfx_paths.h"
29#include "ui/gfx/skia_util.h"
30
31using cc::MatchesPNGFile;
32
33namespace ui {
34
35namespace {
36
37// There are three test classes in here that configure the Compositor and
38// Layer's slightly differently:
39// - LayerWithNullDelegateTest uses NullLayerDelegate as the LayerDelegate. This
40//   is typically the base class you want to use.
41// - LayerWithDelegateTest uses LayerDelegate on the delegates.
42// - LayerWithRealCompositorTest when a real compositor is required for testing.
43//    - Slow because they bring up a window and run the real compositor. This
44//      is typically not what you want.
45
46class ColoredLayer : public Layer, public LayerDelegate {
47 public:
48  explicit ColoredLayer(SkColor color)
49      : Layer(LAYER_TEXTURED),
50        color_(color) {
51    set_delegate(this);
52  }
53
54  virtual ~ColoredLayer() { }
55
56  // Overridden from LayerDelegate:
57  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
58    canvas->DrawColor(color_);
59  }
60
61  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
62  }
63
64  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
65    return base::Closure();
66  }
67
68 private:
69  SkColor color_;
70};
71
72class LayerWithRealCompositorTest : public testing::Test {
73 public:
74  LayerWithRealCompositorTest() {
75    if (PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_)) {
76      test_data_directory_ = test_data_directory_.AppendASCII("compositor");
77    } else {
78      LOG(ERROR) << "Could not open test data directory.";
79    }
80  }
81  virtual ~LayerWithRealCompositorTest() {}
82
83  // Overridden from testing::Test:
84  virtual void SetUp() OVERRIDE {
85    DisableTestCompositor();
86    const gfx::Rect host_bounds(10, 10, 500, 500);
87    window_.reset(TestCompositorHost::Create(host_bounds));
88    window_->Show();
89  }
90
91  virtual void TearDown() OVERRIDE {
92  }
93
94  Compositor* GetCompositor() {
95    return window_->GetCompositor();
96  }
97
98  Layer* CreateLayer(LayerType type) {
99    return new Layer(type);
100  }
101
102  Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
103    Layer* layer = new ColoredLayer(color);
104    layer->SetBounds(bounds);
105    return layer;
106  }
107
108  Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
109    Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
110    layer->SetBounds(bounds);
111    return layer;
112  }
113
114  void DrawTree(Layer* root) {
115    GetCompositor()->SetRootLayer(root);
116    GetCompositor()->ScheduleDraw();
117    WaitForDraw();
118  }
119
120  bool ReadPixels(SkBitmap* bitmap) {
121    return GetCompositor()->ReadPixels(bitmap,
122                                       gfx::Rect(GetCompositor()->size()));
123  }
124
125  void WaitForDraw() {
126    ui::DrawWaiterForTest::Wait(GetCompositor());
127  }
128
129  // Invalidates the entire contents of the layer.
130  void SchedulePaintForLayer(Layer* layer) {
131    layer->SchedulePaint(
132        gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
133  }
134
135  const base::FilePath& test_data_directory() const {
136    return test_data_directory_;
137  }
138
139 private:
140  scoped_ptr<TestCompositorHost> window_;
141
142  // The root directory for test files.
143  base::FilePath test_data_directory_;
144
145  DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
146};
147
148// LayerDelegate that paints colors to the layer.
149class TestLayerDelegate : public LayerDelegate {
150 public:
151  explicit TestLayerDelegate() { reset(); }
152  virtual ~TestLayerDelegate() {}
153
154  void AddColor(SkColor color) {
155    colors_.push_back(color);
156  }
157
158  const gfx::Size& paint_size() const { return paint_size_; }
159  int color_index() const { return color_index_; }
160
161  std::string ToScaleString() const {
162    return base::StringPrintf("%.1f %.1f", scale_x_, scale_y_);
163  }
164
165  float device_scale_factor() const {
166    return device_scale_factor_;
167  }
168
169  // Overridden from LayerDelegate:
170  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
171    gfx::ImageSkiaRep contents = canvas->ExtractImageRep();
172    paint_size_ = gfx::Size(contents.pixel_width(), contents.pixel_height());
173    canvas->FillRect(gfx::Rect(paint_size_), colors_[color_index_]);
174    color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size());
175    const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
176    scale_x_ = matrix.getScaleX();
177    scale_y_ = matrix.getScaleY();
178  }
179
180  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
181    device_scale_factor_ = device_scale_factor;
182  }
183
184  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
185    return base::Closure();
186  }
187
188  void reset() {
189    color_index_ = 0;
190    paint_size_.SetSize(0, 0);
191    scale_x_ = scale_y_ = 0.0f;
192    device_scale_factor_ = 0.0f;
193  }
194
195 private:
196  std::vector<SkColor> colors_;
197  int color_index_;
198  gfx::Size paint_size_;
199  float scale_x_;
200  float scale_y_;
201  float device_scale_factor_;
202
203  DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate);
204};
205
206// LayerDelegate that verifies that a layer was asked to update its canvas.
207class DrawTreeLayerDelegate : public LayerDelegate {
208 public:
209  DrawTreeLayerDelegate() : painted_(false) {}
210  virtual ~DrawTreeLayerDelegate() {}
211
212  void Reset() {
213    painted_ = false;
214  }
215
216  bool painted() const { return painted_; }
217
218 private:
219  // Overridden from LayerDelegate:
220  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
221    painted_ = true;
222  }
223  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
224  }
225  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
226    return base::Closure();
227  }
228
229  bool painted_;
230
231  DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate);
232};
233
234// The simplest possible layer delegate. Does nothing.
235class NullLayerDelegate : public LayerDelegate {
236 public:
237  NullLayerDelegate() {}
238  virtual ~NullLayerDelegate() {}
239
240 private:
241  // Overridden from LayerDelegate:
242  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
243  }
244  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
245  }
246  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
247    return base::Closure();
248  }
249
250  DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate);
251};
252
253// Remembers if it has been notified.
254class TestCompositorObserver : public CompositorObserver {
255 public:
256  TestCompositorObserver()
257      : started_(false), ended_(false), aborted_(false) {}
258
259  bool notified() const { return started_ && ended_; }
260  bool aborted() const { return aborted_; }
261
262  void Reset() {
263    started_ = false;
264    ended_ = false;
265    aborted_ = false;
266  }
267
268 private:
269  virtual void OnCompositingDidCommit(Compositor* compositor) OVERRIDE {
270  }
271
272  virtual void OnCompositingStarted(Compositor* compositor,
273                                    base::TimeTicks start_time) OVERRIDE {
274    started_ = true;
275  }
276
277  virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE {
278    ended_ = true;
279  }
280
281  virtual void OnCompositingAborted(Compositor* compositor) OVERRIDE {
282    aborted_ = true;
283  }
284
285  virtual void OnCompositingLockStateChanged(Compositor* compositor) OVERRIDE {
286  }
287
288  virtual void OnUpdateVSyncParameters(Compositor* compositor,
289                                       base::TimeTicks timebase,
290                                       base::TimeDelta interval) OVERRIDE {
291  }
292
293  bool started_;
294  bool ended_;
295  bool aborted_;
296
297  DISALLOW_COPY_AND_ASSIGN(TestCompositorObserver);
298};
299
300}  // namespace
301
302#if defined(OS_WIN)
303// These are disabled on windows as they don't run correctly on the buildbot.
304// Reenable once we move to the real compositor.
305#define MAYBE_Delegate DISABLED_Delegate
306#define MAYBE_Draw DISABLED_Draw
307#define MAYBE_DrawTree DISABLED_DrawTree
308#define MAYBE_Hierarchy DISABLED_Hierarchy
309#define MAYBE_HierarchyNoTexture DISABLED_HierarchyNoTexture
310#define MAYBE_DrawPixels DISABLED_DrawPixels
311#define MAYBE_SetRootLayer DISABLED_SetRootLayer
312#define MAYBE_CompositorObservers DISABLED_CompositorObservers
313#define MAYBE_ModifyHierarchy DISABLED_ModifyHierarchy
314#define MAYBE_Opacity DISABLED_Opacity
315#define MAYBE_ScaleUpDown DISABLED_ScaleUpDown
316#define MAYBE_ScaleReparent DISABLED_ScaleReparent
317#define MAYBE_NoScaleCanvas DISABLED_NoScaleCanvas
318#define MAYBE_AddRemoveThreadedAnimations DISABLED_AddRemoveThreadedAnimations
319#define MAYBE_SwitchCCLayerAnimations DISABLED_SwitchCCLayerAnimations
320#else
321#define MAYBE_Delegate Delegate
322#define MAYBE_Draw Draw
323#define MAYBE_DrawTree DrawTree
324#define MAYBE_Hierarchy Hierarchy
325#define MAYBE_HierarchyNoTexture HierarchyNoTexture
326#define MAYBE_DrawPixels DrawPixels
327#define MAYBE_SetRootLayer SetRootLayer
328#define MAYBE_CompositorObservers CompositorObservers
329#define MAYBE_ModifyHierarchy ModifyHierarchy
330#define MAYBE_Opacity Opacity
331#define MAYBE_ScaleUpDown ScaleUpDown
332#define MAYBE_ScaleReparent ScaleReparent
333#define MAYBE_NoScaleCanvas NoScaleCanvas
334#define MAYBE_AddRemoveThreadedAnimations AddRemoveThreadedAnimations
335#define MAYBE_SwitchCCLayerAnimations SwitchCCLayerAnimations
336#endif
337
338TEST_F(LayerWithRealCompositorTest, MAYBE_Draw) {
339  scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED,
340                                           gfx::Rect(20, 20, 50, 50)));
341  DrawTree(layer.get());
342}
343
344// Create this hierarchy:
345// L1 - red
346// +-- L2 - blue
347// |   +-- L3 - yellow
348// +-- L4 - magenta
349//
350TEST_F(LayerWithRealCompositorTest, MAYBE_Hierarchy) {
351  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
352                                        gfx::Rect(20, 20, 400, 400)));
353  scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
354                                        gfx::Rect(10, 10, 350, 350)));
355  scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
356                                        gfx::Rect(5, 5, 25, 25)));
357  scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
358                                        gfx::Rect(300, 300, 100, 100)));
359
360  l1->Add(l2.get());
361  l1->Add(l4.get());
362  l2->Add(l3.get());
363
364  DrawTree(l1.get());
365}
366
367class LayerWithDelegateTest : public testing::Test, public CompositorDelegate {
368 public:
369  LayerWithDelegateTest() {}
370  virtual ~LayerWithDelegateTest() {}
371
372  // Overridden from testing::Test:
373  virtual void SetUp() OVERRIDE {
374    ui::SetupTestCompositor();
375    compositor_.reset(new Compositor(this, gfx::kNullAcceleratedWidget));
376    compositor_->SetScaleAndSize(1.0f, gfx::Size(1000, 1000));
377  }
378
379  virtual void TearDown() OVERRIDE {
380  }
381
382  Compositor* compositor() { return compositor_.get(); }
383
384  virtual Layer* CreateLayer(LayerType type) {
385    return new Layer(type);
386  }
387
388  Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
389    Layer* layer = new ColoredLayer(color);
390    layer->SetBounds(bounds);
391    return layer;
392  }
393
394  virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
395    Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
396    layer->SetBounds(bounds);
397    return layer;
398  }
399
400  void DrawTree(Layer* root) {
401    compositor()->SetRootLayer(root);
402    Draw();
403  }
404
405  // Invalidates the entire contents of the layer.
406  void SchedulePaintForLayer(Layer* layer) {
407    layer->SchedulePaint(
408        gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
409  }
410
411  // Invokes DrawTree on the compositor.
412  void Draw() {
413    compositor()->ScheduleDraw();
414    WaitForDraw();
415  }
416
417  void WaitForDraw() {
418    DrawWaiterForTest::Wait(compositor());
419  }
420
421  // CompositorDelegate overrides.
422  virtual void ScheduleDraw() OVERRIDE {
423    DCHECK(!ui::Compositor::WasInitializedWithThread());
424    if (compositor_) {
425      base::MessageLoop::current()->PostTask(
426          FROM_HERE, base::Bind(&Compositor::Draw, compositor_->AsWeakPtr()));
427    }
428  }
429
430 private:
431  scoped_ptr<Compositor> compositor_;
432
433  DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
434};
435
436// L1
437//  +-- L2
438TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
439  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
440                                        gfx::Rect(20, 20, 400, 400)));
441  scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
442                                        gfx::Rect(10, 10, 350, 350)));
443  l1->Add(l2.get());
444  DrawTree(l1.get());
445
446  gfx::Point point1_in_l2_coords(5, 5);
447  Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords);
448  gfx::Point point1_in_l1_coords(15, 15);
449  EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords);
450
451  gfx::Point point2_in_l1_coords(5, 5);
452  Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords);
453  gfx::Point point2_in_l2_coords(-5, -5);
454  EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords);
455}
456
457// L1
458//  +-- L2
459//       +-- L3
460TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
461  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
462                                        gfx::Rect(20, 20, 400, 400)));
463  scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
464                                        gfx::Rect(10, 10, 350, 350)));
465  scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
466                                        gfx::Rect(10, 10, 100, 100)));
467  l1->Add(l2.get());
468  l2->Add(l3.get());
469  DrawTree(l1.get());
470
471  gfx::Point point1_in_l3_coords(5, 5);
472  Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords);
473  gfx::Point point1_in_l1_coords(25, 25);
474  EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords);
475
476  gfx::Point point2_in_l1_coords(5, 5);
477  Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords);
478  gfx::Point point2_in_l3_coords(-15, -15);
479  EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords);
480}
481
482TEST_F(LayerWithRealCompositorTest, MAYBE_Delegate) {
483  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorBLACK,
484                                        gfx::Rect(20, 20, 400, 400)));
485  GetCompositor()->SetRootLayer(l1.get());
486  WaitForDraw();
487
488  TestLayerDelegate delegate;
489  l1->set_delegate(&delegate);
490  delegate.AddColor(SK_ColorWHITE);
491  delegate.AddColor(SK_ColorYELLOW);
492  delegate.AddColor(SK_ColorGREEN);
493
494  l1->SchedulePaint(gfx::Rect(0, 0, 400, 400));
495  WaitForDraw();
496
497  EXPECT_EQ(delegate.color_index(), 1);
498  EXPECT_EQ(delegate.paint_size(), l1->bounds().size());
499
500  l1->SchedulePaint(gfx::Rect(10, 10, 200, 200));
501  WaitForDraw();
502  EXPECT_EQ(delegate.color_index(), 2);
503  EXPECT_EQ(delegate.paint_size(), gfx::Size(200, 200));
504
505  l1->SchedulePaint(gfx::Rect(5, 5, 50, 50));
506  WaitForDraw();
507  EXPECT_EQ(delegate.color_index(), 0);
508  EXPECT_EQ(delegate.paint_size(), gfx::Size(50, 50));
509}
510
511TEST_F(LayerWithRealCompositorTest, MAYBE_DrawTree) {
512  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
513                                        gfx::Rect(20, 20, 400, 400)));
514  scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
515                                        gfx::Rect(10, 10, 350, 350)));
516  scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
517                                        gfx::Rect(10, 10, 100, 100)));
518  l1->Add(l2.get());
519  l2->Add(l3.get());
520
521  GetCompositor()->SetRootLayer(l1.get());
522  WaitForDraw();
523
524  DrawTreeLayerDelegate d1;
525  l1->set_delegate(&d1);
526  DrawTreeLayerDelegate d2;
527  l2->set_delegate(&d2);
528  DrawTreeLayerDelegate d3;
529  l3->set_delegate(&d3);
530
531  l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
532  WaitForDraw();
533  EXPECT_FALSE(d1.painted());
534  EXPECT_TRUE(d2.painted());
535  EXPECT_FALSE(d3.painted());
536}
537
538// Tests no-texture Layers.
539// Create this hierarchy:
540// L1 - red
541// +-- L2 - NO TEXTURE
542// |   +-- L3 - yellow
543// +-- L4 - magenta
544//
545TEST_F(LayerWithRealCompositorTest, MAYBE_HierarchyNoTexture) {
546  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
547                                        gfx::Rect(20, 20, 400, 400)));
548  scoped_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350)));
549  scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
550                                        gfx::Rect(5, 5, 25, 25)));
551  scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
552                                        gfx::Rect(300, 300, 100, 100)));
553
554  l1->Add(l2.get());
555  l1->Add(l4.get());
556  l2->Add(l3.get());
557
558  GetCompositor()->SetRootLayer(l1.get());
559  WaitForDraw();
560
561  DrawTreeLayerDelegate d2;
562  l2->set_delegate(&d2);
563  DrawTreeLayerDelegate d3;
564  l3->set_delegate(&d3);
565
566  l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
567  l3->SchedulePaint(gfx::Rect(5, 5, 5, 5));
568  WaitForDraw();
569
570  // |d2| should not have received a paint notification since it has no texture.
571  EXPECT_FALSE(d2.painted());
572  // |d3| should have received a paint notification.
573  EXPECT_TRUE(d3.painted());
574}
575
576class LayerWithNullDelegateTest : public LayerWithDelegateTest {
577 public:
578  LayerWithNullDelegateTest() {}
579  virtual ~LayerWithNullDelegateTest() {}
580
581  // Overridden from testing::Test:
582  virtual void SetUp() OVERRIDE {
583    LayerWithDelegateTest::SetUp();
584    default_layer_delegate_.reset(new NullLayerDelegate());
585  }
586
587  virtual void TearDown() OVERRIDE {
588  }
589
590  virtual Layer* CreateLayer(LayerType type) OVERRIDE {
591    Layer* layer = new Layer(type);
592    layer->set_delegate(default_layer_delegate_.get());
593    return layer;
594  }
595
596  Layer* CreateTextureRootLayer(const gfx::Rect& bounds) {
597    Layer* layer = CreateTextureLayer(bounds);
598    compositor()->SetRootLayer(layer);
599    return layer;
600  }
601
602  Layer* CreateTextureLayer(const gfx::Rect& bounds) {
603    Layer* layer = CreateLayer(LAYER_TEXTURED);
604    layer->SetBounds(bounds);
605    return layer;
606  }
607
608  virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) OVERRIDE {
609    Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
610    layer->SetBounds(bounds);
611    return layer;
612  }
613
614 private:
615  scoped_ptr<NullLayerDelegate> default_layer_delegate_;
616
617  DISALLOW_COPY_AND_ASSIGN(LayerWithNullDelegateTest);
618};
619
620// Various visibile/drawn assertions.
621TEST_F(LayerWithNullDelegateTest, Visibility) {
622  scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
623  scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
624  scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
625  l1->Add(l2.get());
626  l2->Add(l3.get());
627
628  NullLayerDelegate delegate;
629  l1->set_delegate(&delegate);
630  l2->set_delegate(&delegate);
631  l3->set_delegate(&delegate);
632
633  // Layers should initially be drawn.
634  EXPECT_TRUE(l1->IsDrawn());
635  EXPECT_TRUE(l2->IsDrawn());
636  EXPECT_TRUE(l3->IsDrawn());
637  EXPECT_TRUE(l1->cc_layer()->DrawsContent());
638  EXPECT_TRUE(l2->cc_layer()->DrawsContent());
639  EXPECT_TRUE(l3->cc_layer()->DrawsContent());
640
641  compositor()->SetRootLayer(l1.get());
642
643  Draw();
644
645  l1->SetVisible(false);
646  EXPECT_FALSE(l1->IsDrawn());
647  EXPECT_FALSE(l2->IsDrawn());
648  EXPECT_FALSE(l3->IsDrawn());
649  EXPECT_FALSE(l1->cc_layer()->DrawsContent());
650  EXPECT_FALSE(l2->cc_layer()->DrawsContent());
651  EXPECT_FALSE(l3->cc_layer()->DrawsContent());
652
653  l3->SetVisible(false);
654  EXPECT_FALSE(l1->IsDrawn());
655  EXPECT_FALSE(l2->IsDrawn());
656  EXPECT_FALSE(l3->IsDrawn());
657  EXPECT_FALSE(l1->cc_layer()->DrawsContent());
658  EXPECT_FALSE(l2->cc_layer()->DrawsContent());
659  EXPECT_FALSE(l3->cc_layer()->DrawsContent());
660
661  l1->SetVisible(true);
662  EXPECT_TRUE(l1->IsDrawn());
663  EXPECT_TRUE(l2->IsDrawn());
664  EXPECT_FALSE(l3->IsDrawn());
665  EXPECT_TRUE(l1->cc_layer()->DrawsContent());
666  EXPECT_TRUE(l2->cc_layer()->DrawsContent());
667  EXPECT_FALSE(l3->cc_layer()->DrawsContent());
668}
669
670// Checks that stacking-related methods behave as advertised.
671TEST_F(LayerWithNullDelegateTest, Stacking) {
672  scoped_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
673  scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
674  scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
675  scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
676  l1->set_name("1");
677  l2->set_name("2");
678  l3->set_name("3");
679  root->Add(l3.get());
680  root->Add(l2.get());
681  root->Add(l1.get());
682
683  // Layers' children are stored in bottom-to-top order.
684  EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
685
686  root->StackAtTop(l3.get());
687  EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
688
689  root->StackAtTop(l1.get());
690  EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
691
692  root->StackAtTop(l1.get());
693  EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
694
695  root->StackAbove(l2.get(), l3.get());
696  EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
697
698  root->StackAbove(l1.get(), l3.get());
699  EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
700
701  root->StackAbove(l2.get(), l1.get());
702  EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
703
704  root->StackAtBottom(l2.get());
705  EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
706
707  root->StackAtBottom(l3.get());
708  EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
709
710  root->StackAtBottom(l3.get());
711  EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
712
713  root->StackBelow(l2.get(), l3.get());
714  EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
715
716  root->StackBelow(l1.get(), l3.get());
717  EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
718
719  root->StackBelow(l3.get(), l2.get());
720  EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
721
722  root->StackBelow(l3.get(), l2.get());
723  EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
724
725  root->StackBelow(l3.get(), l1.get());
726  EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
727}
728
729// Verifies SetBounds triggers the appropriate painting/drawing.
730TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
731  scoped_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
732  compositor()->SetRootLayer(l1.get());
733
734  Draw();
735
736  l1->SetBounds(gfx::Rect(5, 5, 200, 200));
737
738  // The CompositorDelegate (us) should have been told to draw for a move.
739  WaitForDraw();
740
741  l1->SetBounds(gfx::Rect(5, 5, 100, 100));
742
743  // The CompositorDelegate (us) should have been told to draw for a resize.
744  WaitForDraw();
745}
746
747// Checks that pixels are actually drawn to the screen with a read back.
748// Currently disabled on all platforms, see http://crbug.com/148709.
749TEST_F(LayerWithRealCompositorTest, MAYBE_DrawPixels) {
750  scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED,
751                                           gfx::Rect(0, 0, 500, 500)));
752  scoped_ptr<Layer> layer2(CreateColorLayer(SK_ColorBLUE,
753                                            gfx::Rect(0, 0, 500, 10)));
754
755  layer->Add(layer2.get());
756
757  DrawTree(layer.get());
758
759  SkBitmap bitmap;
760  gfx::Size size = GetCompositor()->size();
761  ASSERT_TRUE(GetCompositor()->ReadPixels(&bitmap,
762                                          gfx::Rect(0, 10,
763                                          size.width(), size.height() - 10)));
764  ASSERT_FALSE(bitmap.empty());
765
766  SkAutoLockPixels lock(bitmap);
767  bool is_all_red = true;
768  for (int x = 0; is_all_red && x < 500; x++)
769    for (int y = 0; is_all_red && y < 490; y++)
770      is_all_red = is_all_red && (bitmap.getColor(x, y) == SK_ColorRED);
771
772  EXPECT_TRUE(is_all_red);
773}
774
775// Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
776TEST_F(LayerWithRealCompositorTest, MAYBE_SetRootLayer) {
777  Compositor* compositor = GetCompositor();
778  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
779                                        gfx::Rect(20, 20, 400, 400)));
780  scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
781                                        gfx::Rect(10, 10, 350, 350)));
782
783  EXPECT_EQ(NULL, l1->GetCompositor());
784  EXPECT_EQ(NULL, l2->GetCompositor());
785
786  compositor->SetRootLayer(l1.get());
787  EXPECT_EQ(compositor, l1->GetCompositor());
788
789  l1->Add(l2.get());
790  EXPECT_EQ(compositor, l2->GetCompositor());
791
792  l1->Remove(l2.get());
793  EXPECT_EQ(NULL, l2->GetCompositor());
794
795  l1->Add(l2.get());
796  EXPECT_EQ(compositor, l2->GetCompositor());
797
798  compositor->SetRootLayer(NULL);
799  EXPECT_EQ(NULL, l1->GetCompositor());
800  EXPECT_EQ(NULL, l2->GetCompositor());
801}
802
803// Checks that compositor observers are notified when:
804// - DrawTree is called,
805// - After ScheduleDraw is called, or
806// - Whenever SetBounds, SetOpacity or SetTransform are called.
807// TODO(vollick): could be reorganized into compositor_unittest.cc
808TEST_F(LayerWithRealCompositorTest, MAYBE_CompositorObservers) {
809  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
810                                        gfx::Rect(20, 20, 400, 400)));
811  scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
812                                        gfx::Rect(10, 10, 350, 350)));
813  l1->Add(l2.get());
814  TestCompositorObserver observer;
815  GetCompositor()->AddObserver(&observer);
816
817  // Explicitly called DrawTree should cause the observers to be notified.
818  // NOTE: this call to DrawTree sets l1 to be the compositor's root layer.
819  DrawTree(l1.get());
820  EXPECT_TRUE(observer.notified());
821
822  // As should scheduling a draw and waiting.
823  observer.Reset();
824  l1->ScheduleDraw();
825  WaitForDraw();
826  EXPECT_TRUE(observer.notified());
827
828  // Moving, but not resizing, a layer should alert the observers.
829  observer.Reset();
830  l2->SetBounds(gfx::Rect(0, 0, 350, 350));
831  WaitForDraw();
832  EXPECT_TRUE(observer.notified());
833
834  // So should resizing a layer.
835  observer.Reset();
836  l2->SetBounds(gfx::Rect(0, 0, 400, 400));
837  WaitForDraw();
838  EXPECT_TRUE(observer.notified());
839
840  // Opacity changes should alert the observers.
841  observer.Reset();
842  l2->SetOpacity(0.5f);
843  WaitForDraw();
844  EXPECT_TRUE(observer.notified());
845
846  // So should setting the opacity back.
847  observer.Reset();
848  l2->SetOpacity(1.0f);
849  WaitForDraw();
850  EXPECT_TRUE(observer.notified());
851
852  // Setting the transform of a layer should alert the observers.
853  observer.Reset();
854  gfx::Transform transform;
855  transform.Translate(200.0, 200.0);
856  transform.Rotate(90.0);
857  transform.Translate(-200.0, -200.0);
858  l2->SetTransform(transform);
859  WaitForDraw();
860  EXPECT_TRUE(observer.notified());
861
862  // A change resulting in an aborted swap buffer should alert the observer
863  // and also signal an abort.
864  observer.Reset();
865  l2->SetOpacity(0.1f);
866  GetCompositor()->OnSwapBuffersAborted();
867  WaitForDraw();
868  EXPECT_TRUE(observer.notified());
869  EXPECT_TRUE(observer.aborted());
870
871  GetCompositor()->RemoveObserver(&observer);
872
873  // Opacity changes should no longer alert the removed observer.
874  observer.Reset();
875  l2->SetOpacity(0.5f);
876  WaitForDraw();
877
878  EXPECT_FALSE(observer.notified());
879}
880
881// Checks that modifying the hierarchy correctly affects final composite.
882TEST_F(LayerWithRealCompositorTest, MAYBE_ModifyHierarchy) {
883  GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
884
885  // l0
886  //  +-l11
887  //  | +-l21
888  //  +-l12
889  scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
890                                        gfx::Rect(0, 0, 50, 50)));
891  scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
892                                         gfx::Rect(0, 0, 25, 25)));
893  scoped_ptr<Layer> l21(CreateColorLayer(SK_ColorMAGENTA,
894                                         gfx::Rect(0, 0, 15, 15)));
895  scoped_ptr<Layer> l12(CreateColorLayer(SK_ColorBLUE,
896                                         gfx::Rect(10, 10, 25, 25)));
897
898  base::FilePath ref_img1 =
899      test_data_directory().AppendASCII("ModifyHierarchy1.png");
900  base::FilePath ref_img2 =
901      test_data_directory().AppendASCII("ModifyHierarchy2.png");
902  SkBitmap bitmap;
903
904  l0->Add(l11.get());
905  l11->Add(l21.get());
906  l0->Add(l12.get());
907  DrawTree(l0.get());
908  ASSERT_TRUE(ReadPixels(&bitmap));
909  ASSERT_FALSE(bitmap.empty());
910  // WritePNGFile(bitmap, ref_img1);
911  EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
912
913  l0->StackAtTop(l11.get());
914  DrawTree(l0.get());
915  ASSERT_TRUE(ReadPixels(&bitmap));
916  ASSERT_FALSE(bitmap.empty());
917  // WritePNGFile(bitmap, ref_img2);
918  EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
919
920  // l11 is already at the front, should have no effect.
921  l0->StackAtTop(l11.get());
922  DrawTree(l0.get());
923  ASSERT_TRUE(ReadPixels(&bitmap));
924  ASSERT_FALSE(bitmap.empty());
925  EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
926
927  // l11 is already at the front, should have no effect.
928  l0->StackAbove(l11.get(), l12.get());
929  DrawTree(l0.get());
930  ASSERT_TRUE(ReadPixels(&bitmap));
931  ASSERT_FALSE(bitmap.empty());
932  EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
933
934  // should restore to original configuration
935  l0->StackAbove(l12.get(), l11.get());
936  DrawTree(l0.get());
937  ASSERT_TRUE(ReadPixels(&bitmap));
938  ASSERT_FALSE(bitmap.empty());
939  EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
940}
941
942// Opacity is rendered correctly.
943// Checks that modifying the hierarchy correctly affects final composite.
944TEST_F(LayerWithRealCompositorTest, MAYBE_Opacity) {
945  GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
946
947  // l0
948  //  +-l11
949  scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
950                                        gfx::Rect(0, 0, 50, 50)));
951  scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
952                                         gfx::Rect(0, 0, 25, 25)));
953
954  base::FilePath ref_img = test_data_directory().AppendASCII("Opacity.png");
955
956  l11->SetOpacity(0.75);
957  l0->Add(l11.get());
958  DrawTree(l0.get());
959  SkBitmap bitmap;
960  ASSERT_TRUE(ReadPixels(&bitmap));
961  ASSERT_FALSE(bitmap.empty());
962  // WritePNGFile(bitmap, ref_img);
963  EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img, cc::ExactPixelComparator(true)));
964}
965
966namespace {
967
968class SchedulePaintLayerDelegate : public LayerDelegate {
969 public:
970  SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
971
972  virtual ~SchedulePaintLayerDelegate() {}
973
974  void set_layer(Layer* layer) {
975    layer_ = layer;
976    layer_->set_delegate(this);
977  }
978
979  void SetSchedulePaintRect(const gfx::Rect& rect) {
980    schedule_paint_rect_ = rect;
981  }
982
983  int GetPaintCountAndClear() {
984    int value = paint_count_;
985    paint_count_ = 0;
986    return value;
987  }
988
989  const gfx::RectF& last_clip_rect() const { return last_clip_rect_; }
990
991 private:
992  // Overridden from LayerDelegate:
993  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
994    paint_count_++;
995    if (!schedule_paint_rect_.IsEmpty()) {
996      layer_->SchedulePaint(schedule_paint_rect_);
997      schedule_paint_rect_ = gfx::Rect();
998    }
999    SkRect sk_clip_rect;
1000    if (canvas->sk_canvas()->getClipBounds(&sk_clip_rect))
1001      last_clip_rect_ = gfx::SkRectToRectF(sk_clip_rect);
1002  }
1003
1004  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
1005  }
1006
1007  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
1008    return base::Closure();
1009  }
1010
1011  int paint_count_;
1012  Layer* layer_;
1013  gfx::Rect schedule_paint_rect_;
1014  gfx::RectF last_clip_rect_;
1015
1016  DISALLOW_COPY_AND_ASSIGN(SchedulePaintLayerDelegate);
1017};
1018
1019}  // namespace
1020
1021// Verifies that if SchedulePaint is invoked during painting the layer is still
1022// marked dirty.
1023TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
1024  scoped_ptr<Layer> root(CreateColorLayer(SK_ColorRED,
1025                                          gfx::Rect(0, 0, 500, 500)));
1026  SchedulePaintLayerDelegate child_delegate;
1027  scoped_ptr<Layer> child(CreateColorLayer(SK_ColorBLUE,
1028                                           gfx::Rect(0, 0, 200, 200)));
1029  child_delegate.set_layer(child.get());
1030
1031  root->Add(child.get());
1032
1033  SchedulePaintForLayer(root.get());
1034  DrawTree(root.get());
1035  child->SchedulePaint(gfx::Rect(0, 0, 20, 20));
1036  child_delegate.GetPaintCountAndClear();
1037
1038  // Set a rect so that when OnPaintLayer() is invoked SchedulePaint is invoked
1039  // again.
1040  child_delegate.SetSchedulePaintRect(gfx::Rect(10, 10, 30, 30));
1041  WaitForDraw();
1042  // |child| should have been painted once.
1043  EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1044
1045  // Because SchedulePaint() was invoked from OnPaintLayer() |child| should
1046  // still need to be painted.
1047  WaitForDraw();
1048  EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1049  EXPECT_TRUE(child_delegate.last_clip_rect().Contains(
1050                  gfx::Rect(10, 10, 30, 30)));
1051}
1052
1053TEST_F(LayerWithRealCompositorTest, MAYBE_ScaleUpDown) {
1054  scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1055                                          gfx::Rect(10, 20, 200, 220)));
1056  TestLayerDelegate root_delegate;
1057  root_delegate.AddColor(SK_ColorWHITE);
1058  root->set_delegate(&root_delegate);
1059
1060  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1061                                        gfx::Rect(10, 20, 140, 180)));
1062  TestLayerDelegate l1_delegate;
1063  l1_delegate.AddColor(SK_ColorWHITE);
1064  l1->set_delegate(&l1_delegate);
1065
1066  GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1067  GetCompositor()->SetRootLayer(root.get());
1068  root->Add(l1.get());
1069  WaitForDraw();
1070
1071  EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1072  EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1073  gfx::Size size_in_pixel = root->cc_layer()->bounds();
1074  EXPECT_EQ("200x220", size_in_pixel.ToString());
1075  size_in_pixel = l1->cc_layer()->bounds();
1076  EXPECT_EQ("140x180", size_in_pixel.ToString());
1077  // No scale change, so no scale notification.
1078  EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1079  EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1080
1081  EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1082  EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1083
1084  // Scale up to 2.0. Changing scale doesn't change the bounds in DIP.
1085  GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1086  EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1087  EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1088  // Pixel size must have been scaled up.
1089  size_in_pixel = root->cc_layer()->bounds();
1090  EXPECT_EQ("400x440", size_in_pixel.ToString());
1091  size_in_pixel = l1->cc_layer()->bounds();
1092  EXPECT_EQ("280x360", size_in_pixel.ToString());
1093  // New scale factor must have been notified.
1094  EXPECT_EQ(2.0f, root_delegate.device_scale_factor());
1095  EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1096
1097  // Canvas size must have been scaled down up.
1098  WaitForDraw();
1099  EXPECT_EQ("400x440", root_delegate.paint_size().ToString());
1100  EXPECT_EQ("2.0 2.0", root_delegate.ToScaleString());
1101  EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1102  EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1103
1104  // Scale down back to 1.0f.
1105  GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1106  EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1107  EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1108  // Pixel size must have been scaled down.
1109  size_in_pixel = root->cc_layer()->bounds();
1110  EXPECT_EQ("200x220", size_in_pixel.ToString());
1111  size_in_pixel = l1->cc_layer()->bounds();
1112  EXPECT_EQ("140x180", size_in_pixel.ToString());
1113  // New scale factor must have been notified.
1114  EXPECT_EQ(1.0f, root_delegate.device_scale_factor());
1115  EXPECT_EQ(1.0f, l1_delegate.device_scale_factor());
1116
1117  // Canvas size must have been scaled down too.
1118  WaitForDraw();
1119  EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1120  EXPECT_EQ("1.0 1.0", root_delegate.ToScaleString());
1121  EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1122  EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1123
1124  root_delegate.reset();
1125  l1_delegate.reset();
1126  // Just changing the size shouldn't notify the scale change nor
1127  // trigger repaint.
1128  GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(1000, 1000));
1129  // No scale change, so no scale notification.
1130  EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1131  EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1132  WaitForDraw();
1133  EXPECT_EQ("0x0", root_delegate.paint_size().ToString());
1134  EXPECT_EQ("0.0 0.0", root_delegate.ToScaleString());
1135  EXPECT_EQ("0x0", l1_delegate.paint_size().ToString());
1136  EXPECT_EQ("0.0 0.0", l1_delegate.ToScaleString());
1137}
1138
1139TEST_F(LayerWithRealCompositorTest, MAYBE_ScaleReparent) {
1140  scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1141                                          gfx::Rect(10, 20, 200, 220)));
1142  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1143                                        gfx::Rect(10, 20, 140, 180)));
1144  TestLayerDelegate l1_delegate;
1145  l1_delegate.AddColor(SK_ColorWHITE);
1146  l1->set_delegate(&l1_delegate);
1147
1148  GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1149  GetCompositor()->SetRootLayer(root.get());
1150  WaitForDraw();
1151
1152  root->Add(l1.get());
1153  EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1154  gfx::Size size_in_pixel = l1->cc_layer()->bounds();
1155  EXPECT_EQ("140x180", size_in_pixel.ToString());
1156  EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1157
1158  WaitForDraw();
1159  EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1160  EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1161
1162  // Remove l1 from root and change the scale.
1163  root->Remove(l1.get());
1164  EXPECT_EQ(NULL, l1->parent());
1165  EXPECT_EQ(NULL, l1->GetCompositor());
1166  GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1167  // Sanity check on root and l1.
1168  EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1169  size_in_pixel = l1->cc_layer()->bounds();
1170  EXPECT_EQ("140x180", size_in_pixel.ToString());
1171
1172
1173  root->Add(l1.get());
1174  EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1175  size_in_pixel = l1->cc_layer()->bounds();
1176  EXPECT_EQ("280x360", size_in_pixel.ToString());
1177  EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1178  WaitForDraw();
1179  EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1180  EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1181}
1182
1183// Tests layer::set_scale_content(false).
1184TEST_F(LayerWithRealCompositorTest, MAYBE_NoScaleCanvas) {
1185  scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1186                                          gfx::Rect(10, 20, 200, 220)));
1187  scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1188                                        gfx::Rect(10, 20, 140, 180)));
1189  l1->set_scale_content(false);
1190  root->Add(l1.get());
1191  TestLayerDelegate l1_delegate;
1192  l1_delegate.AddColor(SK_ColorWHITE);
1193  l1->set_delegate(&l1_delegate);
1194
1195  GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1196  GetCompositor()->SetRootLayer(root.get());
1197  // Scale factor change is notified regardless of scale_content flag.
1198  EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1199
1200  WaitForDraw();
1201  EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1202  EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1203}
1204
1205// Verifies that when changing bounds on a layer that is invisible, and then
1206// made visible, the right thing happens:
1207// - if just a move, then no painting should happen.
1208// - if a resize, the layer should be repainted.
1209TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
1210  scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1211
1212  scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1213  child->SetBounds(gfx::Rect(0, 0, 500, 500));
1214  DrawTreeLayerDelegate delegate;
1215  child->set_delegate(&delegate);
1216  root->Add(child.get());
1217
1218  // Paint once for initial damage.
1219  child->SetVisible(true);
1220  DrawTree(root.get());
1221
1222  // Reset into invisible state.
1223  child->SetVisible(false);
1224  DrawTree(root.get());
1225  delegate.Reset();
1226
1227  // Move layer.
1228  child->SetBounds(gfx::Rect(200, 200, 500, 500));
1229  child->SetVisible(true);
1230  WaitForDraw();
1231  DrawTree(root.get());
1232  EXPECT_FALSE(delegate.painted());
1233
1234  // Reset into invisible state.
1235  child->SetVisible(false);
1236  DrawTree(root.get());
1237  delegate.Reset();
1238
1239  // Resize layer.
1240  child->SetBounds(gfx::Rect(200, 200, 400, 400));
1241  child->SetVisible(true);
1242  WaitForDraw();
1243  DrawTree(root.get());
1244  EXPECT_TRUE(delegate.painted());
1245}
1246
1247static scoped_ptr<cc::DelegatedFrameData> MakeFrameData(gfx::Size size) {
1248  scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
1249  scoped_ptr<cc::RenderPass> render_pass(cc::RenderPass::Create());
1250  render_pass->SetNew(cc::RenderPass::Id(1, 1),
1251                      gfx::Rect(size),
1252                      gfx::RectF(),
1253                      gfx::Transform());
1254  frame_data->render_pass_list.push_back(render_pass.Pass());
1255  return frame_data.Pass();
1256}
1257
1258TEST_F(LayerWithDelegateTest, DelegatedLayer) {
1259  scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1260
1261  scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1262
1263  child->SetBounds(gfx::Rect(0, 0, 10, 10));
1264  child->SetVisible(true);
1265  root->Add(child.get());
1266  DrawTree(root.get());
1267
1268  // Content matches layer size.
1269  child->SetDelegatedFrame(MakeFrameData(gfx::Size(10, 10)), gfx::Size(10, 10));
1270  EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1271            gfx::Size(10, 10).ToString());
1272
1273  // Content larger than layer.
1274  child->SetBounds(gfx::Rect(0, 0, 5, 5));
1275  EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1276            gfx::Size(5, 5).ToString());
1277
1278  // Content smaller than layer.
1279  child->SetBounds(gfx::Rect(0, 0, 10, 10));
1280  child->SetDelegatedFrame(MakeFrameData(gfx::Size(5, 5)), gfx::Size(5, 5));
1281  EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1282            gfx::Size(5, 5).ToString());
1283
1284  // Hi-DPI content on low-DPI layer.
1285  child->SetDelegatedFrame(MakeFrameData(gfx::Size(20, 20)), gfx::Size(10, 10));
1286  EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1287            gfx::Size(10, 10).ToString());
1288
1289  // Hi-DPI content on hi-DPI layer.
1290  compositor()->SetScaleAndSize(2.f, gfx::Size(1000, 1000));
1291  EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1292            gfx::Size(20, 20).ToString());
1293
1294  // Low-DPI content on hi-DPI layer.
1295  child->SetDelegatedFrame(MakeFrameData(gfx::Size(10, 10)), gfx::Size(10, 10));
1296  EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1297            gfx::Size(20, 20).ToString());
1298}
1299
1300// Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation.
1301TEST_F(LayerWithRealCompositorTest, MAYBE_AddRemoveThreadedAnimations) {
1302  scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1303  scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1304  scoped_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED));
1305
1306  l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1307  l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1308
1309  EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1310
1311  // Trigger a threaded animation.
1312  l1->SetOpacity(0.5f);
1313
1314  EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1315
1316  // Ensure we can remove a pending threaded animation.
1317  l1->GetAnimator()->StopAnimating();
1318
1319  EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1320
1321  // Trigger another threaded animation.
1322  l1->SetOpacity(0.2f);
1323
1324  EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1325
1326  root->Add(l1.get());
1327  GetCompositor()->SetRootLayer(root.get());
1328
1329  // Now that l1 is part of a tree, it should have dispatched the pending
1330  // animation.
1331  EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1332
1333  // Ensure that l1 no longer holds on to animations.
1334  l1->SetOpacity(0.1f);
1335  EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1336
1337  // Ensure that adding a layer to an existing tree causes its pending
1338  // animations to get dispatched.
1339  l2->SetOpacity(0.5f);
1340  EXPECT_TRUE(l2->HasPendingThreadedAnimations());
1341
1342  l1->Add(l2.get());
1343  EXPECT_FALSE(l2->HasPendingThreadedAnimations());
1344}
1345
1346// Tests that in-progress threaded animations complete when a Layer's
1347// cc::Layer changes.
1348TEST_F(LayerWithRealCompositorTest, MAYBE_SwitchCCLayerAnimations) {
1349  scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1350  scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1351  GetCompositor()->SetRootLayer(root.get());
1352  root->Add(l1.get());
1353
1354  l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1355
1356  EXPECT_FLOAT_EQ(l1->opacity(), 1.0f);
1357
1358  // Trigger a threaded animation.
1359  l1->SetOpacity(0.5f);
1360
1361  // Change l1's cc::Layer.
1362  l1->SwitchCCLayerForTest();
1363
1364  // Ensure that the opacity animation completed.
1365  EXPECT_FLOAT_EQ(l1->opacity(), 0.5f);
1366}
1367
1368}  // namespace ui
1369