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