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