summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpowei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-01 06:28:57 +0000
committerpowei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-01 06:28:57 +0000
commitc928076e7b0f787091d512d6e24e4cbeb90159bb (patch)
treed7b38b3e0dc6b28e30418f6228ecba5d116a8577
parenta8a515cf0845fcfdea7163fe1ed78a8c4c2b2e5b (diff)
downloadchromium_src-c928076e7b0f787091d512d6e24e4cbeb90159bb.zip
chromium_src-c928076e7b0f787091d512d6e24e4cbeb90159bb.tar.gz
chromium_src-c928076e7b0f787091d512d6e24e4cbeb90159bb.tar.bz2
Proposed UI Resource Manager. See internal doc:
https://docs.google.com/a/google.com/document/d/1Im8fR0bVsBHC2I1f2MuzW-e-h1H1F5GYH4fbdBTsbQ8/edit BUG=259095,173947 Review URL: https://chromiumcodereview.appspot.com/18191020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214975 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/cc.gyp5
-rw-r--r--cc/cc_tests.gyp2
-rw-r--r--cc/layers/scrollbar_layer.cc248
-rw-r--r--cc/layers/scrollbar_layer.h28
-rw-r--r--cc/layers/scrollbar_layer_impl.cc38
-rw-r--r--cc/layers/scrollbar_layer_impl.h15
-rw-r--r--cc/layers/scrollbar_layer_unittest.cc155
-rw-r--r--cc/resources/scoped_ui_resource.cc43
-rw-r--r--cc/resources/scoped_ui_resource.h46
-rw-r--r--cc/resources/ui_resource_bitmap.cc26
-rw-r--r--cc/resources/ui_resource_bitmap.h50
-rw-r--r--cc/resources/ui_resource_client.h34
-rw-r--r--cc/test/fake_scoped_ui_resource.cc38
-rw-r--r--cc/test/fake_scoped_ui_resource.h33
-rw-r--r--cc/test/fake_scrollbar_layer.cc10
-rw-r--r--cc/test/fake_scrollbar_layer.h8
-rw-r--r--cc/trees/layer_tree_host.cc75
-rw-r--r--cc/trees/layer_tree_host.h38
-rw-r--r--cc/trees/layer_tree_host_impl.cc47
-rw-r--r--cc/trees/layer_tree_host_impl.h18
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc46
-rw-r--r--cc/trees/layer_tree_host_unittest.cc260
-rw-r--r--cc/trees/layer_tree_host_unittest_context.cc279
-rw-r--r--cc/trees/layer_tree_impl.cc36
-rw-r--r--cc/trees/layer_tree_impl.h12
25 files changed, 1167 insertions, 423 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index d934767..315e10a3 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -312,6 +312,8 @@
'resources/resource_update_queue.h',
'resources/scoped_resource.cc',
'resources/scoped_resource.h',
+ 'resources/scoped_ui_resource.cc',
+ 'resources/scoped_ui_resource.h',
'resources/skpicture_content_layer_updater.cc',
'resources/skpicture_content_layer_updater.h',
'resources/sync_point_helper.cc',
@@ -326,6 +328,9 @@
'resources/tile_priority.h',
'resources/transferable_resource.cc',
'resources/transferable_resource.h',
+ 'resources/ui_resource_bitmap.cc',
+ 'resources/ui_resource_bitmap.h',
+ 'resources/ui_resource_client.h',
'resources/video_resource_updater.cc',
'resources/video_resource_updater.h',
'resources/worker_pool.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 181ce09..9278c81 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -135,6 +135,8 @@
'test/fake_output_surface.h',
'test/fake_output_surface_client.cc',
'test/fake_output_surface_client.h',
+ 'test/fake_scoped_ui_resource.cc',
+ 'test/fake_scoped_ui_resource.h',
'test/fake_video_frame_provider.cc',
'test/fake_video_frame_provider.h',
'test/geometry_test_utils.cc',
diff --git a/cc/layers/scrollbar_layer.cc b/cc/layers/scrollbar_layer.cc
index 927ae7b..302e3e0 100644
--- a/cc/layers/scrollbar_layer.cc
+++ b/cc/layers/scrollbar_layer.cc
@@ -1,4 +1,3 @@
-
// 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.
@@ -9,11 +8,14 @@
#include "base/basictypes.h"
#include "base/debug/trace_event.h"
#include "cc/layers/scrollbar_layer_impl.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/resources/ui_resource_bitmap.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 {
@@ -27,16 +29,15 @@ scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl(
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),
- texture_format_(GL_INVALID_ENUM) {
+ scroll_layer_id_(scroll_layer_id) {
if (!scrollbar_->IsOverlay())
SetShouldScrollOnMainThread(true);
}
@@ -128,15 +129,10 @@ void ScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
scrollbar_layer->set_track_length(track_rect_.height());
}
- 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);
+ 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());
scrollbar_layer->set_is_overlay_scrollbar(scrollbar_->IsOverlay());
@@ -149,113 +145,16 @@ ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() {
}
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_updater_ = NULL;
- track_.reset();
- thumb_updater_ = NULL;
- thumb_.reset();
+ track_resource_.reset();
+ thumb_resource_.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
@@ -269,30 +168,16 @@ gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect(
return expanded_rect;
}
-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));
- }
- 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));
+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));
}
bool ScrollbarLayer::Update(ResourceUpdateQueue* queue,
@@ -308,43 +193,62 @@ bool ScrollbarLayer::Update(ResourceUpdateQueue* queue,
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);
- }
}
- dirty_rect_ = gfx::RectF();
- return updated;
+ track_resource_ =
+ ScopedUIResource::Create(layer_tree_host(), RasterizeTrack());
+ if (scrollbar_->HasThumb())
+ thumb_resource_ =
+ ScopedUIResource::Create(layer_tree_host(), RasterizeThumb());
+
+ return true;
+}
+
+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
diff --git a/cc/layers/scrollbar_layer.h b/cc/layers/scrollbar_layer.h
index f500dcc..354d549 100644
--- a/cc/layers/scrollbar_layer.h
+++ b/cc/layers/scrollbar_layer.h
@@ -10,10 +10,9 @@
#include "cc/layers/contents_scaling_layer.h"
#include "cc/layers/scrollbar_theme_painter.h"
#include "cc/resources/layer_updater.h"
+#include "cc/resources/scoped_ui_resource.h"
namespace cc {
-class CachingBitmapContentLayerUpdater;
-class ResourceUpdateQueue;
class ScrollbarThemeComposite;
class CC_EXPORT ScrollbarLayer : public ContentsScalingLayer {
@@ -33,8 +32,6 @@ class CC_EXPORT ScrollbarLayer : public ContentsScalingLayer {
ScrollbarOrientation Orientation() const;
// Layer interface
- virtual void SetTexturePriorities(const PriorityCalculator& priority_calc)
- OVERRIDE;
virtual bool Update(ResourceUpdateQueue* queue,
const OcclusionTracker* occlusion) OVERRIDE;
virtual void SetLayerTreeHost(LayerTreeHost* host) OVERRIDE;
@@ -55,36 +52,25 @@ class CC_EXPORT ScrollbarLayer : public ContentsScalingLayer {
virtual ~ScrollbarLayer();
private:
- bool UpdatePart(CachingBitmapContentLayerUpdater* painter,
- LayerUpdater::Resource* resource,
- gfx::Rect rect,
- ResourceUpdateQueue* queue);
- void CreateUpdaterIfNeeded();
gfx::Rect ScrollbarLayerRectToContentRect(gfx::Rect layer_rect) const;
gfx::Rect OriginThumbRect() const;
- bool is_dirty() const { return !dirty_rect_.IsEmpty(); }
-
int MaxTextureSize();
float ClampScaleToMaxTextureSize(float scale);
+ scoped_refptr<UIResourceBitmap> RasterizeTrack();
+ scoped_refptr<UIResourceBitmap> RasterizeThumb();
+
scoped_ptr<Scrollbar> scrollbar_;
int thumb_thickness_;
int thumb_length_;
gfx::Rect track_rect_;
+ gfx::Rect thumb_rect_;
int scroll_layer_id_;
- unsigned texture_format_;
-
- gfx::RectF dirty_rect_;
-
- scoped_refptr<CachingBitmapContentLayerUpdater> track_updater_;
- scoped_refptr<CachingBitmapContentLayerUpdater> thumb_updater_;
-
- // All the parts of the scrollbar except the thumb
- scoped_ptr<LayerUpdater::Resource> track_;
- scoped_ptr<LayerUpdater::Resource> thumb_;
+ scoped_ptr<ScopedUIResource> track_resource_;
+ scoped_ptr<ScopedUIResource> thumb_resource_;
DISALLOW_COPY_AND_ASSIGN(ScrollbarLayer);
};
diff --git a/cc/layers/scrollbar_layer_impl.cc b/cc/layers/scrollbar_layer_impl.cc
index 0dcfcde..51dbe07 100644
--- a/cc/layers/scrollbar_layer_impl.cc
+++ b/cc/layers/scrollbar_layer_impl.cc
@@ -31,8 +31,8 @@ ScrollbarLayerImpl::ScrollbarLayerImpl(
int id,
ScrollbarOrientation orientation)
: LayerImpl(tree_impl, id),
- track_resource_id_(0),
- thumb_resource_id_(0),
+ track_ui_resource_id_(0),
+ thumb_ui_resource_id_(0),
current_pos_(0.f),
maximum_(0),
thumb_thickness_(0),
@@ -69,8 +69,8 @@ void ScrollbarLayerImpl::PushPropertiesTo(LayerImpl* layer) {
scrollbar_layer->set_track_length(track_length_);
scrollbar_layer->set_is_overlay_scrollbar(is_overlay_scrollbar_);
- scrollbar_layer->set_track_resource_id(track_resource_id_);
- scrollbar_layer->set_thumb_resource_id(thumb_resource_id_);
+ scrollbar_layer->set_track_ui_resource_id(track_ui_resource_id_);
+ scrollbar_layer->set_thumb_ui_resource_id(thumb_ui_resource_id_);
}
bool ScrollbarLayerImpl::WillDraw(DrawMode draw_mode,
@@ -106,14 +106,19 @@ void ScrollbarLayerImpl::AppendQuads(QuadSink* quad_sink,
return;
}
- if (thumb_resource_id_ && !thumb_quad_rect.IsEmpty()) {
+ ResourceProvider::ResourceId thumb_resource_id =
+ layer_tree_impl()->ResourceIdForUIResource(thumb_ui_resource_id_);
+ ResourceProvider::ResourceId track_resource_id =
+ layer_tree_impl()->ResourceIdForUIResource(track_ui_resource_id_);
+
+ if (thumb_resource_id && !thumb_quad_rect.IsEmpty()) {
gfx::Rect opaque_rect;
const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
thumb_quad_rect,
opaque_rect,
- thumb_resource_id_,
+ thumb_resource_id,
premultipled_alpha,
uv_top_left,
uv_bottom_right,
@@ -123,21 +128,15 @@ void ScrollbarLayerImpl::AppendQuads(QuadSink* quad_sink,
quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
}
- if (!track_resource_id_)
- return;
-
- // Order matters here: since the back track texture is being drawn to the
- // entire contents rect, we must append it after the thumb and fore track
- // quads. The back track texture contains (and displays) the buttons.
- if (!content_bounds_rect.IsEmpty()) {
- gfx::Rect quad_rect(content_bounds_rect);
- gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
+ gfx::Rect track_quad_rect = content_bounds_rect;
+ if (track_resource_id && !track_quad_rect.IsEmpty()) {
+ gfx::Rect opaque_rect(contents_opaque() ? track_quad_rect : gfx::Rect());
const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- quad_rect,
+ track_quad_rect,
opaque_rect,
- track_resource_id_,
+ track_resource_id,
premultipled_alpha,
uv_top_left,
uv_bottom_right,
@@ -261,11 +260,6 @@ gfx::Rect ScrollbarLayerImpl::ComputeThumbQuadRect() const {
return ScrollbarLayerRectToContentRect(thumb_rect);
}
-void ScrollbarLayerImpl::DidLoseOutputSurface() {
- track_resource_id_ = 0;
- thumb_resource_id_ = 0;
-}
-
const char* ScrollbarLayerImpl::LayerTypeAsString() const {
return "cc::ScrollbarLayerImpl";
}
diff --git a/cc/layers/scrollbar_layer_impl.h b/cc/layers/scrollbar_layer_impl.h
index f61b660..ffc758f 100644
--- a/cc/layers/scrollbar_layer_impl.h
+++ b/cc/layers/scrollbar_layer_impl.h
@@ -8,6 +8,7 @@
#include "cc/base/cc_export.h"
#include "cc/input/scrollbar.h"
#include "cc/layers/layer_impl.h"
+#include "cc/resources/ui_resource_client.h"
namespace cc {
@@ -33,8 +34,6 @@ class CC_EXPORT ScrollbarLayerImpl : public LayerImpl {
virtual void AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) OVERRIDE;
- virtual void DidLoseOutputSurface() OVERRIDE;
-
int scroll_layer_id() const { return scroll_layer_id_; }
void set_scroll_layer_id(int id) { scroll_layer_id_ = id; }
@@ -58,11 +57,11 @@ class CC_EXPORT ScrollbarLayerImpl : public LayerImpl {
void set_vertical_adjust(float vertical_adjust) {
vertical_adjust_ = vertical_adjust;
}
- void set_track_resource_id(ResourceProvider::ResourceId id) {
- track_resource_id_ = id;
+ void set_track_ui_resource_id(UIResourceId uid) {
+ track_ui_resource_id_ = uid;
}
- void set_thumb_resource_id(ResourceProvider::ResourceId id) {
- thumb_resource_id_ = id;
+ void set_thumb_ui_resource_id(UIResourceId uid) {
+ thumb_ui_resource_id_ = uid;
}
void set_visible_to_total_length_ratio(float ratio) {
visible_to_total_length_ratio_ = ratio;
@@ -87,8 +86,8 @@ class CC_EXPORT ScrollbarLayerImpl : public LayerImpl {
gfx::Rect ScrollbarLayerRectToContentRect(gfx::RectF layer_rect) const;
- ResourceProvider::ResourceId track_resource_id_;
- ResourceProvider::ResourceId thumb_resource_id_;
+ UIResourceId track_ui_resource_id_;
+ UIResourceId thumb_ui_resource_id_;
float current_pos_;
int maximum_;
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 1d46113..c007bb0 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -4,6 +4,7 @@
#include "cc/layers/scrollbar_layer.h"
+#include "base/containers/hash_tables.h"
#include "cc/animation/scrollbar_animation_controller.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/scrollbar_layer_impl.h"
@@ -20,6 +21,7 @@
#include "cc/test/layer_tree_test.h"
#include "cc/test/mock_quad_culler.h"
#include "cc/test/test_web_graphics_context_3d.h"
+#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/tree_synchronizer.h"
@@ -403,9 +405,39 @@ class MockLayerTreeHost : public LayerTreeHost {
public:
MockLayerTreeHost(LayerTreeHostClient* client,
const LayerTreeSettings& settings)
- : LayerTreeHost(client, settings) {
+ : LayerTreeHost(client, settings),
+ next_id_(1),
+ total_ui_resource_created_(0),
+ total_ui_resource_deleted_(0) {
Initialize(NULL);
}
+
+ virtual UIResourceId CreateUIResource(UIResourceClient* content) OVERRIDE {
+ total_ui_resource_created_++;
+ UIResourceId nid = next_id_++;
+ ui_resource_id_set_.insert(nid);
+ return nid;
+ }
+
+ // Deletes a UI resource. May safely be called more than once.
+ virtual void DeleteUIResource(UIResourceId id) OVERRIDE {
+ UIResourceIdSet::iterator iter = ui_resource_id_set_.find(id);
+ if (iter != ui_resource_id_set_.end()) {
+ ui_resource_id_set_.erase(iter);
+ total_ui_resource_deleted_++;
+ }
+ }
+
+ size_t UIResourceCount() { return ui_resource_id_set_.size(); }
+ int TotalUIResourceDeleted() { return total_ui_resource_deleted_; }
+ int TotalUIResourceCreated() { return total_ui_resource_created_; }
+
+ private:
+ typedef base::hash_set<UIResourceId> UIResourceIdSet;
+ UIResourceIdSet ui_resource_id_set_;
+ int next_id_;
+ int total_ui_resource_created_;
+ int total_ui_resource_deleted_;
};
@@ -414,7 +446,10 @@ class ScrollbarLayerTestResourceCreation : public testing::Test {
ScrollbarLayerTestResourceCreation()
: fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
- void TestResourceUpload(size_t expected_resources) {
+ void TestResourceUpload(int num_updates,
+ size_t expected_resources,
+ int expected_created,
+ int expected_deleted) {
layer_tree_host_.reset(
new MockLayerTreeHost(&fake_client_, layer_tree_settings_));
@@ -446,15 +481,17 @@ class ScrollbarLayerTestResourceCreation : public testing::Test {
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get());
- PriorityCalculator calculator;
ResourceUpdateQueue queue;
OcclusionTracker occlusion_tracker(gfx::Rect(), false);
- scrollbar_layer->SetTexturePriorities(calculator);
- layer_tree_host_->contents_texture_manager()->PrioritizeTextures();
- scrollbar_layer->Update(&queue, &occlusion_tracker);
- EXPECT_EQ(0u, queue.FullUploadSize());
- EXPECT_EQ(expected_resources, queue.PartialUploadSize());
+ for (int update_counter = 0; update_counter < num_updates; update_counter++)
+ scrollbar_layer->Update(&queue, &occlusion_tracker);
+
+ // A non-solid-color scrollbar should have requested two textures.
+ // A solid-color scrollbar should have requested two textures.
+ EXPECT_EQ(expected_resources, layer_tree_host_->UIResourceCount());
+ EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated());
+ EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted());
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
@@ -469,104 +506,18 @@ class ScrollbarLayerTestResourceCreation : public testing::Test {
TEST_F(ScrollbarLayerTestResourceCreation, ResourceUpload) {
layer_tree_settings_.solid_color_scrollbars = false;
- TestResourceUpload(2);
+ TestResourceUpload(0, 0, 0, 0);
+ int num_updates[3] = {1, 5, 10};
+ for (int j = 0; j < 3; j++) {
+ TestResourceUpload(
+ num_updates[j], 2, num_updates[j] * 2, (num_updates[j] - 1) * 2);
+ }
}
TEST_F(ScrollbarLayerTestResourceCreation, SolidColorNoResourceUpload) {
layer_tree_settings_.solid_color_scrollbars = true;
- TestResourceUpload(0);
-}
-
-class ScaledScrollbarLayerTestResourceCreation : public testing::Test {
- public:
- ScaledScrollbarLayerTestResourceCreation()
- : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
- void TestResourceUpload(size_t expected_resources, const float test_scale) {
- layer_tree_host_.reset(
- new MockLayerTreeHost(&fake_client_, layer_tree_settings_));
-
- gfx::Point scrollbar_location(0, 185);
- scoped_ptr<FakeScrollbar> scrollbar(new FakeScrollbar(false, true, false));
- scrollbar->set_location(scrollbar_location);
-
- scoped_refptr<Layer> layer_tree_root = Layer::Create();
- scoped_refptr<Layer> content_layer = Layer::Create();
- scoped_refptr<Layer> scrollbar_layer =
- ScrollbarLayer::Create(scrollbar.PassAs<cc::Scrollbar>(),
- layer_tree_root->id());
- layer_tree_root->AddChild(content_layer);
- layer_tree_root->AddChild(scrollbar_layer);
-
- layer_tree_host_->InitializeOutputSurfaceIfNeeded();
- layer_tree_host_->contents_texture_manager()->
- SetMaxMemoryLimitBytes(1024 * 1024);
- layer_tree_host_->SetRootLayer(layer_tree_root);
-
- scrollbar_layer->SetIsDrawable(true);
- scrollbar_layer->SetBounds(gfx::Size(100, 15));
- scrollbar_layer->SetPosition(scrollbar_location);
- layer_tree_root->SetBounds(gfx::Size(100, 200));
- content_layer->SetBounds(gfx::Size(100, 200));
- gfx::SizeF scaled_size =
- gfx::ScaleSize(scrollbar_layer->bounds(), test_scale, test_scale);
- gfx::PointF scaled_location =
- gfx::ScalePoint(scrollbar_layer->position(), test_scale, test_scale);
- scrollbar_layer->draw_properties().content_bounds =
- gfx::Size(scaled_size.width(), scaled_size.height());
- scrollbar_layer->draw_properties().contents_scale_x = test_scale;
- scrollbar_layer->draw_properties().contents_scale_y = test_scale;
- scrollbar_layer->draw_properties().visible_content_rect =
- gfx::Rect(scaled_location.x(),
- scaled_location.y(),
- scaled_size.width(),
- scaled_size.height());
- scrollbar_layer->CreateRenderSurface();
- scrollbar_layer->draw_properties().render_target = scrollbar_layer.get();
-
- testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
- EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get());
-
- PriorityCalculator calculator;
- ResourceUpdateQueue queue;
- OcclusionTracker occlusion_tracker(gfx::Rect(), false);
-
- scrollbar_layer->SetTexturePriorities(calculator);
- layer_tree_host_->contents_texture_manager()->PrioritizeTextures();
- scrollbar_layer->Update(&queue, &occlusion_tracker);
- EXPECT_EQ(expected_resources, queue.PartialUploadSize());
-
- // Verify that we have not generated any content uploads that are larger
- // than their destination textures.
- while (queue.HasMoreUpdates()) {
- ResourceUpdate update = queue.TakeFirstPartialUpload();
- EXPECT_LE(update.texture->size().width(),
- scrollbar_layer->content_bounds().width());
- EXPECT_LE(update.texture->size().height(),
- scrollbar_layer->content_bounds().height());
-
- EXPECT_LE(update.dest_offset.x() + update.content_rect.width(),
- update.texture->size().width());
- EXPECT_LE(update.dest_offset.y() + update.content_rect.height(),
- update.texture->size().height());
- }
-
- testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- scrollbar_layer->ClearRenderSurface();
- }
-
- protected:
- FakeLayerTreeHostClient fake_client_;
- LayerTreeSettings layer_tree_settings_;
- scoped_ptr<MockLayerTreeHost> layer_tree_host_;
-};
-
-TEST_F(ScaledScrollbarLayerTestResourceCreation, ScaledResourceUpload) {
- layer_tree_settings_.solid_color_scrollbars = false;
- // Pick a test scale that moves the scrollbar's (non-zero) position to
- // a non-pixel-aligned location.
- TestResourceUpload(2, 1.41f);
+ TestResourceUpload(0, 0, 0, 0);
+ TestResourceUpload(1, 0, 0, 0);
}
} // namespace
diff --git a/cc/resources/scoped_ui_resource.cc b/cc/resources/scoped_ui_resource.cc
new file mode 100644
index 0000000..1622552
--- /dev/null
+++ b/cc/resources/scoped_ui_resource.cc
@@ -0,0 +1,43 @@
+// Copyright 2013 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.
+
+#include "cc/resources/scoped_ui_resource.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "cc/trees/layer_tree_host.h"
+
+namespace cc {
+
+scoped_ptr<ScopedUIResource> ScopedUIResource::Create(
+ LayerTreeHost* host,
+ scoped_refptr<UIResourceBitmap> bitmap) {
+ return make_scoped_ptr(new ScopedUIResource(host, bitmap));
+}
+
+ScopedUIResource::ScopedUIResource(LayerTreeHost* host,
+ scoped_refptr<UIResourceBitmap> bitmap)
+ : bitmap_(bitmap), host_(host) {
+ DCHECK(host_);
+ id_ = host_->CreateUIResource(this);
+}
+
+// User must make sure that host is still valid before this object goes out of
+// scope.
+ScopedUIResource::~ScopedUIResource() {
+ if (id_) {
+ DCHECK(host_);
+ host_->DeleteUIResource(id_);
+ }
+}
+
+scoped_refptr<UIResourceBitmap> ScopedUIResource::GetBitmap(
+ UIResourceId uid,
+ bool resource_lost) {
+ return bitmap_;
+}
+
+ScopedUIResource::ScopedUIResource() {}
+
+} // namespace cc
diff --git a/cc/resources/scoped_ui_resource.h b/cc/resources/scoped_ui_resource.h
new file mode 100644
index 0000000..628d372
--- /dev/null
+++ b/cc/resources/scoped_ui_resource.h
@@ -0,0 +1,46 @@
+// Copyright 2013 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.
+
+#ifndef CC_RESOURCES_SCOPED_UI_RESOURCE_H_
+#define CC_RESOURCES_SCOPED_UI_RESOURCE_H_
+
+#include "base/memory/ref_counted.h"
+#include "cc/base/cc_export.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "cc/resources/ui_resource_client.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+
+class LayerTreeHost;
+
+class CC_EXPORT ScopedUIResource : public UIResourceClient {
+ public:
+ static scoped_ptr<ScopedUIResource> Create(
+ LayerTreeHost* host,
+ scoped_refptr<UIResourceBitmap> bitmap);
+ virtual ~ScopedUIResource();
+
+ virtual scoped_refptr<UIResourceBitmap> GetBitmap(
+ UIResourceId uid,
+ bool resource_lost) OVERRIDE;
+ UIResourceId id() { return id_; }
+
+ protected:
+ ScopedUIResource(LayerTreeHost* host, scoped_refptr<UIResourceBitmap> bitmap);
+
+ // An empty default contructor for testing.
+ ScopedUIResource();
+
+ scoped_refptr<UIResourceBitmap> bitmap_;
+ LayerTreeHost* host_;
+ UIResourceId id_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedUIResource);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_SCOPED_UI_RESOURCE_H_
diff --git a/cc/resources/ui_resource_bitmap.cc b/cc/resources/ui_resource_bitmap.cc
new file mode 100644
index 0000000..8bbfb37
--- /dev/null
+++ b/cc/resources/ui_resource_bitmap.cc
@@ -0,0 +1,26 @@
+// Copyright 2013 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.
+
+#include "cc/resources/ui_resource_bitmap.h"
+
+#include "base/memory/scoped_ptr.h"
+
+namespace cc {
+
+scoped_refptr<UIResourceBitmap>
+UIResourceBitmap::Create(uint8_t* pixels,
+ UIResourceFormat format,
+ gfx::Size size) {
+ scoped_refptr<UIResourceBitmap> ret = new UIResourceBitmap();
+ ret->pixels_ = scoped_ptr<uint8_t[]>(pixels);
+ ret->format_ = format;
+ ret->size_ = size;
+
+ return ret;
+}
+
+UIResourceBitmap::UIResourceBitmap() {}
+UIResourceBitmap::~UIResourceBitmap() {}
+
+} // namespace cc
diff --git a/cc/resources/ui_resource_bitmap.h b/cc/resources/ui_resource_bitmap.h
new file mode 100644
index 0000000..dbf7069
--- /dev/null
+++ b/cc/resources/ui_resource_bitmap.h
@@ -0,0 +1,50 @@
+// Copyright 2013 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.
+
+#ifndef CC_RESOURCES_UI_RESOURCE_BITMAP_H_
+#define CC_RESOURCES_UI_RESOURCE_BITMAP_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "third_party/skia/include/core/SkTypes.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+
+// Ref-counted bitmap class (can’t use SkBitmap because of ETC1). Thread-safety
+// ensures that both main and impl threads can hold references to the bitmap and
+// that asynchronous uploads are allowed.
+class CC_EXPORT UIResourceBitmap
+ : public base::RefCountedThreadSafe<UIResourceBitmap> {
+ public:
+ enum UIResourceFormat {
+ RGBA8
+ };
+
+ // Takes ownership of “pixels”.
+ static scoped_refptr<UIResourceBitmap> Create(uint8_t* pixels,
+ UIResourceFormat format,
+ gfx::Size size);
+
+ gfx::Size GetSize() const { return size_; }
+ UIResourceFormat GetFormat() const { return format_; }
+ uint8_t* GetPixels() { return pixels_.get(); }
+
+ private:
+ friend class base::RefCountedThreadSafe<UIResourceBitmap>;
+
+ UIResourceBitmap();
+ ~UIResourceBitmap();
+
+ scoped_ptr<uint8_t[]> pixels_;
+ UIResourceFormat format_;
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(UIResourceBitmap);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_UI_RESOURCE_BITMAP_H_
diff --git a/cc/resources/ui_resource_client.h b/cc/resources/ui_resource_client.h
new file mode 100644
index 0000000..d647936
--- /dev/null
+++ b/cc/resources/ui_resource_client.h
@@ -0,0 +1,34 @@
+// Copyright 2013 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.
+
+#ifndef CC_RESOURCES_UI_RESOURCE_CLIENT_H_
+#define CC_RESOURCES_UI_RESOURCE_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+class UIResourceBitmap;
+
+typedef int UIResourceId;
+
+class CC_EXPORT UIResourceClient {
+ public:
+ // GetBitmap() will be called once soon after resource creation and then will
+ // be called afterwards whenever the GL context is lost, on the same thread
+ // that LayerTreeHost::CreateUIResource was called on. It is only safe to
+ // delete a UIResourceClient object after DeleteUIResource has been called for
+ // all IDs associated with it. A valid bitmap always must be returned but it
+ // doesn't need to be the same size or format as the original.
+ virtual scoped_refptr<UIResourceBitmap> GetBitmap(UIResourceId uid,
+ bool resource_lost) = 0;
+ virtual ~UIResourceClient() {}
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_UI_RESOURCE_CLIENT_H_
diff --git a/cc/test/fake_scoped_ui_resource.cc b/cc/test/fake_scoped_ui_resource.cc
new file mode 100644
index 0000000..02f0fa9
--- /dev/null
+++ b/cc/test/fake_scoped_ui_resource.cc
@@ -0,0 +1,38 @@
+// Copyright 2013 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.
+
+#include "cc/test/fake_scoped_ui_resource.h"
+
+#include "cc/trees/layer_tree_host.h"
+
+namespace cc {
+
+scoped_ptr<FakeScopedUIResource> FakeScopedUIResource::Create(
+ LayerTreeHost* host) {
+ return make_scoped_ptr(new FakeScopedUIResource(host));
+}
+
+FakeScopedUIResource::FakeScopedUIResource(LayerTreeHost* host) {
+ ResetCounters();
+ bitmap_ = UIResourceBitmap::Create(
+ new uint8_t[1], UIResourceBitmap::RGBA8, gfx::Size(1, 1));
+ host_ = host;
+ id_ = host_->CreateUIResource(this);
+}
+
+scoped_refptr<UIResourceBitmap> FakeScopedUIResource::GetBitmap(
+ UIResourceId uid,
+ bool resource_lost) {
+ resource_create_count++;
+ if (resource_lost)
+ lost_resource_count++;
+ return ScopedUIResource::GetBitmap(uid, resource_lost);
+}
+
+void FakeScopedUIResource::ResetCounters() {
+ resource_create_count = 0;
+ lost_resource_count = 0;
+}
+
+} // namespace cc
diff --git a/cc/test/fake_scoped_ui_resource.h b/cc/test/fake_scoped_ui_resource.h
new file mode 100644
index 0000000..84c097f
--- /dev/null
+++ b/cc/test/fake_scoped_ui_resource.h
@@ -0,0 +1,33 @@
+// Copyright 2013 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.
+
+#ifndef CC_TEST_FAKE_SCOPED_UI_RESOURCE_H_
+#define CC_TEST_FAKE_SCOPED_UI_RESOURCE_H_
+
+#include "base/memory/ref_counted.h"
+#include "cc/resources/scoped_ui_resource.h"
+
+namespace cc {
+
+class LayerTreeHost;
+
+class FakeScopedUIResource : public ScopedUIResource {
+ public:
+ static scoped_ptr<FakeScopedUIResource> Create(LayerTreeHost* host);
+
+ virtual scoped_refptr<UIResourceBitmap> GetBitmap(
+ UIResourceId uid,
+ bool resource_lost) OVERRIDE;
+ void ResetCounters();
+
+ int resource_create_count;
+ int lost_resource_count;
+
+ private:
+ explicit FakeScopedUIResource(LayerTreeHost* host);
+};
+
+} // namespace cc
+
+#endif // CC_TEST_FAKE_SCOPED_UI_RESOURCE_H_
diff --git a/cc/test/fake_scrollbar_layer.cc b/cc/test/fake_scrollbar_layer.cc
index 64e08ad..77cf826 100644
--- a/cc/test/fake_scrollbar_layer.cc
+++ b/cc/test/fake_scrollbar_layer.cc
@@ -18,9 +18,7 @@ FakeScrollbarLayer::FakeScrollbarLayer(bool paint_during_update,
new FakeScrollbar(paint_during_update, has_thumb, false)).Pass(),
scrolling_layer_id),
update_count_(0),
- push_properties_count_(0),
- last_update_full_upload_size_(0),
- last_update_partial_upload_size_(0) {
+ push_properties_count_(0) {
SetAnchorPoint(gfx::PointF(0.f, 0.f));
SetBounds(gfx::Size(1, 1));
SetIsDrawable(true);
@@ -30,12 +28,8 @@ FakeScrollbarLayer::~FakeScrollbarLayer() {}
bool FakeScrollbarLayer::Update(ResourceUpdateQueue* queue,
const OcclusionTracker* occlusion) {
- size_t full = queue->FullUploadSize();
- size_t partial = queue->PartialUploadSize();
bool updated = ScrollbarLayer::Update(queue, occlusion);
- update_count_++;
- last_update_full_upload_size_ = queue->FullUploadSize() - full;
- last_update_partial_upload_size_ = queue->PartialUploadSize() - partial;
+ ++update_count_;
return updated;
}
diff --git a/cc/test/fake_scrollbar_layer.h b/cc/test/fake_scrollbar_layer.h
index 43be832..60767f4 100644
--- a/cc/test/fake_scrollbar_layer.h
+++ b/cc/test/fake_scrollbar_layer.h
@@ -23,12 +23,6 @@ class FakeScrollbarLayer : public ScrollbarLayer {
int update_count() const { return update_count_; }
void reset_update_count() { update_count_ = 0; }
- size_t last_update_full_upload_size() const {
- return last_update_full_upload_size_;
- }
- size_t last_update_partial_upload_size() const {
- return last_update_partial_upload_size_;
- }
virtual bool Update(ResourceUpdateQueue* queue,
const OcclusionTracker* occlusion) OVERRIDE;
@@ -48,8 +42,6 @@ class FakeScrollbarLayer : public ScrollbarLayer {
int update_count_;
size_t push_properties_count_;
- size_t last_update_full_upload_size_;
- size_t last_update_partial_upload_size_;
};
} // namespace cc
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 86736e6..9d51042 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -29,6 +29,7 @@
#include "cc/layers/render_surface.h"
#include "cc/layers/scrollbar_layer.h"
#include "cc/resources/prioritized_resource_manager.h"
+#include "cc/resources/ui_resource_client.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
@@ -59,6 +60,11 @@ RendererCapabilities::RendererCapabilities()
RendererCapabilities::~RendererCapabilities() {}
+UIResourceRequest::UIResourceRequest()
+ : type(UIResourceInvalidRequest), id(0), bitmap(NULL) {}
+
+UIResourceRequest::~UIResourceRequest() {}
+
bool LayerTreeHost::AnyLayerTreeHostInstanceExists() {
return s_num_layer_tree_instances > 0;
}
@@ -78,7 +84,8 @@ static int s_next_tree_id = 1;
LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client,
const LayerTreeSettings& settings)
- : animating_(false),
+ : next_ui_resource_id_(1),
+ animating_(false),
needs_full_tree_sync_(true),
needs_filter_context_(false),
client_(client),
@@ -354,6 +361,15 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
pending_page_scale_animation_.reset();
}
+ if (!ui_resource_request_queue_.empty()) {
+ sync_tree->set_ui_resource_request_queue(ui_resource_request_queue_);
+ ui_resource_request_queue_.clear();
+ // Process any ui resource requests in the queue. For impl-side-painting,
+ // the queue is processed in LayerTreeHostImpl::ActivatePendingTree.
+ if (!settings_.impl_side_painting)
+ sync_tree->ProcessUIResourceRequestQueue();
+ }
+
DCHECK(!sync_tree->ViewportSizeInvalid());
if (new_impl_tree_has_no_evicted_resources) {
@@ -419,6 +435,8 @@ void LayerTreeHost::DidLoseOutputSurface() {
if (output_surface_lost_)
return;
+ DidLoseUIResources();
+
num_failed_recreate_attempts_ = 0;
output_surface_lost_ = true;
SetNeedsCommit();
@@ -1050,7 +1068,7 @@ bool LayerTreeHost::RequestPartialTextureUpdate() {
}
void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor) {
- if (device_scale_factor == device_scale_factor_)
+ if (device_scale_factor == device_scale_factor_)
return;
device_scale_factor_ = device_scale_factor;
@@ -1106,4 +1124,57 @@ void LayerTreeHost::AnimateLayers(base::TimeTicks time) {
}
}
+UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) {
+ DCHECK(client);
+
+ UIResourceRequest request;
+ bool resource_lost = false;
+ request.type = UIResourceRequest::UIResourceCreate;
+ request.id = next_ui_resource_id_++;
+
+ DCHECK(ui_resource_client_map_.find(request.id) ==
+ ui_resource_client_map_.end());
+
+ request.bitmap = client->GetBitmap(request.id, resource_lost);
+ ui_resource_request_queue_.push_back(request);
+ ui_resource_client_map_[request.id] = client;
+ return request.id;
+}
+
+// Deletes a UI resource. May safely be called more than once.
+void LayerTreeHost::DeleteUIResource(UIResourceId uid) {
+ UIResourceClientMap::iterator iter = ui_resource_client_map_.find(uid);
+ if (iter == ui_resource_client_map_.end())
+ return;
+
+ UIResourceRequest request;
+ request.type = UIResourceRequest::UIResourceDelete;
+ request.id = uid;
+ ui_resource_request_queue_.push_back(request);
+ ui_resource_client_map_.erase(uid);
+}
+
+void LayerTreeHost::UIResourceLost(UIResourceId uid) {
+ UIResourceClientMap::iterator iter = ui_resource_client_map_.find(uid);
+ if (iter == ui_resource_client_map_.end())
+ return;
+
+ UIResourceRequest request;
+ bool resource_lost = true;
+ request.type = UIResourceRequest::UIResourceCreate;
+ request.id = uid;
+ request.bitmap = iter->second->GetBitmap(uid, resource_lost);
+ DCHECK(request.bitmap.get());
+ ui_resource_request_queue_.push_back(request);
+}
+
+void LayerTreeHost::DidLoseUIResources() {
+ // When output surface is lost, we need to recreate the resource.
+ for (UIResourceClientMap::iterator iter = ui_resource_client_map_.begin();
+ iter != ui_resource_client_map_.end();
+ ++iter) {
+ UIResourceLost(iter->first);
+ }
+}
+
} // namespace cc
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index b720a8d..619c18e 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -6,6 +6,7 @@
#define CC_TREES_LAYER_TREE_HOST_H_
#include <limits>
+#include <list>
#include <vector>
#include "base/basictypes.h"
@@ -23,6 +24,8 @@
#include "cc/input/top_controls_state.h"
#include "cc/layers/layer_lists.h"
#include "cc/output/output_surface.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "cc/resources/ui_resource_client.h"
#include "cc/scheduler/rate_limiter.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_common.h"
@@ -81,6 +84,20 @@ struct CC_EXPORT RendererCapabilities {
bool using_shared_memory_resources;
};
+struct CC_EXPORT UIResourceRequest {
+ enum UIResourceRequestType {
+ UIResourceCreate,
+ UIResourceDelete,
+ UIResourceInvalidRequest
+ };
+
+ UIResourceRequest();
+ ~UIResourceRequest();
+ UIResourceRequestType type;
+ UIResourceId id;
+ scoped_refptr<UIResourceBitmap> bitmap;
+};
+
class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
public:
static scoped_ptr<LayerTreeHost> Create(
@@ -256,6 +273,16 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
bool in_paint_layer_contents() const { return in_paint_layer_contents_; }
+ // CreateUIResource creates a resource given a bitmap. The bitmap is
+ // generated via an interface function, which is called when initializing the
+ // resource and when the resource has been lost (due to lost context). The
+ // parameter of the interface is a single boolean, which indicates whether the
+ // resource has been lost or not. CreateUIResource returns an Id of the
+ // resource, which is always positive.
+ virtual UIResourceId CreateUIResource(UIResourceClient* client);
+ // Deletes a UI resource. May safely be called more than once.
+ virtual void DeleteUIResource(UIResourceId id);
+
bool UsingSharedMemoryResources();
int id() const { return tree_id_; }
@@ -292,6 +319,17 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
bool AnimateLayersRecursive(Layer* current, base::TimeTicks time);
+ void UIResourceLost(UIResourceId id);
+
+ void DidLoseUIResources();
+
+ typedef base::hash_map<UIResourceId, UIResourceClient*> UIResourceClientMap;
+ UIResourceClientMap ui_resource_client_map_;
+ int next_ui_resource_id_;
+
+ typedef std::list<UIResourceRequest> UIResourceRequestQueue;
+ UIResourceRequestQueue ui_resource_request_queue_;
+
void CalculateLCDTextMetricsCallback(Layer* layer);
bool animating_;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 3da5659..052797a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -40,6 +40,7 @@
#include "cc/resources/memory_history.h"
#include "cc/resources/picture_layer_tiling.h"
#include "cc/resources/prioritized_resource_manager.h"
+#include "cc/resources/ui_resource_bitmap.h"
#include "cc/scheduler/delay_based_time_source.h"
#include "cc/scheduler/texture_uploader.h"
#include "cc/trees/damage_tracker.h"
@@ -1457,6 +1458,11 @@ void LayerTreeHostImpl::ActivatePendingTree() {
active_tree_->root_layer());
DCHECK(!recycle_tree_);
+ // Process any requests in the UI resource queue. The request queue is given
+ // in LayerTreeHost::FinishCommitOnImplThread. This must take place before
+ // the swap.
+ pending_tree_->ProcessUIResourceRequestQueue();
+
pending_tree_->PushPropertiesTo(active_tree_.get());
// Now that we've synced everything from the pending tree to the active
@@ -1524,6 +1530,9 @@ void LayerTreeHostImpl::ReleaseTreeResources() {
SendReleaseResourcesRecursive(pending_tree_->root_layer());
if (recycle_tree_ && recycle_tree_->root_layer())
SendReleaseResourcesRecursive(recycle_tree_->root_layer());
+
+ // Remove all existing maps from UIResourceId to ResourceId.
+ ui_resource_map_.clear();
}
void LayerTreeHostImpl::CreateAndSetRenderer(
@@ -2449,4 +2458,42 @@ void LayerTreeHostImpl::SetDebugState(
SetFullRootLayerDamage();
}
+void LayerTreeHostImpl::CreateUIResource(
+ UIResourceId uid,
+ scoped_refptr<UIResourceBitmap> bitmap) {
+ DCHECK_GT(uid, 0);
+ DCHECK_EQ(bitmap->GetFormat(), UIResourceBitmap::RGBA8);
+
+ // Allow for multiple creation requests with the same UIResourceId. The
+ // previous resource is simply deleted.
+ ResourceProvider::ResourceId id = ResourceIdForUIResource(uid);
+ if (id)
+ DeleteUIResource(uid);
+ id = resource_provider_->CreateResource(
+ bitmap->GetSize(), GL_RGBA, ResourceProvider::TextureUsageAny);
+
+ ui_resource_map_[uid] = id;
+ resource_provider_->SetPixels(id,
+ reinterpret_cast<uint8_t*>(bitmap->GetPixels()),
+ gfx::Rect(bitmap->GetSize()),
+ gfx::Rect(bitmap->GetSize()),
+ gfx::Vector2d(0, 0));
+}
+
+void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) {
+ ResourceProvider::ResourceId id = ResourceIdForUIResource(uid);
+ if (id) {
+ resource_provider_->DeleteResource(id);
+ ui_resource_map_.erase(uid);
+ }
+}
+
+ResourceProvider::ResourceId LayerTreeHostImpl::ResourceIdForUIResource(
+ UIResourceId uid) const {
+ UIResourceMap::const_iterator iter = ui_resource_map_.find(uid);
+ if (iter != ui_resource_map_.end())
+ return iter->second;
+ return 0;
+}
+
} // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index f4663eb..6830d6d 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -5,10 +5,12 @@
#ifndef CC_TREES_LAYER_TREE_HOST_IMPL_H_
#define CC_TREES_LAYER_TREE_HOST_IMPL_H_
+#include <list>
#include <string>
#include <vector>
#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "cc/animation/animation_events.h"
@@ -24,7 +26,9 @@
#include "cc/output/output_surface_client.h"
#include "cc/output/renderer.h"
#include "cc/quads/render_pass.h"
+#include "cc/resources/resource_provider.h"
#include "cc/resources/tile_manager.h"
+#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/rect.h"
@@ -42,9 +46,10 @@ class PaintTimeCounter;
class MemoryHistory;
class RenderingStatsInstrumentation;
class RenderPassDrawQuad;
-class ResourceProvider;
class TopControlsManager;
+class UIResourceBitmap;
struct RendererCapabilities;
+struct UIResourceRequest;
// LayerTreeHost->Proxy callback interface.
class LayerTreeHostImplClient {
@@ -374,6 +379,13 @@ class CC_EXPORT LayerTreeHostImpl
bool page_scale_animation_active() const { return !!page_scale_animation_; }
+ void CreateUIResource(UIResourceId uid,
+ scoped_refptr<UIResourceBitmap> bitmap);
+ // Deletes a UI resource. May safely be called more than once.
+ void DeleteUIResource(UIResourceId uid);
+
+ ResourceProvider::ResourceId ResourceIdForUIResource(UIResourceId uid) const;
+
protected:
LayerTreeHostImpl(
const LayerTreeSettings& settings,
@@ -443,6 +455,10 @@ class CC_EXPORT LayerTreeHostImpl
void DidInitializeVisibleTile();
+ typedef base::hash_map<UIResourceId, ResourceProvider::ResourceId>
+ UIResourceMap;
+ UIResourceMap ui_resource_map_;
+
scoped_ptr<OutputSurface> output_surface_;
// |resource_provider_| and |tile_manager_| can be NULL, e.g. when using tile-
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index e25699e..f833655 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -6242,5 +6242,51 @@ TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
EXPECT_EQ(not_visible_cutoff_value, current_priority_cutoff_value_);
}
+TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
+ scoped_ptr<TestWebGraphicsContext3D> context =
+ TestWebGraphicsContext3D::Create();
+ TestWebGraphicsContext3D* context3d = context.get();
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(
+ context.PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>();
+ host_impl_->InitializeRenderer(output_surface.Pass());
+
+ EXPECT_EQ(0u, context3d->NumTextures());
+
+ UIResourceId ui_resource_id = 1;
+ scoped_refptr<UIResourceBitmap> bitmap = UIResourceBitmap::Create(
+ new uint8_t[1], UIResourceBitmap::RGBA8, gfx::Size(1, 1));
+ host_impl_->CreateUIResource(ui_resource_id, bitmap);
+ EXPECT_EQ(1u, context3d->NumTextures());
+ ResourceProvider::ResourceId id1 =
+ host_impl_->ResourceIdForUIResource(ui_resource_id);
+ EXPECT_NE(0u, id1);
+
+ // Multiple requests with the same id is allowed. The previous texture is
+ // deleted.
+ host_impl_->CreateUIResource(ui_resource_id, bitmap);
+ EXPECT_EQ(1u, context3d->NumTextures());
+ ResourceProvider::ResourceId id2 =
+ host_impl_->ResourceIdForUIResource(ui_resource_id);
+ EXPECT_NE(0u, id2);
+ EXPECT_NE(id1, id2);
+
+ // Deleting invalid UIResourceId is allowed and does not change state.
+ host_impl_->DeleteUIResource(-1);
+ EXPECT_EQ(1u, context3d->NumTextures());
+
+ // Should return zero for invalid UIResourceId. Number of textures should
+ // not change.
+ EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
+ EXPECT_EQ(1u, context3d->NumTextures());
+
+ host_impl_->DeleteUIResource(ui_resource_id);
+ EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
+ EXPECT_EQ(0u, context3d->NumTextures());
+
+ // Should not change state for multiple deletion on one UIResourceId
+ host_impl_->DeleteUIResource(ui_resource_id);
+ EXPECT_EQ(0u, context3d->NumTextures());
+}
+
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 41aa2e5..05a65b2 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -31,6 +31,7 @@
#include "cc/test/fake_picture_layer.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/fake_proxy.h"
+#include "cc/test/fake_scoped_ui_resource.h"
#include "cc/test/fake_scrollbar_layer.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_tree_test.h"
@@ -1107,7 +1108,7 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers
MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers);
// Verify atomicity of commits and reuse of textures.
-class LayerTreeHostTestAtomicCommit : public LayerTreeHostTest {
+class LayerTreeHostTestDirectRendererAtomicCommit : public LayerTreeHostTest {
public:
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
// Make sure partial texture updates are turned off.
@@ -1158,19 +1159,18 @@ class LayerTreeHostTestAtomicCommit : public LayerTreeHostTest {
PostSetNeedsCommitToMainThread();
break;
case 1:
- // Number of textures should be doubled as the first textures
- // are used by impl thread and cannot by used for update.
- ASSERT_EQ(4u, context->NumTextures());
- // Number of textures used for commit should still be
- // one for each layer.
+ // Number of textures should be one for scrollbar layer since it was
+ // requested and deleted on the impl-thread, and double for the content
+ // layer since its first texture is used by impl thread and cannot by
+ // used for update.
+ ASSERT_EQ(3u, context->NumTextures());
+ // Number of textures used for commit should be one for each layer.
EXPECT_EQ(2u, context->NumUsedTextures());
// First textures should not have been used.
EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
- EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
// New textures should have been used.
EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
-
context->ResetUsedTextures();
PostSetNeedsCommitToMainThread();
break;
@@ -1205,14 +1205,68 @@ class LayerTreeHostTestAtomicCommit : public LayerTreeHostTest {
virtual void AfterTest() OVERRIDE {}
- private:
+ protected:
FakeContentLayerClient client_;
scoped_refptr<FakeContentLayer> layer_;
scoped_refptr<FakeScrollbarLayer> scrollbar_;
int drew_frame_;
};
-MULTI_THREAD_TEST_F(LayerTreeHostTestAtomicCommit);
+MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+ LayerTreeHostTestDirectRendererAtomicCommit);
+
+class LayerTreeHostTestDelegatingRendererAtomicCommit
+ : public LayerTreeHostTestDirectRendererAtomicCommit {
+ public:
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ ASSERT_EQ(0u, layer_tree_host()->settings().max_partial_texture_updates);
+
+ TestWebGraphicsContext3D* context = static_cast<TestWebGraphicsContext3D*>(
+ impl->output_surface()->context3d());
+
+ switch (impl->active_tree()->source_frame_number()) {
+ case 0:
+ // Number of textures should be one for each layer
+ ASSERT_EQ(2u, context->NumTextures());
+ // Number of textures used for commit should be one for each layer.
+ EXPECT_EQ(2u, context->NumUsedTextures());
+ // Verify that used texture is correct.
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
+ context->ResetUsedTextures();
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 1:
+ // Number of textures should be doubled as the first context layer
+ // texture is being used by the impl-thread and cannot be used for
+ // update. The scrollbar behavior is different direct renderer because
+ // UI resource deletion with delegating renderer occurs after tree
+ // activation.
+ ASSERT_EQ(4u, context->NumTextures());
+ // Number of textures used for commit should still be
+ // one for each layer.
+ EXPECT_EQ(2u, context->NumUsedTextures());
+ // First textures should not have been used.
+ EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
+ EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
+ // New textures should have been used.
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
+ context->ResetUsedTextures();
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ EndTest();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+};
+
+MULTI_THREAD_DELEGATING_RENDERER_TEST_F(
+ LayerTreeHostTestDelegatingRendererAtomicCommit);
static void SetLayerPropertiesForTesting(Layer* layer,
Layer* parent,
@@ -1237,8 +1291,6 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
// Allow one partial texture update.
settings->max_partial_texture_updates = 1;
- // Linear fade animator prevents scrollbars from drawing immediately.
- settings->use_linear_fade_scrollbar_animator = false;
// No partial updates when impl side painting is enabled.
settings->impl_side_painting = false;
}
@@ -1251,22 +1303,7 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
child_->SetPosition(gfx::Point(0, 10));
child_->SetBounds(gfx::Size(3, 10));
- bool paint_scrollbar = true;
- bool has_thumb = false;
- scrollbar_with_paints_ =
- FakeScrollbarLayer::Create(paint_scrollbar, has_thumb, parent_->id());
- scrollbar_with_paints_->SetPosition(gfx::Point(3, 10));
- scrollbar_with_paints_->SetBounds(gfx::Size(3, 10));
-
- paint_scrollbar = false;
- scrollbar_without_paints_ =
- FakeScrollbarLayer::Create(paint_scrollbar, has_thumb, parent_->id());
- scrollbar_without_paints_->SetPosition(gfx::Point(6, 10));
- scrollbar_without_paints_->SetBounds(gfx::Size(3, 10));
-
parent_->AddChild(child_);
- parent_->AddChild(scrollbar_with_paints_);
- parent_->AddChild(scrollbar_without_paints_);
layer_tree_host()->SetRootLayer(parent_);
LayerTreeHostTest::SetupTree();
@@ -1281,22 +1318,14 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
case 1:
parent_->SetNeedsDisplay();
child_->SetNeedsDisplay();
- scrollbar_with_paints_->SetNeedsDisplay();
- scrollbar_without_paints_->SetNeedsDisplay();
break;
case 2:
// Damage part of layers.
parent_->SetNeedsDisplayRect(gfx::RectF(0.f, 0.f, 5.f, 5.f));
child_->SetNeedsDisplayRect(gfx::RectF(0.f, 0.f, 5.f, 5.f));
- scrollbar_with_paints_->SetNeedsDisplayRect(
- gfx::RectF(0.f, 0.f, 5.f, 5.f));
- scrollbar_without_paints_->SetNeedsDisplayRect(
- gfx::RectF(0.f, 0.f, 5.f, 5.f));
break;
case 3:
child_->SetNeedsDisplay();
- scrollbar_with_paints_->SetNeedsDisplay();
- scrollbar_without_paints_->SetNeedsDisplay();
layer_tree_host()->SetViewportSize(gfx::Size(10, 10));
break;
case 4:
@@ -1320,53 +1349,40 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
switch (impl->active_tree()->source_frame_number()) {
case 0:
// Number of textures should be one for each layer.
- ASSERT_EQ(4u, context->NumTextures());
+ ASSERT_EQ(2u, context->NumTextures());
// Number of textures used for commit should be one for each layer.
- EXPECT_EQ(4u, context->NumUsedTextures());
+ EXPECT_EQ(2u, context->NumUsedTextures());
// Verify that used textures are correct.
EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
-
context->ResetUsedTextures();
break;
case 1:
- // Number of textures should be two for each content layer and one
- // for each scrollbar, since they always do a partial update.
- ASSERT_EQ(6u, context->NumTextures());
+ // Number of textures should be two for each content layer.
+ ASSERT_EQ(4u, context->NumTextures());
// Number of textures used for commit should be one for each content
- // layer, and one for the scrollbar layer that paints.
- EXPECT_EQ(3u, context->NumUsedTextures());
+ // layer.
+ EXPECT_EQ(2u, context->NumUsedTextures());
// First content textures should not have been used.
EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
- // The non-painting scrollbar's texture wasn't updated.
- EXPECT_FALSE(context->UsedTexture(context->TextureAt(2)));
- // The painting scrollbar's partial update texture was used.
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
// New textures should have been used.
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(4)));
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(5)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
context->ResetUsedTextures();
break;
case 2:
- // Number of textures should be two for each content layer and one
- // for each scrollbar, since they always do a partial update.
- ASSERT_EQ(6u, context->NumTextures());
+ // Number of textures should be two for each content layer.
+ ASSERT_EQ(4u, context->NumTextures());
// Number of textures used for commit should be one for each content
- // layer, and one for the scrollbar layer that paints.
- EXPECT_EQ(3u, context->NumUsedTextures());
+ // layer.
+ EXPECT_EQ(2u, context->NumUsedTextures());
- // The non-painting scrollbar's texture wasn't updated.
- EXPECT_FALSE(context->UsedTexture(context->TextureAt(2)));
- // The painting scrollbar does a partial update.
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
// One content layer does a partial update also.
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(4)));
- EXPECT_FALSE(context->UsedTexture(context->TextureAt(5)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
+ EXPECT_FALSE(context->UsedTexture(context->TextureAt(3)));
context->ResetUsedTextures();
break;
@@ -1377,10 +1393,9 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
context->ResetUsedTextures();
break;
case 4:
- // Number of textures used for commit should be two. One for the
- // content layer, and one for the painting scrollbar. The
- // non-painting scrollbar doesn't update its texture.
- EXPECT_EQ(2u, context->NumUsedTextures());
+ // Number of textures used for commit should be one, for the
+ // content layer.
+ EXPECT_EQ(1u, context->NumUsedTextures());
context->ResetUsedTextures();
break;
@@ -1401,8 +1416,8 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
if (impl->active_tree()->source_frame_number() == 3) {
EXPECT_EQ(1u, context->NumUsedTextures());
} else {
- EXPECT_EQ(4u, context->NumUsedTextures()) <<
- "For frame " << impl->active_tree()->source_frame_number();
+ EXPECT_EQ(2u, context->NumUsedTextures()) <<
+ "For frame " << impl->active_tree()->source_frame_number();
}
context->ResetUsedTextures();
@@ -1414,8 +1429,6 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
FakeContentLayerClient client_;
scoped_refptr<FakeContentLayer> parent_;
scoped_refptr<FakeContentLayer> child_;
- scoped_refptr<FakeScrollbarLayer> scrollbar_with_paints_;
- scoped_refptr<FakeScrollbarLayer> scrollbar_without_paints_;
};
// Partial updates are not possible with a delegating renderer.
@@ -1935,7 +1948,7 @@ class LayerTreeHostWithProxy : public LayerTreeHost {
const LayerTreeSettings& settings,
scoped_ptr<FakeProxy> proxy)
: LayerTreeHost(client, settings) {
- proxy->SetLayerTreeHost(this);
+ proxy->SetLayerTreeHost(this);
EXPECT_TRUE(InitializeForTesting(proxy.PassAs<Proxy>()));
}
};
@@ -2372,7 +2385,7 @@ class MockIOSurfaceWebGraphicsContext3D : public FakeWebGraphicsContext3D {
MOCK_METHOD1(activeTexture, void(WebKit::WGC3Denum texture));
MOCK_METHOD2(bindTexture, void(WebKit::WGC3Denum target,
- WebKit::WebGLId texture_id));
+ WebKit::WebGLId texture_id));
MOCK_METHOD3(texParameteri, void(WebKit::WGC3Denum target,
WebKit::WGC3Denum pname,
WebKit::WGC3Dint param));
@@ -3196,6 +3209,107 @@ class LayerTreeHostTestDeferredInitialize : public LayerTreeHostTest {
MULTI_THREAD_TEST_F(LayerTreeHostTestDeferredInitialize);
+// Test for UI Resource management.
+class LayerTreeHostTestUIResource : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestUIResource() : num_ui_resources_(0), num_commits_(0) {}
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommit() OVERRIDE {
+ int frame = num_commits_;
+ switch (frame) {
+ case 1:
+ CreateResource();
+ CreateResource();
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ // Usually ScopedUIResource are deleted from the manager in their
+ // destructor. Here we just want to test that a direct call to
+ // DeleteUIResource works.
+ layer_tree_host()->DeleteUIResource(ui_resources_[0]->id());
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 3:
+ // DeleteUIResource can be called with an invalid id.
+ layer_tree_host()->DeleteUIResource(ui_resources_[0]->id());
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 4:
+ CreateResource();
+ CreateResource();
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 5:
+ ClearResources();
+ EndTest();
+ break;
+ }
+ }
+
+ void PerformTest(LayerTreeHostImpl* impl) {
+ TestWebGraphicsContext3D* context = static_cast<TestWebGraphicsContext3D*>(
+ impl->output_surface()->context3d());
+
+ int frame = num_commits_;
+ switch (frame) {
+ case 1:
+ ASSERT_EQ(0u, context->NumTextures());
+ break;
+ case 2:
+ // Created two textures.
+ ASSERT_EQ(2u, context->NumTextures());
+ break;
+ case 3:
+ // One texture left after one deletion.
+ ASSERT_EQ(1u, context->NumTextures());
+ break;
+ case 4:
+ // Resource manager state should not change when delete is called on an
+ // invalid id.
+ ASSERT_EQ(1u, context->NumTextures());
+ break;
+ case 5:
+ // Creation after deletion: two more creates should total up to
+ // three textures.
+ ASSERT_EQ(3u, context->NumTextures());
+ break;
+ }
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ ++num_commits_;
+ if (!layer_tree_host()->settings().impl_side_painting)
+ PerformTest(impl);
+ }
+
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ if (layer_tree_host()->settings().impl_side_painting)
+ PerformTest(impl);
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ // Must clear all resources before exiting.
+ void ClearResources() {
+ for (int i = 0; i < num_ui_resources_; i++)
+ ui_resources_[i].reset();
+ }
+
+ void CreateResource() {
+ ui_resources_[num_ui_resources_++] =
+ FakeScopedUIResource::Create(layer_tree_host());
+ }
+
+ scoped_ptr<FakeScopedUIResource> ui_resources_[5];
+ int num_ui_resources_;
+ int num_commits_;
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestUIResource);
+
class PushPropertiesCountingLayer : public Layer {
public:
static scoped_refptr<PushPropertiesCountingLayer> Create() {
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 3c4d08e..1787d31 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -24,6 +24,7 @@
#include "cc/test/fake_delegated_renderer_layer_impl.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_output_surface.h"
+#include "cc/test/fake_scoped_ui_resource.h"
#include "cc/test/fake_scrollbar.h"
#include "cc/test/fake_scrollbar_layer.h"
#include "cc/test/fake_video_frame_provider.h"
@@ -1528,21 +1529,17 @@ class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
LayerTreeHostContextTest::CommitCompleteOnThread(impl);
++commits_;
- size_t upload_count = scrollbar_layer_->last_update_full_upload_size() +
- scrollbar_layer_->last_update_partial_upload_size();
switch (commits_) {
case 1:
// First (regular) update, we should upload 2 resources (thumb, and
// backtrack).
EXPECT_EQ(1, scrollbar_layer_->update_count());
- EXPECT_EQ(2u, upload_count);
LoseContext();
break;
case 2:
// Second update, after the lost context, we should still upload 2
// resources even if the contents haven't changed.
EXPECT_EQ(2, scrollbar_layer_->update_count());
- EXPECT_EQ(2u, upload_count);
EndTest();
break;
default:
@@ -1630,5 +1627,279 @@ class LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface);
+class UIResourceLostTest : public LayerTreeHostContextTest {
+ public:
+ UIResourceLostTest() : time_step_(0) {}
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+ virtual void AfterTest() OVERRIDE {}
+
+ protected:
+ int time_step_;
+ scoped_ptr<FakeScopedUIResource> ui_resource_;
+};
+
+// Losing context after an UI resource has been created.
+class UIResourceLostAfterCommit : public UIResourceLostTest {
+ public:
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::CommitCompleteOnThread(impl);
+ switch (time_step_) {
+ case 0:
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
+ // Expects a valid UIResourceId.
+ EXPECT_NE(0, ui_resource_->id());
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 1:
+ // The resource should have been created on LTHI after the commit.
+ if (!layer_tree_host()->settings().impl_side_painting)
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ LoseContext();
+ break;
+ case 3:
+ // The resources should have been recreated. The bitmap callback should
+ // have been called once with the resource_lost flag set to true.
+ EXPECT_EQ(1, ui_resource_->lost_resource_count);
+ // Resource Id on the impl-side have been recreated as well. Note
+ // that the same UIResourceId persists after the context lost.
+ if (!layer_tree_host()->settings().impl_side_painting)
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 4:
+ // Release resource before ending test.
+ ui_resource_.reset();
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
+ switch (time_step_) {
+ case 1:
+ if (layer_tree_host()->settings().impl_side_painting)
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ break;
+ case 3:
+ if (layer_tree_host()->settings().impl_side_painting)
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ break;
+ }
+ ++time_step_;
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
+
+// Losing context before UI resource requests can be commited. Three sequences
+// of creation/deletion are considered:
+// 1. Create one resource -> Context Lost => Expect the resource to have been
+// created.
+// 2. Delete an exisiting resource (test_id0_) -> create a second resource
+// (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
+// test_id1_ to have been created.
+// 3. Create one resource -> Delete that same resource -> Context Lost => Expect
+// the resource to not exist in the manager.
+class UIResourceLostBeforeCommit : public UIResourceLostTest {
+ public:
+ UIResourceLostBeforeCommit()
+ : test_id0_(0),
+ test_id1_(0) {}
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::CommitCompleteOnThread(impl);
+ switch (time_step_) {
+ case 0:
+ // Sequence 1:
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
+ LoseContext();
+ // Resource Id on the impl-side should no longer be valid after
+ // context is lost.
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ break;
+ case 1:
+ // The resources should have been recreated.
+ EXPECT_EQ(2, ui_resource_->resource_create_count);
+ // "resource lost" callback was called once for the resource in the
+ // resource map.
+ EXPECT_EQ(1, ui_resource_->lost_resource_count);
+ // Resource Id on the impl-side have been recreated as well. Note
+ // that the same UIResourceId persists after the context lost.
+ if (!layer_tree_host()->settings().impl_side_painting)
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ // Sequence 2:
+ // Currently one resource has been created.
+ test_id0_ = ui_resource_->id();
+ // Delete this resource.
+ ui_resource_.reset();
+ // Create another resource.
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
+ test_id1_ = ui_resource_->id();
+ // Sanity check that two resource creations return different ids.
+ EXPECT_NE(test_id0_, test_id1_);
+ // Lose the context before commit.
+ LoseContext();
+ break;
+ case 3:
+ if (!layer_tree_host()->settings().impl_side_painting) {
+ // The previous resource should have been deleted.
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
+ // The second resource should have been created.
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
+ }
+
+ // The second resource called the resource callback once and since the
+ // context is lost, a "resource lost" callback was also issued.
+ EXPECT_EQ(2, ui_resource_->resource_create_count);
+ EXPECT_EQ(1, ui_resource_->lost_resource_count);
+ // Clear the manager of resources.
+ ui_resource_.reset();
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 4:
+ // Sequence 3:
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
+ test_id0_ = ui_resource_->id();
+ // Sanity check the UIResourceId should not be 0.
+ EXPECT_NE(0, test_id0_);
+ // Usually ScopedUIResource are deleted from the manager in their
+ // destructor (so usually ui_resource_.reset()). But here we need
+ // ui_resource_ for the next step, so call DeleteUIResource directly.
+ layer_tree_host()->DeleteUIResource(test_id0_);
+ LoseContext();
+ break;
+ case 5:
+ // Expect the resource callback to have been called once.
+ EXPECT_EQ(1, ui_resource_->resource_create_count);
+ // No "resource lost" callbacks.
+ EXPECT_EQ(0, ui_resource_->lost_resource_count);
+ if (!layer_tree_host()->settings().impl_side_painting) {
+ // The UI resource id should not be valid
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
+ }
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 6:
+ ui_resource_.reset();
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
+ switch (time_step_) {
+ case 1:
+ if (layer_tree_host()->settings().impl_side_painting)
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ break;
+ case 3:
+ if (layer_tree_host()->settings().impl_side_painting) {
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
+ }
+ break;
+ case 5:
+ if (layer_tree_host()->settings().impl_side_painting)
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
+ break;
+ }
+ ++time_step_;
+ }
+
+ private:
+ UIResourceId test_id0_;
+ UIResourceId test_id1_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
+
+// Losing UI resource before the pending trees is activated but after the
+// commit. Impl-side-painting only.
+class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::CommitCompleteOnThread(impl);
+ switch (time_step_) {
+ case 0:
+ ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 3:
+ test_id_ = ui_resource_->id();
+ ui_resource_.reset();
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 4:
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 5:
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ switch (time_step_) {
+ case 0:
+ break;
+ case 1:
+ // The resource creation callback has been called.
+ EXPECT_EQ(1, ui_resource_->resource_create_count);
+ // The resource is not yet lost (sanity check).
+ EXPECT_EQ(0, ui_resource_->lost_resource_count);
+ // The resource should not have been created yet on the impl-side.
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ LoseContext();
+ break;
+ case 3:
+ LoseContext();
+ break;
+ }
+ }
+
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
+ switch (time_step_) {
+ case 1:
+ // The pending requests on the impl-side should have been processed.
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
+ break;
+ case 2:
+ // The "lost resource" callback should have been called once.
+ EXPECT_EQ(1, ui_resource_->lost_resource_count);
+ break;
+ case 4:
+ // The resource is deleted and should not be in the manager. Use
+ // test_id_ since ui_resource_ has been deleted.
+ EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
+ break;
+ }
+ ++time_step_;
+ }
+
+ private:
+ UIResourceId test_id_;
+};
+
+TEST_F(UIResourceLostBeforeActivateTree,
+ RunMultiThread_DirectRenderer_ImplSidePaint) {
+ RunTest(true, false, true);
+}
+
+TEST_F(UIResourceLostBeforeActivateTree,
+ RunMultiThread_DelegatingRenderer_ImplSidePaint) {
+ RunTest(true, true, true);
+}
+
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index d779507..be25e65 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -104,6 +104,9 @@ scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() {
}
void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
+ // The request queue should have been processed and does not require a push.
+ DCHECK_EQ(ui_resource_request_queue_.size(), 0u);
+
target_tree->SetLatencyInfo(latency_info_);
latency_info_.Clear();
target_tree->SetPageScaleFactorAndLimits(
@@ -282,7 +285,7 @@ void LayerTreeImpl::UpdateDrawProperties() {
// For max_texture_size.
if (!layer_tree_host_impl_->renderer())
- return;
+ return;
if (!root_layer())
return;
@@ -529,7 +532,7 @@ scoped_ptr<base::Value> LayerTreeImpl::AsValue() const {
}
void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) {
+ LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) {
root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
if (root_scroll_layer_) {
root_scroll_layer_->SetScrollOffsetDelegate(
@@ -572,6 +575,35 @@ void LayerTreeImpl::WillModifyTilePriorities() {
layer_tree_host_impl_->SetNeedsManageTiles();
}
+void LayerTreeImpl::set_ui_resource_request_queue(
+ const UIResourceRequestQueue& queue) {
+ ui_resource_request_queue_ = queue;
+}
+
+ResourceProvider::ResourceId LayerTreeImpl::ResourceIdForUIResource(
+ UIResourceId uid) const {
+ return layer_tree_host_impl_->ResourceIdForUIResource(uid);
+}
+
+void LayerTreeImpl::ProcessUIResourceRequestQueue() {
+ while (ui_resource_request_queue_.size() > 0) {
+ UIResourceRequest req = ui_resource_request_queue_.front();
+ ui_resource_request_queue_.pop_front();
+
+ switch (req.type) {
+ case UIResourceRequest::UIResourceCreate:
+ layer_tree_host_impl_->CreateUIResource(req.id, req.bitmap);
+ break;
+ case UIResourceRequest::UIResourceDelete:
+ layer_tree_host_impl_->DeleteUIResource(req.id);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
void LayerTreeImpl::AddLayerWithCopyOutputRequest(LayerImpl* layer) {
// Only the active tree needs to know about layers with copy requests, as
// they are aborted if not serviced during draw.
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 27aa6fa..7e66da8 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -5,12 +5,14 @@
#ifndef CC_TREES_LAYER_TREE_IMPL_H_
#define CC_TREES_LAYER_TREE_IMPL_H_
+#include <list>
#include <string>
#include <vector>
#include "base/containers/hash_tables.h"
#include "base/values.h"
#include "cc/layers/layer_impl.h"
+#include "cc/resources/ui_resource_client.h"
#include "ui/base/latency_info.h"
#if defined(COMPILER_GCC)
@@ -40,6 +42,9 @@ class Proxy;
class ResourceProvider;
class TileManager;
struct RendererCapabilities;
+struct UIResourceRequest;
+
+typedef std::list<UIResourceRequest> UIResourceRequestQueue;
class CC_EXPORT LayerTreeImpl {
public:
@@ -150,6 +155,8 @@ class CC_EXPORT LayerTreeImpl {
void set_needs_full_tree_sync(bool needs) { needs_full_tree_sync_ = needs; }
bool needs_full_tree_sync() const { return needs_full_tree_sync_; }
+ void set_ui_resource_request_queue(const UIResourceRequestQueue& queue);
+
const LayerImplList& RenderSurfaceLayerList() const;
// These return the size of the root scrollable area and the size of
@@ -191,6 +198,9 @@ class CC_EXPORT LayerTreeImpl {
void WillModifyTilePriorities();
+ ResourceProvider::ResourceId ResourceIdForUIResource(UIResourceId uid) const;
+ void ProcessUIResourceRequestQueue();
+
void AddLayerWithCopyOutputRequest(LayerImpl* layer);
void RemoveLayerWithCopyOutputRequest(LayerImpl* layer);
const std::vector<LayerImpl*> LayersWithCopyOutputRequest() const;
@@ -240,6 +250,8 @@ class CC_EXPORT LayerTreeImpl {
ui::LatencyInfo latency_info_;
+ UIResourceRequestQueue ui_resource_request_queue_;
+
private:
DISALLOW_COPY_AND_ASSIGN(LayerTreeImpl);
};