Chromium Code Reviews| 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/layers/picture_scrollbar_layer.h" | |
| 6 | |
| 7 #if !USE_REGULAR_SCROLLBAR | |
| 8 | |
| 9 #include "base/auto_reset.h" | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/debug/trace_event.h" | |
| 12 #include "cc/layers/picture_scrollbar_layer_impl.h" | |
| 13 #include "cc/resources/caching_bitmap_content_layer_updater.h" | |
| 14 #include "cc/resources/layer_painter.h" | |
| 15 #include "cc/resources/resource_update_queue.h" | |
| 16 #include "cc/resources/ui_resource_manager.h" | |
| 17 #include "cc/trees/layer_tree_host.h" | |
| 18 #include "cc/trees/layer_tree_impl.h" | |
| 19 #include "skia/ext/platform_canvas.h" | |
| 20 #include "skia/ext/refptr.h" | |
| 21 #include "third_party/skia/include/core/SkSize.h" | |
| 22 #include "ui/gfx/rect_conversions.h" | |
| 23 | |
| 24 namespace cc { | |
| 25 | |
| 26 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( | |
| 27 LayerTreeImpl* tree_impl) { | |
| 28 return ScrollbarLayerImpl::Create( | |
| 29 tree_impl, id(), scrollbar_->Orientation()).PassAs<LayerImpl>(); | |
| 30 } | |
| 31 | |
| 32 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( | |
| 33 scoped_ptr<Scrollbar> scrollbar, | |
| 34 int scroll_layer_id) { | |
| 35 return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(), | |
| 36 scroll_layer_id)); | |
| 37 } | |
| 38 | |
| 39 ScrollbarLayer::ScrollbarLayer( | |
| 40 scoped_ptr<Scrollbar> scrollbar, | |
| 41 int scroll_layer_id) | |
| 42 : scrollbar_(scrollbar.Pass()), | |
| 43 scroll_layer_id_(scroll_layer_id), | |
| 44 track_ui_resource_id_(0), | |
| 45 thumb_ui_resource_id_(0), | |
| 46 track_ui_resource_status_(UIResourceManagerClient::NOT_READY), | |
| 47 thumb_ui_resource_status_(UIResourceManagerClient::NOT_READY), | |
| 48 skip_update_(false) { | |
| 49 if (!scrollbar_->IsOverlay()) | |
| 50 SetShouldScrollOnMainThread(true); | |
| 51 } | |
| 52 | |
| 53 ScrollbarLayer::~ScrollbarLayer() {} | |
| 54 | |
| 55 void ScrollbarLayer::SetScrollLayerId(int id) { | |
| 56 if (id == scroll_layer_id_) | |
| 57 return; | |
| 58 | |
| 59 scroll_layer_id_ = id; | |
| 60 SetNeedsFullTreeSync(); | |
| 61 } | |
| 62 | |
| 63 bool ScrollbarLayer::OpacityCanAnimateOnImplThread() const { | |
| 64 return scrollbar_->IsOverlay(); | |
| 65 } | |
| 66 | |
| 67 ScrollbarOrientation ScrollbarLayer::Orientation() const { | |
| 68 return scrollbar_->Orientation(); | |
| 69 } | |
| 70 | |
| 71 int ScrollbarLayer::MaxTextureSize() { | |
| 72 DCHECK(layer_tree_host()); | |
| 73 return layer_tree_host()->GetRendererCapabilities().max_texture_size; | |
| 74 } | |
| 75 | |
| 76 float ScrollbarLayer::ClampScaleToMaxTextureSize(float scale) { | |
| 77 if (layer_tree_host()->settings().solid_color_scrollbars) | |
| 78 return scale; | |
| 79 | |
| 80 // If the scaled content_bounds() is bigger than the max texture size of the | |
| 81 // device, we need to clamp it by rescaling, since content_bounds() is used | |
| 82 // below to set the texture size. | |
| 83 gfx::Size scaled_bounds = ComputeContentBoundsForScale(scale, scale); | |
| 84 if (scaled_bounds.width() > MaxTextureSize() || | |
| 85 scaled_bounds.height() > MaxTextureSize()) { | |
| 86 if (scaled_bounds.width() > scaled_bounds.height()) | |
| 87 return (MaxTextureSize() - 1) / static_cast<float>(bounds().width()); | |
| 88 else | |
| 89 return (MaxTextureSize() - 1) / static_cast<float>(bounds().height()); | |
| 90 } | |
| 91 return scale; | |
| 92 } | |
| 93 | |
| 94 void ScrollbarLayer::CalculateContentsScale(float ideal_contents_scale, | |
| 95 float device_scale_factor, | |
| 96 float page_scale_factor, | |
| 97 bool animating_transform_to_screen, | |
| 98 float* contents_scale_x, | |
| 99 float* contents_scale_y, | |
| 100 gfx::Size* content_bounds) { | |
| 101 ContentsScalingLayer::CalculateContentsScale( | |
| 102 ClampScaleToMaxTextureSize(ideal_contents_scale), | |
| 103 device_scale_factor, | |
| 104 page_scale_factor, | |
| 105 animating_transform_to_screen, | |
| 106 contents_scale_x, | |
| 107 contents_scale_y, | |
| 108 content_bounds); | |
| 109 } | |
| 110 | |
| 111 void ScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { | |
| 112 ContentsScalingLayer::PushPropertiesTo(layer); | |
| 113 | |
| 114 ScrollbarLayerImpl* scrollbar_layer = static_cast<ScrollbarLayerImpl*>(layer); | |
| 115 | |
| 116 if (layer_tree_host() && | |
| 117 layer_tree_host()->settings().solid_color_scrollbars) { | |
| 118 int thickness_override = | |
| 119 layer_tree_host()->settings().solid_color_scrollbar_thickness_dip; | |
| 120 if (thickness_override != -1) { | |
| 121 scrollbar_layer->set_thumb_thickness(thickness_override); | |
| 122 } else { | |
| 123 if (Orientation() == HORIZONTAL) | |
| 124 scrollbar_layer->set_thumb_thickness(bounds().height()); | |
| 125 else | |
| 126 scrollbar_layer->set_thumb_thickness(bounds().width()); | |
| 127 } | |
| 128 } else { | |
| 129 scrollbar_layer->set_thumb_thickness(thumb_thickness_); | |
| 130 } | |
| 131 scrollbar_layer->set_thumb_length(thumb_length_); | |
| 132 | |
| 133 if (Orientation() == HORIZONTAL) { | |
| 134 scrollbar_layer->set_track_start(track_rect_.x()); | |
| 135 scrollbar_layer->set_track_length(track_rect_.width()); | |
| 136 } else { | |
| 137 scrollbar_layer->set_track_start(track_rect_.y()); | |
| 138 scrollbar_layer->set_track_length(track_rect_.height()); | |
| 139 } | |
| 140 | |
| 141 if (track_ui_resource_status_ == UIResourceManagerClient::READY) { | |
| 142 scrollbar_layer->set_track_ui_resource_id(track_ui_resource_id_); | |
| 143 } else { | |
| 144 scrollbar_layer->set_track_ui_resource_id(0); | |
| 145 } | |
| 146 | |
| 147 if (thumb_ui_resource_status_ == UIResourceManagerClient::READY) { | |
| 148 scrollbar_layer->set_thumb_ui_resource_id(thumb_ui_resource_id_); | |
| 149 } else { | |
| 150 scrollbar_layer->set_thumb_ui_resource_id(0); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { | |
| 155 return this; | |
| 156 } | |
| 157 | |
| 158 void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { | |
| 159 ContentsScalingLayer::SetLayerTreeHost(host); | |
| 160 } | |
| 161 | |
| 162 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( | |
| 163 gfx::Rect layer_rect) const { | |
| 164 // Don't intersect with the bounds as in LayerRectToContentRect() because | |
| 165 // layer_rect here might be in coordinates of the containing layer. | |
| 166 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect( | |
| 167 layer_rect, contents_scale_y(), contents_scale_y()); | |
| 168 // We should never return a rect bigger than the content_bounds(). | |
| 169 gfx::Size clamped_size = expanded_rect.size(); | |
| 170 clamped_size.SetToMin(content_bounds()); | |
| 171 expanded_rect.set_size(clamped_size); | |
| 172 return expanded_rect; | |
| 173 } | |
| 174 | |
| 175 void ScrollbarLayer::Update(ResourceUpdateQueue* queue, | |
| 176 const OcclusionTracker* occlusion) { | |
| 177 track_rect_ = scrollbar_->TrackRect(); | |
| 178 | |
| 179 if (layer_tree_host()->settings().solid_color_scrollbars) | |
| 180 return; | |
| 181 | |
| 182 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, | |
| 183 true); | |
| 184 ContentsScalingLayer::Update(queue, occlusion); | |
| 185 | |
| 186 if (scrollbar_->HasThumb()) { | |
| 187 thumb_thickness_ = scrollbar_->ThumbThickness(); | |
| 188 thumb_length_ = scrollbar_->ThumbLength(); | |
| 189 gfx::Rect origin_thumb_rect = OriginThumbRect(); | |
| 190 } | |
| 191 | |
| 192 if (skip_update_) { | |
| 193 skip_update_ = false; | |
| 194 return; | |
| 195 } | |
| 196 | |
| 197 gfx::Rect track_rect = ScrollbarLayerRectToContentRect( | |
| 198 gfx::Rect(scrollbar_->Location(), bounds())); | |
| 199 gfx::Rect thumb_rect = OriginThumbRect(); | |
| 200 | |
| 201 { | |
| 202 track_bitmap_ = UIResourceBitmap::Create( | |
| 203 new uint8_t[track_rect.width()*track_rect.height()*4], | |
| 204 UIResourceBitmap::RGBA8, | |
| 205 track_rect.size()); | |
| 206 | |
| 207 // raster track | |
| 208 skia::RefPtr<SkCanvas> track_canvas = skia::AdoptRef( | |
| 209 skia::CreatePlatformCanvas(track_rect.width(), | |
| 210 track_rect.height(), | |
| 211 false, | |
| 212 reinterpret_cast<uint8_t*>( | |
| 213 track_bitmap_->GetPixels()), | |
| 214 skia::CRASH_ON_FAILURE)); | |
| 215 | |
| 216 track_canvas->save(); | |
| 217 track_canvas->translate(SkFloatToScalar(-track_rect.x()), | |
| 218 SkFloatToScalar(-track_rect.y())); | |
| 219 SkPaint paint; | |
| 220 paint.setAntiAlias(false); | |
| 221 paint.setXfermodeMode(SkXfermode::kClear_Mode); | |
| 222 SkRect layer_sk_rect = SkRect::MakeXYWH(track_rect.x(), | |
| 223 track_rect.y(), | |
| 224 track_rect.width(), | |
| 225 track_rect.height()); | |
| 226 | |
| 227 track_canvas->drawRect(layer_sk_rect, paint); | |
| 228 track_canvas->clipRect(layer_sk_rect); | |
| 229 scrollbar_->PaintPart(track_canvas.get(), TRACK, track_rect); | |
| 230 track_canvas->restore(); | |
| 231 | |
| 232 if (track_ui_resource_id_) { | |
| 233 layer_tree_host()->DeleteUIResource(track_ui_resource_id_); | |
| 234 } | |
| 235 track_ui_resource_id_ = layer_tree_host()->CreateUIResource(track_bitmap_, | |
| 236 this); | |
| 237 } | |
| 238 | |
| 239 if (scrollbar_->HasThumb()) { | |
| 240 thumb_bitmap_ = UIResourceBitmap::Create( | |
| 241 new uint8_t[thumb_rect.width()*thumb_rect.height()*4], | |
| 242 UIResourceBitmap::RGBA8, | |
| 243 thumb_rect.size()); | |
| 244 | |
| 245 // raster thumb | |
| 246 skia::RefPtr<SkCanvas> thumb_canvas = skia::AdoptRef( | |
| 247 skia::CreatePlatformCanvas(thumb_rect.width(), | |
| 248 thumb_rect.height(), | |
| 249 false, | |
| 250 reinterpret_cast<uint8_t*>( | |
| 251 thumb_bitmap_->GetPixels()), | |
| 252 skia::CRASH_ON_FAILURE)); | |
| 253 | |
| 254 scrollbar_->PaintPart(thumb_canvas.get(), | |
| 255 THUMB, | |
| 256 thumb_rect); | |
| 257 | |
| 258 if (thumb_ui_resource_id_) | |
| 259 layer_tree_host()->DeleteUIResource(thumb_ui_resource_id_); | |
| 260 thumb_ui_resource_id_ = layer_tree_host()->CreateUIResource(thumb_bitmap_, | |
| 261 this); | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 gfx::Rect ScrollbarLayer::OriginThumbRect() const { | |
| 266 gfx::Size thumb_size; | |
| 267 if (Orientation() == HORIZONTAL) { | |
| 268 thumb_size = gfx::Size(scrollbar_->ThumbLength(), | |
| 269 scrollbar_->ThumbThickness()); | |
| 270 } else { | |
| 271 thumb_size = gfx::Size(scrollbar_->ThumbThickness(), | |
| 272 scrollbar_->ThumbLength()); | |
| 273 } | |
| 274 return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); | |
| 275 } | |
| 276 | |
| 277 void ScrollbarLayer::UIResourceReady(UIResourceId id) { | |
| 278 if (thumb_ui_resource_id_ == id) { | |
| 279 thumb_ui_resource_status_ = UIResourceManagerClient::READY; | |
| 280 // need to push the ui resource id to the impl thread. | |
| 281 // Is this the only way? | |
|
enne (OOO)
2013/07/09 17:57:48
I think you're looking for SetNeedsCommit.
powei
2013/07/10 17:47:21
Done.
| |
| 282 SetNeedsDisplay(); | |
| 283 // if we do not have this flag, we will always have a | |
| 284 // setneedsdisplay request in the scheduler | |
| 285 skip_update_ = true; | |
| 286 } | |
| 287 | |
| 288 if (track_ui_resource_id_ == id) { | |
| 289 track_ui_resource_status_ = UIResourceManagerClient::READY; | |
| 290 SetNeedsDisplay(); | |
| 291 skip_update_ = true; | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 void ScrollbarLayer::UIResourceLost(UIResourceId id) { | |
|
enne (OOO)
2013/07/09 17:57:48
As I mentioned in the doc about this, I would real
aelias_OOO_until_Jul13
2013/07/09 20:22:19
OK, after discussing it with dtrainor@, we agree.
| |
| 296 if (thumb_ui_resource_id_ == id) | |
| 297 thumb_ui_resource_status_ = UIResourceManagerClient::LOST; | |
| 298 thumb_ui_resource_id_ = 0; | |
| 299 | |
| 300 if (track_ui_resource_id_ == id) | |
| 301 track_ui_resource_status_ = UIResourceManagerClient::LOST; | |
| 302 track_ui_resource_id_ = 0; | |
| 303 } | |
| 304 | |
| 305 } // namespace cc | |
| 306 | |
| 307 #endif | |
| OLD | NEW |