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