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