Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | |
| 2 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 3 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 4 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 5 | 4 |
| 6 #include "cc/layers/scrollbar_layer.h" | 5 #include "cc/layers/scrollbar_layer.h" |
| 7 | 6 |
| 8 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 9 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 10 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 11 #include "cc/layers/scrollbar_layer_impl.h" | 10 #include "cc/layers/scrollbar_layer_impl.h" |
| 12 #include "cc/resources/caching_bitmap_content_layer_updater.h" | 11 #include "cc/resources/ui_resource_bitmap.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" | 12 #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" | |
| 17 #include "ui/gfx/rect_conversions.h" | 19 #include "ui/gfx/rect_conversions.h" |
| 18 | 20 |
| 19 namespace cc { | 21 namespace cc { |
| 20 | 22 |
| 21 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( | 23 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( |
| 22 LayerTreeImpl* tree_impl) { | 24 LayerTreeImpl* tree_impl) { |
| 23 return ScrollbarLayerImpl::Create( | 25 return ScrollbarLayerImpl::Create( |
| 24 tree_impl, id(), scrollbar_->Orientation()).PassAs<LayerImpl>(); | 26 tree_impl, id(), scrollbar_->Orientation()).PassAs<LayerImpl>(); |
| 25 } | 27 } |
| 26 | 28 |
| 27 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( | 29 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( |
| 28 scoped_ptr<Scrollbar> scrollbar, | 30 scoped_ptr<Scrollbar> scrollbar, |
| 29 int scroll_layer_id) { | 31 int scroll_layer_id) { |
| 30 return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(), | 32 return make_scoped_refptr( |
| 31 scroll_layer_id)); | 33 new ScrollbarLayer(scrollbar.Pass(), scroll_layer_id)); |
| 32 } | 34 } |
| 33 | 35 |
| 34 ScrollbarLayer::ScrollbarLayer( | 36 ScrollbarLayer::ScrollbarLayer( |
| 35 scoped_ptr<Scrollbar> scrollbar, | 37 scoped_ptr<Scrollbar> scrollbar, |
| 36 int scroll_layer_id) | 38 int scroll_layer_id) |
| 37 : scrollbar_(scrollbar.Pass()), | 39 : scrollbar_(scrollbar.Pass()), |
| 38 scroll_layer_id_(scroll_layer_id), | 40 scroll_layer_id_(scroll_layer_id) { |
| 39 texture_format_(GL_INVALID_ENUM) { | |
| 40 if (!scrollbar_->IsOverlay()) | 41 if (!scrollbar_->IsOverlay()) |
| 41 SetShouldScrollOnMainThread(true); | 42 SetShouldScrollOnMainThread(true); |
| 42 } | 43 } |
| 43 | 44 |
| 44 ScrollbarLayer::~ScrollbarLayer() {} | 45 ScrollbarLayer::~ScrollbarLayer() {} |
| 45 | 46 |
| 46 void ScrollbarLayer::SetScrollLayerId(int id) { | 47 void ScrollbarLayer::SetScrollLayerId(int id) { |
| 47 if (id == scroll_layer_id_) | 48 if (id == scroll_layer_id_) |
| 48 return; | 49 return; |
| 49 | 50 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 } | 122 } |
| 122 scrollbar_layer->set_thumb_length(thumb_length_); | 123 scrollbar_layer->set_thumb_length(thumb_length_); |
| 123 if (Orientation() == HORIZONTAL) { | 124 if (Orientation() == HORIZONTAL) { |
| 124 scrollbar_layer->set_track_start(track_rect_.x()); | 125 scrollbar_layer->set_track_start(track_rect_.x()); |
| 125 scrollbar_layer->set_track_length(track_rect_.width()); | 126 scrollbar_layer->set_track_length(track_rect_.width()); |
| 126 } else { | 127 } else { |
| 127 scrollbar_layer->set_track_start(track_rect_.y()); | 128 scrollbar_layer->set_track_start(track_rect_.y()); |
| 128 scrollbar_layer->set_track_length(track_rect_.height()); | 129 scrollbar_layer->set_track_length(track_rect_.height()); |
| 129 } | 130 } |
| 130 | 131 |
| 131 if (track_ && track_->texture()->have_backing_texture()) | 132 if (track_resource_.get()) |
| 132 scrollbar_layer->set_track_resource_id(track_->texture()->resource_id()); | 133 scrollbar_layer->set_track_ui_resource_id(track_resource_->id()); |
| 133 else | 134 if (thumb_resource_.get()) |
| 134 scrollbar_layer->set_track_resource_id(0); | 135 scrollbar_layer->set_thumb_ui_resource_id(thumb_resource_->id()); |
| 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); | |
| 140 | 136 |
| 141 scrollbar_layer->set_is_overlay_scrollbar(scrollbar_->IsOverlay()); | 137 scrollbar_layer->set_is_overlay_scrollbar(scrollbar_->IsOverlay()); |
| 142 | 138 |
| 143 // ScrollbarLayer must push properties every frame. crbug.com/259095 | 139 // ScrollbarLayer must push properties every frame. crbug.com/259095 |
| 144 needs_push_properties_ = true; | 140 needs_push_properties_ = true; |
| 145 } | 141 } |
| 146 | 142 |
| 147 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { | 143 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { |
| 148 return this; | 144 return this; |
| 149 } | 145 } |
| 150 | 146 |
| 151 void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { | 147 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. | |
| 152 if (!host || host != layer_tree_host()) { | 150 if (!host || host != layer_tree_host()) { |
| 153 track_updater_ = NULL; | 151 track_resource_.reset(); |
| 154 track_.reset(); | 152 thumb_resource_.reset(); |
| 155 thumb_updater_ = NULL; | |
| 156 thumb_.reset(); | |
| 157 } | 153 } |
| 158 | 154 |
| 159 ContentsScalingLayer::SetLayerTreeHost(host); | 155 ContentsScalingLayer::SetLayerTreeHost(host); |
| 160 } | 156 } |
| 161 | 157 |
| 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 | |
| 259 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( | 158 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( |
| 260 gfx::Rect layer_rect) const { | 159 gfx::Rect layer_rect) const { |
| 261 // Don't intersect with the bounds as in LayerRectToContentRect() because | 160 // Don't intersect with the bounds as in LayerRectToContentRect() because |
| 262 // layer_rect here might be in coordinates of the containing layer. | 161 // layer_rect here might be in coordinates of the containing layer. |
| 263 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect( | 162 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect( |
| 264 layer_rect, contents_scale_y(), contents_scale_y()); | 163 layer_rect, contents_scale_y(), contents_scale_y()); |
| 265 // We should never return a rect bigger than the content_bounds(). | 164 // We should never return a rect bigger than the content_bounds(). |
| 266 gfx::Size clamped_size = expanded_rect.size(); | 165 gfx::Size clamped_size = expanded_rect.size(); |
| 267 clamped_size.SetToMin(content_bounds()); | 166 clamped_size.SetToMin(content_bounds()); |
| 268 expanded_rect.set_size(clamped_size); | 167 expanded_rect.set_size(clamped_size); |
| 269 return expanded_rect; | 168 return expanded_rect; |
| 270 } | 169 } |
| 271 | 170 |
| 272 void ScrollbarLayer::SetTexturePriorities( | 171 gfx::Rect ScrollbarLayer::OriginThumbRect() const { |
| 273 const PriorityCalculator& priority_calc) { | 172 gfx::Size thumb_size; |
| 274 if (layer_tree_host()->settings().solid_color_scrollbars) | 173 if (Orientation() == HORIZONTAL) { |
| 275 return; | 174 thumb_size = |
| 276 | 175 gfx::Size(scrollbar_->ThumbLength(), scrollbar_->ThumbThickness()); |
| 277 if (content_bounds().IsEmpty()) | 176 } else { |
| 278 return; | 177 thumb_size = |
| 279 DCHECK_LE(content_bounds().width(), MaxTextureSize()); | 178 gfx::Size(scrollbar_->ThumbThickness(), scrollbar_->ThumbLength()); |
| 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)); | |
| 289 } | 179 } |
| 290 if (thumb_) { | 180 return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); |
| 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 } | |
| 296 } | 181 } |
| 297 | 182 |
| 298 bool ScrollbarLayer::Update(ResourceUpdateQueue* queue, | 183 bool ScrollbarLayer::Update(ResourceUpdateQueue* queue, |
| 299 const OcclusionTracker* occlusion) { | 184 const OcclusionTracker* occlusion) { |
| 300 track_rect_ = scrollbar_->TrackRect(); | 185 track_rect_ = scrollbar_->TrackRect(); |
| 301 | 186 |
| 302 if (layer_tree_host()->settings().solid_color_scrollbars) | 187 if (layer_tree_host()->settings().solid_color_scrollbars) |
| 303 return false; | 188 return false; |
| 304 | 189 |
| 305 { | 190 { |
| 306 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, | 191 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, |
| 307 true); | 192 true); |
| 308 ContentsScalingLayer::Update(queue, occlusion); | 193 ContentsScalingLayer::Update(queue, occlusion); |
| 309 } | 194 } |
| 310 | 195 |
| 311 dirty_rect_.Union(update_rect_); | |
| 312 if (content_bounds().IsEmpty()) | |
| 313 return false; | |
| 314 if (visible_content_rect().IsEmpty()) | |
| 315 return false; | |
| 316 | 196 |
| 317 CreateUpdaterIfNeeded(); | 197 track_resource_ = ScopedUIResource::Create( |
| 318 | 198 layer_tree_host(), |
| 319 gfx::Rect content_rect = ScrollbarLayerRectToContentRect( | 199 RasterizeScrollbarPart(ScrollbarLayerRectToContentRect( |
| 320 gfx::Rect(scrollbar_->Location(), bounds())); | 200 gfx::Rect(scrollbar_->Location(), bounds())), |
| 321 bool updated = UpdatePart(track_updater_.get(), track_.get(), content_rect, | 201 TRACK)); |
| 322 queue); | |
| 323 | 202 |
| 324 if (scrollbar_->HasThumb()) { | 203 if (scrollbar_->HasThumb()) { |
| 325 thumb_thickness_ = scrollbar_->ThumbThickness(); | 204 thumb_thickness_ = scrollbar_->ThumbThickness(); |
| 326 thumb_length_ = scrollbar_->ThumbLength(); | 205 thumb_length_ = scrollbar_->ThumbLength(); |
| 327 gfx::Rect origin_thumb_rect = OriginThumbRect(); | 206 |
| 328 if (!origin_thumb_rect.IsEmpty()) { | 207 thumb_resource_ = ScopedUIResource::Create( |
| 329 updated |= UpdatePart(thumb_updater_.get(), thumb_.get(), | 208 layer_tree_host(), RasterizeScrollbarPart(OriginThumbRect(), THUMB)); |
| 330 origin_thumb_rect, queue); | |
| 331 } | |
| 332 } | 209 } |
| 333 | 210 |
| 334 dirty_rect_ = gfx::RectF(); | 211 return true; |
| 335 return updated; | |
| 336 } | 212 } |
| 337 | 213 |
| 338 gfx::Rect ScrollbarLayer::OriginThumbRect() const { | 214 scoped_refptr<UIResourceBitmap> ScrollbarLayer::RasterizeScrollbarPart( |
| 339 gfx::Size thumb_size; | 215 gfx::Rect rect, |
| 340 if (Orientation() == HORIZONTAL) { | 216 ScrollbarPart part) { |
| 341 thumb_size = gfx::Size(scrollbar_->ThumbLength(), | 217 DCHECK(!layer_tree_host()->settings().solid_color_scrollbars); |
| 342 scrollbar_->ThumbThickness()); | 218 |
| 343 } else { | 219 scoped_refptr<UIResourceBitmap> bitmap = |
| 344 thumb_size = gfx::Size(scrollbar_->ThumbThickness(), | 220 UIResourceBitmap::Create(new uint8_t[rect.width() * rect.height() * 4], |
| 345 scrollbar_->ThumbLength()); | 221 UIResourceBitmap::RGBA8, |
| 346 } | 222 rect.size()); |
| 347 return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); | 223 |
| 224 SkBitmap skbitmap; | |
| 225 skbitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); | |
| 226 skbitmap.setPixels(bitmap->GetPixels()); | |
| 227 | |
| 228 SkCanvas skcanvas(skbitmap); | |
| 229 skcanvas.translate(SkFloatToScalar(-rect.x()), SkFloatToScalar(-rect.y())); | |
| 230 skcanvas.scale(SkFloatToScalar(contents_scale_x()), | |
| 231 SkFloatToScalar(contents_scale_y())); | |
| 232 | |
| 233 gfx::Rect layer_rect = rect; | |
| 234 if (contents_scale_x() != 1.f || contents_scale_y() != 1.f) | |
|
aelias_OOO_until_Jul13
2013/08/03 01:34:23
This if() statement doesn't change any behavior so
powei
2013/08/05 23:49:29
Done.
| |
| 235 layer_rect = gfx::ScaleToEnclosingRect( | |
| 236 rect, 1.f / contents_scale_x(), 1.f / contents_scale_y()); | |
| 237 | |
| 238 SkRect layer_skrect = SkRect::MakeXYWH( | |
|
aelias_OOO_until_Jul13
2013/08/03 01:34:23
Use RectToSkRect() in ui/gfx/skia_util.h instead.
powei
2013/08/05 23:49:29
Done.
| |
| 239 layer_rect.x(), layer_rect.y(), layer_rect.width(), layer_rect.height()); | |
| 240 | |
| 241 SkPaint paint; | |
| 242 paint.setAntiAlias(false); | |
| 243 paint.setXfermodeMode(SkXfermode::kClear_Mode); | |
| 244 skcanvas.drawRect(layer_skrect, paint); | |
| 245 skcanvas.clipRect(layer_skrect); | |
| 246 | |
| 247 scrollbar_->PaintPart(&skcanvas, part, layer_rect); | |
| 248 | |
| 249 return bitmap; | |
| 348 } | 250 } |
| 349 | 251 |
| 350 } // namespace cc | 252 } // namespace cc |
| OLD | NEW |