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