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