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