OLD | NEW |
| (Empty) |
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 "base/containers/hash_tables.h" | |
6 #include "cc/animation/scrollbar_animation_controller.h" | |
7 #include "cc/layers/append_quads_data.h" | |
8 #include "cc/layers/painted_scrollbar_layer.h" | |
9 #include "cc/layers/painted_scrollbar_layer_impl.h" | |
10 #include "cc/layers/scrollbar_layer_interface.h" | |
11 #include "cc/layers/solid_color_scrollbar_layer.h" | |
12 #include "cc/layers/solid_color_scrollbar_layer_impl.h" | |
13 #include "cc/quads/solid_color_draw_quad.h" | |
14 #include "cc/resources/resource_update_queue.h" | |
15 #include "cc/test/fake_impl_proxy.h" | |
16 #include "cc/test/fake_layer_tree_host.h" | |
17 #include "cc/test/fake_layer_tree_host_client.h" | |
18 #include "cc/test/fake_layer_tree_host_impl.h" | |
19 #include "cc/test/fake_painted_scrollbar_layer.h" | |
20 #include "cc/test/fake_scrollbar.h" | |
21 #include "cc/test/geometry_test_utils.h" | |
22 #include "cc/test/layer_tree_test.h" | |
23 #include "cc/test/mock_occlusion_tracker.h" | |
24 #include "cc/test/test_task_graph_runner.h" | |
25 #include "cc/test/test_web_graphics_context_3d.h" | |
26 #include "cc/trees/layer_tree_host.h" | |
27 #include "cc/trees/layer_tree_impl.h" | |
28 #include "cc/trees/occlusion_tracker.h" | |
29 #include "cc/trees/single_thread_proxy.h" | |
30 #include "cc/trees/tree_synchronizer.h" | |
31 #include "testing/gmock/include/gmock/gmock.h" | |
32 #include "testing/gtest/include/gtest/gtest.h" | |
33 | |
34 namespace cc { | |
35 namespace { | |
36 | |
37 LayerImpl* LayerImplForScrollAreaAndScrollbar(FakeLayerTreeHost* host, | |
38 scoped_ptr<Scrollbar> scrollbar, | |
39 bool reverse_order, | |
40 bool use_solid_color_scrollbar, | |
41 int thumb_thickness, | |
42 int track_start) { | |
43 scoped_refptr<Layer> layer_tree_root = Layer::Create(); | |
44 scoped_refptr<Layer> child1 = Layer::Create(); | |
45 scoped_refptr<Layer> child2; | |
46 if (use_solid_color_scrollbar) { | |
47 const bool kIsLeftSideVerticalScrollbar = false; | |
48 child2 = SolidColorScrollbarLayer::Create(scrollbar->Orientation(), | |
49 thumb_thickness, | |
50 track_start, | |
51 kIsLeftSideVerticalScrollbar, | |
52 child1->id()); | |
53 } else { | |
54 child2 = PaintedScrollbarLayer::Create(scrollbar.Pass(), child1->id()); | |
55 } | |
56 child2->ToScrollbarLayer()->SetClipLayer(layer_tree_root->id()); | |
57 layer_tree_root->AddChild(child1); | |
58 layer_tree_root->InsertChild(child2, reverse_order ? 0 : 1); | |
59 host->SetRootLayer(layer_tree_root); | |
60 return host->CommitAndCreateLayerImplTree(); | |
61 } | |
62 | |
63 class FakeResourceTrackingLayerTreeHost : public FakeLayerTreeHost { | |
64 public: | |
65 FakeResourceTrackingLayerTreeHost(FakeLayerTreeHostClient* client, | |
66 const LayerTreeSettings& settings) | |
67 : FakeLayerTreeHost(client, settings), | |
68 next_id_(1), | |
69 total_ui_resource_created_(0), | |
70 total_ui_resource_deleted_(0) { | |
71 InitializeSingleThreaded(client, base::MessageLoopProxy::current(), | |
72 nullptr); | |
73 } | |
74 | |
75 UIResourceId CreateUIResource(UIResourceClient* content) override { | |
76 total_ui_resource_created_++; | |
77 UIResourceId nid = next_id_++; | |
78 ui_resource_bitmap_map_.insert( | |
79 std::make_pair(nid, content->GetBitmap(nid, false))); | |
80 return nid; | |
81 } | |
82 | |
83 // Deletes a UI resource. May safely be called more than once. | |
84 void DeleteUIResource(UIResourceId id) override { | |
85 UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id); | |
86 if (iter != ui_resource_bitmap_map_.end()) { | |
87 ui_resource_bitmap_map_.erase(iter); | |
88 total_ui_resource_deleted_++; | |
89 } | |
90 } | |
91 | |
92 size_t UIResourceCount() { return ui_resource_bitmap_map_.size(); } | |
93 int TotalUIResourceDeleted() { return total_ui_resource_deleted_; } | |
94 int TotalUIResourceCreated() { return total_ui_resource_created_; } | |
95 | |
96 gfx::Size ui_resource_size(UIResourceId id) { | |
97 UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id); | |
98 if (iter != ui_resource_bitmap_map_.end()) | |
99 return iter->second.GetSize(); | |
100 return gfx::Size(); | |
101 } | |
102 | |
103 UIResourceBitmap* ui_resource_bitmap(UIResourceId id) { | |
104 UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id); | |
105 if (iter != ui_resource_bitmap_map_.end()) | |
106 return &iter->second; | |
107 return nullptr; | |
108 } | |
109 | |
110 private: | |
111 using UIResourceBitmapMap = base::hash_map<UIResourceId, UIResourceBitmap>; | |
112 UIResourceBitmapMap ui_resource_bitmap_map_; | |
113 | |
114 int next_id_; | |
115 int total_ui_resource_created_; | |
116 int total_ui_resource_deleted_; | |
117 }; | |
118 | |
119 class ScrollbarLayerTest : public testing::Test { | |
120 public: | |
121 ScrollbarLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) { | |
122 layer_tree_settings_.single_thread_proxy_scheduler = false; | |
123 layer_tree_host_.reset(new FakeResourceTrackingLayerTreeHost( | |
124 &fake_client_, layer_tree_settings_)); | |
125 fake_client_.SetLayerTreeHost(layer_tree_host_.get()); | |
126 // Force output surface creation for renderer capabilities. | |
127 layer_tree_host_->Composite(base::TimeTicks()); | |
128 EXPECT_FALSE(layer_tree_host_->output_surface_lost()); | |
129 } | |
130 | |
131 protected: | |
132 FakeLayerTreeHostClient fake_client_; | |
133 LayerTreeSettings layer_tree_settings_; | |
134 scoped_ptr<FakeResourceTrackingLayerTreeHost> layer_tree_host_; | |
135 }; | |
136 | |
137 TEST_F(ScrollbarLayerTest, ResolveScrollLayerPointer) { | |
138 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); | |
139 LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( | |
140 layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0); | |
141 | |
142 LayerImpl* cc_child1 = layer_impl_tree_root->children()[0]; | |
143 PaintedScrollbarLayerImpl* cc_child2 = | |
144 static_cast<PaintedScrollbarLayerImpl*>( | |
145 layer_impl_tree_root->children()[1]); | |
146 | |
147 EXPECT_EQ(cc_child1->scrollbars()->size(), 1UL); | |
148 EXPECT_EQ(*(cc_child1->scrollbars()->begin()), cc_child2); | |
149 } | |
150 | |
151 TEST_F(ScrollbarLayerTest, ResolveScrollLayerPointer_ReverseOrder) { | |
152 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); | |
153 LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( | |
154 layer_tree_host_.get(), scrollbar.Pass(), true, false, 0, 0); | |
155 | |
156 PaintedScrollbarLayerImpl* cc_child1 = | |
157 static_cast<PaintedScrollbarLayerImpl*>( | |
158 layer_impl_tree_root->children()[0]); | |
159 LayerImpl* cc_child2 = layer_impl_tree_root->children()[1]; | |
160 | |
161 EXPECT_EQ(cc_child2->scrollbars()->size(), 1UL); | |
162 EXPECT_EQ(*(cc_child2->scrollbars()->begin()), cc_child1); | |
163 } | |
164 | |
165 TEST_F(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) { | |
166 // Create and attach a non-overlay scrollbar. | |
167 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); | |
168 LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( | |
169 layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0); | |
170 PaintedScrollbarLayerImpl* scrollbar_layer_impl = | |
171 static_cast<PaintedScrollbarLayerImpl*>( | |
172 layer_impl_tree_root->children()[1]); | |
173 | |
174 // When the scrollbar is not an overlay scrollbar, the scroll should be | |
175 // responded to on the main thread as the compositor does not yet implement | |
176 // scrollbar scrolling. | |
177 EXPECT_EQ( | |
178 InputHandler::SCROLL_ON_MAIN_THREAD, | |
179 scrollbar_layer_impl->TryScroll(gfx::Point(0, 0), InputHandler::GESTURE, | |
180 SCROLL_BLOCKS_ON_NONE)); | |
181 | |
182 // Create and attach an overlay scrollbar. | |
183 scrollbar.reset(new FakeScrollbar(false, false, true)); | |
184 | |
185 layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( | |
186 layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0); | |
187 scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>( | |
188 layer_impl_tree_root->children()[1]); | |
189 | |
190 // The user shouldn't be able to drag an overlay scrollbar and the scroll | |
191 // may be handled in the compositor. | |
192 EXPECT_EQ( | |
193 InputHandler::SCROLL_IGNORED, | |
194 scrollbar_layer_impl->TryScroll(gfx::Point(0, 0), InputHandler::GESTURE, | |
195 SCROLL_BLOCKS_ON_NONE)); | |
196 } | |
197 | |
198 TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { | |
199 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); | |
200 scoped_refptr<Layer> layer_tree_root = Layer::Create(); | |
201 scoped_refptr<Layer> scroll_layer = Layer::Create(); | |
202 scoped_refptr<Layer> content_layer = Layer::Create(); | |
203 scoped_refptr<Layer> scrollbar_layer = | |
204 PaintedScrollbarLayer::Create(scrollbar.Pass(), layer_tree_root->id()); | |
205 | |
206 // Choose bounds to give max_scroll_offset = (30, 50). | |
207 layer_tree_root->SetBounds(gfx::Size(70, 150)); | |
208 scroll_layer->SetScrollClipLayerId(layer_tree_root->id()); | |
209 scroll_layer->SetScrollOffset(gfx::ScrollOffset(10, 20)); | |
210 scroll_layer->SetBounds(gfx::Size(100, 200)); | |
211 content_layer->SetBounds(gfx::Size(100, 200)); | |
212 | |
213 layer_tree_host_->SetRootLayer(layer_tree_root); | |
214 layer_tree_root->AddChild(scroll_layer); | |
215 scroll_layer->AddChild(content_layer); | |
216 layer_tree_root->AddChild(scrollbar_layer); | |
217 scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id()); | |
218 scrollbar_layer->ToScrollbarLayer()->SetClipLayer(layer_tree_root->id()); | |
219 | |
220 layer_tree_root->SavePaintProperties(); | |
221 content_layer->SavePaintProperties(); | |
222 | |
223 LayerImpl* layer_impl_tree_root = | |
224 layer_tree_host_->CommitAndCreateLayerImplTree(); | |
225 | |
226 ScrollbarLayerImplBase* cc_scrollbar_layer = | |
227 static_cast<PaintedScrollbarLayerImpl*>( | |
228 layer_impl_tree_root->children()[1]); | |
229 | |
230 EXPECT_EQ(10.f, cc_scrollbar_layer->current_pos()); | |
231 EXPECT_EQ(30, cc_scrollbar_layer->maximum()); | |
232 | |
233 layer_tree_root->SetBounds(gfx::Size(700, 1500)); | |
234 layer_tree_root->SavePaintProperties(); | |
235 scroll_layer->SetBounds(gfx::Size(1000, 2000)); | |
236 scroll_layer->SetScrollOffset(gfx::ScrollOffset(100, 200)); | |
237 scroll_layer->SavePaintProperties(); | |
238 content_layer->SetBounds(gfx::Size(1000, 2000)); | |
239 content_layer->SavePaintProperties(); | |
240 | |
241 ScrollbarAnimationController* scrollbar_controller = | |
242 layer_impl_tree_root->scrollbar_animation_controller(); | |
243 layer_impl_tree_root = layer_tree_host_->CommitAndCreateLayerImplTree(); | |
244 EXPECT_EQ(scrollbar_controller, | |
245 layer_impl_tree_root->scrollbar_animation_controller()); | |
246 | |
247 EXPECT_EQ(100.f, cc_scrollbar_layer->current_pos()); | |
248 EXPECT_EQ(300, cc_scrollbar_layer->maximum()); | |
249 | |
250 LayerImpl* scroll_layer_impl = layer_impl_tree_root->children()[0]; | |
251 scroll_layer_impl->ScrollBy(gfx::Vector2d(12, 34)); | |
252 | |
253 EXPECT_EQ(112.f, cc_scrollbar_layer->current_pos()); | |
254 EXPECT_EQ(300, cc_scrollbar_layer->maximum()); | |
255 } | |
256 | |
257 #define UPDATE_AND_EXTRACT_LAYER_POINTERS() \ | |
258 do { \ | |
259 scrollbar_layer->UpdateInternalContentScale(); \ | |
260 scrollbar_layer->UpdateThumbAndTrackGeometry(); \ | |
261 root_clip_layer_impl = layer_tree_host_->CommitAndCreateLayerImplTree(); \ | |
262 root_layer_impl = root_clip_layer_impl->children()[0]; \ | |
263 scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>( \ | |
264 root_layer_impl->children()[1]); \ | |
265 scrollbar_layer_impl->ScrollbarParametersDidChange(false); \ | |
266 } while (false) | |
267 | |
268 TEST_F(ScrollbarLayerTest, UpdatePropertiesOfScrollBarWhenThumbRemoved) { | |
269 scoped_refptr<Layer> root_clip_layer = Layer::Create(); | |
270 scoped_refptr<Layer> root_layer = Layer::Create(); | |
271 scoped_refptr<Layer> content_layer = Layer::Create(); | |
272 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = | |
273 FakePaintedScrollbarLayer::Create(false, true, root_layer->id()); | |
274 | |
275 root_layer->SetScrollClipLayerId(root_clip_layer->id()); | |
276 // Give the root-clip a size that will result in MaxScrollOffset = (80, 0). | |
277 root_clip_layer->SetBounds(gfx::Size(20, 50)); | |
278 root_layer->SetBounds(gfx::Size(100, 50)); | |
279 content_layer->SetBounds(gfx::Size(100, 50)); | |
280 | |
281 layer_tree_host_->SetRootLayer(root_clip_layer); | |
282 root_clip_layer->AddChild(root_layer); | |
283 root_layer->AddChild(content_layer); | |
284 root_layer->AddChild(scrollbar_layer); | |
285 | |
286 root_layer->SetScrollOffset(gfx::ScrollOffset(0, 0)); | |
287 scrollbar_layer->SetBounds(gfx::Size(70, 10)); | |
288 scrollbar_layer->SetScrollLayer(root_layer->id()); | |
289 scrollbar_layer->SetClipLayer(root_clip_layer->id()); | |
290 scrollbar_layer->fake_scrollbar()->set_location(gfx::Point(20, 10)); | |
291 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); | |
292 scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10); | |
293 scrollbar_layer->fake_scrollbar()->set_thumb_length(4); | |
294 LayerImpl* root_clip_layer_impl = nullptr; | |
295 LayerImpl* root_layer_impl = nullptr; | |
296 PaintedScrollbarLayerImpl* scrollbar_layer_impl = nullptr; | |
297 | |
298 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
299 EXPECT_EQ(gfx::Rect(10, 0, 4, 10).ToString(), | |
300 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
301 | |
302 scrollbar_layer->fake_scrollbar()->set_has_thumb(false); | |
303 | |
304 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
305 EXPECT_EQ(gfx::Rect(10, 0, 0, 0).ToString(), | |
306 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
307 } | |
308 | |
309 TEST_F(ScrollbarLayerTest, ThumbRect) { | |
310 scoped_refptr<Layer> root_clip_layer = Layer::Create(); | |
311 scoped_refptr<Layer> root_layer = Layer::Create(); | |
312 scoped_refptr<Layer> content_layer = Layer::Create(); | |
313 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = | |
314 FakePaintedScrollbarLayer::Create(false, true, root_layer->id()); | |
315 | |
316 root_layer->SetScrollClipLayerId(root_clip_layer->id()); | |
317 // Give the root-clip a size that will result in MaxScrollOffset = (80, 0). | |
318 root_clip_layer->SetBounds(gfx::Size(20, 50)); | |
319 root_layer->SetBounds(gfx::Size(100, 50)); | |
320 content_layer->SetBounds(gfx::Size(100, 50)); | |
321 | |
322 layer_tree_host_->SetRootLayer(root_clip_layer); | |
323 root_clip_layer->AddChild(root_layer); | |
324 root_layer->AddChild(content_layer); | |
325 root_layer->AddChild(scrollbar_layer); | |
326 | |
327 root_layer->SetScrollOffset(gfx::ScrollOffset(0, 0)); | |
328 scrollbar_layer->SetBounds(gfx::Size(70, 10)); | |
329 scrollbar_layer->SetScrollLayer(root_layer->id()); | |
330 scrollbar_layer->SetClipLayer(root_clip_layer->id()); | |
331 scrollbar_layer->fake_scrollbar()->set_location(gfx::Point(20, 10)); | |
332 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); | |
333 scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10); | |
334 scrollbar_layer->fake_scrollbar()->set_thumb_length(4); | |
335 LayerImpl* root_clip_layer_impl = nullptr; | |
336 LayerImpl* root_layer_impl = nullptr; | |
337 PaintedScrollbarLayerImpl* scrollbar_layer_impl = nullptr; | |
338 | |
339 // Thumb is at the edge of the scrollbar (should be inset to | |
340 // the start of the track within the scrollbar layer's | |
341 // position). | |
342 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
343 EXPECT_EQ(gfx::Rect(10, 0, 4, 10).ToString(), | |
344 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
345 | |
346 // Under-scroll (thumb position should clamp and be unchanged). | |
347 root_layer->SetScrollOffset(gfx::ScrollOffset(-5, 0)); | |
348 | |
349 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
350 EXPECT_EQ(gfx::Rect(10, 0, 4, 10).ToString(), | |
351 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
352 | |
353 // Over-scroll (thumb position should clamp on the far side). | |
354 root_layer->SetScrollOffset(gfx::ScrollOffset(85, 0)); | |
355 | |
356 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
357 EXPECT_EQ(gfx::Rect(56, 0, 4, 10).ToString(), | |
358 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
359 | |
360 // Change thumb thickness and length. | |
361 scrollbar_layer->fake_scrollbar()->set_thumb_thickness(4); | |
362 scrollbar_layer->fake_scrollbar()->set_thumb_length(6); | |
363 | |
364 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
365 EXPECT_EQ(gfx::Rect(54, 0, 6, 4).ToString(), | |
366 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
367 | |
368 // Shrink the scrollbar layer to cover only the track. | |
369 scrollbar_layer->SetBounds(gfx::Size(50, 10)); | |
370 scrollbar_layer->fake_scrollbar()->set_location(gfx::Point(30, 10)); | |
371 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); | |
372 | |
373 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
374 EXPECT_EQ(gfx::Rect(44, 0, 6, 4).ToString(), | |
375 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
376 | |
377 // Shrink the track in the non-scrolling dimension so that it only covers the | |
378 // middle third of the scrollbar layer (this does not affect the thumb | |
379 // position). | |
380 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 12, 50, 6)); | |
381 | |
382 UPDATE_AND_EXTRACT_LAYER_POINTERS(); | |
383 EXPECT_EQ(gfx::Rect(44, 0, 6, 4).ToString(), | |
384 scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); | |
385 } | |
386 | |
387 TEST_F(ScrollbarLayerTest, SolidColorDrawQuads) { | |
388 const int kThumbThickness = 3; | |
389 const int kTrackStart = 1; | |
390 const int kTrackLength = 100; | |
391 | |
392 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true)); | |
393 LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( | |
394 layer_tree_host_.get(), scrollbar.Pass(), false, true, kThumbThickness, | |
395 kTrackStart); | |
396 ScrollbarLayerImplBase* scrollbar_layer_impl = | |
397 static_cast<SolidColorScrollbarLayerImpl*>( | |
398 layer_impl_tree_root->children()[1]); | |
399 scrollbar_layer_impl->SetBounds(gfx::Size(kTrackLength, kThumbThickness)); | |
400 scrollbar_layer_impl->SetCurrentPos(10.f); | |
401 scrollbar_layer_impl->SetMaximum(100); | |
402 scrollbar_layer_impl->SetVisibleToTotalLengthRatio(0.4f); | |
403 | |
404 // Thickness should be overridden to 3. | |
405 { | |
406 scoped_ptr<RenderPass> render_pass = RenderPass::Create(); | |
407 AppendQuadsData data; | |
408 scrollbar_layer_impl->AppendQuads(render_pass.get(), &data); | |
409 | |
410 const QuadList& quads = render_pass->quad_list; | |
411 ASSERT_EQ(1u, quads.size()); | |
412 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads.front()->material); | |
413 EXPECT_EQ(gfx::Rect(6, 0, 39, 3), quads.front()->rect); | |
414 } | |
415 | |
416 // Contents scale should scale the draw quad. | |
417 scrollbar_layer_impl->draw_properties().contents_scale_x = 2.f; | |
418 scrollbar_layer_impl->draw_properties().contents_scale_y = 2.f; | |
419 { | |
420 scoped_ptr<RenderPass> render_pass = RenderPass::Create(); | |
421 AppendQuadsData data; | |
422 scrollbar_layer_impl->AppendQuads(render_pass.get(), &data); | |
423 | |
424 const QuadList& quads = render_pass->quad_list; | |
425 ASSERT_EQ(1u, quads.size()); | |
426 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads.front()->material); | |
427 EXPECT_EQ(gfx::Rect(12, 0, 78, 6), quads.front()->rect); | |
428 } | |
429 scrollbar_layer_impl->draw_properties().contents_scale_x = 1.f; | |
430 scrollbar_layer_impl->draw_properties().contents_scale_y = 1.f; | |
431 | |
432 // For solid color scrollbars, position and size should reflect the | |
433 // current viewport state. | |
434 scrollbar_layer_impl->SetVisibleToTotalLengthRatio(0.2f); | |
435 { | |
436 scoped_ptr<RenderPass> render_pass = RenderPass::Create(); | |
437 AppendQuadsData data; | |
438 scrollbar_layer_impl->AppendQuads(render_pass.get(), &data); | |
439 | |
440 const QuadList& quads = render_pass->quad_list; | |
441 ASSERT_EQ(1u, quads.size()); | |
442 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads.front()->material); | |
443 EXPECT_EQ(gfx::Rect(8, 0, 19, 3), quads.front()->rect); | |
444 } | |
445 | |
446 // We shouldn't attempt div-by-zero when the maximum is zero. | |
447 scrollbar_layer_impl->SetCurrentPos(0.f); | |
448 scrollbar_layer_impl->SetMaximum(0); | |
449 { | |
450 scoped_ptr<RenderPass> render_pass = RenderPass::Create(); | |
451 AppendQuadsData data; | |
452 scrollbar_layer_impl->AppendQuads(render_pass.get(), &data); | |
453 | |
454 const QuadList& quads = render_pass->quad_list; | |
455 ASSERT_EQ(1u, quads.size()); | |
456 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads.front()->material); | |
457 EXPECT_EQ(gfx::Rect(1, 0, 19, 3), quads.front()->rect); | |
458 } | |
459 } | |
460 | |
461 TEST_F(ScrollbarLayerTest, LayerDrivenSolidColorDrawQuads) { | |
462 const int kThumbThickness = 3; | |
463 const int kTrackStart = 0; | |
464 const int kTrackLength = 10; | |
465 | |
466 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true)); | |
467 | |
468 { | |
469 scoped_refptr<Layer> layer_tree_root = Layer::Create(); | |
470 scoped_refptr<Layer> scroll_layer = Layer::Create(); | |
471 scroll_layer->SetScrollClipLayerId(layer_tree_root->id()); | |
472 scoped_refptr<Layer> child1 = Layer::Create(); | |
473 scoped_refptr<Layer> child2; | |
474 const bool kIsLeftSideVerticalScrollbar = false; | |
475 child2 = SolidColorScrollbarLayer::Create(scrollbar->Orientation(), | |
476 kThumbThickness, | |
477 kTrackStart, | |
478 kIsLeftSideVerticalScrollbar, | |
479 child1->id()); | |
480 child2->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id()); | |
481 child2->ToScrollbarLayer()->SetClipLayer(layer_tree_root->id()); | |
482 scroll_layer->AddChild(child1); | |
483 scroll_layer->InsertChild(child2, 1); | |
484 layer_tree_root->AddChild(scroll_layer); | |
485 layer_tree_host_->SetRootLayer(layer_tree_root); | |
486 } | |
487 LayerImpl* layer_impl_tree_root = | |
488 layer_tree_host_->CommitAndCreateLayerImplTree(); | |
489 LayerImpl* scroll_layer_impl = layer_impl_tree_root->children()[0]; | |
490 | |
491 ScrollbarLayerImplBase* scrollbar_layer_impl = | |
492 static_cast<PaintedScrollbarLayerImpl*>(scroll_layer_impl->children()[1]); | |
493 | |
494 // Choose layer bounds to give max_scroll_offset = (8, 8). | |
495 layer_impl_tree_root->SetBounds(gfx::Size(2, 2)); | |
496 scroll_layer_impl->SetBounds(gfx::Size(10, 10)); | |
497 scroll_layer_impl->ScrollBy(gfx::Vector2dF(4.f, 0.f)); | |
498 | |
499 scrollbar_layer_impl->SetBounds(gfx::Size(kTrackLength, kThumbThickness)); | |
500 scrollbar_layer_impl->SetCurrentPos(4.f); | |
501 scrollbar_layer_impl->SetMaximum(8); | |
502 | |
503 { | |
504 scoped_ptr<RenderPass> render_pass = RenderPass::Create(); | |
505 | |
506 AppendQuadsData data; | |
507 scrollbar_layer_impl->AppendQuads(render_pass.get(), &data); | |
508 | |
509 const QuadList& quads = render_pass->quad_list; | |
510 ASSERT_EQ(1u, quads.size()); | |
511 EXPECT_EQ(DrawQuad::SOLID_COLOR, quads.front()->material); | |
512 EXPECT_EQ(gfx::Rect(3, 0, 3, 3), quads.front()->rect); | |
513 } | |
514 } | |
515 | |
516 class ScrollbarLayerSolidColorThumbTest : public testing::Test { | |
517 public: | |
518 ScrollbarLayerSolidColorThumbTest() { | |
519 LayerTreeSettings layer_tree_settings; | |
520 host_impl_.reset(new FakeLayerTreeHostImpl(layer_tree_settings, &proxy_, | |
521 &shared_bitmap_manager_, | |
522 &task_graph_runner_)); | |
523 | |
524 const int kThumbThickness = 3; | |
525 const int kTrackStart = 0; | |
526 const bool kIsLeftSideVerticalScrollbar = false; | |
527 const bool kIsOverlayScrollbar = false; | |
528 | |
529 horizontal_scrollbar_layer_ = | |
530 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), | |
531 1, | |
532 HORIZONTAL, | |
533 kThumbThickness, | |
534 kTrackStart, | |
535 kIsLeftSideVerticalScrollbar, | |
536 kIsOverlayScrollbar); | |
537 vertical_scrollbar_layer_ = | |
538 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), | |
539 2, | |
540 VERTICAL, | |
541 kThumbThickness, | |
542 kTrackStart, | |
543 kIsLeftSideVerticalScrollbar, | |
544 kIsOverlayScrollbar); | |
545 } | |
546 | |
547 protected: | |
548 FakeImplProxy proxy_; | |
549 TestSharedBitmapManager shared_bitmap_manager_; | |
550 TestTaskGraphRunner task_graph_runner_; | |
551 scoped_ptr<FakeLayerTreeHostImpl> host_impl_; | |
552 scoped_ptr<SolidColorScrollbarLayerImpl> horizontal_scrollbar_layer_; | |
553 scoped_ptr<SolidColorScrollbarLayerImpl> vertical_scrollbar_layer_; | |
554 }; | |
555 | |
556 TEST_F(ScrollbarLayerSolidColorThumbTest, SolidColorThumbLength) { | |
557 horizontal_scrollbar_layer_->SetCurrentPos(0); | |
558 horizontal_scrollbar_layer_->SetMaximum(10); | |
559 | |
560 // Simple case - one third of the scrollable area is visible, so the thumb | |
561 // should be one third as long as the track. | |
562 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(0.33f); | |
563 horizontal_scrollbar_layer_->SetBounds(gfx::Size(100, 3)); | |
564 EXPECT_EQ(33, horizontal_scrollbar_layer_->ComputeThumbQuadRect().width()); | |
565 | |
566 // The thumb's length should never be less than its thickness. | |
567 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(0.01f); | |
568 horizontal_scrollbar_layer_->SetBounds(gfx::Size(100, 3)); | |
569 EXPECT_EQ(3, horizontal_scrollbar_layer_->ComputeThumbQuadRect().width()); | |
570 } | |
571 | |
572 TEST_F(ScrollbarLayerSolidColorThumbTest, SolidColorThumbPosition) { | |
573 horizontal_scrollbar_layer_->SetBounds(gfx::Size(100, 3)); | |
574 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(0.1f); | |
575 | |
576 horizontal_scrollbar_layer_->SetCurrentPos(0); | |
577 horizontal_scrollbar_layer_->SetMaximum(100); | |
578 EXPECT_EQ(0, horizontal_scrollbar_layer_->ComputeThumbQuadRect().x()); | |
579 EXPECT_EQ(10, horizontal_scrollbar_layer_->ComputeThumbQuadRect().width()); | |
580 | |
581 horizontal_scrollbar_layer_->SetCurrentPos(100); | |
582 // The thumb is 10px long and the track is 100px, so the maximum thumb | |
583 // position is 90px. | |
584 EXPECT_EQ(90, horizontal_scrollbar_layer_->ComputeThumbQuadRect().x()); | |
585 | |
586 horizontal_scrollbar_layer_->SetCurrentPos(80); | |
587 // The scroll position is 80% of the maximum, so the thumb's position should | |
588 // be at 80% of its maximum or 72px. | |
589 EXPECT_EQ(72, horizontal_scrollbar_layer_->ComputeThumbQuadRect().x()); | |
590 } | |
591 | |
592 TEST_F(ScrollbarLayerSolidColorThumbTest, SolidColorThumbVerticalAdjust) { | |
593 SolidColorScrollbarLayerImpl* layers[2] = | |
594 { horizontal_scrollbar_layer_.get(), vertical_scrollbar_layer_.get() }; | |
595 for (size_t i = 0; i < 2; ++i) { | |
596 layers[i]->SetVisibleToTotalLengthRatio(0.2f); | |
597 layers[i]->SetCurrentPos(25); | |
598 layers[i]->SetMaximum(100); | |
599 } | |
600 layers[0]->SetBounds(gfx::Size(100, 3)); | |
601 layers[1]->SetBounds(gfx::Size(3, 100)); | |
602 | |
603 EXPECT_EQ(gfx::RectF(20.f, 0.f, 20.f, 3.f), | |
604 horizontal_scrollbar_layer_->ComputeThumbQuadRect()); | |
605 EXPECT_EQ(gfx::RectF(0.f, 20.f, 3.f, 20.f), | |
606 vertical_scrollbar_layer_->ComputeThumbQuadRect()); | |
607 | |
608 horizontal_scrollbar_layer_->SetVerticalAdjust(10.f); | |
609 vertical_scrollbar_layer_->SetVerticalAdjust(10.f); | |
610 | |
611 // The vertical adjustment factor has two effects: | |
612 // 1.) Moves the horizontal scrollbar down | |
613 // 2.) Increases the vertical scrollbar's effective track length which both | |
614 // increases the thumb's length and its position within the track. | |
615 EXPECT_EQ(gfx::Rect(20.f, 10.f, 20.f, 3.f), | |
616 horizontal_scrollbar_layer_->ComputeThumbQuadRect()); | |
617 EXPECT_EQ(gfx::Rect(0.f, 22, 3.f, 22.f), | |
618 vertical_scrollbar_layer_->ComputeThumbQuadRect()); | |
619 } | |
620 | |
621 class ScrollbarLayerTestMaxTextureSize : public LayerTreeTest { | |
622 public: | |
623 ScrollbarLayerTestMaxTextureSize() {} | |
624 | |
625 void SetScrollbarBounds(const gfx::Size& bounds) { bounds_ = bounds; } | |
626 | |
627 void BeginTest() override { | |
628 scroll_layer_ = Layer::Create(); | |
629 layer_tree_host()->root_layer()->AddChild(scroll_layer_); | |
630 | |
631 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar); | |
632 scrollbar_layer_ = | |
633 PaintedScrollbarLayer::Create(scrollbar.Pass(), scroll_layer_->id()); | |
634 scrollbar_layer_->SetScrollLayer(scroll_layer_->id()); | |
635 scrollbar_layer_->SetLayerTreeHost(layer_tree_host()); | |
636 scrollbar_layer_->SetBounds(bounds_); | |
637 scrollbar_layer_->SetIsDrawable(true); | |
638 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_); | |
639 | |
640 PostSetNeedsCommitToMainThread(); | |
641 } | |
642 | |
643 void DidCommitAndDrawFrame() override { | |
644 const int kMaxTextureSize = | |
645 layer_tree_host()->GetRendererCapabilities().max_texture_size; | |
646 | |
647 // Check first that we're actually testing something. | |
648 EXPECT_GT(scrollbar_layer_->bounds().width(), kMaxTextureSize); | |
649 | |
650 EXPECT_EQ(scrollbar_layer_->internal_content_bounds().width(), | |
651 kMaxTextureSize - 1); | |
652 EXPECT_EQ(scrollbar_layer_->internal_content_bounds().height(), | |
653 kMaxTextureSize - 1); | |
654 | |
655 EndTest(); | |
656 } | |
657 | |
658 void AfterTest() override {} | |
659 | |
660 private: | |
661 scoped_refptr<PaintedScrollbarLayer> scrollbar_layer_; | |
662 scoped_refptr<Layer> scroll_layer_; | |
663 gfx::Size bounds_; | |
664 }; | |
665 | |
666 TEST_F(ScrollbarLayerTestMaxTextureSize, DirectRenderer) { | |
667 scoped_ptr<TestWebGraphicsContext3D> context = | |
668 TestWebGraphicsContext3D::Create(); | |
669 int max_size = 0; | |
670 context->getIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); | |
671 SetScrollbarBounds(gfx::Size(max_size + 100, max_size + 100)); | |
672 RunTest(true, false, true); | |
673 } | |
674 | |
675 TEST_F(ScrollbarLayerTestMaxTextureSize, DelegatingRenderer) { | |
676 scoped_ptr<TestWebGraphicsContext3D> context = | |
677 TestWebGraphicsContext3D::Create(); | |
678 int max_size = 0; | |
679 context->getIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); | |
680 SetScrollbarBounds(gfx::Size(max_size + 100, max_size + 100)); | |
681 RunTest(true, true, true); | |
682 } | |
683 | |
684 class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest { | |
685 public: | |
686 void TestResourceUpload(int num_updates, | |
687 size_t expected_resources, | |
688 int expected_created, | |
689 int expected_deleted, | |
690 bool use_solid_color_scrollbar) { | |
691 scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, false)); | |
692 scoped_refptr<Layer> layer_tree_root = Layer::Create(); | |
693 scoped_refptr<Layer> content_layer = Layer::Create(); | |
694 scoped_refptr<Layer> scrollbar_layer; | |
695 if (use_solid_color_scrollbar) { | |
696 const int kThumbThickness = 3; | |
697 const int kTrackStart = 0; | |
698 const bool kIsLeftSideVerticalScrollbar = false; | |
699 scrollbar_layer = | |
700 SolidColorScrollbarLayer::Create(scrollbar->Orientation(), | |
701 kThumbThickness, | |
702 kTrackStart, | |
703 kIsLeftSideVerticalScrollbar, | |
704 layer_tree_root->id()); | |
705 } else { | |
706 scrollbar_layer = PaintedScrollbarLayer::Create(scrollbar.Pass(), | |
707 layer_tree_root->id()); | |
708 } | |
709 layer_tree_root->AddChild(content_layer); | |
710 layer_tree_root->AddChild(scrollbar_layer); | |
711 | |
712 layer_tree_host_->SetRootLayer(layer_tree_root); | |
713 | |
714 scrollbar_layer->SetIsDrawable(true); | |
715 scrollbar_layer->SetBounds(gfx::Size(100, 100)); | |
716 layer_tree_root->SetScrollOffset(gfx::ScrollOffset(10, 20)); | |
717 layer_tree_root->SetBounds(gfx::Size(100, 200)); | |
718 content_layer->SetBounds(gfx::Size(100, 200)); | |
719 scrollbar_layer->draw_properties().content_bounds = gfx::Size(100, 200); | |
720 scrollbar_layer->draw_properties().visible_content_rect = | |
721 gfx::Rect(0, 0, 100, 200); | |
722 scrollbar_layer->CreateRenderSurface(); | |
723 scrollbar_layer->draw_properties().render_target = scrollbar_layer.get(); | |
724 | |
725 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
726 EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); | |
727 | |
728 ResourceUpdateQueue queue; | |
729 gfx::Rect screen_space_clip_rect; | |
730 OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); | |
731 | |
732 scrollbar_layer->SavePaintProperties(); | |
733 for (int update_counter = 0; update_counter < num_updates; update_counter++) | |
734 scrollbar_layer->Update(&queue, &occlusion_tracker); | |
735 | |
736 // A non-solid-color scrollbar should have requested two textures. | |
737 EXPECT_EQ(expected_resources, layer_tree_host_->UIResourceCount()); | |
738 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
739 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
740 | |
741 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
742 | |
743 scrollbar_layer->ClearRenderSurface(); | |
744 } | |
745 }; | |
746 | |
747 TEST_F(ScrollbarLayerTestResourceCreationAndRelease, ResourceUpload) { | |
748 bool use_solid_color_scrollbars = false; | |
749 TestResourceUpload(0, 0, 0, 0, use_solid_color_scrollbars); | |
750 int num_updates[3] = {1, 5, 10}; | |
751 int created = 0; | |
752 int deleted = 0; | |
753 for (int j = 0; j < 3; j++) { | |
754 created += num_updates[j] * 2; | |
755 deleted = created - 2; | |
756 TestResourceUpload(num_updates[j], 2, created, deleted, | |
757 use_solid_color_scrollbars); | |
758 } | |
759 } | |
760 | |
761 TEST_F(ScrollbarLayerTestResourceCreationAndRelease, | |
762 SolidColorNoResourceUpload) { | |
763 bool use_solid_color_scrollbars = true; | |
764 TestResourceUpload(0, 0, 0, 0, use_solid_color_scrollbars); | |
765 TestResourceUpload(1, 0, 0, 0, use_solid_color_scrollbars); | |
766 } | |
767 | |
768 TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { | |
769 gfx::Point scrollbar_location(0, 185); | |
770 scoped_refptr<Layer> layer_tree_root = Layer::Create(); | |
771 scoped_refptr<Layer> content_layer = Layer::Create(); | |
772 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = | |
773 FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id()); | |
774 | |
775 layer_tree_root->AddChild(content_layer); | |
776 layer_tree_root->AddChild(scrollbar_layer); | |
777 | |
778 layer_tree_host_->SetRootLayer(layer_tree_root); | |
779 | |
780 scrollbar_layer->SetIsDrawable(true); | |
781 scrollbar_layer->SetBounds(gfx::Size(100, 15)); | |
782 scrollbar_layer->SetPosition(scrollbar_location); | |
783 layer_tree_root->SetBounds(gfx::Size(100, 200)); | |
784 content_layer->SetBounds(gfx::Size(100, 200)); | |
785 | |
786 scrollbar_layer->draw_properties().content_bounds = gfx::Size(100, 200); | |
787 scrollbar_layer->draw_properties().visible_content_rect = | |
788 gfx::Rect(0, 0, 100, 200); | |
789 | |
790 scrollbar_layer->CreateRenderSurface(); | |
791 scrollbar_layer->draw_properties().render_target = scrollbar_layer.get(); | |
792 | |
793 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
794 EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); | |
795 | |
796 ResourceUpdateQueue queue; | |
797 gfx::Rect screen_space_clip_rect; | |
798 size_t resource_count; | |
799 int expected_created, expected_deleted; | |
800 OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); | |
801 scrollbar_layer->SavePaintProperties(); | |
802 | |
803 resource_count = 2; | |
804 expected_created = 2; | |
805 expected_deleted = 0; | |
806 EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
807 EXPECT_NE(0, scrollbar_layer->track_resource_id()); | |
808 EXPECT_NE(0, scrollbar_layer->thumb_resource_id()); | |
809 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
810 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
811 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
812 | |
813 resource_count = 0; | |
814 expected_created = 2; | |
815 expected_deleted = 2; | |
816 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0)); | |
817 EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
818 EXPECT_EQ(0, scrollbar_layer->track_resource_id()); | |
819 EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); | |
820 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
821 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
822 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
823 | |
824 resource_count = 0; | |
825 expected_created = 2; | |
826 expected_deleted = 2; | |
827 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0)); | |
828 EXPECT_FALSE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
829 EXPECT_EQ(0, scrollbar_layer->track_resource_id()); | |
830 EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); | |
831 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
832 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
833 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
834 | |
835 resource_count = 2; | |
836 expected_created = 4; | |
837 expected_deleted = 2; | |
838 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); | |
839 EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
840 EXPECT_NE(0, scrollbar_layer->track_resource_id()); | |
841 EXPECT_NE(0, scrollbar_layer->thumb_resource_id()); | |
842 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
843 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
844 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
845 | |
846 resource_count = 1; | |
847 expected_created = 5; | |
848 expected_deleted = 4; | |
849 scrollbar_layer->fake_scrollbar()->set_has_thumb(false); | |
850 EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
851 EXPECT_NE(0, scrollbar_layer->track_resource_id()); | |
852 EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); | |
853 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
854 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
855 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
856 | |
857 resource_count = 0; | |
858 expected_created = 5; | |
859 expected_deleted = 5; | |
860 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0)); | |
861 EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
862 EXPECT_EQ(0, scrollbar_layer->track_resource_id()); | |
863 EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); | |
864 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
865 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
866 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
867 | |
868 resource_count = 2; | |
869 expected_created = 7; | |
870 expected_deleted = 5; | |
871 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); | |
872 scrollbar_layer->fake_scrollbar()->set_has_thumb(true); | |
873 EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
874 EXPECT_NE(0, scrollbar_layer->track_resource_id()); | |
875 EXPECT_NE(0, scrollbar_layer->thumb_resource_id()); | |
876 | |
877 resource_count = 1; | |
878 expected_created = 8; | |
879 expected_deleted = 7; | |
880 scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); | |
881 scrollbar_layer->fake_scrollbar()->set_has_thumb(false); | |
882 scrollbar_layer->SetBounds(gfx::Size(90, 15)); | |
883 EXPECT_TRUE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
884 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
885 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
886 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
887 EXPECT_EQ( | |
888 gfx::Size(90, 15), | |
889 layer_tree_host_->ui_resource_size(scrollbar_layer->track_resource_id())); | |
890 | |
891 scrollbar_layer->ResetNeedsDisplayForTesting(); | |
892 EXPECT_FALSE(scrollbar_layer->Update(&queue, &occlusion_tracker)); | |
893 EXPECT_NE(0, scrollbar_layer->track_resource_id()); | |
894 EXPECT_EQ(0, scrollbar_layer->thumb_resource_id()); | |
895 EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount()); | |
896 EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated()); | |
897 EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted()); | |
898 | |
899 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
900 scrollbar_layer->ClearRenderSurface(); | |
901 } | |
902 | |
903 class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest { | |
904 public: | |
905 void TestResourceUpload(const float test_scale) { | |
906 gfx::Point scrollbar_location(0, 185); | |
907 scoped_refptr<Layer> layer_tree_root = Layer::Create(); | |
908 scoped_refptr<Layer> content_layer = Layer::Create(); | |
909 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = | |
910 FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id()); | |
911 | |
912 layer_tree_root->AddChild(content_layer); | |
913 layer_tree_root->AddChild(scrollbar_layer); | |
914 | |
915 layer_tree_host_->SetRootLayer(layer_tree_root); | |
916 | |
917 scrollbar_layer->SetIsDrawable(true); | |
918 scrollbar_layer->SetBounds(gfx::Size(100, 15)); | |
919 scrollbar_layer->SetPosition(scrollbar_location); | |
920 layer_tree_root->SetBounds(gfx::Size(100, 200)); | |
921 content_layer->SetBounds(gfx::Size(100, 200)); | |
922 gfx::SizeF scaled_size = | |
923 gfx::ScaleSize(scrollbar_layer->bounds(), test_scale, test_scale); | |
924 gfx::PointF scaled_location = | |
925 gfx::ScalePoint(scrollbar_layer->position(), test_scale, test_scale); | |
926 scrollbar_layer->draw_properties().content_bounds = | |
927 gfx::Size(scaled_size.width(), scaled_size.height()); | |
928 scrollbar_layer->draw_properties().contents_scale_x = test_scale; | |
929 scrollbar_layer->draw_properties().contents_scale_y = test_scale; | |
930 scrollbar_layer->draw_properties().visible_content_rect = | |
931 gfx::Rect(scaled_location.x(), | |
932 scaled_location.y(), | |
933 scaled_size.width(), | |
934 scaled_size.height()); | |
935 scrollbar_layer->CreateRenderSurface(); | |
936 scrollbar_layer->draw_properties().render_target = scrollbar_layer.get(); | |
937 | |
938 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
939 EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); | |
940 | |
941 ResourceUpdateQueue queue; | |
942 gfx::Rect screen_space_clip_rect; | |
943 OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); | |
944 scrollbar_layer->SavePaintProperties(); | |
945 scrollbar_layer->Update(&queue, &occlusion_tracker); | |
946 | |
947 // Verify that we have not generated any content uploads that are larger | |
948 // than their destination textures. | |
949 | |
950 gfx::Size track_size = layer_tree_host_->ui_resource_size( | |
951 scrollbar_layer->track_resource_id()); | |
952 gfx::Size thumb_size = layer_tree_host_->ui_resource_size( | |
953 scrollbar_layer->thumb_resource_id()); | |
954 | |
955 EXPECT_LE(track_size.width(), | |
956 scrollbar_layer->internal_content_bounds().width()); | |
957 EXPECT_LE(track_size.height(), | |
958 scrollbar_layer->internal_content_bounds().height()); | |
959 EXPECT_LE(thumb_size.width(), | |
960 scrollbar_layer->internal_content_bounds().width()); | |
961 EXPECT_LE(thumb_size.height(), | |
962 scrollbar_layer->internal_content_bounds().height()); | |
963 | |
964 testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
965 | |
966 scrollbar_layer->ClearRenderSurface(); | |
967 } | |
968 }; | |
969 | |
970 TEST_F(ScaledScrollbarLayerTestResourceCreation, ScaledResourceUpload) { | |
971 // Pick a test scale that moves the scrollbar's (non-zero) position to | |
972 // a non-pixel-aligned location. | |
973 TestResourceUpload(.041f); | |
974 TestResourceUpload(1.41f); | |
975 TestResourceUpload(4.1f); | |
976 } | |
977 | |
978 class ScaledScrollbarLayerTestScaledRasterization : public ScrollbarLayerTest { | |
979 public: | |
980 void TestScale(const gfx::Rect scrollbar_rect, const float test_scale) { | |
981 bool paint_during_update = true; | |
982 bool has_thumb = false; | |
983 scoped_refptr<Layer> layer_tree_root = Layer::Create(); | |
984 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = | |
985 FakePaintedScrollbarLayer::Create(paint_during_update, | |
986 has_thumb, | |
987 layer_tree_root->id()); | |
988 | |
989 layer_tree_root->AddChild(scrollbar_layer); | |
990 | |
991 layer_tree_host_->SetRootLayer(layer_tree_root); | |
992 | |
993 scrollbar_layer->SetBounds(scrollbar_rect.size()); | |
994 scrollbar_layer->SetPosition(scrollbar_rect.origin()); | |
995 scrollbar_layer->fake_scrollbar()->set_location(scrollbar_rect.origin()); | |
996 scrollbar_layer->fake_scrollbar()->set_track_rect(scrollbar_rect); | |
997 gfx::SizeF scaled_size = | |
998 gfx::ScaleSize(scrollbar_layer->bounds(), test_scale, test_scale); | |
999 gfx::PointF scaled_location = | |
1000 gfx::ScalePoint(scrollbar_layer->position(), test_scale, test_scale); | |
1001 scrollbar_layer->draw_properties().content_bounds = | |
1002 gfx::Size(scaled_size.width(), scaled_size.height()); | |
1003 scrollbar_layer->draw_properties().contents_scale_x = test_scale; | |
1004 scrollbar_layer->draw_properties().contents_scale_y = test_scale; | |
1005 scrollbar_layer->draw_properties().visible_content_rect = | |
1006 gfx::Rect(scaled_location.x(), | |
1007 scaled_location.y(), | |
1008 scaled_size.width(), | |
1009 scaled_size.height()); | |
1010 | |
1011 ResourceUpdateQueue queue; | |
1012 gfx::Rect screen_space_clip_rect; | |
1013 OcclusionTracker<Layer> occlusion_tracker(screen_space_clip_rect); | |
1014 scrollbar_layer->SavePaintProperties(); | |
1015 | |
1016 scrollbar_layer->Update(&queue, &occlusion_tracker); | |
1017 | |
1018 UIResourceBitmap* bitmap = layer_tree_host_->ui_resource_bitmap( | |
1019 scrollbar_layer->track_resource_id()); | |
1020 | |
1021 DCHECK(bitmap); | |
1022 | |
1023 AutoLockUIResourceBitmap locked_bitmap(*bitmap); | |
1024 | |
1025 const SkColor* pixels = | |
1026 reinterpret_cast<const SkColor*>(locked_bitmap.GetPixels()); | |
1027 SkColor color = argb_to_skia( | |
1028 scrollbar_layer->fake_scrollbar()->paint_fill_color()); | |
1029 int width = bitmap->GetSize().width(); | |
1030 int height = bitmap->GetSize().height(); | |
1031 | |
1032 // Make sure none of the corners of the bitmap were inadvertently clipped. | |
1033 EXPECT_EQ(color, pixels[0]) | |
1034 << "Top left pixel doesn't match scrollbar color."; | |
1035 | |
1036 EXPECT_EQ(color, pixels[width - 1]) | |
1037 << "Top right pixel doesn't match scrollbar color."; | |
1038 | |
1039 EXPECT_EQ(color, pixels[width * (height - 1)]) | |
1040 << "Bottom left pixel doesn't match scrollbar color."; | |
1041 | |
1042 EXPECT_EQ(color, pixels[width * height - 1]) | |
1043 << "Bottom right pixel doesn't match scrollbar color."; | |
1044 } | |
1045 | |
1046 protected: | |
1047 // On Android, Skia uses ABGR | |
1048 static SkColor argb_to_skia(SkColor c) { | |
1049 return (SkColorGetA(c) << SK_A32_SHIFT) | | |
1050 (SkColorGetR(c) << SK_R32_SHIFT) | | |
1051 (SkColorGetG(c) << SK_G32_SHIFT) | | |
1052 (SkColorGetB(c) << SK_B32_SHIFT); | |
1053 } | |
1054 }; | |
1055 | |
1056 TEST_F(ScaledScrollbarLayerTestScaledRasterization, TestLostPrecisionInClip) { | |
1057 // Try rasterization at coordinates and scale that caused problematic | |
1058 // rounding and clipping errors. | |
1059 // Vertical Scrollbars. | |
1060 TestScale(gfx::Rect(1240, 0, 15, 1333), 2.7754839f); | |
1061 TestScale(gfx::Rect(1240, 0, 15, 677), 2.46677136f); | |
1062 | |
1063 // Horizontal Scrollbars. | |
1064 TestScale(gfx::Rect(0, 1240, 1333, 15), 2.7754839f); | |
1065 TestScale(gfx::Rect(0, 1240, 677, 15), 2.46677136f); | |
1066 } | |
1067 | |
1068 } // namespace | |
1069 } // namespace cc | |
OLD | NEW |