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