summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorpowei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-12 06:18:19 +0000
committerpowei@chromium.org <powei@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-12 06:18:19 +0000
commit4d600d105c6f07a13a365bebc9d35025b563d966 (patch)
tree4e0ecb719e59e0a0dbfe0d01f157381a752246c1 /cc
parent5c13605d33248e0c6dcf89e06513bc05f015d5fb (diff)
downloadchromium_src-4d600d105c6f07a13a365bebc9d35025b563d966.zip
chromium_src-4d600d105c6f07a13a365bebc9d35025b563d966.tar.gz
chromium_src-4d600d105c6f07a13a365bebc9d35025b563d966.tar.bz2
Update the nine patch layer to use UI resources
The old nine-patch layer used priority resource manager for requesting textures. This patch updates the nine-patch layer to use the UI resource manager. this patch clarifies the semantics of the aperture in both image and layer The new semantics corresponds to existing logic on the android-side. Changes have been made to UIResourceBitmap to use SkPixelRef as ref-counted of the bitmap content. The android-side changes: https://gerrit-int.chromium.org/#/c/43103/ BUG=276482,276487 Review URL: https://chromiumcodereview.appspot.com/22870016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222732 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/layers/nine_patch_layer.cc172
-rw-r--r--cc/layers/nine_patch_layer.h43
-rw-r--r--cc/layers/nine_patch_layer_impl.cc299
-rw-r--r--cc/layers/nine_patch_layer_impl.h42
-rw-r--r--cc/layers/nine_patch_layer_impl_unittest.cc199
-rw-r--r--cc/layers/nine_patch_layer_unittest.cc103
-rw-r--r--cc/layers/painted_scrollbar_layer.cc15
-rw-r--r--cc/layers/painted_scrollbar_layer.h4
-rw-r--r--cc/layers/scrollbar_layer_unittest.cc9
-rw-r--r--cc/resources/scoped_ui_resource.cc15
-rw-r--r--cc/resources/scoped_ui_resource.h25
-rw-r--r--cc/resources/ui_resource_bitmap.cc46
-rw-r--r--cc/resources/ui_resource_bitmap.h40
-rw-r--r--cc/resources/ui_resource_client.h4
-rw-r--r--cc/test/fake_scoped_ui_resource.cc29
-rw-r--r--cc/test/fake_scoped_ui_resource.h5
-rw-r--r--cc/trees/layer_tree_host.cc96
-rw-r--r--cc/trees/layer_tree_host.h37
-rw-r--r--cc/trees/layer_tree_host_impl.cc17
-rw-r--r--cc/trees/layer_tree_host_impl.h11
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc22
-rw-r--r--cc/trees/layer_tree_impl.cc6
-rw-r--r--cc/trees/layer_tree_impl.h2
23 files changed, 748 insertions, 493 deletions
diff --git a/cc/layers/nine_patch_layer.cc b/cc/layers/nine_patch_layer.cc
index 517b49b..5e00007 100644
--- a/cc/layers/nine_patch_layer.cc
+++ b/cc/layers/nine_patch_layer.cc
@@ -8,16 +8,55 @@
#include "cc/resources/prioritized_resource.h"
#include "cc/resources/resource_update.h"
#include "cc/resources/resource_update_queue.h"
+#include "cc/resources/scoped_ui_resource.h"
+#include "cc/resources/ui_resource_bitmap.h"
#include "cc/trees/layer_tree_host.h"
namespace cc {
+
+namespace {
+
+class ScopedUIResourceHolder : public NinePatchLayer::UIResourceHolder {
+ public:
+ static scoped_ptr<ScopedUIResourceHolder> Create(LayerTreeHost* host,
+ const SkBitmap& skbitmap) {
+ return make_scoped_ptr(new ScopedUIResourceHolder(host, skbitmap));
+ }
+ virtual UIResourceId id() OVERRIDE { return resource_->id(); }
+
+ private:
+ ScopedUIResourceHolder(LayerTreeHost* host, const SkBitmap& skbitmap) {
+ resource_ = ScopedUIResource::Create(host, UIResourceBitmap(skbitmap));
+ }
+
+ scoped_ptr<ScopedUIResource> resource_;
+};
+
+class SharedUIResourceHolder : public NinePatchLayer::UIResourceHolder {
+ public:
+ static scoped_ptr<SharedUIResourceHolder> Create(UIResourceId id) {
+ return make_scoped_ptr(new SharedUIResourceHolder(id));
+ }
+
+ virtual UIResourceId id() OVERRIDE { return id_; }
+
+ private:
+ explicit SharedUIResourceHolder(UIResourceId id) : id_(id) {}
+
+ UIResourceId id_;
+};
+
+} // anonymous namespace
+
+
+NinePatchLayer::UIResourceHolder::~UIResourceHolder() {}
+
scoped_refptr<NinePatchLayer> NinePatchLayer::Create() {
return make_scoped_refptr(new NinePatchLayer());
}
-NinePatchLayer::NinePatchLayer()
- : bitmap_dirty_(false) {}
+NinePatchLayer::NinePatchLayer() : fill_center_(false) {}
NinePatchLayer::~NinePatchLayer() {}
@@ -26,97 +65,90 @@ scoped_ptr<LayerImpl> NinePatchLayer::CreateLayerImpl(
return NinePatchLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
}
-void NinePatchLayer::SetTexturePriorities(
- const PriorityCalculator& priority_calc) {
- if (resource_ && !resource_->texture()->resource_manager()) {
- // Release the resource here, as it is no longer tied to a resource manager.
- resource_.reset();
- if (!bitmap_.isNull())
- CreateResource();
- } else if (bitmap_dirty_ && DrawsContent()) {
- CreateResource();
- }
+void NinePatchLayer::SetLayerTreeHost(LayerTreeHost* host) {
+ if (host == layer_tree_host())
+ return;
- if (resource_) {
- resource_->texture()->set_request_priority(
- PriorityCalculator::UIPriority(true));
- GLenum texture_format =
- layer_tree_host()->GetRendererCapabilities().best_texture_format;
- resource_->texture()->SetDimensions(
- gfx::Size(bitmap_.width(), bitmap_.height()), texture_format);
- }
-}
+ Layer::SetLayerTreeHost(host);
-void NinePatchLayer::SetBitmap(const SkBitmap& bitmap, gfx::Rect aperture) {
- bitmap_ = bitmap;
- image_aperture_ = aperture;
- bitmap_dirty_ = true;
- SetNeedsDisplay();
+ // Recreate the resource hold against the new LTH.
+ RecreateUIResourceHolder();
}
-bool NinePatchLayer::Update(ResourceUpdateQueue* queue,
- const OcclusionTracker* occlusion) {
- bool updated = Layer::Update(queue, occlusion);
-
- CreateUpdaterIfNeeded();
-
- if (resource_ &&
- (bitmap_dirty_ || resource_->texture()->resource_id() == 0)) {
- gfx::Rect content_rect(0, 0, bitmap_.width(), bitmap_.height());
- ResourceUpdate upload = ResourceUpdate::Create(resource_->texture(),
- &bitmap_,
- content_rect,
- content_rect,
- gfx::Vector2d());
- queue->AppendFullUpload(upload);
- bitmap_dirty_ = false;
- updated = true;
- }
+void NinePatchLayer::RecreateUIResourceHolder() {
+ ui_resource_holder_.reset();
+ if (!layer_tree_host() || bitmap_.empty())
+ return;
- return updated;
+ ui_resource_holder_ =
+ ScopedUIResourceHolder::Create(layer_tree_host(), bitmap_);
}
-void NinePatchLayer::CreateUpdaterIfNeeded() {
- if (updater_.get())
+void NinePatchLayer::SetBorder(gfx::Rect border) {
+ if (border == border_)
return;
+ border_ = border;
+ SetNeedsCommit();
+}
- updater_ = ImageLayerUpdater::Create();
+void NinePatchLayer::SetBitmap(const SkBitmap& skbitmap, gfx::Rect aperture) {
+ image_aperture_ = aperture;
+ bitmap_ = skbitmap;
+
+ // TODO(ccameron): Remove this. This provides the default border that was
+ // provided before borders were required to be explicitly provided. Once Blink
+ // fixes its callers to call SetBorder, this can be removed.
+ SetBorder(gfx::Rect(aperture.x(),
+ aperture.y(),
+ skbitmap.width() - aperture.width(),
+ skbitmap.height() - aperture.height()));
+ RecreateUIResourceHolder();
+ SetNeedsCommit();
}
-void NinePatchLayer::CreateResource() {
- DCHECK(!bitmap_.isNull());
- CreateUpdaterIfNeeded();
- updater_->SetBitmap(bitmap_);
+void NinePatchLayer::SetUIResourceId(UIResourceId resource_id,
+ gfx::Rect aperture) {
+ if (ui_resource_holder_ && ui_resource_holder_->id() == resource_id &&
+ image_aperture_ == aperture)
+ return;
- if (!resource_) {
- resource_ = updater_->CreateResource(
- layer_tree_host()->contents_texture_manager());
+ image_aperture_ = aperture;
+ if (resource_id) {
+ ui_resource_holder_ = SharedUIResourceHolder::Create(resource_id);
+ } else {
+ ui_resource_holder_.reset();
}
+
+ SetNeedsCommit();
+}
+
+void NinePatchLayer::SetFillCenter(bool fill_center) {
+ if (fill_center_ == fill_center)
+ return;
+
+ fill_center_ = fill_center;
+ SetNeedsCommit();
}
bool NinePatchLayer::DrawsContent() const {
- bool draws = !bitmap_.isNull() &&
- Layer::DrawsContent() &&
- bitmap_.width() &&
- bitmap_.height();
- return draws;
+ return ui_resource_holder_ && ui_resource_holder_->id() &&
+ Layer::DrawsContent();
}
void NinePatchLayer::PushPropertiesTo(LayerImpl* layer) {
Layer::PushPropertiesTo(layer);
NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer);
- if (resource_) {
- DCHECK(!bitmap_.isNull());
- layer_impl->SetResourceId(resource_->texture()->resource_id());
- layer_impl->SetLayout(
- gfx::Size(bitmap_.width(), bitmap_.height()), image_aperture_);
- }
+ if (!ui_resource_holder_) {
+ layer_impl->SetUIResourceId(0);
+ } else {
+ DCHECK(layer_tree_host());
- // NinePatchLayer must push properties every commit to make sure
- // NinePatchLayerImpl::resource_id_ is valid.
- // http://crbug.com/276482
- needs_push_properties_ = true;
+ gfx::Size image_size =
+ layer_tree_host()->GetUIResourceSize(ui_resource_holder_->id());
+ layer_impl->SetUIResourceId(ui_resource_holder_->id());
+ layer_impl->SetLayout(image_size, image_aperture_, border_, fill_center_);
+ }
}
} // namespace cc
diff --git a/cc/layers/nine_patch_layer.h b/cc/layers/nine_patch_layer.h
index 35d0881..5880635 100644
--- a/cc/layers/nine_patch_layer.h
+++ b/cc/layers/nine_patch_layer.h
@@ -8,47 +8,60 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/layers/layer.h"
-#include "cc/resources/image_layer_updater.h"
-#include "third_party/skia/include/core/SkBitmap.h"
+#include "cc/resources/ui_resource_client.h"
#include "ui/gfx/rect.h"
namespace cc {
-class ResourceUpdateQueue;
+class LayerTreeHost;
+class ScopedUIResource;
class CC_EXPORT NinePatchLayer : public Layer {
public:
static scoped_refptr<NinePatchLayer> Create();
virtual bool DrawsContent() const OVERRIDE;
- virtual void SetTexturePriorities(const PriorityCalculator& priority_calc)
- OVERRIDE;
- virtual bool Update(ResourceUpdateQueue* queue,
- const OcclusionTracker* occlusion) OVERRIDE;
+
virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE;
+ virtual void SetLayerTreeHost(LayerTreeHost* host) OVERRIDE;
+
+ // |border| is the space around the center rectangular region in layer space
+ // (known as aperture in image space). |border.x()| and |border.y()| are the
+ // size of the left and top boundary, respectively.
+ // |border.width()-border.x()| and |border.height()-border.y()| are the size
+ // of the right and bottom boundary, respectively.
+ void SetBorder(gfx::Rect border);
+
// aperture is in the pixel space of the bitmap resource and refers to
// the center patch of the ninepatch (which is unused in this
// implementation). We split off eight rects surrounding it and stick them
// on the edges of the layer. The corners are unscaled, the top and bottom
// rects are x-stretched to fit, and the left and right rects are
// y-stretched to fit.
- void SetBitmap(const SkBitmap& bitmap, gfx::Rect aperture);
+ void SetBitmap(const SkBitmap& skbitmap, gfx::Rect aperture);
+
+ // An alternative way of setting the resource to allow for sharing.
+ void SetUIResourceId(UIResourceId resource_id, gfx::Rect aperture);
+ void SetFillCenter(bool fill_center);
+
+ class UIResourceHolder {
+ public:
+ virtual UIResourceId id() = 0;
+ virtual ~UIResourceHolder();
+ };
private:
NinePatchLayer();
virtual ~NinePatchLayer();
virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
OVERRIDE;
+ void RecreateUIResourceHolder();
- void CreateUpdaterIfNeeded();
- void CreateResource();
-
- scoped_refptr<ImageLayerUpdater> updater_;
- scoped_ptr<LayerUpdater::Resource> resource_;
-
+ gfx::Rect border_;
+ bool fill_center_;
+ scoped_ptr<UIResourceHolder> ui_resource_holder_;
SkBitmap bitmap_;
- bool bitmap_dirty_;
// The transparent center region that shows the parent layer's contents in
// image space.
diff --git a/cc/layers/nine_patch_layer_impl.cc b/cc/layers/nine_patch_layer_impl.cc
index 4274bf0..d2c7e09 100644
--- a/cc/layers/nine_patch_layer_impl.cc
+++ b/cc/layers/nine_patch_layer_impl.cc
@@ -6,15 +6,18 @@
#include "base/strings/stringprintf.h"
#include "base/values.h"
+#include "cc/base/math_util.h"
#include "cc/layers/quad_sink.h"
#include "cc/quads/texture_draw_quad.h"
+#include "cc/trees/layer_tree_impl.h"
#include "ui/gfx/rect_f.h"
namespace cc {
NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id)
: LayerImpl(tree_impl, id),
- resource_id_(0) {}
+ fill_center_(false),
+ ui_resource_id_(0) {}
NinePatchLayerImpl::~NinePatchLayerImpl() {}
@@ -31,11 +34,8 @@ void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) {
LayerImpl::PushPropertiesTo(layer);
NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer);
- if (!resource_id_)
- return;
-
- layer_impl->SetResourceId(resource_id_);
- layer_impl->SetLayout(image_bounds_, image_aperture_);
+ layer_impl->SetUIResourceId(ui_resource_id_);
+ layer_impl->SetLayout(image_bounds_, image_aperture_, border_, fill_center_);
}
static gfx::RectF NormalizedRect(float x,
@@ -50,14 +50,59 @@ static gfx::RectF NormalizedRect(float x,
height / total_height);
}
-void NinePatchLayerImpl::SetLayout(gfx::Size image_bounds, gfx::Rect aperture) {
+void NinePatchLayerImpl::SetUIResourceId(UIResourceId uid) {
+ if (uid == ui_resource_id_)
+ return;
+ ui_resource_id_ = uid;
+ NoteLayerPropertyChanged();
+}
+
+void NinePatchLayerImpl::SetLayout(gfx::Size image_bounds,
+ gfx::Rect aperture,
+ gfx::Rect border,
+ bool fill_center) {
+ // This check imposes an ordering on the call sequence. An UIResource must
+ // exist before SetLayout can be called.
+ DCHECK(ui_resource_id_);
+
+ // |border| is in layer space. It cannot exceed the bounds of the layer.
+ DCHECK(!border.size().IsEmpty());
+ DCHECK_GT(bounds().width(), border.width());
+ DCHECK_GT(bounds().height(), border.height());
+
+ // Sanity Check on |border|
+ DCHECK_LT(border.x(), border.width());
+ DCHECK_LT(border.y(), border.height());
+ DCHECK_GT(border.x(), 0);
+ DCHECK_GT(border.y(), 0);
+
+ // |aperture| is in image space. It cannot exceed the bounds of the bitmap.
+ DCHECK(!aperture.size().IsEmpty());
+ DCHECK(gfx::Rect(image_bounds.width(), image_bounds.height())
+ .Contains(aperture));
+
+ // Avoid the degenerate cases where the aperture touches the edge of the
+ // image.
+ DCHECK_LT(aperture.width(), image_bounds.width() - 1);
+ DCHECK_LT(aperture.height(), image_bounds.height()-1);
+ DCHECK_GT(aperture.x(), 0);
+ DCHECK_GT(aperture.y(), 0);
+
+ if (image_bounds_ == image_bounds && image_aperture_ != aperture &&
+ border_ != border && fill_center_ != fill_center)
+ return;
+
image_bounds_ = image_bounds;
image_aperture_ = aperture;
+ border_ = border;
+ fill_center_ = fill_center;
+
+ NoteLayerPropertyChanged();
}
bool NinePatchLayerImpl::WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) {
- if (!resource_id_ || draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
+ if (!ui_resource_id_ || draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
return false;
return LayerImpl::WillDraw(draw_mode, resource_provider);
}
@@ -68,7 +113,13 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad_sink->UseSharedQuadState(CreateSharedQuadState());
AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
- if (!resource_id_)
+ if (!ui_resource_id_)
+ return;
+
+ ResourceProvider::ResourceId resource =
+ layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_);
+
+ if (!resource)
return;
static const bool flipped = false;
@@ -76,95 +127,106 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
DCHECK(!bounds().IsEmpty());
- // NinePatch border widths in bitmap pixel space
- int left_width = image_aperture_.x();
- int top_height = image_aperture_.y();
- int right_width = image_bounds_.width() - image_aperture_.right();
- int bottom_height = image_bounds_.height() - image_aperture_.bottom();
+ // NinePatch border widths in layer space.
+ int layer_left_width = border_.x();
+ int layer_top_height = border_.y();
+ int layer_right_width = border_.width() - layer_left_width;
+ int layer_bottom_height = border_.height() - layer_top_height;
- // If layer can't fit the corners, clip to show the outer edges of the
- // image.
- int corner_total_width = left_width + right_width;
- int middle_width = bounds().width() - corner_total_width;
- if (middle_width < 0) {
- float left_width_proportion =
- static_cast<float>(left_width) / corner_total_width;
- int left_width_crop = middle_width * left_width_proportion;
- left_width += left_width_crop;
- right_width = bounds().width() - left_width;
- middle_width = 0;
- }
- int corner_total_height = top_height + bottom_height;
- int middle_height = bounds().height() - corner_total_height;
- if (middle_height < 0) {
- float top_height_proportion =
- static_cast<float>(top_height) / corner_total_height;
- int top_height_crop = middle_height * top_height_proportion;
- top_height += top_height_crop;
- bottom_height = bounds().height() - top_height;
- middle_height = 0;
- }
+ int layer_middle_width = bounds().width() - border_.width();
+ int layer_middle_height = bounds().height() - border_.height();
// Patch positions in layer space
- gfx::Rect top_left(0, 0, left_width, top_height);
- gfx::Rect top_right(
- bounds().width() - right_width, 0, right_width, top_height);
- gfx::Rect bottom_left(
- 0, bounds().height() - bottom_height, left_width, bottom_height);
- gfx::Rect bottom_right(
- top_right.x(), bottom_left.y(), right_width, bottom_height);
- gfx::Rect top(top_left.right(), 0, middle_width, top_height);
- gfx::Rect left(0, top_left.bottom(), left_width, middle_height);
- gfx::Rect right(top_right.x(),
- top_right.bottom(),
- right_width,
- left.height());
- gfx::Rect bottom(top.x(), bottom_left.y(), top.width(), bottom_height);
-
- float img_width = image_bounds_.width();
- float img_height = image_bounds_.height();
-
+ gfx::Rect layer_top_left(0, 0, layer_left_width, layer_top_height);
+ gfx::Rect layer_top_right(bounds().width() - layer_right_width,
+ 0,
+ layer_right_width,
+ layer_top_height);
+ gfx::Rect layer_bottom_left(0,
+ bounds().height() - layer_bottom_height,
+ layer_left_width,
+ layer_bottom_height);
+ gfx::Rect layer_bottom_right(layer_top_right.x(),
+ layer_bottom_left.y(),
+ layer_right_width,
+ layer_bottom_height);
+ gfx::Rect layer_top(
+ layer_top_left.right(), 0, layer_middle_width, layer_top_height);
+ gfx::Rect layer_left(
+ 0, layer_top_left.bottom(), layer_left_width, layer_middle_height);
+ gfx::Rect layer_right(layer_top_right.x(),
+ layer_top_right.bottom(),
+ layer_right_width,
+ layer_left.height());
+ gfx::Rect layer_bottom(layer_top.x(),
+ layer_bottom_left.y(),
+ layer_top.width(),
+ layer_bottom_height);
+ gfx::Rect layer_center(layer_left_width,
+ layer_top_height,
+ layer_middle_width,
+ layer_middle_height);
+
+ // Note the following values are in image (bitmap) space.
+ float image_width = image_bounds_.width();
+ float image_height = image_bounds_.height();
+
+ int image_aperture_left_width = image_aperture_.x();
+ int image_aperture_top_height = image_aperture_.y();
+ int image_aperture_right_width = image_width - image_aperture_.right();
+ int image_aperture_bottom_height = image_height - image_aperture_.bottom();
// Patch positions in bitmap UV space (from zero to one)
gfx::RectF uv_top_left = NormalizedRect(0,
0,
- left_width,
- top_height,
- img_width,
- img_height);
- gfx::RectF uv_top_right = NormalizedRect(img_width - right_width,
- 0,
- right_width,
- top_height,
- img_width,
- img_height);
- gfx::RectF uv_bottom_left = NormalizedRect(0,
- img_height - bottom_height,
- left_width,
- bottom_height,
- img_width,
- img_height);
- gfx::RectF uv_bottom_right = NormalizedRect(img_width - right_width,
- img_height - bottom_height,
- right_width,
- bottom_height,
- img_width,
- img_height);
- gfx::RectF uv_top(uv_top_left.right(),
- 0,
- (img_width - left_width - right_width) / img_width,
- (top_height) / img_height);
+ image_aperture_left_width,
+ image_aperture_top_height,
+ image_width,
+ image_height);
+ gfx::RectF uv_top_right =
+ NormalizedRect(image_width - image_aperture_right_width,
+ 0,
+ image_aperture_right_width,
+ image_aperture_top_height,
+ image_width,
+ image_height);
+ gfx::RectF uv_bottom_left =
+ NormalizedRect(0,
+ image_height - image_aperture_bottom_height,
+ image_aperture_left_width,
+ image_aperture_bottom_height,
+ image_width,
+ image_height);
+ gfx::RectF uv_bottom_right =
+ NormalizedRect(image_width - image_aperture_right_width,
+ image_height - image_aperture_bottom_height,
+ image_aperture_right_width,
+ image_aperture_bottom_height,
+ image_width,
+ image_height);
+ gfx::RectF uv_top(
+ uv_top_left.right(),
+ 0,
+ (image_width - image_aperture_left_width - image_aperture_right_width) /
+ image_width,
+ (image_aperture_top_height) / image_height);
gfx::RectF uv_left(0,
- uv_top_left.bottom(),
- left_width / img_width,
- (img_height - top_height - bottom_height) / img_height);
+ uv_top_left.bottom(),
+ image_aperture_left_width / image_width,
+ (image_height - image_aperture_top_height -
+ image_aperture_bottom_height) /
+ image_height);
gfx::RectF uv_right(uv_top_right.x(),
- uv_top_right.bottom(),
- right_width / img_width,
- uv_left.height());
+ uv_top_right.bottom(),
+ image_aperture_right_width / image_width,
+ uv_left.height());
gfx::RectF uv_bottom(uv_top.x(),
- uv_bottom_left.y(),
- uv_top.width(),
- bottom_height / img_height);
+ uv_bottom_left.y(),
+ uv_top.width(),
+ image_aperture_bottom_height / image_height);
+ gfx::RectF uv_center(uv_top_left.right(),
+ uv_top_left.bottom(),
+ uv_top.width(),
+ uv_left.height());
// Nothing is opaque here.
// TODO(danakj): Should we look at the SkBitmaps to determine opaqueness?
@@ -174,9 +236,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- top_left,
+ layer_top_left,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_top_left.origin(),
uv_top_left.bottom_right(),
@@ -187,9 +249,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- top_right,
+ layer_top_right,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_top_right.origin(),
uv_top_right.bottom_right(),
@@ -200,9 +262,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- bottom_left,
+ layer_bottom_left,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_bottom_left.origin(),
uv_bottom_left.bottom_right(),
@@ -213,9 +275,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- bottom_right,
+ layer_bottom_right,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_bottom_right.origin(),
uv_bottom_right.bottom_right(),
@@ -226,9 +288,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- top,
+ layer_top,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_top.origin(),
uv_top.bottom_right(),
@@ -239,9 +301,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- left,
+ layer_left,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_left.origin(),
uv_left.bottom_right(),
@@ -252,9 +314,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- right,
+ layer_right,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_right.origin(),
uv_right.bottom_right(),
@@ -265,9 +327,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
- bottom,
+ layer_bottom,
opaque_rect,
- resource_id_,
+ resource,
premultiplied_alpha,
uv_bottom.origin(),
uv_bottom.bottom_right(),
@@ -275,10 +337,21 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
vertex_opacity,
flipped);
quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
-}
-void NinePatchLayerImpl::DidLoseOutputSurface() {
- resource_id_ = 0;
+ if (fill_center_) {
+ quad = TextureDrawQuad::Create();
+ quad->SetNew(shared_quad_state,
+ layer_center,
+ opaque_rect,
+ resource,
+ premultiplied_alpha,
+ uv_center.origin(),
+ uv_center.bottom_right(),
+ SK_ColorTRANSPARENT,
+ vertex_opacity,
+ flipped);
+ quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
+ }
}
const char* NinePatchLayerImpl::LayerTypeAsString() const {
@@ -295,10 +368,12 @@ base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const {
list->AppendInteger(image_aperture_.size().height());
result->Set("ImageAperture", list);
- list = new base::ListValue;
- list->AppendInteger(image_bounds_.width());
- list->AppendInteger(image_bounds_.height());
- result->Set("ImageBounds", list);
+ result->Set("ImageBounds", MathUtil::AsValue(image_bounds_).release());
+ result->Set("Border", MathUtil::AsValue(border_).release());
+
+ base::FundamentalValue* fill_center =
+ base::Value::CreateBooleanValue(fill_center_);
+ result->Set("FillCenter", fill_center);
return result;
}
diff --git a/cc/layers/nine_patch_layer_impl.h b/cc/layers/nine_patch_layer_impl.h
index bc442d4..ba414ae 100644
--- a/cc/layers/nine_patch_layer_impl.h
+++ b/cc/layers/nine_patch_layer_impl.h
@@ -10,6 +10,7 @@
#include "cc/base/cc_export.h"
#include "cc/layers/layer_impl.h"
#include "cc/resources/resource_provider.h"
+#include "cc/resources/ui_resource_client.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -27,8 +28,37 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
}
virtual ~NinePatchLayerImpl();
- void SetResourceId(unsigned id) { resource_id_ = id; }
- void SetLayout(gfx::Size image_bounds, gfx::Rect aperture);
+
+ void SetUIResourceId(UIResourceId uid);
+
+ // The bitmap stretches out the bounds of the layer. The following picture
+ // illustrates the parameters associated with the dimensions.
+ //
+ // Layer space layout Bitmap space layout
+ //
+ // ------------------------ ~~~~~~~~~~ W ~~~~~~~~~~
+ // | : | : : |
+ // | C | : Y |
+ // | : | : : |
+ // | ------------ | :~~X~~------------ |
+ // | | | | : | : |
+ // | | | | : | : |
+ // |~~A~~| |~~B~~| H | Q |
+ // | | | | : | : |
+ // | ------------ | : ~~~~~P~~~~~ |
+ // | : | : |
+ // | D | : |
+ // | : | : |
+ // ------------------------ ------------------------
+ //
+ // |image_bounds| = (W, H)
+ // |image_aperture| = (X, Y, P, Q)
+ // |border| = (A, C, A + B, C + D)
+ // |fill_center| indicates whether to draw the center quad or not.
+ void SetLayout(gfx::Size image_bounds,
+ gfx::Rect image_aperture,
+ gfx::Rect border,
+ bool fill_center);
virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
OVERRIDE;
@@ -39,7 +69,6 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
virtual void AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) OVERRIDE;
virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE;
- virtual void DidLoseOutputSurface() OVERRIDE;
virtual base::DictionaryValue* LayerTreeAsJson() const OVERRIDE;
@@ -56,7 +85,12 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
// image space.
gfx::Rect image_aperture_;
- ResourceProvider::ResourceId resource_id_;
+ // An inset border that the patches will be mapped to.
+ gfx::Rect border_;
+
+ bool fill_center_;
+
+ UIResourceId ui_resource_id_;
DISALLOW_COPY_AND_ASSIGN(NinePatchLayerImpl);
};
diff --git a/cc/layers/nine_patch_layer_impl_unittest.cc b/cc/layers/nine_patch_layer_impl_unittest.cc
index 1985bd4..0fbc645 100644
--- a/cc/layers/nine_patch_layer_impl_unittest.cc
+++ b/cc/layers/nine_patch_layer_impl_unittest.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <stdio.h>
-
+#include "base/containers/hash_tables.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/nine_patch_layer_impl.h"
#include "cc/quads/texture_draw_quad.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "cc/resources/ui_resource_client.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/geometry_test_utils.h"
@@ -22,6 +23,40 @@
namespace cc {
namespace {
+class FakeUIResourceLayerTreeHostImpl : public FakeLayerTreeHostImpl {
+ public:
+ explicit FakeUIResourceLayerTreeHostImpl(Proxy* proxy)
+ : FakeLayerTreeHostImpl(proxy), fake_next_resource_id_(1) {}
+
+ virtual void CreateUIResource(
+ UIResourceId uid,
+ const UIResourceBitmap& bitmap) OVERRIDE {
+ if (ResourceIdForUIResource(uid))
+ DeleteUIResource(uid);
+ fake_ui_resource_map_[uid] = fake_next_resource_id_;
+ }
+
+ virtual void DeleteUIResource(UIResourceId uid) OVERRIDE {
+ ResourceProvider::ResourceId id = ResourceIdForUIResource(uid);
+ if (id)
+ fake_ui_resource_map_.erase(uid);
+ }
+
+ virtual ResourceProvider::ResourceId ResourceIdForUIResource(
+ UIResourceId uid) const OVERRIDE {
+ UIResourceMap::const_iterator iter = fake_ui_resource_map_.find(uid);
+ if (iter != fake_ui_resource_map_.end())
+ return iter->second;
+ return 0;
+ }
+
+ private:
+ ResourceProvider::ResourceId fake_next_resource_id_;
+ typedef base::hash_map<UIResourceId, ResourceProvider::ResourceId>
+ UIResourceMap;
+ UIResourceMap fake_ui_resource_map_;
+};
+
gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) {
return gfx::Rect(gfx::ToRoundedInt(rect_f.x()),
gfx::ToRoundedInt(rect_f.y()),
@@ -29,19 +64,21 @@ gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) {
gfx::ToRoundedInt(rect_f.height()));
}
-TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
- // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30.
- // The bounds of the layer are set to 400x400, so the draw quads
- // generated should leave the border width (40) intact.
+void NinePatchLayerLayoutTest(gfx::Size bitmap_size,
+ gfx::Rect aperture_rect,
+ gfx::Size layer_size,
+ gfx::Rect border,
+ bool fill_center,
+ size_t expected_quad_size) {
MockQuadCuller quad_culler;
- gfx::Size bitmap_size(100, 100);
- gfx::Size layer_size(400, 400);
gfx::Rect visible_content_rect(layer_size);
- gfx::Rect aperture_rect(20, 30, 40, 50);
- gfx::Rect scaled_aperture_non_uniform(20, 30, 340, 350);
+ gfx::Rect expected_remaining(border.x(),
+ border.y(),
+ layer_size.width() - border.width(),
+ layer_size.height() - border.height());
FakeImplProxy proxy;
- FakeLayerTreeHostImpl host_impl(&proxy);
+ FakeUIResourceLayerTreeHostImpl host_impl(&proxy);
scoped_ptr<NinePatchLayerImpl> layer =
NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
layer->draw_properties().visible_content_rect = visible_content_rect;
@@ -49,21 +86,26 @@ TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
layer->SetContentBounds(layer_size);
layer->CreateRenderSurface();
layer->draw_properties().render_target = layer.get();
- layer->SetLayout(bitmap_size, aperture_rect);
- layer->SetResourceId(1);
- // This scale should not affect the generated quad geometry, but only
- // the shared draw transform.
- gfx::Transform transform;
- transform.Scale(10, 10);
- layer->draw_properties().target_space_transform = transform;
+ UIResourceId uid = 1;
+ SkBitmap skbitmap;
+ skbitmap.setConfig(
+ SkBitmap::kARGB_8888_Config, bitmap_size.width(), bitmap_size.height());
+ skbitmap.allocPixels();
+ skbitmap.setImmutable();
+ UIResourceBitmap bitmap(skbitmap);
+
+ host_impl.CreateUIResource(uid, bitmap);
+ layer->SetUIResourceId(uid);
+ layer->SetLayout(bitmap_size, aperture_rect, border, fill_center);
AppendQuadsData data;
layer->AppendQuads(&quad_culler, &data);
// Verify quad rects
const QuadList& quads = quad_culler.quad_list();
- EXPECT_EQ(8u, quads.size());
+ EXPECT_EQ(expected_quad_size, quads.size());
+
Region remaining(visible_content_rect);
for (size_t i = 0; i < quads.size(); ++i) {
DrawQuad* quad = quads[i];
@@ -71,12 +113,16 @@ TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
EXPECT_TRUE(visible_content_rect.Contains(quad_rect)) << i;
EXPECT_TRUE(remaining.Contains(quad_rect)) << i;
- EXPECT_EQ(transform, quad->quadTransform());
remaining.Subtract(Region(quad_rect));
}
- EXPECT_RECT_EQ(scaled_aperture_non_uniform, remaining.bounds());
- Region scaled_aperture_region(scaled_aperture_non_uniform);
- EXPECT_EQ(scaled_aperture_region, remaining);
+
+ // Check if the left-over quad is the same size as the mapped aperture quad in
+ // layer space.
+ if (!fill_center) {
+ EXPECT_RECT_EQ(expected_remaining, gfx::ToEnclosedRect(remaining.bounds()));
+ } else {
+ EXPECT_TRUE(remaining.bounds().IsEmpty());
+ }
// Verify UV rects
gfx::Rect bitmap_rect(bitmap_size);
@@ -89,66 +135,59 @@ TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
}
- EXPECT_RECT_EQ(aperture_rect, tex_remaining.bounds());
- Region aperture_region(aperture_rect);
- EXPECT_EQ(aperture_region, tex_remaining);
-}
-
-TEST(NinePatchLayerImplTest, VerifyDrawQuadsForSqueezedLayer) {
- // Test with a layer much smaller than the bitmap.
- MockQuadCuller quad_culler;
- gfx::Size bitmap_size(101, 101);
- gfx::Size layer_size(51, 51);
- gfx::Rect visible_content_rect(layer_size);
- gfx::Rect aperture_rect(20, 30, 40, 45); // rightWidth: 40, botHeight: 25
-
- FakeImplProxy proxy;
- FakeLayerTreeHostImpl host_impl(&proxy);
- scoped_ptr<NinePatchLayerImpl> layer =
- NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
- layer->draw_properties().visible_content_rect = visible_content_rect;
- layer->SetBounds(layer_size);
- layer->SetContentBounds(layer_size);
- layer->CreateRenderSurface();
- layer->draw_properties().render_target = layer.get();
- layer->SetLayout(bitmap_size, aperture_rect);
- layer->SetResourceId(1);
- AppendQuadsData data;
- layer->AppendQuads(&quad_culler, &data);
-
- // Verify corner rects fill the layer and don't overlap
- const QuadList& quads = quad_culler.quad_list();
- EXPECT_EQ(4u, quads.size());
- Region filled;
- for (size_t i = 0; i < quads.size(); ++i) {
- DrawQuad* quad = quads[i];
- gfx::Rect quad_rect = quad->rect;
-
- EXPECT_FALSE(filled.Intersects(quad_rect));
- filled.Union(quad_rect);
+ if (!fill_center) {
+ EXPECT_RECT_EQ(aperture_rect, tex_remaining.bounds());
+ Region aperture_region(aperture_rect);
+ EXPECT_EQ(aperture_region, tex_remaining);
+ } else {
+ EXPECT_TRUE(remaining.bounds().IsEmpty());
}
- Region expected_full(visible_content_rect);
- EXPECT_EQ(expected_full, filled);
+}
- // Verify UV rects cover the corners of the bitmap and the crop is weighted
- // proportionately to the relative corner sizes (for uneven apertures).
- gfx::Rect bitmap_rect(bitmap_size);
- Region tex_remaining(bitmap_rect);
- for (size_t i = 0; i < quads.size(); ++i) {
- DrawQuad* quad = quads[i];
- const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(quad);
- gfx::RectF tex_rect =
- gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right);
- tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
- tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
- }
- Region expected_remaining_region = Region(gfx::Rect(bitmap_size));
- expected_remaining_region.Subtract(gfx::Rect(0, 0, 17, 28));
- expected_remaining_region.Subtract(gfx::Rect(67, 0, 34, 28));
- expected_remaining_region.Subtract(gfx::Rect(0, 78, 17, 23));
- expected_remaining_region.Subtract(gfx::Rect(67, 78, 34, 23));
- EXPECT_EQ(expected_remaining_region, tex_remaining);
+TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
+ // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30.
+ // The bounds of the layer are set to 400x400.
+ gfx::Size bitmap_size(100, 100);
+ gfx::Size layer_size(400, 500);
+ gfx::Rect aperture_rect(20, 30, 40, 50);
+ gfx::Rect border(40, 40, 80, 80);
+ bool fill_center = false;
+ size_t expected_quad_size = 8;
+ NinePatchLayerLayoutTest(bitmap_size,
+ aperture_rect,
+ layer_size,
+ border,
+ fill_center,
+ expected_quad_size);
+
+ // The bounds of the layer are set to less than the bitmap size.
+ bitmap_size = gfx::Size(100, 100);
+ layer_size = gfx::Size(40, 50);
+ aperture_rect = gfx::Rect(20, 30, 40, 50);
+ border = gfx::Rect(10, 10, 25, 15);
+ fill_center = true;
+ expected_quad_size = 9;
+ NinePatchLayerLayoutTest(bitmap_size,
+ aperture_rect,
+ layer_size,
+ border,
+ fill_center,
+ expected_quad_size);
+
+ // Layer and image sizes are equal.
+ bitmap_size = gfx::Size(100, 100);
+ layer_size = gfx::Size(100, 100);
+ aperture_rect = gfx::Rect(20, 30, 40, 50);
+ border = gfx::Rect(20, 30, 40, 50);
+ fill_center = true;
+ expected_quad_size = 9;
+ NinePatchLayerLayoutTest(bitmap_size,
+ aperture_rect,
+ layer_size,
+ border,
+ fill_center,
+ expected_quad_size);
}
} // namespace
diff --git a/cc/layers/nine_patch_layer_unittest.cc b/cc/layers/nine_patch_layer_unittest.cc
index f918efb..1283642 100644
--- a/cc/layers/nine_patch_layer_unittest.cc
+++ b/cc/layers/nine_patch_layer_unittest.cc
@@ -8,6 +8,7 @@
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/resource_update_queue.h"
+#include "cc/resources/scoped_ui_resource.h"
#include "cc/scheduler/texture_uploader.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_output_surface.h"
@@ -55,7 +56,7 @@ class NinePatchLayerTest : public testing::Test {
FakeLayerTreeHostClient fake_client_;
};
-TEST_F(NinePatchLayerTest, TriggerFullUploadOnceWhenChangingBitmap) {
+TEST_F(NinePatchLayerTest, SetBitmap) {
scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create();
ASSERT_TRUE(test_layer.get());
test_layer->SetIsDrawable(true);
@@ -67,82 +68,60 @@ TEST_F(NinePatchLayerTest, TriggerFullUploadOnceWhenChangingBitmap) {
layer_tree_host_->InitializeOutputSurfaceIfNeeded();
- PriorityCalculator calculator;
ResourceUpdateQueue queue;
OcclusionTracker occlusion_tracker(gfx::Rect(), false);
-
- // No bitmap set should not trigger any uploads.
test_layer->SavePaintProperties();
- test_layer->SetTexturePriorities(calculator);
test_layer->Update(&queue, &occlusion_tracker);
- EXPECT_EQ(0u, queue.FullUploadSize());
- EXPECT_EQ(0u, queue.PartialUploadSize());
- // Setting a bitmap set should trigger a single full upload.
+ EXPECT_FALSE(test_layer->DrawsContent());
+
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
bitmap.allocPixels();
- test_layer->SetBitmap(bitmap, gfx::Rect(5, 5, 1, 1));
- test_layer->SavePaintProperties();
- test_layer->SetTexturePriorities(calculator);
+ bitmap.setImmutable();
+
+ gfx::Rect aperture(5, 5, 1, 1);
+ bool fill_center = false;
+ test_layer->SetBitmap(bitmap, aperture);
+ test_layer->SetFillCenter(fill_center);
test_layer->Update(&queue, &occlusion_tracker);
- EXPECT_EQ(1u, queue.FullUploadSize());
- EXPECT_EQ(0u, queue.PartialUploadSize());
- ResourceUpdate params = queue.TakeFirstFullUpload();
- EXPECT_TRUE(params.texture != NULL);
-
- // Upload the texture.
- layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
- 1024 * 1024);
- layer_tree_host_->contents_texture_manager()->PrioritizeTextures();
-
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface;
- scoped_ptr<ResourceProvider> resource_provider;
- {
- DebugScopedSetImplThread impl_thread(Proxy());
- DebugScopedSetMainThreadBlocked main_thread_blocked(Proxy());
- output_surface = FakeOutputSurface::Create3d();
- CHECK(output_surface->BindToClient(&output_surface_client));
- resource_provider = ResourceProvider::Create(output_surface.get(), 0);
- params.texture->AcquireBackingTexture(resource_provider.get());
- ASSERT_TRUE(params.texture->have_backing_texture());
- }
- // Nothing changed, so no repeated upload.
+ EXPECT_TRUE(test_layer->DrawsContent());
+}
+
+TEST_F(NinePatchLayerTest, SetSharedBitmap) {
+ scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create();
+ ASSERT_TRUE(test_layer.get());
+ test_layer->SetIsDrawable(true);
+ test_layer->SetBounds(gfx::Size(100, 100));
+
+ layer_tree_host_->SetRootLayer(test_layer);
+ Mock::VerifyAndClearExpectations(layer_tree_host_.get());
+ EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
+
+ layer_tree_host_->InitializeOutputSurfaceIfNeeded();
+
+ ResourceUpdateQueue queue;
+ OcclusionTracker occlusion_tracker(gfx::Rect(), false);
test_layer->SavePaintProperties();
- test_layer->SetTexturePriorities(calculator);
test_layer->Update(&queue, &occlusion_tracker);
- EXPECT_EQ(0u, queue.FullUploadSize());
- EXPECT_EQ(0u, queue.PartialUploadSize());
- {
- DebugScopedSetImplThread impl_thread(Proxy());
- DebugScopedSetMainThreadBlocked main_thread_blocked(Proxy());
- layer_tree_host_->contents_texture_manager()->ClearAllMemory(
- resource_provider.get());
- }
- // Reupload after eviction
- test_layer->SavePaintProperties();
- test_layer->SetTexturePriorities(calculator);
+ EXPECT_FALSE(test_layer->DrawsContent());
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
+ bitmap.allocPixels();
+ bitmap.setImmutable();
+
+ scoped_ptr<ScopedUIResource> resource = ScopedUIResource::Create(
+ layer_tree_host_.get(), UIResourceBitmap(bitmap));
+ gfx::Rect aperture(5, 5, 1, 1);
+ bool fill_center = true;
+ test_layer->SetUIResourceId(resource->id(), aperture);
+ test_layer->SetFillCenter(fill_center);
test_layer->Update(&queue, &occlusion_tracker);
- EXPECT_EQ(1u, queue.FullUploadSize());
- EXPECT_EQ(0u, queue.PartialUploadSize());
- // PrioritizedResourceManager clearing
- layer_tree_host_->contents_texture_manager()->UnregisterTexture(
- params.texture);
- EXPECT_EQ(NULL, params.texture->resource_manager());
- test_layer->SavePaintProperties();
- test_layer->SetTexturePriorities(calculator);
- ResourceUpdateQueue queue2;
- test_layer->Update(&queue2, &occlusion_tracker);
- EXPECT_EQ(1u, queue2.FullUploadSize());
- EXPECT_EQ(0u, queue2.PartialUploadSize());
- params = queue2.TakeFirstFullUpload();
- EXPECT_TRUE(params.texture != NULL);
- EXPECT_EQ(params.texture->resource_manager(),
- layer_tree_host_->contents_texture_manager());
+ EXPECT_TRUE(test_layer->DrawsContent());
}
} // namespace
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc
index f5795de..4272fe6 100644
--- a/cc/layers/painted_scrollbar_layer.cc
+++ b/cc/layers/painted_scrollbar_layer.cc
@@ -210,20 +210,14 @@ bool PaintedScrollbarLayer::Update(ResourceUpdateQueue* queue,
return true;
}
-scoped_refptr<UIResourceBitmap> PaintedScrollbarLayer::RasterizeScrollbarPart(
+UIResourceBitmap PaintedScrollbarLayer::RasterizeScrollbarPart(
gfx::Rect rect,
ScrollbarPart part) {
DCHECK(!rect.size().IsEmpty());
- scoped_refptr<UIResourceBitmap> bitmap =
- UIResourceBitmap::Create(new uint8_t[rect.width() * rect.height() * 4],
- UIResourceBitmap::RGBA8,
- UIResourceBitmap::CLAMP_TO_EDGE,
- rect.size());
-
SkBitmap skbitmap;
skbitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height());
- skbitmap.setPixels(bitmap->GetPixels());
+ skbitmap.allocPixels();
SkCanvas skcanvas(skbitmap);
skcanvas.translate(SkFloatToScalar(-rect.x()), SkFloatToScalar(-rect.y()));
@@ -240,8 +234,11 @@ scoped_refptr<UIResourceBitmap> PaintedScrollbarLayer::RasterizeScrollbarPart(
skcanvas.clipRect(layer_skrect);
scrollbar_->PaintPart(&skcanvas, part, layer_rect);
+ // Make sure that the pixels are no longer mutable to unavoid unnecessary
+ // allocation and copying.
+ skbitmap.setImmutable();
- return bitmap;
+ return UIResourceBitmap(skbitmap);
}
} // namespace cc
diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h
index 8140f8c..e84377d 100644
--- a/cc/layers/painted_scrollbar_layer.h
+++ b/cc/layers/painted_scrollbar_layer.h
@@ -68,8 +68,8 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface,
int MaxTextureSize();
float ClampScaleToMaxTextureSize(float scale);
- scoped_refptr<UIResourceBitmap> RasterizeScrollbarPart(gfx::Rect rect,
- ScrollbarPart part);
+ UIResourceBitmap RasterizeScrollbarPart(gfx::Rect rect,
+ ScrollbarPart part);
scoped_ptr<Scrollbar> scrollbar_;
int scroll_layer_id_;
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 1e9442d5..a58f24b 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -527,7 +527,8 @@ class MockLayerTreeHost : public LayerTreeHost {
virtual UIResourceId CreateUIResource(UIResourceClient* content) OVERRIDE {
total_ui_resource_created_++;
UIResourceId nid = next_id_++;
- ui_resource_bitmap_map_[nid] = content->GetBitmap(nid, false);
+ ui_resource_bitmap_map_.insert(
+ std::make_pair(nid, content->GetBitmap(nid, false)));
return nid;
}
@@ -546,13 +547,13 @@ class MockLayerTreeHost : public LayerTreeHost {
gfx::Size ui_resource_size(UIResourceId id) {
UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id);
- if (iter != ui_resource_bitmap_map_.end() && iter->second.get())
- return iter->second->GetSize();
+ if (iter != ui_resource_bitmap_map_.end())
+ return iter->second.GetSize();
return gfx::Size();
}
private:
- typedef base::hash_map<UIResourceId, scoped_refptr<UIResourceBitmap> >
+ typedef base::hash_map<UIResourceId, UIResourceBitmap>
UIResourceBitmapMap;
UIResourceBitmapMap ui_resource_bitmap_map_;
diff --git a/cc/resources/scoped_ui_resource.cc b/cc/resources/scoped_ui_resource.cc
index 0136a8e..e69b4bc 100644
--- a/cc/resources/scoped_ui_resource.cc
+++ b/cc/resources/scoped_ui_resource.cc
@@ -12,12 +12,12 @@ namespace cc {
scoped_ptr<ScopedUIResource> ScopedUIResource::Create(
LayerTreeHost* host,
- scoped_refptr<UIResourceBitmap> bitmap) {
+ const UIResourceBitmap& bitmap) {
return make_scoped_ptr(new ScopedUIResource(host, bitmap));
}
ScopedUIResource::ScopedUIResource(LayerTreeHost* host,
- scoped_refptr<UIResourceBitmap> bitmap)
+ const UIResourceBitmap& bitmap)
: bitmap_(bitmap), host_(host) {
DCHECK(host_);
id_ = host_->CreateUIResource(this);
@@ -32,16 +32,9 @@ ScopedUIResource::~ScopedUIResource() {
}
}
-gfx::Size ScopedUIResource::GetSize() const {
- return bitmap_->GetSize();
-}
-
-scoped_refptr<UIResourceBitmap> ScopedUIResource::GetBitmap(
- UIResourceId uid,
- bool resource_lost) {
+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
index a4525e6..c257e1e 100644
--- a/cc/resources/scoped_ui_resource.h
+++ b/cc/resources/scoped_ui_resource.h
@@ -15,28 +15,27 @@ namespace cc {
class LayerTreeHost;
+// ScopedUIResource creates an UIResource from a bitmap and a LayerTreeHost.
+// This class holds a pointer to the host so that when the instance goes out of
+// scope, the created resource is deleted. On a GetBitmap call from the
+// UIResource manager, ScopeUIResource always returns the reference to the
+// initially given bitmap regardless of whether the request was due to lost
+// resource or not.
class CC_EXPORT ScopedUIResource : public UIResourceClient {
public:
- static scoped_ptr<ScopedUIResource> Create(
- LayerTreeHost* host,
- scoped_refptr<UIResourceBitmap> bitmap);
+ static scoped_ptr<ScopedUIResource> Create(LayerTreeHost* host,
+ const UIResourceBitmap& bitmap);
virtual ~ScopedUIResource();
- gfx::Size GetSize() const;
-
// UIResourceClient implementation.
- virtual scoped_refptr<UIResourceBitmap> GetBitmap(
- UIResourceId uid,
- bool resource_lost) OVERRIDE;
+ virtual 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();
+ ScopedUIResource(LayerTreeHost* host, const UIResourceBitmap& bitmap);
- scoped_refptr<UIResourceBitmap> bitmap_;
+ UIResourceBitmap bitmap_;
LayerTreeHost* host_;
UIResourceId id_;
diff --git a/cc/resources/ui_resource_bitmap.cc b/cc/resources/ui_resource_bitmap.cc
index 1510607d..2acbd95 100644
--- a/cc/resources/ui_resource_bitmap.cc
+++ b/cc/resources/ui_resource_bitmap.cc
@@ -4,25 +4,45 @@
#include "cc/resources/ui_resource_bitmap.h"
+#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkBitmap.h"
namespace cc {
-scoped_refptr<UIResourceBitmap>
-UIResourceBitmap::Create(uint8_t* pixels,
- UIResourceFormat format,
- UIResourceWrapMode wrap_mode,
- gfx::Size size) {
- scoped_refptr<UIResourceBitmap> ret = new UIResourceBitmap();
- ret->pixels_ = scoped_ptr<uint8_t[]>(pixels);
- ret->format_ = format;
- ret->wrap_mode_ = wrap_mode;
- ret->size_ = size;
-
- return ret;
+uint8_t* UIResourceBitmap::GetPixels() const {
+ if (!pixel_ref_)
+ return NULL;
+ return static_cast<uint8_t*>(pixel_ref_->pixels());
+}
+
+void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
+ UIResourceFormat format,
+ UIResourceWrapMode wrap_mode,
+ gfx::Size size) {
+ DCHECK(size.width());
+ DCHECK(size.height());
+ DCHECK(pixel_ref);
+ DCHECK(pixel_ref->isImmutable());
+ format_ = format;
+ wrap_mode_ = wrap_mode;
+ size_ = size;
+ pixel_ref_ = pixel_ref;
+}
+
+UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap,
+ UIResourceWrapMode wrap_mode) {
+ DCHECK_EQ(skbitmap.config(), SkBitmap::kARGB_8888_Config);
+ DCHECK_EQ(skbitmap.width(), skbitmap.rowBytesAsPixels());
+ DCHECK(skbitmap.isImmutable());
+
+ skia::RefPtr<SkPixelRef> pixel_ref = skia::SharePtr(skbitmap.pixelRef());
+ Create(pixel_ref,
+ UIResourceBitmap::RGBA8,
+ wrap_mode,
+ gfx::Size(skbitmap.width(), skbitmap.height()));
}
-UIResourceBitmap::UIResourceBitmap() {}
UIResourceBitmap::~UIResourceBitmap() {}
} // namespace cc
diff --git a/cc/resources/ui_resource_bitmap.h b/cc/resources/ui_resource_bitmap.h
index e1b5aee..f10fed9 100644
--- a/cc/resources/ui_resource_bitmap.h
+++ b/cc/resources/ui_resource_bitmap.h
@@ -8,16 +8,20 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
#include "third_party/skia/include/core/SkTypes.h"
#include "ui/gfx/size.h"
+class SkBitmap;
+
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> {
+// A bitmap class that contains a ref-counted reference to a SkPixelRef* that
+// holds the content of the bitmap (cannot use SkBitmap because of ETC1).
+// Thread-safety (by ways of SkPixelRef) ensures that both main and impl threads
+// can hold references to the bitmap and that asynchronous uploads are allowed.
+class CC_EXPORT UIResourceBitmap {
public:
enum UIResourceFormat {
RGBA8
@@ -27,29 +31,29 @@ class CC_EXPORT UIResourceBitmap
REPEAT
};
- // Takes ownership of “pixels”.
- static scoped_refptr<UIResourceBitmap> Create(uint8_t* pixels,
- UIResourceFormat format,
- UIResourceWrapMode wrap_mode,
- gfx::Size size);
-
gfx::Size GetSize() const { return size_; }
UIResourceFormat GetFormat() const { return format_; }
UIResourceWrapMode GetWrapMode() const { return wrap_mode_; }
- uint8_t* GetPixels() { return pixels_.get(); }
+ uint8_t* GetPixels() const;
- private:
- friend class base::RefCountedThreadSafe<UIResourceBitmap>;
+ // The constructor for the UIResourceBitmap. User must ensure that |skbitmap|
+ // is immutable. The SkBitmap format should be in 32-bit RGBA. Wrap mode is
+ // unnecessary for most UI resources and is defaulted to CLAMP_TO_EDGE.
+ UIResourceBitmap(const SkBitmap& skbitmap,
+ UIResourceWrapMode wrap_mode = CLAMP_TO_EDGE);
- UIResourceBitmap();
~UIResourceBitmap();
- scoped_ptr<uint8_t[]> pixels_;
+ private:
+ void Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
+ UIResourceFormat format,
+ UIResourceWrapMode wrap_mode,
+ gfx::Size size);
+
+ skia::RefPtr<SkPixelRef> pixel_ref_;
UIResourceFormat format_;
UIResourceWrapMode wrap_mode_;
gfx::Size size_;
-
- DISALLOW_COPY_AND_ASSIGN(UIResourceBitmap);
};
} // namespace cc
diff --git a/cc/resources/ui_resource_client.h b/cc/resources/ui_resource_client.h
index d647936..24309a5 100644
--- a/cc/resources/ui_resource_client.h
+++ b/cc/resources/ui_resource_client.h
@@ -24,8 +24,8 @@ class CC_EXPORT UIResourceClient {
// 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 UIResourceBitmap GetBitmap(UIResourceId uid,
+ bool resource_lost) = 0;
virtual ~UIResourceClient() {}
};
diff --git a/cc/test/fake_scoped_ui_resource.cc b/cc/test/fake_scoped_ui_resource.cc
index ce5ee11..bf86f54 100644
--- a/cc/test/fake_scoped_ui_resource.cc
+++ b/cc/test/fake_scoped_ui_resource.cc
@@ -8,25 +8,34 @@
namespace cc {
+namespace {
+
+UIResourceBitmap CreateMockUIResourceBitmap() {
+ SkBitmap skbitmap;
+ skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+ skbitmap.allocPixels();
+ skbitmap.setImmutable();
+ return UIResourceBitmap(skbitmap);
+}
+
+} // anonymous namespace
+
scoped_ptr<FakeScopedUIResource> FakeScopedUIResource::Create(
LayerTreeHost* host) {
return make_scoped_ptr(new FakeScopedUIResource(host));
}
-FakeScopedUIResource::FakeScopedUIResource(LayerTreeHost* host) {
+FakeScopedUIResource::FakeScopedUIResource(LayerTreeHost* host)
+ : ScopedUIResource(host, CreateMockUIResourceBitmap()) {
+ // The constructor of ScopedUIResource already created a resource so we need
+ // to delete the created resource to wipe the state clean.
+ host_->DeleteUIResource(id_);
ResetCounters();
- bitmap_ = UIResourceBitmap::Create(
- new uint8_t[1],
- UIResourceBitmap::RGBA8,
- UIResourceBitmap::CLAMP_TO_EDGE,
- gfx::Size(1, 1));
- host_ = host;
id_ = host_->CreateUIResource(this);
}
-scoped_refptr<UIResourceBitmap> FakeScopedUIResource::GetBitmap(
- UIResourceId uid,
- bool resource_lost) {
+UIResourceBitmap FakeScopedUIResource::GetBitmap(UIResourceId uid,
+ bool resource_lost) {
resource_create_count++;
if (resource_lost)
lost_resource_count++;
diff --git a/cc/test/fake_scoped_ui_resource.h b/cc/test/fake_scoped_ui_resource.h
index 84c097f..970d7b0 100644
--- a/cc/test/fake_scoped_ui_resource.h
+++ b/cc/test/fake_scoped_ui_resource.h
@@ -16,9 +16,8 @@ class FakeScopedUIResource : public ScopedUIResource {
public:
static scoped_ptr<FakeScopedUIResource> Create(LayerTreeHost* host);
- virtual scoped_refptr<UIResourceBitmap> GetBitmap(
- UIResourceId uid,
- bool resource_lost) OVERRIDE;
+ virtual UIResourceBitmap GetBitmap(UIResourceId uid,
+ bool resource_lost) OVERRIDE;
void ResetCounters();
int resource_create_count;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 611d6ae..6d5a7d9 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -61,8 +61,31 @@ RendererCapabilities::RendererCapabilities()
RendererCapabilities::~RendererCapabilities() {}
-UIResourceRequest::UIResourceRequest()
- : type(UIResourceInvalidRequest), id(0), bitmap(NULL) {}
+UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
+ UIResourceId id)
+ : type_(type), id_(id) {}
+
+UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
+ UIResourceId id,
+ const UIResourceBitmap& bitmap)
+ : type_(type), id_(id), bitmap_(new UIResourceBitmap(bitmap)) {}
+
+UIResourceRequest::UIResourceRequest(const UIResourceRequest& request) {
+ (*this) = request;
+}
+
+UIResourceRequest& UIResourceRequest::operator=(
+ const UIResourceRequest& request) {
+ type_ = request.type_;
+ id_ = request.id_;
+ if (request.bitmap_) {
+ bitmap_ = make_scoped_ptr(new UIResourceBitmap(*request.bitmap_.get()));
+ } else {
+ bitmap_.reset();
+ }
+
+ return *this;
+}
UIResourceRequest::~UIResourceRequest() {}
@@ -376,7 +399,7 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
if (overhang_ui_resource_) {
host_impl->SetOverhangUIResource(
overhang_ui_resource_->id(),
- overhang_ui_resource_->GetSize());
+ GetUIResourceSize(overhang_ui_resource_->id()));
}
DCHECK(!sync_tree->ViewportSizeInvalid());
@@ -634,16 +657,16 @@ void LayerTreeHost::SetOverhangBitmap(const SkBitmap& bitmap) {
DCHECK(bitmap.width() && bitmap.height());
DCHECK_EQ(bitmap.bytesPerPixel(), 4);
- scoped_refptr<UIResourceBitmap> overhang_ui_bitmap(UIResourceBitmap::Create(
- new uint8_t[bitmap.width() * bitmap.height() * bitmap.bytesPerPixel()],
- UIResourceBitmap::RGBA8,
- UIResourceBitmap::REPEAT,
- gfx::Size(bitmap.width(), bitmap.height())));
- bitmap.copyPixelsTo(
- overhang_ui_bitmap->GetPixels(),
- bitmap.width() * bitmap.height() * bitmap.bytesPerPixel(),
- bitmap.width() * bitmap.bytesPerPixel());
- overhang_ui_resource_ = ScopedUIResource::Create(this, overhang_ui_bitmap);
+ SkBitmap bitmap_copy;
+ if (bitmap.isImmutable()) {
+ bitmap_copy = bitmap;
+ } else {
+ bitmap.copyTo(&bitmap_copy, bitmap.config());
+ bitmap_copy.setImmutable();
+ }
+
+ overhang_ui_resource_ = ScopedUIResource::Create(
+ this, UIResourceBitmap(bitmap_copy, UIResourceBitmap::REPEAT));
}
void LayerTreeHost::SetVisible(bool visible) {
@@ -1146,18 +1169,22 @@ 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) ==
+ UIResourceId next_id = next_ui_resource_id_++;
+ DCHECK(ui_resource_client_map_.find(next_id) ==
ui_resource_client_map_.end());
- request.bitmap = client->GetBitmap(request.id, resource_lost);
+ bool resource_lost = false;
+ UIResourceRequest request(UIResourceRequest::UIResourceCreate,
+ next_id,
+ client->GetBitmap(next_id, resource_lost));
ui_resource_request_queue_.push_back(request);
- ui_resource_client_map_[request.id] = client;
- return request.id;
+
+ UIResourceClientData data;
+ data.client = client;
+ data.size = request.GetBitmap().GetSize();
+
+ ui_resource_client_map_[request.GetId()] = data;
+ return request.GetId();
}
// Deletes a UI resource. May safely be called more than once.
@@ -1166,11 +1193,9 @@ void LayerTreeHost::DeleteUIResource(UIResourceId uid) {
if (iter == ui_resource_client_map_.end())
return;
- UIResourceRequest request;
- request.type = UIResourceRequest::UIResourceDelete;
- request.id = uid;
+ UIResourceRequest request(UIResourceRequest::UIResourceDelete, uid);
ui_resource_request_queue_.push_back(request);
- ui_resource_client_map_.erase(uid);
+ ui_resource_client_map_.erase(iter);
}
void LayerTreeHost::RecreateUIResources() {
@@ -1178,14 +1203,23 @@ void LayerTreeHost::RecreateUIResources() {
iter != ui_resource_client_map_.end();
++iter) {
UIResourceId uid = iter->first;
- UIResourceRequest request;
- request.type = UIResourceRequest::UIResourceCreate;
- request.id = uid;
+ const UIResourceClientData& data = iter->second;
bool resource_lost = true;
- request.bitmap = iter->second->GetBitmap(uid, resource_lost);
- DCHECK(request.bitmap.get());
+ UIResourceRequest request(UIResourceRequest::UIResourceCreate,
+ uid,
+ data.client->GetBitmap(uid, resource_lost));
ui_resource_request_queue_.push_back(request);
}
}
+// Returns the size of a resource given its id.
+gfx::Size LayerTreeHost::GetUIResourceSize(UIResourceId uid) const {
+ UIResourceClientMap::const_iterator iter = ui_resource_client_map_.find(uid);
+ if (iter == ui_resource_client_map_.end())
+ return gfx::Size();
+
+ const UIResourceClientData& data = iter->second;
+ return data.size;
+}
+
} // namespace cc
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 5211ac8..304127f 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -86,18 +86,35 @@ struct CC_EXPORT RendererCapabilities {
bool using_discard_framebuffer;
};
-struct CC_EXPORT UIResourceRequest {
+class CC_EXPORT UIResourceRequest {
+ public:
enum UIResourceRequestType {
UIResourceCreate,
UIResourceDelete,
UIResourceInvalidRequest
};
- UIResourceRequest();
+ UIResourceRequest(UIResourceRequestType type, UIResourceId id);
+ UIResourceRequest(UIResourceRequestType type,
+ UIResourceId id,
+ const UIResourceBitmap& bitmap);
+ UIResourceRequest(const UIResourceRequest& request);
+
~UIResourceRequest();
- UIResourceRequestType type;
- UIResourceId id;
- scoped_refptr<UIResourceBitmap> bitmap;
+
+ UIResourceRequestType GetType() const { return type_; }
+ UIResourceId GetId() const { return id_; }
+ UIResourceBitmap GetBitmap() const {
+ DCHECK(bitmap_);
+ return *bitmap_.get();
+ }
+
+ UIResourceRequest& operator=(const UIResourceRequest& request);
+
+ private:
+ UIResourceRequestType type_;
+ UIResourceId id_;
+ scoped_ptr<UIResourceBitmap> bitmap_;
};
class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
@@ -290,6 +307,8 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
// were evicted on the impl thread.
void RecreateUIResources();
+ virtual gfx::Size GetUIResourceSize(UIResourceId id) const;
+
bool UsingSharedMemoryResources();
int id() const { return tree_id_; }
@@ -326,7 +345,13 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
bool AnimateLayersRecursive(Layer* current, base::TimeTicks time);
- typedef base::hash_map<UIResourceId, UIResourceClient*> UIResourceClientMap;
+ struct UIResourceClientData {
+ UIResourceClient* client;
+ gfx::Size size;
+ };
+
+ typedef base::hash_map<UIResourceId, UIResourceClientData>
+ UIResourceClientMap;
UIResourceClientMap ui_resource_client_map_;
int next_ui_resource_id_;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 82a67ee..50b2f46 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2617,14 +2617,13 @@ void LayerTreeHostImpl::SetDebugState(
SetFullRootLayerDamage();
}
-void LayerTreeHostImpl::CreateUIResource(
- UIResourceId uid,
- scoped_refptr<UIResourceBitmap> bitmap) {
+void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
+ const UIResourceBitmap& bitmap) {
DCHECK_GT(uid, 0);
- DCHECK_EQ(bitmap->GetFormat(), UIResourceBitmap::RGBA8);
+ DCHECK_EQ(bitmap.GetFormat(), UIResourceBitmap::RGBA8);
GLint wrap_mode = 0;
- switch (bitmap->GetWrapMode()) {
+ switch (bitmap.GetWrapMode()) {
case UIResourceBitmap::CLAMP_TO_EDGE:
wrap_mode = GL_CLAMP_TO_EDGE;
break;
@@ -2639,16 +2638,16 @@ void LayerTreeHostImpl::CreateUIResource(
if (id)
DeleteUIResource(uid);
id = resource_provider_->CreateResource(
- bitmap->GetSize(),
+ bitmap.GetSize(),
resource_provider_->best_texture_format(),
wrap_mode,
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()),
+ bitmap.GetPixels(),
+ gfx::Rect(bitmap.GetSize()),
+ gfx::Rect(bitmap.GetSize()),
gfx::Vector2d(0, 0));
MarkUIResourceNotEvicted(uid);
}
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index cd5eda5..4830714 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -50,8 +50,8 @@ class RenderPassDrawQuad;
class TextureMailboxDeleter;
class TopControlsManager;
class UIResourceBitmap;
+class UIResourceRequest;
struct RendererCapabilities;
-struct UIResourceRequest;
// LayerTreeHost->Proxy callback interface.
class LayerTreeHostImplClient {
@@ -398,14 +398,15 @@ class CC_EXPORT LayerTreeHostImpl
bool page_scale_animation_active() const { return !!page_scale_animation_; }
- void CreateUIResource(UIResourceId uid,
- scoped_refptr<UIResourceBitmap> bitmap);
+ virtual void CreateUIResource(UIResourceId uid,
+ const UIResourceBitmap& bitmap);
// Deletes a UI resource. May safely be called more than once.
- void DeleteUIResource(UIResourceId uid);
+ virtual void DeleteUIResource(UIResourceId uid);
void EvictAllUIResources();
bool EvictedUIResourcesExist() const;
- ResourceProvider::ResourceId ResourceIdForUIResource(UIResourceId uid) const;
+ virtual ResourceProvider::ResourceId ResourceIdForUIResource(
+ UIResourceId uid) const;
void DidInitializeVisibleTileForTesting() { DidInitializeVisibleTile(); }
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index deaab09..29b4ee3 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -3070,12 +3070,13 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
SetupActiveTreeLayers();
+ SkBitmap skbitmap;
+ skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
+ skbitmap.allocPixels();
+ skbitmap.setImmutable();
+
// Specify an overhang bitmap to use.
- scoped_refptr<UIResourceBitmap> ui_resource_bitmap(UIResourceBitmap::Create(
- new uint8_t[4],
- UIResourceBitmap::RGBA8,
- UIResourceBitmap::REPEAT,
- gfx::Size(1, 1)));
+ UIResourceBitmap ui_resource_bitmap(skbitmap, UIResourceBitmap::REPEAT);
UIResourceId ui_resource_id = 12345;
host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
@@ -6541,12 +6542,13 @@ TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
EXPECT_EQ(0u, context3d->NumTextures());
+ SkBitmap skbitmap;
+ skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+ skbitmap.allocPixels();
+ skbitmap.setImmutable();
+
UIResourceId ui_resource_id = 1;
- scoped_refptr<UIResourceBitmap> bitmap = UIResourceBitmap::Create(
- new uint8_t[1],
- UIResourceBitmap::RGBA8,
- UIResourceBitmap::CLAMP_TO_EDGE,
- gfx::Size(1, 1));
+ UIResourceBitmap bitmap(skbitmap);
host_impl_->CreateUIResource(ui_resource_id, bitmap);
EXPECT_EQ(1u, context3d->NumTextures());
ResourceProvider::ResourceId id1 =
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index faff70e..13894058 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -621,12 +621,12 @@ void LayerTreeImpl::ProcessUIResourceRequestQueue() {
UIResourceRequest req = ui_resource_request_queue_.front();
ui_resource_request_queue_.pop_front();
- switch (req.type) {
+ switch (req.GetType()) {
case UIResourceRequest::UIResourceCreate:
- layer_tree_host_impl_->CreateUIResource(req.id, req.bitmap);
+ layer_tree_host_impl_->CreateUIResource(req.GetId(), req.GetBitmap());
break;
case UIResourceRequest::UIResourceDelete:
- layer_tree_host_impl_->DeleteUIResource(req.id);
+ layer_tree_host_impl_->DeleteUIResource(req.GetId());
break;
case UIResourceRequest::UIResourceInvalidRequest:
NOTREACHED();
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 969cba2..05c86ec 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -42,8 +42,8 @@ class PaintTimeCounter;
class Proxy;
class ResourceProvider;
class TileManager;
+class UIResourceRequest;
struct RendererCapabilities;
-struct UIResourceRequest;
typedef std::list<UIResourceRequest> UIResourceRequestQueue;