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