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