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