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 "cc/scrollbar_layer.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/debug/trace_event.h" | |
9 #include "cc/resources/caching_bitmap_content_layer_updater.h" | |
10 #include "cc/resources/layer_painter.h" | |
11 #include "cc/resources/prioritized_resource.h" | |
12 #include "cc/resources/resource_update_queue.h" | |
13 #include "cc/scrollbar_layer_impl.h" | |
14 #include "cc/trees/layer_tree_host.h" | |
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebRect.h" | |
16 #include "ui/gfx/rect_conversions.h" | |
17 | |
18 namespace cc { | |
19 | |
20 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( | |
21 LayerTreeImpl* tree_impl) { | |
22 return ScrollbarLayerImpl::Create( | |
23 tree_impl, | |
24 id(), | |
25 ScrollbarGeometryFixedThumb::create(make_scoped_ptr(geometry_->clone()))) | |
26 .PassAs<LayerImpl>(); | |
27 } | |
28 | |
29 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( | |
30 scoped_ptr<WebKit::WebScrollbar> scrollbar, | |
31 scoped_ptr<ScrollbarThemePainter> painter, | |
32 scoped_ptr<WebKit::WebScrollbarThemeGeometry> geometry, | |
33 int scrollLayerId) { | |
34 return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(), | |
35 painter.Pass(), | |
36 geometry.Pass(), | |
37 scrollLayerId)); | |
38 } | |
39 | |
40 ScrollbarLayer::ScrollbarLayer( | |
41 scoped_ptr<WebKit::WebScrollbar> scrollbar, | |
42 scoped_ptr<ScrollbarThemePainter> painter, | |
43 scoped_ptr<WebKit::WebScrollbarThemeGeometry> geometry, | |
44 int scrollLayerId) | |
45 : scrollbar_(scrollbar.Pass()), | |
46 painter_(painter.Pass()), | |
47 geometry_(geometry.Pass()), | |
48 scroll_layer_id_(scrollLayerId), | |
49 texture_format_(GL_INVALID_ENUM) { | |
50 if (!scrollbar_->isOverlay()) | |
51 SetShouldScrollOnMainThread(true); | |
52 } | |
53 | |
54 ScrollbarLayer::~ScrollbarLayer() {} | |
55 | |
56 void ScrollbarLayer::SetScrollLayerId(int id) { | |
57 if (id == scroll_layer_id_) | |
58 return; | |
59 | |
60 scroll_layer_id_ = id; | |
61 SetNeedsFullTreeSync(); | |
62 } | |
63 | |
64 bool ScrollbarLayer::OpacityCanAnimateOnImplThread() const { | |
65 return scrollbar_->isOverlay(); | |
66 } | |
67 | |
68 WebKit::WebScrollbar::Orientation ScrollbarLayer::Orientation() const { | |
69 return scrollbar_->orientation(); | |
70 } | |
71 | |
72 int ScrollbarLayer::MaxTextureSize() { | |
73 DCHECK(layer_tree_host()); | |
74 return layer_tree_host()->GetRendererCapabilities().max_texture_size; | |
75 } | |
76 | |
77 float ScrollbarLayer::ClampScaleToMaxTextureSize(float scale) { | |
78 if (layer_tree_host()->settings().solidColorScrollbars) | |
79 return scale; | |
80 | |
81 // If the scaled content_bounds() is bigger than the max texture size of the | |
82 // device, we need to clamp it by rescaling, since content_bounds() is used | |
83 // below to set the texture size. | |
84 gfx::Size scaled_bounds = ComputeContentBoundsForScale(scale, scale); | |
85 if (scaled_bounds.width() > MaxTextureSize() || | |
86 scaled_bounds.height() > MaxTextureSize()) { | |
87 if (scaled_bounds.width() > scaled_bounds.height()) | |
88 return (MaxTextureSize() - 1) / static_cast<float>(bounds().width()); | |
89 else | |
90 return (MaxTextureSize() - 1) / static_cast<float>(bounds().height()); | |
91 } | |
92 return scale; | |
93 } | |
94 | |
95 void ScrollbarLayer::CalculateContentsScale(float ideal_contents_scale, | |
96 bool animating_transform_to_screen, | |
97 float* contents_scale_x, | |
98 float* contents_scale_y, | |
99 gfx::Size* contentBounds) { | |
100 ContentsScalingLayer::CalculateContentsScale( | |
101 ClampScaleToMaxTextureSize(ideal_contents_scale), | |
102 animating_transform_to_screen, | |
103 contents_scale_x, | |
104 contents_scale_y, | |
105 contentBounds); | |
106 DCHECK_LE(contentBounds->width(), MaxTextureSize()); | |
107 DCHECK_LE(contentBounds->height(), MaxTextureSize()); | |
108 } | |
109 | |
110 void ScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { | |
111 ContentsScalingLayer::PushPropertiesTo(layer); | |
112 | |
113 ScrollbarLayerImpl* scrollbar_layer = static_cast<ScrollbarLayerImpl*>(layer); | |
114 | |
115 scrollbar_layer->SetScrollbarData(scrollbar_.get()); | |
116 scrollbar_layer->SetThumbSize(thumb_size_); | |
117 | |
118 if (back_track_ && back_track_->texture()->haveBackingTexture()) { | |
119 scrollbar_layer->set_back_track_resource_id( | |
120 back_track_->texture()->resourceId()); | |
121 } else { | |
122 scrollbar_layer->set_back_track_resource_id(0); | |
123 } | |
124 | |
125 if (fore_track_ && fore_track_->texture()->haveBackingTexture()) { | |
126 scrollbar_layer->set_fore_track_resource_id( | |
127 fore_track_->texture()->resourceId()); | |
128 } else { | |
129 scrollbar_layer->set_fore_track_resource_id(0); | |
130 } | |
131 | |
132 if (thumb_ && thumb_->texture()->haveBackingTexture()) | |
133 scrollbar_layer->set_thumb_resource_id(thumb_->texture()->resourceId()); | |
134 else | |
135 scrollbar_layer->set_thumb_resource_id(0); | |
136 | |
137 // Pinch zoom scrollbarLayerImpl does not get its scroll_layer_id_ | |
138 // set in LayerImpl, so we need to push it here. | |
139 if (scroll_layer_id_ == Layer::PINCH_ZOOM_ROOT_SCROLL_LAYER_ID) | |
140 scrollbar_layer->set_scroll_layer_id(scroll_layer_id_); | |
141 } | |
142 | |
143 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { | |
144 return this; | |
145 } | |
146 | |
147 class ScrollbarBackgroundPainter : public LayerPainter { | |
148 public: | |
149 static scoped_ptr<ScrollbarBackgroundPainter> Create( | |
150 WebKit::WebScrollbar* scrollbar, | |
151 ScrollbarThemePainter *painter, | |
152 WebKit::WebScrollbarThemeGeometry* geometry, | |
153 WebKit::WebScrollbar::ScrollbarPart trackPart) { | |
154 return make_scoped_ptr(new ScrollbarBackgroundPainter(scrollbar, | |
155 painter, | |
156 geometry, | |
157 trackPart)); | |
158 } | |
159 | |
160 virtual void Paint(SkCanvas* canvas, | |
161 gfx::Rect content_rect, | |
162 gfx::RectF* opaque) OVERRIDE { | |
163 // The following is a simplification of ScrollbarThemeComposite::paint. | |
164 painter_->PaintScrollbarBackground(canvas, content_rect); | |
165 | |
166 if (geometry_->hasButtons(scrollbar_)) { | |
167 gfx::Rect back_button_start_paint_rect = | |
168 geometry_->backButtonStartRect(scrollbar_); | |
169 painter_->PaintBackButtonStart(canvas, back_button_start_paint_rect); | |
170 | |
171 gfx::Rect back_button_end_paint_rect = | |
172 geometry_->backButtonEndRect(scrollbar_); | |
173 painter_->PaintBackButtonEnd(canvas, back_button_end_paint_rect); | |
174 | |
175 gfx::Rect forward_button_start_paint_rect = | |
176 geometry_->forwardButtonStartRect(scrollbar_); | |
177 painter_->PaintForwardButtonStart(canvas, | |
178 forward_button_start_paint_rect); | |
179 | |
180 gfx::Rect forward_button_end_paint_rect = | |
181 geometry_->forwardButtonEndRect(scrollbar_); | |
182 painter_->PaintForwardButtonEnd(canvas, forward_button_end_paint_rect); | |
183 } | |
184 | |
185 gfx::Rect track_paint_rect = geometry_->trackRect(scrollbar_); | |
186 painter_->PaintTrackBackground(canvas, track_paint_rect); | |
187 | |
188 bool thumb_present = geometry_->hasThumb(scrollbar_); | |
189 if (thumb_present) { | |
190 if (track_part_ == WebKit::WebScrollbar::ForwardTrackPart) | |
191 painter_->PaintForwardTrackPart(canvas, track_paint_rect); | |
192 else | |
193 painter_->PaintBackTrackPart(canvas, track_paint_rect); | |
194 } | |
195 | |
196 painter_->PaintTickmarks(canvas, track_paint_rect); | |
197 } | |
198 private: | |
199 ScrollbarBackgroundPainter(WebKit::WebScrollbar* scrollbar, | |
200 ScrollbarThemePainter *painter, | |
201 WebKit::WebScrollbarThemeGeometry* geometry, | |
202 WebKit::WebScrollbar::ScrollbarPart trackPart) | |
203 : scrollbar_(scrollbar), | |
204 painter_(painter), | |
205 geometry_(geometry), | |
206 track_part_(trackPart) {} | |
207 | |
208 WebKit::WebScrollbar* scrollbar_; | |
209 ScrollbarThemePainter* painter_; | |
210 WebKit::WebScrollbarThemeGeometry* geometry_; | |
211 WebKit::WebScrollbar::ScrollbarPart track_part_; | |
212 | |
213 DISALLOW_COPY_AND_ASSIGN(ScrollbarBackgroundPainter); | |
214 }; | |
215 | |
216 class ScrollbarThumbPainter : public LayerPainter { | |
217 public: | |
218 static scoped_ptr<ScrollbarThumbPainter> Create( | |
219 WebKit::WebScrollbar* scrollbar, | |
220 ScrollbarThemePainter* painter, | |
221 WebKit::WebScrollbarThemeGeometry* geometry) { | |
222 return make_scoped_ptr(new ScrollbarThumbPainter(scrollbar, | |
223 painter, | |
224 geometry)); | |
225 } | |
226 | |
227 virtual void Paint(SkCanvas* canvas, | |
228 gfx::Rect content_rect, | |
229 gfx::RectF* opaque) OVERRIDE { | |
230 // Consider the thumb to be at the origin when painting. | |
231 gfx::Rect thumb_rect = geometry_->thumbRect(scrollbar_); | |
232 painter_->PaintThumb(canvas, gfx::Rect(thumb_rect.size())); | |
233 } | |
234 | |
235 private: | |
236 ScrollbarThumbPainter(WebKit::WebScrollbar* scrollbar, | |
237 ScrollbarThemePainter* painter, | |
238 WebKit::WebScrollbarThemeGeometry* geometry) | |
239 : scrollbar_(scrollbar), | |
240 painter_(painter), | |
241 geometry_(geometry) {} | |
242 | |
243 WebKit::WebScrollbar* scrollbar_; | |
244 ScrollbarThemePainter* painter_; | |
245 WebKit::WebScrollbarThemeGeometry* geometry_; | |
246 | |
247 DISALLOW_COPY_AND_ASSIGN(ScrollbarThumbPainter); | |
248 }; | |
249 | |
250 void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { | |
251 if (!host || host != layer_tree_host()) { | |
252 back_track_updater_ = NULL; | |
253 back_track_.reset(); | |
254 thumb_updater_ = NULL; | |
255 thumb_.reset(); | |
256 } | |
257 | |
258 ContentsScalingLayer::SetLayerTreeHost(host); | |
259 } | |
260 | |
261 void ScrollbarLayer::CreateUpdaterIfNeeded() { | |
262 if (layer_tree_host()->settings().solidColorScrollbars) | |
263 return; | |
264 | |
265 texture_format_ = | |
266 layer_tree_host()->GetRendererCapabilities().best_texture_format; | |
267 | |
268 if (!back_track_updater_) { | |
269 back_track_updater_ = CachingBitmapContentLayerUpdater::Create( | |
270 ScrollbarBackgroundPainter::Create( | |
271 scrollbar_.get(), | |
272 painter_.get(), | |
273 geometry_.get(), | |
274 WebKit::WebScrollbar::BackTrackPart).PassAs<LayerPainter>()); | |
275 } | |
276 if (!back_track_) { | |
277 back_track_ = back_track_updater_->CreateResource( | |
278 layer_tree_host()->contents_texture_manager()); | |
279 } | |
280 | |
281 // Only create two-part track if we think the two parts could be different in | |
282 // appearance. | |
283 if (scrollbar_->isCustomScrollbar()) { | |
284 if (!fore_track_updater_) { | |
285 fore_track_updater_ = CachingBitmapContentLayerUpdater::Create( | |
286 ScrollbarBackgroundPainter::Create( | |
287 scrollbar_.get(), | |
288 painter_.get(), | |
289 geometry_.get(), | |
290 WebKit::WebScrollbar::ForwardTrackPart).PassAs<LayerPainter>()); | |
291 } | |
292 if (!fore_track_) { | |
293 fore_track_ = fore_track_updater_->CreateResource( | |
294 layer_tree_host()->contents_texture_manager()); | |
295 } | |
296 } | |
297 | |
298 if (!thumb_updater_) { | |
299 thumb_updater_ = CachingBitmapContentLayerUpdater::Create( | |
300 ScrollbarThumbPainter::Create(scrollbar_.get(), | |
301 painter_.get(), | |
302 geometry_.get()).PassAs<LayerPainter>()); | |
303 } | |
304 if (!thumb_) { | |
305 thumb_ = thumb_updater_->CreateResource( | |
306 layer_tree_host()->contents_texture_manager()); | |
307 } | |
308 } | |
309 | |
310 void ScrollbarLayer::UpdatePart(CachingBitmapContentLayerUpdater* painter, | |
311 LayerUpdater::Resource* resource, | |
312 gfx::Rect rect, | |
313 ResourceUpdateQueue* queue, | |
314 RenderingStats* stats) { | |
315 if (layer_tree_host()->settings().solidColorScrollbars) | |
316 return; | |
317 | |
318 // Skip painting and uploading if there are no invalidations and | |
319 // we already have valid texture data. | |
320 if (resource->texture()->haveBackingTexture() && | |
321 resource->texture()->size() == rect.size() && | |
322 !is_dirty()) | |
323 return; | |
324 | |
325 // We should always have enough memory for UI. | |
326 DCHECK(resource->texture()->canAcquireBackingTexture()); | |
327 if (!resource->texture()->canAcquireBackingTexture()) | |
328 return; | |
329 | |
330 // Paint and upload the entire part. | |
331 gfx::Rect painted_opaque_rect; | |
332 painter->PrepareToUpdate(rect, | |
333 rect.size(), | |
334 contents_scale_x(), | |
335 contents_scale_y(), | |
336 &painted_opaque_rect, | |
337 stats); | |
338 if (!painter->pixels_did_change() && | |
339 resource->texture()->haveBackingTexture()) { | |
340 TRACE_EVENT_INSTANT0("cc", | |
341 "ScrollbarLayer::updatePart no texture upload needed"); | |
342 return; | |
343 } | |
344 | |
345 bool partial_updates_allowed = | |
346 layer_tree_host()->settings().maxPartialTextureUpdates > 0; | |
347 if (!partial_updates_allowed) | |
348 resource->texture()->returnBackingTexture(); | |
349 | |
350 gfx::Vector2d dest_offset(0, 0); | |
351 resource->Update(queue, rect, dest_offset, partial_updates_allowed, stats); | |
352 } | |
353 | |
354 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( | |
355 gfx::Rect layer_rect) const { | |
356 // Don't intersect with the bounds as in LayerRectToContentRect() because | |
357 // layer_rect here might be in coordinates of the containing layer. | |
358 gfx::RectF content_rect = gfx::ScaleRect(layer_rect, | |
359 contents_scale_y(), | |
360 contents_scale_y()); | |
361 return gfx::ToEnclosingRect(content_rect); | |
362 } | |
363 | |
364 void ScrollbarLayer::SetTexturePriorities( | |
365 const PriorityCalculator& priority_calc) { | |
366 if (layer_tree_host()->settings().solidColorScrollbars) | |
367 return; | |
368 | |
369 if (content_bounds().IsEmpty()) | |
370 return; | |
371 DCHECK_LE(content_bounds().width(), MaxTextureSize()); | |
372 DCHECK_LE(content_bounds().height(), MaxTextureSize()); | |
373 | |
374 CreateUpdaterIfNeeded(); | |
375 | |
376 bool draws_to_root = !render_target()->parent(); | |
377 if (back_track_) { | |
378 back_track_->texture()->setDimensions(content_bounds(), texture_format_); | |
379 back_track_->texture()->setRequestPriority( | |
380 PriorityCalculator::UIPriority(draws_to_root)); | |
381 } | |
382 if (fore_track_) { | |
383 fore_track_->texture()->setDimensions(content_bounds(), texture_format_); | |
384 fore_track_->texture()->setRequestPriority( | |
385 PriorityCalculator::UIPriority(draws_to_root)); | |
386 } | |
387 if (thumb_) { | |
388 gfx::Rect thumb_layer_rect = geometry_->thumbRect(scrollbar_.get()); | |
389 gfx::Size thumb_size = | |
390 ScrollbarLayerRectToContentRect(thumb_layer_rect).size(); | |
391 thumb_->texture()->setDimensions(thumb_size, texture_format_); | |
392 thumb_->texture()->setRequestPriority( | |
393 PriorityCalculator::UIPriority(draws_to_root)); | |
394 } | |
395 } | |
396 | |
397 void ScrollbarLayer::Update(ResourceUpdateQueue* queue, | |
398 const OcclusionTracker* occlusion, | |
399 RenderingStats* stats) { | |
400 ContentsScalingLayer::Update(queue, occlusion, stats); | |
401 | |
402 dirty_rect_.Union(update_rect_); | |
403 if (content_bounds().IsEmpty()) | |
404 return; | |
405 if (visible_content_rect().IsEmpty()) | |
406 return; | |
407 | |
408 CreateUpdaterIfNeeded(); | |
409 | |
410 gfx::Rect content_rect = ScrollbarLayerRectToContentRect( | |
411 gfx::Rect(scrollbar_->location(), bounds())); | |
412 UpdatePart(back_track_updater_.get(), | |
413 back_track_.get(), | |
414 content_rect, | |
415 queue, | |
416 stats); | |
417 if (fore_track_ && fore_track_updater_) { | |
418 UpdatePart(fore_track_updater_.get(), | |
419 fore_track_.get(), | |
420 content_rect, | |
421 queue, | |
422 stats); | |
423 } | |
424 | |
425 // Consider the thumb to be at the origin when painting. | |
426 gfx::Rect thumb_rect = geometry_->thumbRect(scrollbar_.get()); | |
427 thumb_size_ = thumb_rect.size(); | |
428 gfx::Rect origin_thumb_rect = | |
429 ScrollbarLayerRectToContentRect(gfx::Rect(thumb_rect.size())); | |
430 if (!origin_thumb_rect.IsEmpty()) { | |
431 UpdatePart(thumb_updater_.get(), | |
432 thumb_.get(), | |
433 origin_thumb_rect, | |
434 queue, | |
435 stats); | |
436 } | |
437 | |
438 dirty_rect_ = gfx::RectF(); | |
439 } | |
440 | |
441 } // namespace cc | |
OLD | NEW |