Revert 201510 "Revert 201498 "Add devtools instrumentation for c..."
[chromium-blink-merge.git] / cc / layers / scrollbar_layer.cc
blobed25d2ed97d51d0dbeff225c47ce48204e344b8f
2 // Copyright 2012 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
6 #include "cc/layers/scrollbar_layer.h"
8 #include "base/auto_reset.h"
9 #include "base/basictypes.h"
10 #include "base/debug/trace_event.h"
11 #include "cc/layers/scrollbar_layer_impl.h"
12 #include "cc/resources/caching_bitmap_content_layer_updater.h"
13 #include "cc/resources/layer_painter.h"
14 #include "cc/resources/prioritized_resource.h"
15 #include "cc/resources/resource_update_queue.h"
16 #include "cc/trees/layer_tree_host.h"
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebRect.h"
18 #include "ui/gfx/rect_conversions.h"
20 namespace cc {
22 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl(
23 LayerTreeImpl* tree_impl) {
24 return ScrollbarLayerImpl::Create(
25 tree_impl,
26 id(),
27 ScrollbarGeometryFixedThumb::Create(make_scoped_ptr(geometry_->clone())))
28 .PassAs<LayerImpl>();
31 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create(
32 scoped_ptr<WebKit::WebScrollbar> scrollbar,
33 scoped_ptr<ScrollbarThemePainter> painter,
34 scoped_ptr<WebKit::WebScrollbarThemeGeometry> geometry,
35 int scroll_layer_id) {
36 return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(),
37 painter.Pass(),
38 geometry.Pass(),
39 scroll_layer_id));
42 ScrollbarLayer::ScrollbarLayer(
43 scoped_ptr<WebKit::WebScrollbar> scrollbar,
44 scoped_ptr<ScrollbarThemePainter> painter,
45 scoped_ptr<WebKit::WebScrollbarThemeGeometry> geometry,
46 int scroll_layer_id)
47 : scrollbar_(scrollbar.Pass()),
48 painter_(painter.Pass()),
49 geometry_(geometry.Pass()),
50 scroll_layer_id_(scroll_layer_id),
51 texture_format_(GL_INVALID_ENUM) {
52 if (!scrollbar_->isOverlay())
53 SetShouldScrollOnMainThread(true);
56 ScrollbarLayer::~ScrollbarLayer() {}
58 void ScrollbarLayer::SetScrollLayerId(int id) {
59 if (id == scroll_layer_id_)
60 return;
62 scroll_layer_id_ = id;
63 SetNeedsFullTreeSync();
66 bool ScrollbarLayer::OpacityCanAnimateOnImplThread() const {
67 return scrollbar_->isOverlay();
70 WebKit::WebScrollbar::Orientation ScrollbarLayer::Orientation() const {
71 return scrollbar_->orientation();
74 int ScrollbarLayer::MaxTextureSize() {
75 DCHECK(layer_tree_host());
76 return layer_tree_host()->GetRendererCapabilities().max_texture_size;
79 float ScrollbarLayer::ClampScaleToMaxTextureSize(float scale) {
80 if (layer_tree_host()->settings().solid_color_scrollbars)
81 return scale;
83 // If the scaled content_bounds() is bigger than the max texture size of the
84 // device, we need to clamp it by rescaling, since content_bounds() is used
85 // below to set the texture size.
86 gfx::Size scaled_bounds = ComputeContentBoundsForScale(scale, scale);
87 if (scaled_bounds.width() > MaxTextureSize() ||
88 scaled_bounds.height() > MaxTextureSize()) {
89 if (scaled_bounds.width() > scaled_bounds.height())
90 return (MaxTextureSize() - 1) / static_cast<float>(bounds().width());
91 else
92 return (MaxTextureSize() - 1) / static_cast<float>(bounds().height());
94 return scale;
97 void ScrollbarLayer::CalculateContentsScale(float ideal_contents_scale,
98 float device_scale_factor,
99 float page_scale_factor,
100 bool animating_transform_to_screen,
101 float* contents_scale_x,
102 float* contents_scale_y,
103 gfx::Size* content_bounds) {
104 ContentsScalingLayer::CalculateContentsScale(
105 ClampScaleToMaxTextureSize(ideal_contents_scale),
106 device_scale_factor,
107 page_scale_factor,
108 animating_transform_to_screen,
109 contents_scale_x,
110 contents_scale_y,
111 content_bounds);
114 void ScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
115 ContentsScalingLayer::PushPropertiesTo(layer);
117 ScrollbarLayerImpl* scrollbar_layer = static_cast<ScrollbarLayerImpl*>(layer);
119 scrollbar_layer->SetScrollbarData(scrollbar_.get());
120 scrollbar_layer->SetThumbSize(thumb_size_);
122 if (back_track_ && back_track_->texture()->have_backing_texture()) {
123 scrollbar_layer->set_back_track_resource_id(
124 back_track_->texture()->resource_id());
125 } else {
126 scrollbar_layer->set_back_track_resource_id(0);
129 if (fore_track_ && fore_track_->texture()->have_backing_texture()) {
130 scrollbar_layer->set_fore_track_resource_id(
131 fore_track_->texture()->resource_id());
132 } else {
133 scrollbar_layer->set_fore_track_resource_id(0);
136 if (thumb_ && thumb_->texture()->have_backing_texture())
137 scrollbar_layer->set_thumb_resource_id(thumb_->texture()->resource_id());
138 else
139 scrollbar_layer->set_thumb_resource_id(0);
142 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() {
143 return this;
146 class ScrollbarBackgroundPainter : public LayerPainter {
147 public:
148 static scoped_ptr<ScrollbarBackgroundPainter> Create(
149 WebKit::WebScrollbar* scrollbar,
150 ScrollbarThemePainter *painter,
151 WebKit::WebScrollbarThemeGeometry* geometry,
152 WebKit::WebScrollbar::ScrollbarPart trackPart) {
153 return make_scoped_ptr(new ScrollbarBackgroundPainter(scrollbar,
154 painter,
155 geometry,
156 trackPart));
159 virtual void Paint(SkCanvas* canvas,
160 gfx::Rect content_rect,
161 gfx::RectF* opaque) OVERRIDE {
162 // The following is a simplification of ScrollbarThemeComposite::paint.
163 painter_->PaintScrollbarBackground(canvas, content_rect);
165 if (geometry_->hasButtons(scrollbar_)) {
166 gfx::Rect back_button_start_paint_rect =
167 geometry_->backButtonStartRect(scrollbar_);
168 painter_->PaintBackButtonStart(canvas, back_button_start_paint_rect);
170 gfx::Rect back_button_end_paint_rect =
171 geometry_->backButtonEndRect(scrollbar_);
172 painter_->PaintBackButtonEnd(canvas, back_button_end_paint_rect);
174 gfx::Rect forward_button_start_paint_rect =
175 geometry_->forwardButtonStartRect(scrollbar_);
176 painter_->PaintForwardButtonStart(canvas,
177 forward_button_start_paint_rect);
179 gfx::Rect forward_button_end_paint_rect =
180 geometry_->forwardButtonEndRect(scrollbar_);
181 painter_->PaintForwardButtonEnd(canvas, forward_button_end_paint_rect);
184 gfx::Rect track_paint_rect = geometry_->trackRect(scrollbar_);
185 painter_->PaintTrackBackground(canvas, track_paint_rect);
187 bool thumb_present = geometry_->hasThumb(scrollbar_);
188 if (thumb_present) {
189 if (track_part_ == WebKit::WebScrollbar::ForwardTrackPart)
190 painter_->PaintForwardTrackPart(canvas, track_paint_rect);
191 else
192 painter_->PaintBackTrackPart(canvas, track_paint_rect);
195 painter_->PaintTickmarks(canvas, track_paint_rect);
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) {}
208 WebKit::WebScrollbar* scrollbar_;
209 ScrollbarThemePainter* painter_;
210 WebKit::WebScrollbarThemeGeometry* geometry_;
211 WebKit::WebScrollbar::ScrollbarPart track_part_;
213 DISALLOW_COPY_AND_ASSIGN(ScrollbarBackgroundPainter);
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));
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()));
235 private:
236 ScrollbarThumbPainter(WebKit::WebScrollbar* scrollbar,
237 ScrollbarThemePainter* painter,
238 WebKit::WebScrollbarThemeGeometry* geometry)
239 : scrollbar_(scrollbar),
240 painter_(painter),
241 geometry_(geometry) {}
243 WebKit::WebScrollbar* scrollbar_;
244 ScrollbarThemePainter* painter_;
245 WebKit::WebScrollbarThemeGeometry* geometry_;
247 DISALLOW_COPY_AND_ASSIGN(ScrollbarThumbPainter);
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();
258 ContentsScalingLayer::SetLayerTreeHost(host);
261 void ScrollbarLayer::CreateUpdaterIfNeeded() {
262 if (layer_tree_host()->settings().solid_color_scrollbars)
263 return;
265 texture_format_ =
266 layer_tree_host()->GetRendererCapabilities().best_texture_format;
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 rendering_stats_instrumentation(),
276 id());
278 if (!back_track_) {
279 back_track_ = back_track_updater_->CreateResource(
280 layer_tree_host()->contents_texture_manager());
283 // Only create two-part track if we think the two parts could be different in
284 // appearance.
285 if (scrollbar_->isCustomScrollbar()) {
286 if (!fore_track_updater_) {
287 fore_track_updater_ = CachingBitmapContentLayerUpdater::Create(
288 ScrollbarBackgroundPainter::Create(
289 scrollbar_.get(),
290 painter_.get(),
291 geometry_.get(),
292 WebKit::WebScrollbar::ForwardTrackPart).PassAs<LayerPainter>(),
293 rendering_stats_instrumentation(),
294 id());
296 if (!fore_track_) {
297 fore_track_ = fore_track_updater_->CreateResource(
298 layer_tree_host()->contents_texture_manager());
302 if (!thumb_updater_) {
303 thumb_updater_ = CachingBitmapContentLayerUpdater::Create(
304 ScrollbarThumbPainter::Create(scrollbar_.get(),
305 painter_.get(),
306 geometry_.get()).PassAs<LayerPainter>(),
307 rendering_stats_instrumentation(),
308 id());
310 if (!thumb_) {
311 thumb_ = thumb_updater_->CreateResource(
312 layer_tree_host()->contents_texture_manager());
316 void ScrollbarLayer::UpdatePart(CachingBitmapContentLayerUpdater* painter,
317 LayerUpdater::Resource* resource,
318 gfx::Rect rect,
319 ResourceUpdateQueue* queue,
320 RenderingStats* stats) {
321 if (layer_tree_host()->settings().solid_color_scrollbars)
322 return;
324 // Skip painting and uploading if there are no invalidations and
325 // we already have valid texture data.
326 if (resource->texture()->have_backing_texture() &&
327 resource->texture()->size() == rect.size() &&
328 !is_dirty())
329 return;
331 // We should always have enough memory for UI.
332 DCHECK(resource->texture()->can_acquire_backing_texture());
333 if (!resource->texture()->can_acquire_backing_texture())
334 return;
336 // Paint and upload the entire part.
337 gfx::Rect painted_opaque_rect;
338 painter->PrepareToUpdate(rect,
339 rect.size(),
340 contents_scale_x(),
341 contents_scale_y(),
342 &painted_opaque_rect,
343 stats);
344 if (!painter->pixels_did_change() &&
345 resource->texture()->have_backing_texture()) {
346 TRACE_EVENT_INSTANT0("cc",
347 "ScrollbarLayer::UpdatePart no texture upload needed",
348 TRACE_EVENT_SCOPE_THREAD);
349 return;
352 bool partial_updates_allowed =
353 layer_tree_host()->settings().max_partial_texture_updates > 0;
354 if (!partial_updates_allowed)
355 resource->texture()->ReturnBackingTexture();
357 gfx::Vector2d dest_offset(0, 0);
358 resource->Update(queue, rect, dest_offset, partial_updates_allowed, stats);
361 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect(
362 gfx::Rect layer_rect) const {
363 // Don't intersect with the bounds as in LayerRectToContentRect() because
364 // layer_rect here might be in coordinates of the containing layer.
365 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect(
366 layer_rect, contents_scale_y(), contents_scale_y());
367 // We should never return a rect bigger than the content_bounds().
368 gfx::Size clamped_size = expanded_rect.size();
369 clamped_size.ClampToMax(content_bounds());
370 expanded_rect.set_size(clamped_size);
371 return expanded_rect;
374 void ScrollbarLayer::SetTexturePriorities(
375 const PriorityCalculator& priority_calc) {
376 if (layer_tree_host()->settings().solid_color_scrollbars)
377 return;
379 if (content_bounds().IsEmpty())
380 return;
381 DCHECK_LE(content_bounds().width(), MaxTextureSize());
382 DCHECK_LE(content_bounds().height(), MaxTextureSize());
384 CreateUpdaterIfNeeded();
386 bool draws_to_root = !render_target()->parent();
387 if (back_track_) {
388 back_track_->texture()->SetDimensions(content_bounds(), texture_format_);
389 back_track_->texture()->set_request_priority(
390 PriorityCalculator::UIPriority(draws_to_root));
392 if (fore_track_) {
393 fore_track_->texture()->SetDimensions(content_bounds(), texture_format_);
394 fore_track_->texture()->set_request_priority(
395 PriorityCalculator::UIPriority(draws_to_root));
397 if (thumb_) {
398 gfx::Rect thumb_layer_rect = geometry_->thumbRect(scrollbar_.get());
399 gfx::Size thumb_size =
400 ScrollbarLayerRectToContentRect(thumb_layer_rect).size();
401 thumb_->texture()->SetDimensions(thumb_size, texture_format_);
402 thumb_->texture()->set_request_priority(
403 PriorityCalculator::UIPriority(draws_to_root));
407 void ScrollbarLayer::Update(ResourceUpdateQueue* queue,
408 const OcclusionTracker* occlusion,
409 RenderingStats* stats) {
411 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
412 true);
413 ContentsScalingLayer::Update(queue, occlusion, stats);
416 dirty_rect_.Union(update_rect_);
417 if (content_bounds().IsEmpty())
418 return;
419 if (visible_content_rect().IsEmpty())
420 return;
422 CreateUpdaterIfNeeded();
424 gfx::Rect content_rect = ScrollbarLayerRectToContentRect(
425 gfx::Rect(scrollbar_->location(), bounds()));
426 UpdatePart(back_track_updater_.get(),
427 back_track_.get(),
428 content_rect,
429 queue,
430 stats);
431 if (fore_track_ && fore_track_updater_) {
432 UpdatePart(fore_track_updater_.get(),
433 fore_track_.get(),
434 content_rect,
435 queue,
436 stats);
439 // Consider the thumb to be at the origin when painting.
440 gfx::Rect thumb_rect = geometry_->thumbRect(scrollbar_.get());
441 thumb_size_ = thumb_rect.size();
442 gfx::Rect origin_thumb_rect =
443 ScrollbarLayerRectToContentRect(gfx::Rect(thumb_rect.size()));
444 if (!origin_thumb_rect.IsEmpty()) {
445 UpdatePart(thumb_updater_.get(),
446 thumb_.get(),
447 origin_thumb_rect,
448 queue,
449 stats);
452 dirty_rect_ = gfx::RectF();
455 } // namespace cc