OLD | NEW |
| 1 |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 2 // 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 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 4 // found in the LICENSE file. |
4 | 5 |
5 #include "cc/layers/scrollbar_layer.h" | 6 #include "cc/layers/scrollbar_layer.h" |
6 | 7 |
7 #include "base/auto_reset.h" | 8 #include "base/auto_reset.h" |
8 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
9 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
10 #include "cc/layers/scrollbar_layer_impl.h" | 11 #include "cc/layers/scrollbar_layer_impl.h" |
11 #include "cc/resources/ui_resource_bitmap.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" |
12 #include "cc/trees/layer_tree_host.h" | 16 #include "cc/trees/layer_tree_host.h" |
13 #include "cc/trees/layer_tree_impl.h" | |
14 #include "skia/ext/platform_canvas.h" | |
15 #include "skia/ext/refptr.h" | |
16 #include "third_party/skia/include/core/SkBitmap.h" | |
17 #include "third_party/skia/include/core/SkCanvas.h" | |
18 #include "third_party/skia/include/core/SkSize.h" | |
19 #include "ui/gfx/rect_conversions.h" | 17 #include "ui/gfx/rect_conversions.h" |
20 | 18 |
21 namespace cc { | 19 namespace cc { |
22 | 20 |
23 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( | 21 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( |
24 LayerTreeImpl* tree_impl) { | 22 LayerTreeImpl* tree_impl) { |
25 return ScrollbarLayerImpl::Create( | 23 return ScrollbarLayerImpl::Create( |
26 tree_impl, id(), scrollbar_->Orientation()).PassAs<LayerImpl>(); | 24 tree_impl, id(), scrollbar_->Orientation()).PassAs<LayerImpl>(); |
27 } | 25 } |
28 | 26 |
29 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( | 27 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( |
30 scoped_ptr<Scrollbar> scrollbar, | 28 scoped_ptr<Scrollbar> scrollbar, |
31 int scroll_layer_id) { | 29 int scroll_layer_id) { |
32 return make_scoped_refptr( | 30 return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(), |
33 new ScrollbarLayer(scrollbar.Pass(), scroll_layer_id)); | 31 scroll_layer_id)); |
34 } | 32 } |
35 | 33 |
36 ScrollbarLayer::ScrollbarLayer( | 34 ScrollbarLayer::ScrollbarLayer( |
37 scoped_ptr<Scrollbar> scrollbar, | 35 scoped_ptr<Scrollbar> scrollbar, |
38 int scroll_layer_id) | 36 int scroll_layer_id) |
39 : scrollbar_(scrollbar.Pass()), | 37 : scrollbar_(scrollbar.Pass()), |
40 scroll_layer_id_(scroll_layer_id) { | 38 scroll_layer_id_(scroll_layer_id), |
| 39 texture_format_(GL_INVALID_ENUM) { |
41 if (!scrollbar_->IsOverlay()) | 40 if (!scrollbar_->IsOverlay()) |
42 SetShouldScrollOnMainThread(true); | 41 SetShouldScrollOnMainThread(true); |
43 } | 42 } |
44 | 43 |
45 ScrollbarLayer::~ScrollbarLayer() {} | 44 ScrollbarLayer::~ScrollbarLayer() {} |
46 | 45 |
47 void ScrollbarLayer::SetScrollLayerId(int id) { | 46 void ScrollbarLayer::SetScrollLayerId(int id) { |
48 if (id == scroll_layer_id_) | 47 if (id == scroll_layer_id_) |
49 return; | 48 return; |
50 | 49 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 } | 121 } |
123 scrollbar_layer->set_thumb_length(thumb_length_); | 122 scrollbar_layer->set_thumb_length(thumb_length_); |
124 if (Orientation() == HORIZONTAL) { | 123 if (Orientation() == HORIZONTAL) { |
125 scrollbar_layer->set_track_start(track_rect_.x()); | 124 scrollbar_layer->set_track_start(track_rect_.x()); |
126 scrollbar_layer->set_track_length(track_rect_.width()); | 125 scrollbar_layer->set_track_length(track_rect_.width()); |
127 } else { | 126 } else { |
128 scrollbar_layer->set_track_start(track_rect_.y()); | 127 scrollbar_layer->set_track_start(track_rect_.y()); |
129 scrollbar_layer->set_track_length(track_rect_.height()); | 128 scrollbar_layer->set_track_length(track_rect_.height()); |
130 } | 129 } |
131 | 130 |
132 if (track_resource_.get()) | 131 if (track_ && track_->texture()->have_backing_texture()) |
133 scrollbar_layer->set_track_ui_resource_id(track_resource_->id()); | 132 scrollbar_layer->set_track_resource_id(track_->texture()->resource_id()); |
134 if (thumb_resource_.get()) | 133 else |
135 scrollbar_layer->set_thumb_ui_resource_id(thumb_resource_->id()); | 134 scrollbar_layer->set_track_resource_id(0); |
| 135 |
| 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); |
136 | 140 |
137 scrollbar_layer->set_is_overlay_scrollbar(scrollbar_->IsOverlay()); | 141 scrollbar_layer->set_is_overlay_scrollbar(scrollbar_->IsOverlay()); |
138 | 142 |
139 // ScrollbarLayer must push properties every frame. crbug.com/259095 | 143 // ScrollbarLayer must push properties every frame. crbug.com/259095 |
140 needs_push_properties_ = true; | 144 needs_push_properties_ = true; |
141 } | 145 } |
142 | 146 |
143 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { | 147 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { |
144 return this; | 148 return this; |
145 } | 149 } |
146 | 150 |
147 void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { | 151 void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { |
148 // When the LTH is set to null or has changed, then this layer should remove | |
149 // all of its associated resources. | |
150 if (!host || host != layer_tree_host()) { | 152 if (!host || host != layer_tree_host()) { |
151 track_resource_.reset(); | 153 track_updater_ = NULL; |
152 thumb_resource_.reset(); | 154 track_.reset(); |
| 155 thumb_updater_ = NULL; |
| 156 thumb_.reset(); |
153 } | 157 } |
154 | 158 |
155 ContentsScalingLayer::SetLayerTreeHost(host); | 159 ContentsScalingLayer::SetLayerTreeHost(host); |
156 } | 160 } |
157 | 161 |
| 162 class ScrollbarPartPainter : public LayerPainter { |
| 163 public: |
| 164 ScrollbarPartPainter(Scrollbar* scrollbar, ScrollbarPart part) |
| 165 : scrollbar_(scrollbar), |
| 166 part_(part) {} |
| 167 virtual ~ScrollbarPartPainter() {} |
| 168 |
| 169 // LayerPainter implementation |
| 170 virtual void Paint(SkCanvas* canvas, |
| 171 gfx::Rect content_rect, |
| 172 gfx::RectF* opaque) OVERRIDE { |
| 173 scrollbar_->PaintPart(canvas, part_, content_rect); |
| 174 } |
| 175 |
| 176 private: |
| 177 Scrollbar* scrollbar_; |
| 178 ScrollbarPart part_; |
| 179 }; |
| 180 |
| 181 void ScrollbarLayer::CreateUpdaterIfNeeded() { |
| 182 if (layer_tree_host()->settings().solid_color_scrollbars) |
| 183 return; |
| 184 |
| 185 texture_format_ = |
| 186 layer_tree_host()->GetRendererCapabilities().best_texture_format; |
| 187 |
| 188 if (!track_updater_.get()) { |
| 189 track_updater_ = CachingBitmapContentLayerUpdater::Create( |
| 190 scoped_ptr<LayerPainter>( |
| 191 new ScrollbarPartPainter(scrollbar_.get(), TRACK)) |
| 192 .Pass(), |
| 193 rendering_stats_instrumentation(), |
| 194 id()); |
| 195 } |
| 196 if (!track_) { |
| 197 track_ = track_updater_->CreateResource( |
| 198 layer_tree_host()->contents_texture_manager()); |
| 199 } |
| 200 |
| 201 if (!thumb_updater_.get()) { |
| 202 thumb_updater_ = CachingBitmapContentLayerUpdater::Create( |
| 203 scoped_ptr<LayerPainter>( |
| 204 new ScrollbarPartPainter(scrollbar_.get(), THUMB)) |
| 205 .Pass(), |
| 206 rendering_stats_instrumentation(), |
| 207 id()); |
| 208 } |
| 209 if (!thumb_ && scrollbar_->HasThumb()) { |
| 210 thumb_ = thumb_updater_->CreateResource( |
| 211 layer_tree_host()->contents_texture_manager()); |
| 212 } |
| 213 } |
| 214 |
| 215 bool ScrollbarLayer::UpdatePart(CachingBitmapContentLayerUpdater* painter, |
| 216 LayerUpdater::Resource* resource, |
| 217 gfx::Rect rect, |
| 218 ResourceUpdateQueue* queue) { |
| 219 if (layer_tree_host()->settings().solid_color_scrollbars) |
| 220 return false; |
| 221 |
| 222 // Skip painting and uploading if there are no invalidations and |
| 223 // we already have valid texture data. |
| 224 if (resource->texture()->have_backing_texture() && |
| 225 resource->texture()->size() == rect.size() && |
| 226 !is_dirty()) |
| 227 return false; |
| 228 |
| 229 // We should always have enough memory for UI. |
| 230 DCHECK(resource->texture()->can_acquire_backing_texture()); |
| 231 if (!resource->texture()->can_acquire_backing_texture()) |
| 232 return false; |
| 233 |
| 234 // Paint and upload the entire part. |
| 235 gfx::Rect painted_opaque_rect; |
| 236 painter->PrepareToUpdate(rect, |
| 237 rect.size(), |
| 238 contents_scale_x(), |
| 239 contents_scale_y(), |
| 240 &painted_opaque_rect); |
| 241 if (!painter->pixels_did_change() && |
| 242 resource->texture()->have_backing_texture()) { |
| 243 TRACE_EVENT_INSTANT0("cc", |
| 244 "ScrollbarLayer::UpdatePart no texture upload needed", |
| 245 TRACE_EVENT_SCOPE_THREAD); |
| 246 return false; |
| 247 } |
| 248 |
| 249 bool partial_updates_allowed = |
| 250 layer_tree_host()->settings().max_partial_texture_updates > 0; |
| 251 if (!partial_updates_allowed) |
| 252 resource->texture()->ReturnBackingTexture(); |
| 253 |
| 254 gfx::Vector2d dest_offset(0, 0); |
| 255 resource->Update(queue, rect, dest_offset, partial_updates_allowed); |
| 256 return true; |
| 257 } |
| 258 |
158 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( | 259 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( |
159 gfx::Rect layer_rect) const { | 260 gfx::Rect layer_rect) const { |
160 // Don't intersect with the bounds as in LayerRectToContentRect() because | 261 // Don't intersect with the bounds as in LayerRectToContentRect() because |
161 // layer_rect here might be in coordinates of the containing layer. | 262 // layer_rect here might be in coordinates of the containing layer. |
162 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect( | 263 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect( |
163 layer_rect, contents_scale_y(), contents_scale_y()); | 264 layer_rect, contents_scale_y(), contents_scale_y()); |
164 // We should never return a rect bigger than the content_bounds(). | 265 // We should never return a rect bigger than the content_bounds(). |
165 gfx::Size clamped_size = expanded_rect.size(); | 266 gfx::Size clamped_size = expanded_rect.size(); |
166 clamped_size.SetToMin(content_bounds()); | 267 clamped_size.SetToMin(content_bounds()); |
167 expanded_rect.set_size(clamped_size); | 268 expanded_rect.set_size(clamped_size); |
168 return expanded_rect; | 269 return expanded_rect; |
169 } | 270 } |
170 | 271 |
171 gfx::Rect ScrollbarLayer::OriginThumbRect() const { | 272 void ScrollbarLayer::SetTexturePriorities( |
172 gfx::Size thumb_size; | 273 const PriorityCalculator& priority_calc) { |
173 if (Orientation() == HORIZONTAL) { | 274 if (layer_tree_host()->settings().solid_color_scrollbars) |
174 thumb_size = | 275 return; |
175 gfx::Size(scrollbar_->ThumbLength(), scrollbar_->ThumbThickness()); | 276 |
176 } else { | 277 if (content_bounds().IsEmpty()) |
177 thumb_size = | 278 return; |
178 gfx::Size(scrollbar_->ThumbThickness(), scrollbar_->ThumbLength()); | 279 DCHECK_LE(content_bounds().width(), MaxTextureSize()); |
| 280 DCHECK_LE(content_bounds().height(), MaxTextureSize()); |
| 281 |
| 282 CreateUpdaterIfNeeded(); |
| 283 |
| 284 bool draws_to_root = !render_target()->parent(); |
| 285 if (track_) { |
| 286 track_->texture()->SetDimensions(content_bounds(), texture_format_); |
| 287 track_->texture()->set_request_priority( |
| 288 PriorityCalculator::UIPriority(draws_to_root)); |
179 } | 289 } |
180 return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); | 290 if (thumb_) { |
| 291 gfx::Size thumb_size = OriginThumbRect().size(); |
| 292 thumb_->texture()->SetDimensions(thumb_size, texture_format_); |
| 293 thumb_->texture()->set_request_priority( |
| 294 PriorityCalculator::UIPriority(draws_to_root)); |
| 295 } |
181 } | 296 } |
182 | 297 |
183 bool ScrollbarLayer::Update(ResourceUpdateQueue* queue, | 298 bool ScrollbarLayer::Update(ResourceUpdateQueue* queue, |
184 const OcclusionTracker* occlusion) { | 299 const OcclusionTracker* occlusion) { |
185 track_rect_ = scrollbar_->TrackRect(); | 300 track_rect_ = scrollbar_->TrackRect(); |
186 | 301 |
187 if (layer_tree_host()->settings().solid_color_scrollbars) | 302 if (layer_tree_host()->settings().solid_color_scrollbars) |
188 return false; | 303 return false; |
189 | 304 |
190 { | 305 { |
191 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, | 306 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, |
192 true); | 307 true); |
193 ContentsScalingLayer::Update(queue, occlusion); | 308 ContentsScalingLayer::Update(queue, occlusion); |
194 } | 309 } |
195 | 310 |
| 311 dirty_rect_.Union(update_rect_); |
| 312 if (content_bounds().IsEmpty()) |
| 313 return false; |
| 314 if (visible_content_rect().IsEmpty()) |
| 315 return false; |
| 316 |
| 317 CreateUpdaterIfNeeded(); |
| 318 |
| 319 gfx::Rect content_rect = ScrollbarLayerRectToContentRect( |
| 320 gfx::Rect(scrollbar_->Location(), bounds())); |
| 321 bool updated = UpdatePart(track_updater_.get(), track_.get(), content_rect, |
| 322 queue); |
| 323 |
196 if (scrollbar_->HasThumb()) { | 324 if (scrollbar_->HasThumb()) { |
197 thumb_thickness_ = scrollbar_->ThumbThickness(); | 325 thumb_thickness_ = scrollbar_->ThumbThickness(); |
198 thumb_length_ = scrollbar_->ThumbLength(); | 326 thumb_length_ = scrollbar_->ThumbLength(); |
| 327 gfx::Rect origin_thumb_rect = OriginThumbRect(); |
| 328 if (!origin_thumb_rect.IsEmpty()) { |
| 329 updated |= UpdatePart(thumb_updater_.get(), thumb_.get(), |
| 330 origin_thumb_rect, queue); |
| 331 } |
199 } | 332 } |
200 | 333 |
201 track_resource_ = | 334 dirty_rect_ = gfx::RectF(); |
202 ScopedUIResource::Create(layer_tree_host(), RasterizeTrack()); | 335 return updated; |
203 if (scrollbar_->HasThumb()) | |
204 thumb_resource_ = | |
205 ScopedUIResource::Create(layer_tree_host(), RasterizeThumb()); | |
206 | |
207 return true; | |
208 } | 336 } |
209 | 337 |
210 scoped_refptr<UIResourceBitmap> ScrollbarLayer::RasterizeTrack() { | 338 gfx::Rect ScrollbarLayer::OriginThumbRect() const { |
211 DCHECK(!layer_tree_host()->settings().solid_color_scrollbars); | 339 gfx::Size thumb_size; |
212 | 340 if (Orientation() == HORIZONTAL) { |
213 gfx::Rect track_rect = ScrollbarLayerRectToContentRect( | 341 thumb_size = gfx::Size(scrollbar_->ThumbLength(), |
214 gfx::Rect(scrollbar_->Location(), bounds())); | 342 scrollbar_->ThumbThickness()); |
215 scoped_refptr<UIResourceBitmap> track_bitmap = UIResourceBitmap::Create( | 343 } else { |
216 new uint8_t[track_rect.width() * track_rect.height() * 4], | 344 thumb_size = gfx::Size(scrollbar_->ThumbThickness(), |
217 UIResourceBitmap::RGBA8, | 345 scrollbar_->ThumbLength()); |
218 track_rect.size()); | 346 } |
219 | 347 return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); |
220 SkBitmap skbitmap; | |
221 skbitmap.setConfig( | |
222 SkBitmap::kARGB_8888_Config, track_rect.width(), track_rect.height()); | |
223 skbitmap.setPixels(track_bitmap->GetPixels()); | |
224 | |
225 SkCanvas track_canvas(skbitmap); | |
226 track_canvas.translate(SkFloatToScalar(-track_rect.x()), | |
227 SkFloatToScalar(-track_rect.y())); | |
228 scrollbar_->PaintPart(&track_canvas, TRACK, track_rect); | |
229 | |
230 return track_bitmap; | |
231 } | |
232 | |
233 scoped_refptr<UIResourceBitmap> ScrollbarLayer::RasterizeThumb() { | |
234 DCHECK(!layer_tree_host()->settings().solid_color_scrollbars); | |
235 DCHECK(scrollbar_->HasThumb()); | |
236 | |
237 gfx::Rect thumb_rect = OriginThumbRect(); | |
238 scoped_refptr<UIResourceBitmap> thumb_bitmap = UIResourceBitmap::Create( | |
239 new uint8_t[thumb_rect.width() * thumb_rect.height() * 4], | |
240 UIResourceBitmap::RGBA8, | |
241 thumb_rect.size()); | |
242 | |
243 SkBitmap skbitmap; | |
244 skbitmap.setConfig( | |
245 SkBitmap::kARGB_8888_Config, thumb_rect.width(), thumb_rect.height()); | |
246 skbitmap.setPixels(thumb_bitmap->GetPixels()); | |
247 | |
248 SkCanvas thumb_canvas(skbitmap); | |
249 scrollbar_->PaintPart(&thumb_canvas, THUMB, thumb_rect); | |
250 | |
251 return thumb_bitmap; | |
252 } | 348 } |
253 | 349 |
254 } // namespace cc | 350 } // namespace cc |
OLD | NEW |