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