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