| OLD | NEW |
| (Empty) |
| 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/files/file_path.h" | |
| 10 #include "base/files/file_util.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 | |
| 39 using cc::MatchesPNGFile; | |
| 40 | |
| 41 namespace ui { | |
| 42 | |
| 43 namespace { | |
| 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 | |
| 54 class 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 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 | |
| 83 class 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. | |
| 210 class 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->DrawColor(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. | |
| 271 class 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 canvas->DrawColor(SK_ColorWHITE); | |
| 287 } | |
| 288 virtual void OnDelegatedFrameDamage( | |
| 289 const gfx::Rect& damage_rect_in_dip) override {} | |
| 290 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) override { | |
| 291 } | |
| 292 virtual base::Closure PrepareForLayerBoundsChange() override { | |
| 293 return base::Closure(); | |
| 294 } | |
| 295 | |
| 296 bool painted_; | |
| 297 | |
| 298 DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate); | |
| 299 }; | |
| 300 | |
| 301 // The simplest possible layer delegate. Does nothing. | |
| 302 class NullLayerDelegate : public LayerDelegate { | |
| 303 public: | |
| 304 NullLayerDelegate() {} | |
| 305 virtual ~NullLayerDelegate() {} | |
| 306 | |
| 307 private: | |
| 308 // Overridden from LayerDelegate: | |
| 309 virtual void OnPaintLayer(gfx::Canvas* canvas) override {} | |
| 310 virtual void OnDelegatedFrameDamage( | |
| 311 const gfx::Rect& damage_rect_in_dip) override {} | |
| 312 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) override {} | |
| 313 virtual base::Closure PrepareForLayerBoundsChange() override { | |
| 314 return base::Closure(); | |
| 315 } | |
| 316 | |
| 317 DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate); | |
| 318 }; | |
| 319 | |
| 320 // Remembers if it has been notified. | |
| 321 class TestCompositorObserver : public CompositorObserver { | |
| 322 public: | |
| 323 TestCompositorObserver() | |
| 324 : committed_(false), started_(false), ended_(false), aborted_(false) {} | |
| 325 | |
| 326 bool committed() const { return committed_; } | |
| 327 bool notified() const { return started_ && ended_; } | |
| 328 bool aborted() const { return aborted_; } | |
| 329 | |
| 330 void Reset() { | |
| 331 committed_ = false; | |
| 332 started_ = false; | |
| 333 ended_ = false; | |
| 334 aborted_ = false; | |
| 335 } | |
| 336 | |
| 337 private: | |
| 338 virtual void OnCompositingDidCommit(Compositor* compositor) override { | |
| 339 committed_ = true; | |
| 340 } | |
| 341 | |
| 342 virtual void OnCompositingStarted(Compositor* compositor, | |
| 343 base::TimeTicks start_time) override { | |
| 344 started_ = true; | |
| 345 } | |
| 346 | |
| 347 virtual void OnCompositingEnded(Compositor* compositor) override { | |
| 348 ended_ = true; | |
| 349 } | |
| 350 | |
| 351 virtual void OnCompositingAborted(Compositor* compositor) override { | |
| 352 aborted_ = true; | |
| 353 } | |
| 354 | |
| 355 virtual void OnCompositingLockStateChanged(Compositor* compositor) override { | |
| 356 } | |
| 357 | |
| 358 bool committed_; | |
| 359 bool started_; | |
| 360 bool ended_; | |
| 361 bool aborted_; | |
| 362 | |
| 363 DISALLOW_COPY_AND_ASSIGN(TestCompositorObserver); | |
| 364 }; | |
| 365 | |
| 366 } // namespace | |
| 367 | |
| 368 TEST_F(LayerWithRealCompositorTest, Draw) { | |
| 369 scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED, | |
| 370 gfx::Rect(20, 20, 50, 50))); | |
| 371 DrawTree(layer.get()); | |
| 372 } | |
| 373 | |
| 374 // Create this hierarchy: | |
| 375 // L1 - red | |
| 376 // +-- L2 - blue | |
| 377 // | +-- L3 - yellow | |
| 378 // +-- L4 - magenta | |
| 379 // | |
| 380 TEST_F(LayerWithRealCompositorTest, Hierarchy) { | |
| 381 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, | |
| 382 gfx::Rect(20, 20, 400, 400))); | |
| 383 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE, | |
| 384 gfx::Rect(10, 10, 350, 350))); | |
| 385 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW, | |
| 386 gfx::Rect(5, 5, 25, 25))); | |
| 387 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA, | |
| 388 gfx::Rect(300, 300, 100, 100))); | |
| 389 | |
| 390 l1->Add(l2.get()); | |
| 391 l1->Add(l4.get()); | |
| 392 l2->Add(l3.get()); | |
| 393 | |
| 394 DrawTree(l1.get()); | |
| 395 } | |
| 396 | |
| 397 class LayerWithDelegateTest : public testing::Test { | |
| 398 public: | |
| 399 LayerWithDelegateTest() {} | |
| 400 virtual ~LayerWithDelegateTest() {} | |
| 401 | |
| 402 // Overridden from testing::Test: | |
| 403 virtual void SetUp() override { | |
| 404 bool enable_pixel_output = false; | |
| 405 ui::ContextFactory* context_factory = | |
| 406 InitializeContextFactoryForTests(enable_pixel_output); | |
| 407 | |
| 408 const gfx::Rect host_bounds(1000, 1000); | |
| 409 compositor_host_.reset(TestCompositorHost::Create(host_bounds, | |
| 410 context_factory)); | |
| 411 compositor_host_->Show(); | |
| 412 } | |
| 413 | |
| 414 virtual void TearDown() override { | |
| 415 compositor_host_.reset(); | |
| 416 TerminateContextFactoryForTests(); | |
| 417 } | |
| 418 | |
| 419 Compositor* compositor() { return compositor_host_->GetCompositor(); } | |
| 420 | |
| 421 virtual Layer* CreateLayer(LayerType type) { | |
| 422 return new Layer(type); | |
| 423 } | |
| 424 | |
| 425 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) { | |
| 426 Layer* layer = new ColoredLayer(color); | |
| 427 layer->SetBounds(bounds); | |
| 428 return layer; | |
| 429 } | |
| 430 | |
| 431 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) { | |
| 432 Layer* layer = CreateLayer(LAYER_NOT_DRAWN); | |
| 433 layer->SetBounds(bounds); | |
| 434 return layer; | |
| 435 } | |
| 436 | |
| 437 void DrawTree(Layer* root) { | |
| 438 compositor()->SetRootLayer(root); | |
| 439 Draw(); | |
| 440 } | |
| 441 | |
| 442 // Invalidates the entire contents of the layer. | |
| 443 void SchedulePaintForLayer(Layer* layer) { | |
| 444 layer->SchedulePaint( | |
| 445 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height())); | |
| 446 } | |
| 447 | |
| 448 // Invokes DrawTree on the compositor. | |
| 449 void Draw() { | |
| 450 compositor()->ScheduleDraw(); | |
| 451 WaitForDraw(); | |
| 452 } | |
| 453 | |
| 454 void WaitForDraw() { DrawWaiterForTest::Wait(compositor()); } | |
| 455 | |
| 456 void WaitForCommit() { | |
| 457 DrawWaiterForTest::WaitForCommit(compositor()); | |
| 458 } | |
| 459 | |
| 460 private: | |
| 461 scoped_ptr<TestCompositorHost> compositor_host_; | |
| 462 | |
| 463 DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest); | |
| 464 }; | |
| 465 | |
| 466 // L1 | |
| 467 // +-- L2 | |
| 468 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) { | |
| 469 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, | |
| 470 gfx::Rect(20, 20, 400, 400))); | |
| 471 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE, | |
| 472 gfx::Rect(10, 10, 350, 350))); | |
| 473 l1->Add(l2.get()); | |
| 474 DrawTree(l1.get()); | |
| 475 | |
| 476 gfx::Point point1_in_l2_coords(5, 5); | |
| 477 Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords); | |
| 478 gfx::Point point1_in_l1_coords(15, 15); | |
| 479 EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords); | |
| 480 | |
| 481 gfx::Point point2_in_l1_coords(5, 5); | |
| 482 Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords); | |
| 483 gfx::Point point2_in_l2_coords(-5, -5); | |
| 484 EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords); | |
| 485 } | |
| 486 | |
| 487 // L1 | |
| 488 // +-- L2 | |
| 489 // +-- L3 | |
| 490 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) { | |
| 491 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, | |
| 492 gfx::Rect(20, 20, 400, 400))); | |
| 493 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE, | |
| 494 gfx::Rect(10, 10, 350, 350))); | |
| 495 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW, | |
| 496 gfx::Rect(10, 10, 100, 100))); | |
| 497 l1->Add(l2.get()); | |
| 498 l2->Add(l3.get()); | |
| 499 DrawTree(l1.get()); | |
| 500 | |
| 501 gfx::Point point1_in_l3_coords(5, 5); | |
| 502 Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords); | |
| 503 gfx::Point point1_in_l1_coords(25, 25); | |
| 504 EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords); | |
| 505 | |
| 506 gfx::Point point2_in_l1_coords(5, 5); | |
| 507 Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords); | |
| 508 gfx::Point point2_in_l3_coords(-15, -15); | |
| 509 EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords); | |
| 510 } | |
| 511 | |
| 512 TEST_F(LayerWithRealCompositorTest, Delegate) { | |
| 513 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorBLACK, | |
| 514 gfx::Rect(20, 20, 400, 400))); | |
| 515 GetCompositor()->SetRootLayer(l1.get()); | |
| 516 WaitForDraw(); | |
| 517 | |
| 518 TestLayerDelegate delegate; | |
| 519 l1->set_delegate(&delegate); | |
| 520 delegate.AddColor(SK_ColorWHITE); | |
| 521 delegate.AddColor(SK_ColorYELLOW); | |
| 522 delegate.AddColor(SK_ColorGREEN); | |
| 523 | |
| 524 l1->SchedulePaint(gfx::Rect(0, 0, 400, 400)); | |
| 525 WaitForDraw(); | |
| 526 | |
| 527 EXPECT_EQ(delegate.color_index(), 1); | |
| 528 EXPECT_EQ(delegate.paint_size(), l1->bounds().size()); | |
| 529 | |
| 530 l1->SchedulePaint(gfx::Rect(10, 10, 200, 200)); | |
| 531 WaitForDraw(); | |
| 532 EXPECT_EQ(delegate.color_index(), 2); | |
| 533 EXPECT_EQ(delegate.paint_size(), gfx::Size(200, 200)); | |
| 534 | |
| 535 l1->SchedulePaint(gfx::Rect(5, 5, 50, 50)); | |
| 536 WaitForDraw(); | |
| 537 EXPECT_EQ(delegate.color_index(), 0); | |
| 538 EXPECT_EQ(delegate.paint_size(), gfx::Size(50, 50)); | |
| 539 } | |
| 540 | |
| 541 TEST_F(LayerWithRealCompositorTest, DrawTree) { | |
| 542 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, | |
| 543 gfx::Rect(20, 20, 400, 400))); | |
| 544 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE, | |
| 545 gfx::Rect(10, 10, 350, 350))); | |
| 546 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW, | |
| 547 gfx::Rect(10, 10, 100, 100))); | |
| 548 l1->Add(l2.get()); | |
| 549 l2->Add(l3.get()); | |
| 550 | |
| 551 GetCompositor()->SetRootLayer(l1.get()); | |
| 552 WaitForDraw(); | |
| 553 | |
| 554 DrawTreeLayerDelegate d1; | |
| 555 l1->set_delegate(&d1); | |
| 556 DrawTreeLayerDelegate d2; | |
| 557 l2->set_delegate(&d2); | |
| 558 DrawTreeLayerDelegate d3; | |
| 559 l3->set_delegate(&d3); | |
| 560 | |
| 561 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5)); | |
| 562 WaitForDraw(); | |
| 563 EXPECT_FALSE(d1.painted()); | |
| 564 EXPECT_TRUE(d2.painted()); | |
| 565 EXPECT_FALSE(d3.painted()); | |
| 566 } | |
| 567 | |
| 568 // Tests no-texture Layers. | |
| 569 // Create this hierarchy: | |
| 570 // L1 - red | |
| 571 // +-- L2 - NO TEXTURE | |
| 572 // | +-- L3 - yellow | |
| 573 // +-- L4 - magenta | |
| 574 // | |
| 575 TEST_F(LayerWithRealCompositorTest, HierarchyNoTexture) { | |
| 576 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, | |
| 577 gfx::Rect(20, 20, 400, 400))); | |
| 578 scoped_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350))); | |
| 579 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW, | |
| 580 gfx::Rect(5, 5, 25, 25))); | |
| 581 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA, | |
| 582 gfx::Rect(300, 300, 100, 100))); | |
| 583 | |
| 584 l1->Add(l2.get()); | |
| 585 l1->Add(l4.get()); | |
| 586 l2->Add(l3.get()); | |
| 587 | |
| 588 GetCompositor()->SetRootLayer(l1.get()); | |
| 589 WaitForDraw(); | |
| 590 | |
| 591 DrawTreeLayerDelegate d2; | |
| 592 l2->set_delegate(&d2); | |
| 593 DrawTreeLayerDelegate d3; | |
| 594 l3->set_delegate(&d3); | |
| 595 | |
| 596 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5)); | |
| 597 l3->SchedulePaint(gfx::Rect(5, 5, 5, 5)); | |
| 598 WaitForDraw(); | |
| 599 | |
| 600 // |d2| should not have received a paint notification since it has no texture. | |
| 601 EXPECT_FALSE(d2.painted()); | |
| 602 // |d3| should have received a paint notification. | |
| 603 EXPECT_TRUE(d3.painted()); | |
| 604 } | |
| 605 | |
| 606 class LayerWithNullDelegateTest : public LayerWithDelegateTest { | |
| 607 public: | |
| 608 LayerWithNullDelegateTest() {} | |
| 609 virtual ~LayerWithNullDelegateTest() {} | |
| 610 | |
| 611 virtual void SetUp() override { | |
| 612 LayerWithDelegateTest::SetUp(); | |
| 613 default_layer_delegate_.reset(new NullLayerDelegate()); | |
| 614 } | |
| 615 | |
| 616 virtual Layer* CreateLayer(LayerType type) override { | |
| 617 Layer* layer = new Layer(type); | |
| 618 layer->set_delegate(default_layer_delegate_.get()); | |
| 619 return layer; | |
| 620 } | |
| 621 | |
| 622 Layer* CreateTextureRootLayer(const gfx::Rect& bounds) { | |
| 623 Layer* layer = CreateTextureLayer(bounds); | |
| 624 compositor()->SetRootLayer(layer); | |
| 625 return layer; | |
| 626 } | |
| 627 | |
| 628 Layer* CreateTextureLayer(const gfx::Rect& bounds) { | |
| 629 Layer* layer = CreateLayer(LAYER_TEXTURED); | |
| 630 layer->SetBounds(bounds); | |
| 631 return layer; | |
| 632 } | |
| 633 | |
| 634 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) override { | |
| 635 Layer* layer = CreateLayer(LAYER_NOT_DRAWN); | |
| 636 layer->SetBounds(bounds); | |
| 637 return layer; | |
| 638 } | |
| 639 | |
| 640 private: | |
| 641 scoped_ptr<NullLayerDelegate> default_layer_delegate_; | |
| 642 | |
| 643 DISALLOW_COPY_AND_ASSIGN(LayerWithNullDelegateTest); | |
| 644 }; | |
| 645 | |
| 646 TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) { | |
| 647 scoped_ptr<Layer> layer(CreateLayer(LAYER_NOT_DRAWN)); | |
| 648 std::string name = "\"\'\\/\b\f\n\r\t\n"; | |
| 649 layer->set_name(name); | |
| 650 scoped_refptr<base::debug::ConvertableToTraceFormat> debug_info = | |
| 651 layer->TakeDebugInfo(); | |
| 652 EXPECT_TRUE(!!debug_info.get()); | |
| 653 std::string json; | |
| 654 debug_info->AppendAsTraceFormat(&json); | |
| 655 base::JSONReader json_reader; | |
| 656 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(json)); | |
| 657 EXPECT_TRUE(!!debug_info_value); | |
| 658 EXPECT_TRUE(debug_info_value->IsType(base::Value::TYPE_DICTIONARY)); | |
| 659 base::DictionaryValue* dictionary = 0; | |
| 660 EXPECT_TRUE(debug_info_value->GetAsDictionary(&dictionary)); | |
| 661 std::string roundtrip; | |
| 662 EXPECT_TRUE(dictionary->GetString("layer_name", &roundtrip)); | |
| 663 EXPECT_EQ(name, roundtrip); | |
| 664 } | |
| 665 | |
| 666 void ReturnMailbox(bool* run, uint32 sync_point, bool is_lost) { | |
| 667 *run = true; | |
| 668 } | |
| 669 | |
| 670 TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) { | |
| 671 scoped_ptr<Layer> l1(CreateLayer(LAYER_SOLID_COLOR)); | |
| 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->SetShowSolidColorContent(); | |
| 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. | |
| 719 TEST_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. | |
| 769 TEST_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. | |
| 828 TEST_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 | |
| 845 void 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. | |
| 861 TEST_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. | |
| 897 TEST_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. | |
| 934 TEST_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. | |
| 975 TEST_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 | |
| 1007 TEST_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. | |
| 1081 TEST_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. | |
| 1150 TEST_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 | |
| 1172 namespace { | |
| 1173 | |
| 1174 class 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. | |
| 1232 TEST_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 | |
| 1261 TEST_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 | |
| 1347 TEST_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. | |
| 1394 TEST_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 | |
| 1430 static 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 | |
| 1439 TEST_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 | |
| 1492 TEST_F(LayerWithDelegateTest, ExternalContent) { | |
| 1493 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000))); | |
| 1494 scoped_ptr<Layer> child(CreateLayer(LAYER_SOLID_COLOR)); | |
| 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 solid color content, so the cc layer won't | |
| 1501 // change. | |
| 1502 scoped_refptr<cc::Layer> before = child->cc_layer(); | |
| 1503 child->SetShowSolidColorContent(); | |
| 1504 EXPECT_TRUE(child->cc_layer()); | |
| 1505 EXPECT_EQ(before.get(), child->cc_layer()); | |
| 1506 | |
| 1507 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection = | |
| 1508 new cc::DelegatedFrameResourceCollection; | |
| 1509 scoped_refptr<cc::DelegatedFrameProvider> frame_provider = | |
| 1510 new cc::DelegatedFrameProvider(resource_collection.get(), | |
| 1511 MakeFrameData(gfx::Size(10, 10))); | |
| 1512 | |
| 1513 // Showing delegated content changes the underlying cc layer. | |
| 1514 before = child->cc_layer(); | |
| 1515 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10)); | |
| 1516 EXPECT_TRUE(child->cc_layer()); | |
| 1517 EXPECT_NE(before.get(), child->cc_layer()); | |
| 1518 | |
| 1519 // Changing to painted content should change the underlying cc layer. | |
| 1520 before = child->cc_layer(); | |
| 1521 child->SetShowSolidColorContent(); | |
| 1522 EXPECT_TRUE(child->cc_layer()); | |
| 1523 EXPECT_NE(before.get(), child->cc_layer()); | |
| 1524 } | |
| 1525 | |
| 1526 // Verifies that layer filters still attached after changing implementation | |
| 1527 // layer. | |
| 1528 TEST_F(LayerWithDelegateTest, LayerFiltersSurvival) { | |
| 1529 scoped_ptr<Layer> layer(CreateLayer(LAYER_TEXTURED)); | |
| 1530 layer->SetBounds(gfx::Rect(0, 0, 10, 10)); | |
| 1531 EXPECT_TRUE(layer->cc_layer()); | |
| 1532 EXPECT_EQ(0u, layer->cc_layer()->filters().size()); | |
| 1533 | |
| 1534 layer->SetLayerGrayscale(0.5f); | |
| 1535 EXPECT_EQ(layer->layer_grayscale(), 0.5f); | |
| 1536 EXPECT_EQ(1u, layer->cc_layer()->filters().size()); | |
| 1537 | |
| 1538 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection = | |
| 1539 new cc::DelegatedFrameResourceCollection; | |
| 1540 scoped_refptr<cc::DelegatedFrameProvider> frame_provider = | |
| 1541 new cc::DelegatedFrameProvider(resource_collection.get(), | |
| 1542 MakeFrameData(gfx::Size(10, 10))); | |
| 1543 | |
| 1544 // Showing delegated content changes the underlying cc layer. | |
| 1545 scoped_refptr<cc::Layer> before = layer->cc_layer(); | |
| 1546 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10)); | |
| 1547 EXPECT_EQ(layer->layer_grayscale(), 0.5f); | |
| 1548 EXPECT_TRUE(layer->cc_layer()); | |
| 1549 EXPECT_NE(before.get(), layer->cc_layer()); | |
| 1550 EXPECT_EQ(1u, layer->cc_layer()->filters().size()); | |
| 1551 } | |
| 1552 | |
| 1553 // Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation. | |
| 1554 TEST_F(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) { | |
| 1555 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED)); | |
| 1556 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED)); | |
| 1557 scoped_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED)); | |
| 1558 | |
| 1559 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator()); | |
| 1560 l2->SetAnimator(LayerAnimator::CreateImplicitAnimator()); | |
| 1561 | |
| 1562 EXPECT_FALSE(l1->HasPendingThreadedAnimations()); | |
| 1563 | |
| 1564 // Trigger a threaded animation. | |
| 1565 l1->SetOpacity(0.5f); | |
| 1566 | |
| 1567 EXPECT_TRUE(l1->HasPendingThreadedAnimations()); | |
| 1568 | |
| 1569 // Ensure we can remove a pending threaded animation. | |
| 1570 l1->GetAnimator()->StopAnimating(); | |
| 1571 | |
| 1572 EXPECT_FALSE(l1->HasPendingThreadedAnimations()); | |
| 1573 | |
| 1574 // Trigger another threaded animation. | |
| 1575 l1->SetOpacity(0.2f); | |
| 1576 | |
| 1577 EXPECT_TRUE(l1->HasPendingThreadedAnimations()); | |
| 1578 | |
| 1579 root->Add(l1.get()); | |
| 1580 GetCompositor()->SetRootLayer(root.get()); | |
| 1581 | |
| 1582 // Now that l1 is part of a tree, it should have dispatched the pending | |
| 1583 // animation. | |
| 1584 EXPECT_FALSE(l1->HasPendingThreadedAnimations()); | |
| 1585 | |
| 1586 // Ensure that l1 no longer holds on to animations. | |
| 1587 l1->SetOpacity(0.1f); | |
| 1588 EXPECT_FALSE(l1->HasPendingThreadedAnimations()); | |
| 1589 | |
| 1590 // Ensure that adding a layer to an existing tree causes its pending | |
| 1591 // animations to get dispatched. | |
| 1592 l2->SetOpacity(0.5f); | |
| 1593 EXPECT_TRUE(l2->HasPendingThreadedAnimations()); | |
| 1594 | |
| 1595 l1->Add(l2.get()); | |
| 1596 EXPECT_FALSE(l2->HasPendingThreadedAnimations()); | |
| 1597 } | |
| 1598 | |
| 1599 // Tests that in-progress threaded animations complete when a Layer's | |
| 1600 // cc::Layer changes. | |
| 1601 TEST_F(LayerWithRealCompositorTest, SwitchCCLayerAnimations) { | |
| 1602 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED)); | |
| 1603 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED)); | |
| 1604 GetCompositor()->SetRootLayer(root.get()); | |
| 1605 root->Add(l1.get()); | |
| 1606 | |
| 1607 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator()); | |
| 1608 | |
| 1609 EXPECT_FLOAT_EQ(l1->opacity(), 1.0f); | |
| 1610 | |
| 1611 // Trigger a threaded animation. | |
| 1612 l1->SetOpacity(0.5f); | |
| 1613 | |
| 1614 // Change l1's cc::Layer. | |
| 1615 l1->SwitchCCLayerForTest(); | |
| 1616 | |
| 1617 // Ensure that the opacity animation completed. | |
| 1618 EXPECT_FLOAT_EQ(l1->opacity(), 0.5f); | |
| 1619 } | |
| 1620 | |
| 1621 // Tests that the animators in the layer tree is added to the | |
| 1622 // animator-collection when the root-layer is set to the compositor. | |
| 1623 TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) { | |
| 1624 scoped_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR)); | |
| 1625 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10))); | |
| 1626 child->SetAnimator(LayerAnimator::CreateImplicitAnimator()); | |
| 1627 child->SetOpacity(0.5f); | |
| 1628 root->Add(child.get()); | |
| 1629 | |
| 1630 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators()); | |
| 1631 compositor()->SetRootLayer(root.get()); | |
| 1632 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators()); | |
| 1633 } | |
| 1634 | |
| 1635 // Tests that adding/removing a layer adds/removes the animator from its entire | |
| 1636 // subtree from the compositor's animator-collection. | |
| 1637 TEST_F(LayerWithDelegateTest, AddRemoveLayerUpdatesAnimatorsFromSubtree) { | |
| 1638 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED)); | |
| 1639 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED)); | |
| 1640 scoped_ptr<Layer> grandchild(CreateColorLayer(SK_ColorRED, | |
| 1641 gfx::Rect(10, 10))); | |
| 1642 root->Add(child.get()); | |
| 1643 child->Add(grandchild.get()); | |
| 1644 compositor()->SetRootLayer(root.get()); | |
| 1645 | |
| 1646 grandchild->SetAnimator(LayerAnimator::CreateImplicitAnimator()); | |
| 1647 grandchild->SetOpacity(0.5f); | |
| 1648 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators()); | |
| 1649 | |
| 1650 root->Remove(child.get()); | |
| 1651 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators()); | |
| 1652 | |
| 1653 root->Add(child.get()); | |
| 1654 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators()); | |
| 1655 } | |
| 1656 | |
| 1657 TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) { | |
| 1658 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED)); | |
| 1659 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED)); | |
| 1660 root->Add(child.get()); | |
| 1661 compositor()->SetRootLayer(root.get()); | |
| 1662 | |
| 1663 child->SetAnimator(LayerAnimator::CreateImplicitAnimator()); | |
| 1664 child->SetOpacity(0.5f); | |
| 1665 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators()); | |
| 1666 | |
| 1667 child.reset(); | |
| 1668 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators()); | |
| 1669 } | |
| 1670 | |
| 1671 namespace { | |
| 1672 | |
| 1673 std::string Vector2dFTo100thPercisionString(const gfx::Vector2dF& vector) { | |
| 1674 return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y()); | |
| 1675 } | |
| 1676 | |
| 1677 } // namespace | |
| 1678 | |
| 1679 TEST_F(LayerWithRealCompositorTest, SnapLayerToPixels) { | |
| 1680 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED)); | |
| 1681 scoped_ptr<Layer> c1(CreateLayer(LAYER_TEXTURED)); | |
| 1682 scoped_ptr<Layer> c11(CreateLayer(LAYER_TEXTURED)); | |
| 1683 | |
| 1684 GetCompositor()->SetScaleAndSize(1.25f, gfx::Size(100, 100)); | |
| 1685 GetCompositor()->SetRootLayer(root.get()); | |
| 1686 root->Add(c1.get()); | |
| 1687 c1->Add(c11.get()); | |
| 1688 | |
| 1689 root->SetBounds(gfx::Rect(0, 0, 100, 100)); | |
| 1690 c1->SetBounds(gfx::Rect(1, 1, 10, 10)); | |
| 1691 c11->SetBounds(gfx::Rect(1, 1, 10, 10)); | |
| 1692 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get()); | |
| 1693 // 0.5 at 1.25 scale : (1 - 0.25 + 0.25) / 1.25 = 0.4 | |
| 1694 EXPECT_EQ("0.40 0.40", | |
| 1695 Vector2dFTo100thPercisionString(c11->subpixel_position_offset())); | |
| 1696 | |
| 1697 GetCompositor()->SetScaleAndSize(1.5f, gfx::Size(100, 100)); | |
| 1698 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get()); | |
| 1699 // c11 must already be aligned at 1.5 scale. | |
| 1700 EXPECT_EQ("0.00 0.00", | |
| 1701 Vector2dFTo100thPercisionString(c11->subpixel_position_offset())); | |
| 1702 | |
| 1703 c11->SetBounds(gfx::Rect(2, 2, 10, 10)); | |
| 1704 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get()); | |
| 1705 // c11 is now off the pixel. | |
| 1706 // 0.5 / 1.5 = 0.333... | |
| 1707 EXPECT_EQ("0.33 0.33", | |
| 1708 Vector2dFTo100thPercisionString(c11->subpixel_position_offset())); | |
| 1709 } | |
| 1710 | |
| 1711 class FrameDamageCheckingDelegate : public TestLayerDelegate { | |
| 1712 public: | |
| 1713 FrameDamageCheckingDelegate() : delegated_frame_damage_called_(false) {} | |
| 1714 | |
| 1715 virtual void OnDelegatedFrameDamage( | |
| 1716 const gfx::Rect& damage_rect_in_dip) override { | |
| 1717 delegated_frame_damage_called_ = true; | |
| 1718 delegated_frame_damage_rect_ = damage_rect_in_dip; | |
| 1719 } | |
| 1720 | |
| 1721 const gfx::Rect& delegated_frame_damage_rect() const { | |
| 1722 return delegated_frame_damage_rect_; | |
| 1723 } | |
| 1724 bool delegated_frame_damage_called() const { | |
| 1725 return delegated_frame_damage_called_; | |
| 1726 } | |
| 1727 | |
| 1728 private: | |
| 1729 gfx::Rect delegated_frame_damage_rect_; | |
| 1730 bool delegated_frame_damage_called_; | |
| 1731 | |
| 1732 DISALLOW_COPY_AND_ASSIGN(FrameDamageCheckingDelegate); | |
| 1733 }; | |
| 1734 | |
| 1735 TEST(LayerDelegateTest, DelegatedFrameDamage) { | |
| 1736 scoped_ptr<Layer> layer(new Layer(LAYER_TEXTURED)); | |
| 1737 gfx::Rect damage_rect(2, 1, 5, 3); | |
| 1738 | |
| 1739 FrameDamageCheckingDelegate delegate; | |
| 1740 layer->set_delegate(&delegate); | |
| 1741 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection = | |
| 1742 new cc::DelegatedFrameResourceCollection; | |
| 1743 scoped_refptr<cc::DelegatedFrameProvider> frame_provider( | |
| 1744 new cc::DelegatedFrameProvider(resource_collection.get(), | |
| 1745 MakeFrameData(gfx::Size(10, 10)))); | |
| 1746 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10)); | |
| 1747 | |
| 1748 EXPECT_FALSE(delegate.delegated_frame_damage_called()); | |
| 1749 layer->OnDelegatedFrameDamage(damage_rect); | |
| 1750 EXPECT_TRUE(delegate.delegated_frame_damage_called()); | |
| 1751 EXPECT_EQ(damage_rect, delegate.delegated_frame_damage_rect()); | |
| 1752 } | |
| 1753 | |
| 1754 } // namespace ui | |
| OLD | NEW |