1 // Copyright 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 "cc/layers/scrollbar_layer.h" 6 7 #include "cc/animation/scrollbar_animation_controller.h" 8 #include "cc/layers/append_quads_data.h" 9 #include "cc/layers/scrollbar_layer_impl.h" 10 #include "cc/quads/solid_color_draw_quad.h" 11 #include "cc/resources/prioritized_resource_manager.h" 12 #include "cc/resources/priority_calculator.h" 13 #include "cc/resources/resource_update_queue.h" 14 #include "cc/test/fake_impl_proxy.h" 15 #include "cc/test/fake_layer_tree_host.h" 16 #include "cc/test/fake_layer_tree_host_client.h" 17 #include "cc/test/fake_layer_tree_host_impl.h" 18 #include "cc/test/fake_scrollbar.h" 19 #include "cc/test/geometry_test_utils.h" 20 #include "cc/test/layer_tree_test.h" 21 #include "cc/test/mock_quad_culler.h" 22 #include "cc/test/test_web_graphics_context_3d.h" 23 #include "cc/trees/layer_tree_impl.h" 24 #include "cc/trees/single_thread_proxy.h" 25 #include "cc/trees/tree_synchronizer.h" 26 #include "testing/gmock/include/gmock/gmock.h" 27 #include "testing/gtest/include/gtest/gtest.h" 28 29 namespace cc { 30 namespace { 31 32 LayerImpl* LayerImplForScrollAreaAndScrollbar( 33 FakeLayerTreeHost* host, 34 scoped_ptr<Scrollbar> scrollbar, 35 bool reverse_order) { 36 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 37 scoped_refptr<Layer> child1 = Layer::Create(); 38 scoped_refptr<Layer> child2 = 39 ScrollbarLayer::Create(scrollbar.Pass(), 40 child1->id()); 41 layer_tree_root->AddChild(child1); 42 layer_tree_root->InsertChild(child2, reverse_order ? 0 : 1); 43 host->SetRootLayer(layer_tree_root); 44 return host->CommitAndCreateLayerImplTree(); 45 } 46 47 TEST(ScrollbarLayerTest, ResolveScrollLayerPointer) { 48 scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(); 49 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); 50 LayerImpl* layer_impl_tree_root = 51 LayerImplForScrollAreaAndScrollbar(host.get(), scrollbar.Pass(), false); 52 53 LayerImpl* cc_child1 = layer_impl_tree_root->children()[0]; 54 ScrollbarLayerImpl* cc_child2 = static_cast<ScrollbarLayerImpl*>( 55 layer_impl_tree_root->children()[1]); 56 57 EXPECT_EQ(cc_child1->horizontal_scrollbar_layer(), cc_child2); 58 } 59 60 TEST(ScrollbarLayerTest, ResolveScrollLayerPointer_ReverseOrder) { 61 scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(); 62 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); 63 LayerImpl* layer_impl_tree_root = 64 LayerImplForScrollAreaAndScrollbar(host.get(), scrollbar.Pass(), true); 65 66 ScrollbarLayerImpl* cc_child1 = static_cast<ScrollbarLayerImpl*>( 67 layer_impl_tree_root->children()[0]); 68 LayerImpl* cc_child2 = layer_impl_tree_root->children()[1]; 69 70 EXPECT_EQ(cc_child2->horizontal_scrollbar_layer(), cc_child1); 71 } 72 73 TEST(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) { 74 scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(); 75 76 // Create and attach a non-overlay scrollbar. 77 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); 78 LayerImpl* layer_impl_tree_root = 79 LayerImplForScrollAreaAndScrollbar(host.get(), scrollbar.Pass(), false); 80 ScrollbarLayerImpl* scrollbar_layer_impl = 81 static_cast<ScrollbarLayerImpl*>(layer_impl_tree_root->children()[1]); 82 83 // When the scrollbar is not an overlay scrollbar, the scroll should be 84 // responded to on the main thread as the compositor does not yet implement 85 // scrollbar scrolling. 86 EXPECT_EQ(InputHandler::ScrollOnMainThread, 87 scrollbar_layer_impl->TryScroll(gfx::Point(0, 0), 88 InputHandler::Gesture)); 89 90 // Create and attach an overlay scrollbar. 91 scrollbar.reset(new FakeScrollbar(false, false, true)); 92 93 layer_impl_tree_root = 94 LayerImplForScrollAreaAndScrollbar(host.get(), scrollbar.Pass(), false); 95 scrollbar_layer_impl = 96 static_cast<ScrollbarLayerImpl*>(layer_impl_tree_root->children()[1]); 97 98 // The user shouldn't be able to drag an overlay scrollbar and the scroll 99 // may be handled in the compositor. 100 EXPECT_EQ(InputHandler::ScrollIgnored, 101 scrollbar_layer_impl->TryScroll(gfx::Point(0, 0), 102 InputHandler::Gesture)); 103 } 104 105 TEST(ScrollbarLayerTest, ScrollOffsetSynchronization) { 106 scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(); 107 108 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); 109 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 110 scoped_refptr<Layer> content_layer = Layer::Create(); 111 scoped_refptr<Layer> scrollbar_layer = 112 ScrollbarLayer::Create(scrollbar.Pass(), 113 layer_tree_root->id()); 114 115 layer_tree_root->SetScrollable(true); 116 layer_tree_root->SetScrollOffset(gfx::Vector2d(10, 20)); 117 layer_tree_root->SetMaxScrollOffset(gfx::Vector2d(30, 50)); 118 layer_tree_root->SetBounds(gfx::Size(100, 200)); 119 content_layer->SetBounds(gfx::Size(100, 200)); 120 121 host->SetRootLayer(layer_tree_root); 122 layer_tree_root->AddChild(content_layer); 123 layer_tree_root->AddChild(scrollbar_layer); 124 125 layer_tree_root->SavePaintProperties(); 126 content_layer->SavePaintProperties(); 127 128 LayerImpl* layer_impl_tree_root = host->CommitAndCreateLayerImplTree(); 129 130 ScrollbarLayerImpl* cc_scrollbar_layer = 131 static_cast<ScrollbarLayerImpl*>(layer_impl_tree_root->children()[1]); 132 133 EXPECT_EQ(10.f, cc_scrollbar_layer->CurrentPos()); 134 EXPECT_EQ(30, cc_scrollbar_layer->Maximum()); 135 136 layer_tree_root->SetScrollOffset(gfx::Vector2d(100, 200)); 137 layer_tree_root->SetMaxScrollOffset(gfx::Vector2d(300, 500)); 138 layer_tree_root->SetBounds(gfx::Size(1000, 2000)); 139 layer_tree_root->SavePaintProperties(); 140 content_layer->SetBounds(gfx::Size(1000, 2000)); 141 content_layer->SavePaintProperties(); 142 143 ScrollbarAnimationController* scrollbar_controller = 144 layer_impl_tree_root->scrollbar_animation_controller(); 145 layer_impl_tree_root = host->CommitAndCreateLayerImplTree(); 146 EXPECT_EQ(scrollbar_controller, 147 layer_impl_tree_root->scrollbar_animation_controller()); 148 149 EXPECT_EQ(100.f, cc_scrollbar_layer->CurrentPos()); 150 EXPECT_EQ(300, cc_scrollbar_layer->Maximum()); 151 152 layer_impl_tree_root->ScrollBy(gfx::Vector2d(12, 34)); 153 154 EXPECT_EQ(112.f, cc_scrollbar_layer->CurrentPos()); 155 EXPECT_EQ(300, cc_scrollbar_layer->Maximum()); 156 } 157 158 TEST(ScrollbarLayerTest, SolidColorDrawQuads) { 159 LayerTreeSettings layer_tree_settings; 160 layer_tree_settings.solid_color_scrollbars = true; 161 layer_tree_settings.solid_color_scrollbar_thickness_dip = 3; 162 scoped_ptr<FakeLayerTreeHost> host = 163 FakeLayerTreeHost::Create(layer_tree_settings); 164 165 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true)); 166 LayerImpl* layer_impl_tree_root = 167 LayerImplForScrollAreaAndScrollbar(host.get(), scrollbar.Pass(), false); 168 ScrollbarLayerImpl* scrollbar_layer_impl = 169 static_cast<ScrollbarLayerImpl*>(layer_impl_tree_root->children()[1]); 170 scrollbar_layer_impl->SetThumbThickness(3); 171 scrollbar_layer_impl->SetCurrentPos(10.f); 172 scrollbar_layer_impl->SetMaximum(100); 173 scrollbar_layer_impl->SetTrackLength(100); 174 scrollbar_layer_impl->SetVisibleToTotalLengthRatio(0.4f); 175 176 // Thickness should be overridden to 3. 177 { 178 MockQuadCuller quad_culler; 179 AppendQuadsData data; 180 scrollbar_layer_impl->AppendQuads(&quad_culler, &data); 181 182 const QuadList& quads = quad_culler.quad_list(); 183 ASSERT_EQ(1u, quads.size()); 184 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads[0]->material); 185 EXPECT_RECT_EQ(gfx::Rect(6, 0, 40, 3), quads[0]->rect); 186 } 187 188 // Contents scale should scale the draw quad. 189 scrollbar_layer_impl->draw_properties().contents_scale_x = 2.f; 190 scrollbar_layer_impl->draw_properties().contents_scale_y = 2.f; 191 { 192 MockQuadCuller quad_culler; 193 AppendQuadsData data; 194 scrollbar_layer_impl->AppendQuads(&quad_culler, &data); 195 196 const QuadList& quads = quad_culler.quad_list(); 197 ASSERT_EQ(1u, quads.size()); 198 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads[0]->material); 199 EXPECT_RECT_EQ(gfx::Rect(12, 0, 80, 6), quads[0]->rect); 200 } 201 scrollbar_layer_impl->draw_properties().contents_scale_x = 1.f; 202 scrollbar_layer_impl->draw_properties().contents_scale_y = 1.f; 203 204 // For solid color scrollbars, position and size should reflect the 205 // current viewport state. 206 scrollbar_layer_impl->SetVisibleToTotalLengthRatio(0.2f); 207 { 208 MockQuadCuller quad_culler; 209 AppendQuadsData data; 210 scrollbar_layer_impl->AppendQuads(&quad_culler, &data); 211 212 const QuadList& quads = quad_culler.quad_list(); 213 ASSERT_EQ(1u, quads.size()); 214 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads[0]->material); 215 EXPECT_RECT_EQ(gfx::Rect(8, 0, 20, 3), quads[0]->rect); 216 } 217 } 218 219 TEST(ScrollbarLayerTest, LayerDrivenSolidColorDrawQuads) { 220 LayerTreeSettings layer_tree_settings; 221 layer_tree_settings.solid_color_scrollbars = true; 222 layer_tree_settings.solid_color_scrollbar_thickness_dip = 3; 223 scoped_ptr<FakeLayerTreeHost> host = 224 FakeLayerTreeHost::Create(layer_tree_settings); 225 226 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true)); 227 LayerImpl* layer_impl_tree_root = 228 LayerImplForScrollAreaAndScrollbar(host.get(), scrollbar.Pass(), false); 229 ScrollbarLayerImpl* scrollbar_layer_impl = 230 static_cast<ScrollbarLayerImpl*>(layer_impl_tree_root->children()[1]); 231 232 scrollbar_layer_impl->SetThumbThickness(3); 233 scrollbar_layer_impl->SetTrackLength(10); 234 scrollbar_layer_impl->SetCurrentPos(4.f); 235 scrollbar_layer_impl->SetMaximum(8); 236 237 layer_impl_tree_root->SetScrollable(true); 238 layer_impl_tree_root->SetHorizontalScrollbarLayer(scrollbar_layer_impl); 239 layer_impl_tree_root->SetMaxScrollOffset(gfx::Vector2d(8, 8)); 240 layer_impl_tree_root->SetBounds(gfx::Size(2, 2)); 241 layer_impl_tree_root->ScrollBy(gfx::Vector2dF(4.f, 0.f)); 242 243 { 244 MockQuadCuller quad_culler; 245 AppendQuadsData data; 246 scrollbar_layer_impl->AppendQuads(&quad_culler, &data); 247 248 const QuadList& quads = quad_culler.quad_list(); 249 ASSERT_EQ(1u, quads.size()); 250 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads[0]->material); 251 EXPECT_RECT_EQ(gfx::Rect(3, 0, 3, 3), quads[0]->rect); 252 } 253 } 254 255 class ScrollbarLayerSolidColorThumbTest : public testing::Test { 256 public: 257 ScrollbarLayerSolidColorThumbTest() { 258 LayerTreeSettings layer_tree_settings; 259 layer_tree_settings.solid_color_scrollbars = true; 260 host_impl_.reset(new FakeLayerTreeHostImpl(layer_tree_settings, &proxy_)); 261 262 horizontal_scrollbar_layer_ = ScrollbarLayerImpl::Create( 263 host_impl_->active_tree(), 1, HORIZONTAL); 264 vertical_scrollbar_layer_ = ScrollbarLayerImpl::Create( 265 host_impl_->active_tree(), 2, VERTICAL); 266 } 267 268 protected: 269 FakeImplProxy proxy_; 270 scoped_ptr<FakeLayerTreeHostImpl> host_impl_; 271 scoped_ptr<ScrollbarLayerImpl> horizontal_scrollbar_layer_; 272 scoped_ptr<ScrollbarLayerImpl> vertical_scrollbar_layer_; 273 }; 274 275 TEST_F(ScrollbarLayerSolidColorThumbTest, SolidColorThumbLength) { 276 horizontal_scrollbar_layer_->SetCurrentPos(0); 277 horizontal_scrollbar_layer_->SetMaximum(10); 278 horizontal_scrollbar_layer_->SetThumbThickness(3); 279 280 // Simple case - one third of the scrollable area is visible, so the thumb 281 // should be one third as long as the track. 282 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(0.33f); 283 horizontal_scrollbar_layer_->SetTrackLength(100); 284 EXPECT_EQ(33, horizontal_scrollbar_layer_->ComputeThumbQuadRect().width()); 285 286 // The thumb's length should never be less than its thickness. 287 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(0.01f); 288 horizontal_scrollbar_layer_->SetTrackLength(100); 289 EXPECT_EQ(3, horizontal_scrollbar_layer_->ComputeThumbQuadRect().width()); 290 } 291 292 TEST_F(ScrollbarLayerSolidColorThumbTest, SolidColorThumbPosition) { 293 horizontal_scrollbar_layer_->SetTrackLength(100); 294 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(0.1f); 295 horizontal_scrollbar_layer_->SetThumbThickness(3); 296 297 horizontal_scrollbar_layer_->SetCurrentPos(0); 298 horizontal_scrollbar_layer_->SetMaximum(100); 299 EXPECT_EQ(0, horizontal_scrollbar_layer_->ComputeThumbQuadRect().x()); 300 EXPECT_EQ(10, horizontal_scrollbar_layer_->ComputeThumbQuadRect().width()); 301 302 horizontal_scrollbar_layer_->SetCurrentPos(100); 303 // The thumb is 10px long and the track is 100px, so the maximum thumb 304 // position is 90px. 305 EXPECT_EQ(90, horizontal_scrollbar_layer_->ComputeThumbQuadRect().x()); 306 307 horizontal_scrollbar_layer_->SetCurrentPos(80); 308 // The scroll position is 80% of the maximum, so the thumb's position should 309 // be at 80% of its maximum or 72px. 310 EXPECT_EQ(72, horizontal_scrollbar_layer_->ComputeThumbQuadRect().x()); 311 } 312 313 TEST_F(ScrollbarLayerSolidColorThumbTest, SolidColorThumbVerticalAdjust) { 314 ScrollbarLayerImpl* layers[2] = 315 { horizontal_scrollbar_layer_.get(), vertical_scrollbar_layer_.get() }; 316 for (size_t i = 0; i < 2; ++i) { 317 layers[i]->SetTrackLength(100); 318 layers[i]->SetVisibleToTotalLengthRatio(0.2f); 319 layers[i]->SetThumbThickness(3); 320 layers[i]->SetCurrentPos(25); 321 layers[i]->SetMaximum(100); 322 } 323 324 EXPECT_RECT_EQ(gfx::RectF(20.f, 0.f, 20.f, 3.f), 325 horizontal_scrollbar_layer_->ComputeThumbQuadRect()); 326 EXPECT_RECT_EQ(gfx::RectF(0.f, 20.f, 3.f, 20.f), 327 vertical_scrollbar_layer_->ComputeThumbQuadRect()); 328 329 horizontal_scrollbar_layer_->SetVerticalAdjust(10.f); 330 vertical_scrollbar_layer_->SetVerticalAdjust(10.f); 331 332 // The vertical adjustment factor has two effects: 333 // 1.) Moves the horizontal scrollbar down 334 // 2.) Increases the vertical scrollbar's effective track length which both 335 // increases the thumb's length and its position within the track. 336 EXPECT_RECT_EQ(gfx::Rect(20.f, 10.f, 20.f, 3.f), 337 horizontal_scrollbar_layer_->ComputeThumbQuadRect()); 338 EXPECT_RECT_EQ(gfx::Rect(0.f, 22, 3.f, 22.f), 339 vertical_scrollbar_layer_->ComputeThumbQuadRect()); 340 } 341 342 class ScrollbarLayerTestMaxTextureSize : public LayerTreeTest { 343 public: 344 ScrollbarLayerTestMaxTextureSize() {} 345 346 void SetScrollbarBounds(gfx::Size bounds) { bounds_ = bounds; } 347 348 virtual void BeginTest() OVERRIDE { 349 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); 350 scrollbar_layer_ = ScrollbarLayer::Create(scrollbar.Pass(), 1); 351 scrollbar_layer_->SetLayerTreeHost(layer_tree_host()); 352 scrollbar_layer_->SetBounds(bounds_); 353 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_); 354 355 scroll_layer_ = Layer::Create(); 356 scrollbar_layer_->SetScrollLayerId(scroll_layer_->id()); 357 layer_tree_host()->root_layer()->AddChild(scroll_layer_); 358 359 PostSetNeedsCommitToMainThread(); 360 } 361 362 virtual void DidCommitAndDrawFrame() OVERRIDE { 363 const int kMaxTextureSize = 364 layer_tree_host()->GetRendererCapabilities().max_texture_size; 365 366 // Check first that we're actually testing something. 367 EXPECT_GT(scrollbar_layer_->bounds().width(), kMaxTextureSize); 368 369 EXPECT_EQ(scrollbar_layer_->content_bounds().width(), 370 kMaxTextureSize - 1); 371 EXPECT_EQ(scrollbar_layer_->content_bounds().height(), 372 kMaxTextureSize - 1); 373 374 EndTest(); 375 } 376 377 virtual void AfterTest() OVERRIDE {} 378 379 private: 380 scoped_refptr<ScrollbarLayer> scrollbar_layer_; 381 scoped_refptr<Layer> scroll_layer_; 382 gfx::Size bounds_; 383 }; 384 385 TEST_F(ScrollbarLayerTestMaxTextureSize, DirectRenderer) { 386 scoped_ptr<TestWebGraphicsContext3D> context = 387 TestWebGraphicsContext3D::Create(); 388 int max_size = 0; 389 context->getIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); 390 SetScrollbarBounds(gfx::Size(max_size + 100, max_size + 100)); 391 RunTest(true, false, true); 392 } 393 394 TEST_F(ScrollbarLayerTestMaxTextureSize, DelegatingRenderer) { 395 scoped_ptr<TestWebGraphicsContext3D> context = 396 TestWebGraphicsContext3D::Create(); 397 int max_size = 0; 398 context->getIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); 399 SetScrollbarBounds(gfx::Size(max_size + 100, max_size + 100)); 400 RunTest(true, true, true); 401 } 402 403 class MockLayerTreeHost : public LayerTreeHost { 404 public: 405 MockLayerTreeHost(LayerTreeHostClient* client, 406 const LayerTreeSettings& settings) 407 : LayerTreeHost(client, settings) { 408 Initialize(NULL); 409 } 410 }; 411 412 413 class ScrollbarLayerTestResourceCreation : public testing::Test { 414 public: 415 ScrollbarLayerTestResourceCreation() 416 : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {} 417 418 void TestResourceUpload(size_t expected_resources) { 419 layer_tree_host_.reset( 420 new MockLayerTreeHost(&fake_client_, layer_tree_settings_)); 421 422 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, false)); 423 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 424 scoped_refptr<Layer> content_layer = Layer::Create(); 425 scoped_refptr<Layer> scrollbar_layer = 426 ScrollbarLayer::Create(scrollbar.Pass(), layer_tree_root->id()); 427 layer_tree_root->AddChild(content_layer); 428 layer_tree_root->AddChild(scrollbar_layer); 429 430 layer_tree_host_->InitializeOutputSurfaceIfNeeded(); 431 layer_tree_host_->contents_texture_manager()-> 432 SetMaxMemoryLimitBytes(1024 * 1024); 433 layer_tree_host_->SetRootLayer(layer_tree_root); 434 435 scrollbar_layer->SetIsDrawable(true); 436 scrollbar_layer->SetBounds(gfx::Size(100, 100)); 437 layer_tree_root->SetScrollOffset(gfx::Vector2d(10, 20)); 438 layer_tree_root->SetMaxScrollOffset(gfx::Vector2d(30, 50)); 439 layer_tree_root->SetBounds(gfx::Size(100, 200)); 440 content_layer->SetBounds(gfx::Size(100, 200)); 441 scrollbar_layer->draw_properties().content_bounds = gfx::Size(100, 200); 442 scrollbar_layer->draw_properties().visible_content_rect = 443 gfx::Rect(0, 0, 100, 200); 444 scrollbar_layer->CreateRenderSurface(); 445 scrollbar_layer->draw_properties().render_target = scrollbar_layer.get(); 446 447 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 448 EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); 449 450 PriorityCalculator calculator; 451 ResourceUpdateQueue queue; 452 OcclusionTracker occlusion_tracker(gfx::Rect(), false); 453 454 scrollbar_layer->SavePaintProperties(); 455 scrollbar_layer->SetTexturePriorities(calculator); 456 layer_tree_host_->contents_texture_manager()->PrioritizeTextures(); 457 scrollbar_layer->Update(&queue, &occlusion_tracker); 458 EXPECT_EQ(0u, queue.FullUploadSize()); 459 EXPECT_EQ(expected_resources, queue.PartialUploadSize()); 460 461 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 462 463 scrollbar_layer->ClearRenderSurface(); 464 } 465 466 protected: 467 FakeLayerTreeHostClient fake_client_; 468 LayerTreeSettings layer_tree_settings_; 469 scoped_ptr<MockLayerTreeHost> layer_tree_host_; 470 }; 471 472 TEST_F(ScrollbarLayerTestResourceCreation, ResourceUpload) { 473 layer_tree_settings_.solid_color_scrollbars = false; 474 TestResourceUpload(2); 475 } 476 477 TEST_F(ScrollbarLayerTestResourceCreation, SolidColorNoResourceUpload) { 478 layer_tree_settings_.solid_color_scrollbars = true; 479 TestResourceUpload(0); 480 } 481 482 class ScaledScrollbarLayerTestResourceCreation : public testing::Test { 483 public: 484 ScaledScrollbarLayerTestResourceCreation() 485 : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {} 486 487 void TestResourceUpload(size_t expected_resources, const float test_scale) { 488 layer_tree_host_.reset( 489 new MockLayerTreeHost(&fake_client_, layer_tree_settings_)); 490 491 gfx::Point scrollbar_location(0, 185); 492 scoped_ptr<FakeScrollbar> scrollbar(new FakeScrollbar(false, true, false)); 493 scrollbar->set_location(scrollbar_location); 494 495 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 496 scoped_refptr<Layer> content_layer = Layer::Create(); 497 scoped_refptr<Layer> scrollbar_layer = 498 ScrollbarLayer::Create(scrollbar.PassAs<cc::Scrollbar>(), 499 layer_tree_root->id()); 500 layer_tree_root->AddChild(content_layer); 501 layer_tree_root->AddChild(scrollbar_layer); 502 503 layer_tree_host_->InitializeOutputSurfaceIfNeeded(); 504 layer_tree_host_->contents_texture_manager()-> 505 SetMaxMemoryLimitBytes(1024 * 1024); 506 layer_tree_host_->SetRootLayer(layer_tree_root); 507 508 scrollbar_layer->SetIsDrawable(true); 509 scrollbar_layer->SetBounds(gfx::Size(100, 15)); 510 scrollbar_layer->SetPosition(scrollbar_location); 511 layer_tree_root->SetBounds(gfx::Size(100, 200)); 512 content_layer->SetBounds(gfx::Size(100, 200)); 513 gfx::SizeF scaled_size = 514 gfx::ScaleSize(scrollbar_layer->bounds(), test_scale, test_scale); 515 gfx::PointF scaled_location = 516 gfx::ScalePoint(scrollbar_layer->position(), test_scale, test_scale); 517 scrollbar_layer->draw_properties().content_bounds = 518 gfx::Size(scaled_size.width(), scaled_size.height()); 519 scrollbar_layer->draw_properties().contents_scale_x = test_scale; 520 scrollbar_layer->draw_properties().contents_scale_y = test_scale; 521 scrollbar_layer->draw_properties().visible_content_rect = 522 gfx::Rect(scaled_location.x(), 523 scaled_location.y(), 524 scaled_size.width(), 525 scaled_size.height()); 526 scrollbar_layer->CreateRenderSurface(); 527 scrollbar_layer->draw_properties().render_target = scrollbar_layer.get(); 528 529 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 530 EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); 531 532 PriorityCalculator calculator; 533 ResourceUpdateQueue queue; 534 OcclusionTracker occlusion_tracker(gfx::Rect(), false); 535 536 scrollbar_layer->SavePaintProperties(); 537 scrollbar_layer->SetTexturePriorities(calculator); 538 layer_tree_host_->contents_texture_manager()->PrioritizeTextures(); 539 scrollbar_layer->Update(&queue, &occlusion_tracker); 540 EXPECT_EQ(expected_resources, queue.PartialUploadSize()); 541 542 // Verify that we have not generated any content uploads that are larger 543 // than their destination textures. 544 while (queue.HasMoreUpdates()) { 545 ResourceUpdate update = queue.TakeFirstPartialUpload(); 546 EXPECT_LE(update.texture->size().width(), 547 scrollbar_layer->content_bounds().width()); 548 EXPECT_LE(update.texture->size().height(), 549 scrollbar_layer->content_bounds().height()); 550 551 EXPECT_LE(update.dest_offset.x() + update.content_rect.width(), 552 update.texture->size().width()); 553 EXPECT_LE(update.dest_offset.y() + update.content_rect.height(), 554 update.texture->size().height()); 555 } 556 557 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 558 559 scrollbar_layer->ClearRenderSurface(); 560 } 561 562 protected: 563 FakeLayerTreeHostClient fake_client_; 564 LayerTreeSettings layer_tree_settings_; 565 scoped_ptr<MockLayerTreeHost> layer_tree_host_; 566 }; 567 568 TEST_F(ScaledScrollbarLayerTestResourceCreation, ScaledResourceUpload) { 569 layer_tree_settings_.solid_color_scrollbars = false; 570 // Pick a test scale that moves the scrollbar's (non-zero) position to 571 // a non-pixel-aligned location. 572 TestResourceUpload(2, 1.41f); 573 } 574 575 } // namespace 576 } // namespace cc 577