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