Index: cc/layers/scrollbar_layer.cc |
=================================================================== |
--- cc/layers/scrollbar_layer.cc (revision 215030) |
+++ cc/layers/scrollbar_layer.cc (working copy) |
@@ -1,3 +1,4 @@ |
+ |
// Copyright 2012 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
@@ -8,14 +9,11 @@ |
#include "base/basictypes.h" |
#include "base/debug/trace_event.h" |
#include "cc/layers/scrollbar_layer_impl.h" |
-#include "cc/resources/ui_resource_bitmap.h" |
+#include "cc/resources/caching_bitmap_content_layer_updater.h" |
+#include "cc/resources/layer_painter.h" |
+#include "cc/resources/prioritized_resource.h" |
+#include "cc/resources/resource_update_queue.h" |
#include "cc/trees/layer_tree_host.h" |
-#include "cc/trees/layer_tree_impl.h" |
-#include "skia/ext/platform_canvas.h" |
-#include "skia/ext/refptr.h" |
-#include "third_party/skia/include/core/SkBitmap.h" |
-#include "third_party/skia/include/core/SkCanvas.h" |
-#include "third_party/skia/include/core/SkSize.h" |
#include "ui/gfx/rect_conversions.h" |
namespace cc { |
@@ -29,15 +27,16 @@ |
scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( |
scoped_ptr<Scrollbar> scrollbar, |
int scroll_layer_id) { |
- return make_scoped_refptr( |
- new ScrollbarLayer(scrollbar.Pass(), scroll_layer_id)); |
+ return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(), |
+ scroll_layer_id)); |
} |
ScrollbarLayer::ScrollbarLayer( |
scoped_ptr<Scrollbar> scrollbar, |
int scroll_layer_id) |
: scrollbar_(scrollbar.Pass()), |
- scroll_layer_id_(scroll_layer_id) { |
+ scroll_layer_id_(scroll_layer_id), |
+ texture_format_(GL_INVALID_ENUM) { |
if (!scrollbar_->IsOverlay()) |
SetShouldScrollOnMainThread(true); |
} |
@@ -129,11 +128,16 @@ |
scrollbar_layer->set_track_length(track_rect_.height()); |
} |
- if (track_resource_.get()) |
- scrollbar_layer->set_track_ui_resource_id(track_resource_->id()); |
- if (thumb_resource_.get()) |
- scrollbar_layer->set_thumb_ui_resource_id(thumb_resource_->id()); |
+ if (track_ && track_->texture()->have_backing_texture()) |
+ scrollbar_layer->set_track_resource_id(track_->texture()->resource_id()); |
+ else |
+ scrollbar_layer->set_track_resource_id(0); |
+ if (thumb_ && thumb_->texture()->have_backing_texture()) |
+ scrollbar_layer->set_thumb_resource_id(thumb_->texture()->resource_id()); |
+ else |
+ scrollbar_layer->set_thumb_resource_id(0); |
+ |
scrollbar_layer->set_is_overlay_scrollbar(scrollbar_->IsOverlay()); |
// ScrollbarLayer must push properties every frame. crbug.com/259095 |
@@ -145,16 +149,113 @@ |
} |
void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { |
- // When the LTH is set to null or has changed, then this layer should remove |
- // all of its associated resources. |
if (!host || host != layer_tree_host()) { |
- track_resource_.reset(); |
- thumb_resource_.reset(); |
+ track_updater_ = NULL; |
+ track_.reset(); |
+ thumb_updater_ = NULL; |
+ thumb_.reset(); |
} |
ContentsScalingLayer::SetLayerTreeHost(host); |
} |
+class ScrollbarPartPainter : public LayerPainter { |
+ public: |
+ ScrollbarPartPainter(Scrollbar* scrollbar, ScrollbarPart part) |
+ : scrollbar_(scrollbar), |
+ part_(part) {} |
+ virtual ~ScrollbarPartPainter() {} |
+ |
+ // LayerPainter implementation |
+ virtual void Paint(SkCanvas* canvas, |
+ gfx::Rect content_rect, |
+ gfx::RectF* opaque) OVERRIDE { |
+ scrollbar_->PaintPart(canvas, part_, content_rect); |
+ } |
+ |
+ private: |
+ Scrollbar* scrollbar_; |
+ ScrollbarPart part_; |
+}; |
+ |
+void ScrollbarLayer::CreateUpdaterIfNeeded() { |
+ if (layer_tree_host()->settings().solid_color_scrollbars) |
+ return; |
+ |
+ texture_format_ = |
+ layer_tree_host()->GetRendererCapabilities().best_texture_format; |
+ |
+ if (!track_updater_.get()) { |
+ track_updater_ = CachingBitmapContentLayerUpdater::Create( |
+ scoped_ptr<LayerPainter>( |
+ new ScrollbarPartPainter(scrollbar_.get(), TRACK)) |
+ .Pass(), |
+ rendering_stats_instrumentation(), |
+ id()); |
+ } |
+ if (!track_) { |
+ track_ = track_updater_->CreateResource( |
+ layer_tree_host()->contents_texture_manager()); |
+ } |
+ |
+ if (!thumb_updater_.get()) { |
+ thumb_updater_ = CachingBitmapContentLayerUpdater::Create( |
+ scoped_ptr<LayerPainter>( |
+ new ScrollbarPartPainter(scrollbar_.get(), THUMB)) |
+ .Pass(), |
+ rendering_stats_instrumentation(), |
+ id()); |
+ } |
+ if (!thumb_ && scrollbar_->HasThumb()) { |
+ thumb_ = thumb_updater_->CreateResource( |
+ layer_tree_host()->contents_texture_manager()); |
+ } |
+} |
+ |
+bool ScrollbarLayer::UpdatePart(CachingBitmapContentLayerUpdater* painter, |
+ LayerUpdater::Resource* resource, |
+ gfx::Rect rect, |
+ ResourceUpdateQueue* queue) { |
+ if (layer_tree_host()->settings().solid_color_scrollbars) |
+ return false; |
+ |
+ // Skip painting and uploading if there are no invalidations and |
+ // we already have valid texture data. |
+ if (resource->texture()->have_backing_texture() && |
+ resource->texture()->size() == rect.size() && |
+ !is_dirty()) |
+ return false; |
+ |
+ // We should always have enough memory for UI. |
+ DCHECK(resource->texture()->can_acquire_backing_texture()); |
+ if (!resource->texture()->can_acquire_backing_texture()) |
+ return false; |
+ |
+ // Paint and upload the entire part. |
+ gfx::Rect painted_opaque_rect; |
+ painter->PrepareToUpdate(rect, |
+ rect.size(), |
+ contents_scale_x(), |
+ contents_scale_y(), |
+ &painted_opaque_rect); |
+ if (!painter->pixels_did_change() && |
+ resource->texture()->have_backing_texture()) { |
+ TRACE_EVENT_INSTANT0("cc", |
+ "ScrollbarLayer::UpdatePart no texture upload needed", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ return false; |
+ } |
+ |
+ bool partial_updates_allowed = |
+ layer_tree_host()->settings().max_partial_texture_updates > 0; |
+ if (!partial_updates_allowed) |
+ resource->texture()->ReturnBackingTexture(); |
+ |
+ gfx::Vector2d dest_offset(0, 0); |
+ resource->Update(queue, rect, dest_offset, partial_updates_allowed); |
+ return true; |
+} |
+ |
gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( |
gfx::Rect layer_rect) const { |
// Don't intersect with the bounds as in LayerRectToContentRect() because |
@@ -168,16 +269,30 @@ |
return expanded_rect; |
} |
-gfx::Rect ScrollbarLayer::OriginThumbRect() const { |
- gfx::Size thumb_size; |
- if (Orientation() == HORIZONTAL) { |
- thumb_size = |
- gfx::Size(scrollbar_->ThumbLength(), scrollbar_->ThumbThickness()); |
- } else { |
- thumb_size = |
- gfx::Size(scrollbar_->ThumbThickness(), scrollbar_->ThumbLength()); |
+void ScrollbarLayer::SetTexturePriorities( |
+ const PriorityCalculator& priority_calc) { |
+ if (layer_tree_host()->settings().solid_color_scrollbars) |
+ return; |
+ |
+ if (content_bounds().IsEmpty()) |
+ return; |
+ DCHECK_LE(content_bounds().width(), MaxTextureSize()); |
+ DCHECK_LE(content_bounds().height(), MaxTextureSize()); |
+ |
+ CreateUpdaterIfNeeded(); |
+ |
+ bool draws_to_root = !render_target()->parent(); |
+ if (track_) { |
+ track_->texture()->SetDimensions(content_bounds(), texture_format_); |
+ track_->texture()->set_request_priority( |
+ PriorityCalculator::UIPriority(draws_to_root)); |
} |
- return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); |
+ if (thumb_) { |
+ gfx::Size thumb_size = OriginThumbRect().size(); |
+ thumb_->texture()->SetDimensions(thumb_size, texture_format_); |
+ thumb_->texture()->set_request_priority( |
+ PriorityCalculator::UIPriority(draws_to_root)); |
+ } |
} |
bool ScrollbarLayer::Update(ResourceUpdateQueue* queue, |
@@ -193,62 +308,43 @@ |
ContentsScalingLayer::Update(queue, occlusion); |
} |
+ dirty_rect_.Union(update_rect_); |
+ if (content_bounds().IsEmpty()) |
+ return false; |
+ if (visible_content_rect().IsEmpty()) |
+ return false; |
+ |
+ CreateUpdaterIfNeeded(); |
+ |
+ gfx::Rect content_rect = ScrollbarLayerRectToContentRect( |
+ gfx::Rect(scrollbar_->Location(), bounds())); |
+ bool updated = UpdatePart(track_updater_.get(), track_.get(), content_rect, |
+ queue); |
+ |
if (scrollbar_->HasThumb()) { |
thumb_thickness_ = scrollbar_->ThumbThickness(); |
thumb_length_ = scrollbar_->ThumbLength(); |
+ gfx::Rect origin_thumb_rect = OriginThumbRect(); |
+ if (!origin_thumb_rect.IsEmpty()) { |
+ updated |= UpdatePart(thumb_updater_.get(), thumb_.get(), |
+ origin_thumb_rect, queue); |
+ } |
} |
- track_resource_ = |
- ScopedUIResource::Create(layer_tree_host(), RasterizeTrack()); |
- if (scrollbar_->HasThumb()) |
- thumb_resource_ = |
- ScopedUIResource::Create(layer_tree_host(), RasterizeThumb()); |
- |
- return true; |
+ dirty_rect_ = gfx::RectF(); |
+ return updated; |
} |
-scoped_refptr<UIResourceBitmap> ScrollbarLayer::RasterizeTrack() { |
- DCHECK(!layer_tree_host()->settings().solid_color_scrollbars); |
- |
- gfx::Rect track_rect = ScrollbarLayerRectToContentRect( |
- gfx::Rect(scrollbar_->Location(), bounds())); |
- scoped_refptr<UIResourceBitmap> track_bitmap = UIResourceBitmap::Create( |
- new uint8_t[track_rect.width() * track_rect.height() * 4], |
- UIResourceBitmap::RGBA8, |
- track_rect.size()); |
- |
- SkBitmap skbitmap; |
- skbitmap.setConfig( |
- SkBitmap::kARGB_8888_Config, track_rect.width(), track_rect.height()); |
- skbitmap.setPixels(track_bitmap->GetPixels()); |
- |
- SkCanvas track_canvas(skbitmap); |
- track_canvas.translate(SkFloatToScalar(-track_rect.x()), |
- SkFloatToScalar(-track_rect.y())); |
- scrollbar_->PaintPart(&track_canvas, TRACK, track_rect); |
- |
- return track_bitmap; |
+gfx::Rect ScrollbarLayer::OriginThumbRect() const { |
+ gfx::Size thumb_size; |
+ if (Orientation() == HORIZONTAL) { |
+ thumb_size = gfx::Size(scrollbar_->ThumbLength(), |
+ scrollbar_->ThumbThickness()); |
+ } else { |
+ thumb_size = gfx::Size(scrollbar_->ThumbThickness(), |
+ scrollbar_->ThumbLength()); |
+ } |
+ return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); |
} |
-scoped_refptr<UIResourceBitmap> ScrollbarLayer::RasterizeThumb() { |
- DCHECK(!layer_tree_host()->settings().solid_color_scrollbars); |
- DCHECK(scrollbar_->HasThumb()); |
- |
- gfx::Rect thumb_rect = OriginThumbRect(); |
- scoped_refptr<UIResourceBitmap> thumb_bitmap = UIResourceBitmap::Create( |
- new uint8_t[thumb_rect.width() * thumb_rect.height() * 4], |
- UIResourceBitmap::RGBA8, |
- thumb_rect.size()); |
- |
- SkBitmap skbitmap; |
- skbitmap.setConfig( |
- SkBitmap::kARGB_8888_Config, thumb_rect.width(), thumb_rect.height()); |
- skbitmap.setPixels(thumb_bitmap->GetPixels()); |
- |
- SkCanvas thumb_canvas(skbitmap); |
- scrollbar_->PaintPart(&thumb_canvas, THUMB, thumb_rect); |
- |
- return thumb_bitmap; |
-} |
- |
} // namespace cc |