summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 18:12:05 +0000
committerjdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 18:13:08 +0000
commit33d76bb0f87cd9e3ad5b1589bb29872924e4e5e3 (patch)
tree53c71fe658765d5b61701554d224876baf20834c
parentc16f8d313d371c7fc6e38cc87fab155cdfbb94ec (diff)
downloadchromium_src-33d76bb0f87cd9e3ad5b1589bb29872924e4e5e3.zip
chromium_src-33d76bb0f87cd9e3ad5b1589bb29872924e4e5e3.tar.gz
chromium_src-33d76bb0f87cd9e3ad5b1589bb29872924e4e5e3.tar.bz2
Revert of Revert of [Android] Use UIResource for overscroll glow (https://codereview.chromium.org/454863003/)
Reason for revert: The ToT builder failures appear to be unrelated to this change, and the upstream instrumentation already exercise these code paths. Tentatively reverting the revert and will keep an eye on downstream rolls. Original issue's description: > Revert of [Android] Use UIResource for overscroll glow (https://codereview.chromium.org/422013003/) > > Reason for revert: > This is breaking chrome ToT downstream and the change quie complex so > I don't feel qualified to try to fix it in place. > > The failure we hit is > F/chromium( 2961): [FATAL:system_ui_resource_manager_impl.cc(35)] Check failed: !bitmap.empty(). > > See an example of a failed run in > https://uberchromegw.corp.google.com/i/clank.tot/builders/instrumentation-yakju-clankium-tot/builds/32007 > > (but just trying to boot clank with this patch will trigger it) > > > Original issue's description: > > [Android] Use UIResource for overscroll glow > > > > Introduce a SystemUIResourceManager class for loading and providing access to > > shared UIResourceId's. Wire this class to the existing OverscrollGlow effect, > > using the shared id's with a UIResourceLayer for both glow and edge layers. > > > > This patch is a subset of powei@'s original SystemUIResource patch found at > > https://codereview.chromium.org/377013002/. > > > > BUG=326326 > > > > Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=288095 > > Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=288330 TBR=aelias@chromium.org,powei@chromium.org,yfriedman@chromium.org,sky@chromium.org,miguelg@chromium.org NOTREECHECKS=true NOTRY=true BUG=326326 Review URL: https://codereview.chromium.org/454113002 Cr-Commit-Position: refs/heads/master@{#288392} git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288392 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/android/edge_effect.cc139
-rw-r--r--content/browser/android/edge_effect.h20
-rw-r--r--content/browser/android/overscroll_glow.cc97
-rw-r--r--content/browser/android/overscroll_glow.h17
-rw-r--r--content/browser/android/system_ui_resource_manager_impl.cc137
-rw-r--r--content/browser/android/system_ui_resource_manager_impl.h55
-rw-r--r--content/browser/android/system_ui_resource_manager_impl_unittest.cc167
-rw-r--r--content/browser/android/ui_resource_provider_impl.cc8
-rw-r--r--content/browser/android/ui_resource_provider_impl.h5
-rw-r--r--content/browser/renderer_host/compositor_impl_android.cc4
-rw-r--r--content/browser/renderer_host/compositor_impl_android.h7
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.cc38
-rw-r--r--content/browser/renderer_host/render_widget_host_view_android.h1
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/content_tests.gypi1
-rw-r--r--ui/base/BUILD.gn1
-rw-r--r--ui/base/android/system_ui_resource_manager.h41
-rw-r--r--ui/base/android/window_android_compositor.h2
-rw-r--r--ui/base/ui_base.gyp1
-rw-r--r--ui/gfx/android/java_bitmap.cc32
-rw-r--r--ui/gfx/android/java_bitmap.h12
21 files changed, 602 insertions, 185 deletions
diff --git a/content/browser/android/edge_effect.cc b/content/browser/android/edge_effect.cc
index 94e5b51..2979872 100644
--- a/content/browser/android/edge_effect.cc
+++ b/content/browser/android/edge_effect.cc
@@ -5,6 +5,8 @@
#include "content/browser/android/edge_effect.h"
#include "cc/layers/layer.h"
+#include "cc/layers/ui_resource_layer.h"
+#include "ui/base/android/system_ui_resource_manager.h"
namespace content {
@@ -118,52 +120,70 @@ gfx::Size ComputeBounds(EdgeEffect::Edge edge,
};
}
-void DisableLayer(cc::Layer* layer) {
- DCHECK(layer);
- layer->SetIsDrawable(false);
- layer->SetTransform(gfx::Transform());
- layer->SetOpacity(1.f);
-}
+} // namespace
-void UpdateLayer(cc::Layer* layer,
- EdgeEffect::Edge edge,
- const gfx::SizeF& window_size,
- int offset,
- int height,
- float opacity) {
- DCHECK(layer);
- layer->SetIsDrawable(true);
- gfx::Size bounds = ComputeBounds(edge, window_size, height);
- layer->SetTransformOrigin(
- gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0));
- layer->SetTransform(ComputeTransform(edge, window_size, offset, height));
- layer->SetBounds(bounds);
- layer->SetOpacity(Clamp(opacity, 0.f, 1.f));
-}
+class EdgeEffect::EffectLayer {
+ public:
+ EffectLayer(ui::SystemUIResourceManager::ResourceType resource_type,
+ ui::SystemUIResourceManager* resource_manager)
+ : ui_resource_layer_(cc::UIResourceLayer::Create()),
+ resource_type_(resource_type),
+ resource_manager_(resource_manager) {}
+
+ ~EffectLayer() { ui_resource_layer_->RemoveFromParent(); }
+
+ void SetParent(cc::Layer* parent) {
+ if (ui_resource_layer_->parent() != parent)
+ parent->AddChild(ui_resource_layer_);
+ ui_resource_layer_->SetUIResourceId(
+ resource_manager_->GetUIResourceId(resource_type_));
+ }
+
+ void Disable() { ui_resource_layer_->SetIsDrawable(false); }
+
+ void Update(EdgeEffect::Edge edge,
+ const gfx::SizeF& window_size,
+ int offset,
+ int height,
+ float opacity) {
+ ui_resource_layer_->SetUIResourceId(
+ resource_manager_->GetUIResourceId(resource_type_));
+ ui_resource_layer_->SetIsDrawable(true);
+ gfx::Size bounds = ComputeBounds(edge, window_size, height);
+ ui_resource_layer_->SetTransformOrigin(
+ gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0));
+ ui_resource_layer_->SetTransform(
+ ComputeTransform(edge, window_size, offset, height));
+ ui_resource_layer_->SetBounds(bounds);
+ ui_resource_layer_->SetOpacity(Clamp(opacity, 0.f, 1.f));
+ }
-} // namespace
-
-EdgeEffect::EdgeEffect(scoped_refptr<cc::Layer> edge,
- scoped_refptr<cc::Layer> glow)
- : edge_(edge)
- , glow_(glow)
- , edge_alpha_(0)
- , edge_scale_y_(0)
- , glow_alpha_(0)
- , glow_scale_y_(0)
- , edge_alpha_start_(0)
- , edge_alpha_finish_(0)
- , edge_scale_y_start_(0)
- , edge_scale_y_finish_(0)
- , glow_alpha_start_(0)
- , glow_alpha_finish_(0)
- , glow_scale_y_start_(0)
- , glow_scale_y_finish_(0)
- , state_(STATE_IDLE)
- , pull_distance_(0) {
- // Prevent the provided layers from drawing until the effect is activated.
- DisableLayer(edge_.get());
- DisableLayer(glow_.get());
+ scoped_refptr<cc::UIResourceLayer> ui_resource_layer_;
+ ui::SystemUIResourceManager::ResourceType resource_type_;
+ ui::SystemUIResourceManager* resource_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(EffectLayer);
+};
+
+EdgeEffect::EdgeEffect(ui::SystemUIResourceManager* resource_manager)
+ : edge_(new EffectLayer(ui::SystemUIResourceManager::OVERSCROLL_EDGE,
+ resource_manager)),
+ glow_(new EffectLayer(ui::SystemUIResourceManager::OVERSCROLL_GLOW,
+ resource_manager)),
+ edge_alpha_(0),
+ edge_scale_y_(0),
+ glow_alpha_(0),
+ glow_scale_y_(0),
+ edge_alpha_start_(0),
+ edge_alpha_finish_(0),
+ edge_scale_y_start_(0),
+ edge_scale_y_finish_(0),
+ glow_alpha_start_(0),
+ glow_alpha_finish_(0),
+ glow_scale_y_start_(0),
+ glow_scale_y_finish_(0),
+ state_(STATE_IDLE),
+ pull_distance_(0) {
}
EdgeEffect::~EdgeEffect() { }
@@ -173,8 +193,8 @@ bool EdgeEffect::IsFinished() const {
}
void EdgeEffect::Finish() {
- DisableLayer(edge_.get());
- DisableLayer(glow_.get());
+ edge_->Disable();
+ glow_->Disable();
pull_distance_ = 0;
state_ = STATE_IDLE;
}
@@ -359,8 +379,8 @@ void EdgeEffect::ApplyToLayers(gfx::SizeF window_size,
// An empty window size, while meaningless, is also relatively harmless, and
// will simply prevent any drawing of the layers.
if (window_size.IsEmpty()) {
- DisableLayer(edge_.get());
- DisableLayer(glow_.get());
+ edge_->Disable();
+ glow_->Disable();
return;
}
@@ -368,13 +388,26 @@ void EdgeEffect::ApplyToLayers(gfx::SizeF window_size,
const int scaled_glow_height = static_cast<int>(
std::min(glow_height * glow_scale_y_ * kGlowHeightToWidthRatio * 0.6f,
glow_height * kMaxGlowHeight) + 0.5f);
- UpdateLayer(
- glow_.get(), edge, window_size, offset, scaled_glow_height, glow_alpha_);
+ glow_->Update(edge, window_size, offset, scaled_glow_height, glow_alpha_);
// Edge
- const int scaled_edge_height = static_cast<int>(edge_height * edge_scale_y_);
- UpdateLayer(
- edge_.get(), edge, window_size, offset, scaled_edge_height, edge_alpha_);
+ const int scaled_edge_height = static_cast<int>(edge_height * edge_scale_y_);
+ edge_->Update(edge, window_size, offset, scaled_edge_height, edge_alpha_);
+}
+
+void EdgeEffect::SetParent(cc::Layer* parent) {
+ edge_->SetParent(parent);
+ glow_->SetParent(parent);
+}
+
+// static
+void EdgeEffect::PreloadResources(
+ ui::SystemUIResourceManager* resource_manager) {
+ DCHECK(resource_manager);
+ resource_manager->PreloadResource(
+ ui::SystemUIResourceManager::OVERSCROLL_EDGE);
+ resource_manager->PreloadResource(
+ ui::SystemUIResourceManager::OVERSCROLL_GLOW);
}
} // namespace content
diff --git a/content/browser/android/edge_effect.h b/content/browser/android/edge_effect.h
index b8febba..a8f944c 100644
--- a/content/browser/android/edge_effect.h
+++ b/content/browser/android/edge_effect.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_ANDROID_EDGE_EFFECT_H_
#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "ui/gfx/size_f.h"
@@ -14,6 +14,10 @@ namespace cc {
class Layer;
}
+namespace ui {
+class SystemUIResourceManager;
+}
+
namespace content {
/* |EdgeEffect| mirrors its Android counterpart, EdgeEffect.java.
@@ -24,7 +28,7 @@ namespace content {
* All coordinates and dimensions are in device pixels.
*/
class EdgeEffect {
-public:
+ public:
enum Edge {
EDGE_TOP = 0,
EDGE_LEFT,
@@ -33,7 +37,7 @@ public:
EDGE_COUNT
};
- EdgeEffect(scoped_refptr<cc::Layer> edge, scoped_refptr<cc::Layer> glow);
+ explicit EdgeEffect(ui::SystemUIResourceManager* resource_manager);
~EdgeEffect();
void Pull(base::TimeTicks current_time, float delta_distance);
@@ -50,8 +54,11 @@ public:
float glow_height,
float offset);
-private:
+ void SetParent(cc::Layer* parent);
+
+ static void PreloadResources(ui::SystemUIResourceManager* resource_manager);
+ private:
enum State {
STATE_IDLE = 0,
STATE_PULL,
@@ -60,8 +67,9 @@ private:
STATE_PULL_DECAY
};
- scoped_refptr<cc::Layer> edge_;
- scoped_refptr<cc::Layer> glow_;
+ class EffectLayer;
+ scoped_ptr<EffectLayer> edge_;
+ scoped_ptr<EffectLayer> glow_;
float edge_alpha_;
float edge_scale_y_;
diff --git a/content/browser/android/overscroll_glow.cc b/content/browser/android/overscroll_glow.cc
index fb491f3..3f316d8 100644
--- a/content/browser/android/overscroll_glow.cc
+++ b/content/browser/android/overscroll_glow.cc
@@ -6,11 +6,8 @@
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
-#include "base/threading/worker_pool.h"
-#include "cc/layers/image_layer.h"
+#include "cc/layers/layer.h"
#include "content/browser/android/edge_effect.h"
-#include "skia/ext/image_operations.h"
-#include "ui/gfx/android/java_bitmap.h"
using std::max;
using std::min;
@@ -20,57 +17,9 @@ namespace content {
namespace {
const float kEpsilon = 1e-3f;
-const int kScaledEdgeHeight = 12;
-const int kScaledGlowHeight = 64;
const float kEdgeHeightAtMdpi = 12.f;
const float kGlowHeightAtMdpi = 128.f;
-SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) {
- base::android::ScopedJavaLocalRef<jobject> jobj =
- gfx::CreateJavaBitmapFromAndroidResource(name, size);
- if (jobj.is_null())
- return SkBitmap();
-
- SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj()));
- if (bitmap.isNull())
- return bitmap;
-
- return skia::ImageOperations::Resize(
- bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
-}
-
-class OverscrollResources {
- public:
- OverscrollResources() {
- TRACE_EVENT0("browser", "OverscrollResources::Create");
- edge_bitmap_ =
- CreateSkBitmapFromAndroidResource("android:drawable/overscroll_edge",
- gfx::Size(128, kScaledEdgeHeight));
- glow_bitmap_ =
- CreateSkBitmapFromAndroidResource("android:drawable/overscroll_glow",
- gfx::Size(128, kScaledGlowHeight));
- }
-
- const SkBitmap& edge_bitmap() const { return edge_bitmap_; }
- const SkBitmap& glow_bitmap() const { return glow_bitmap_; }
-
- private:
- SkBitmap edge_bitmap_;
- SkBitmap glow_bitmap_;
-
- DISALLOW_COPY_AND_ASSIGN(OverscrollResources);
-};
-
-// Leaky to allow access from a worker thread.
-base::LazyInstance<OverscrollResources>::Leaky g_overscroll_resources =
- LAZY_INSTANCE_INITIALIZER;
-
-scoped_refptr<cc::Layer> CreateImageLayer(const SkBitmap& bitmap) {
- scoped_refptr<cc::ImageLayer> layer = cc::ImageLayer::Create();
- layer->SetBitmap(bitmap);
- return layer;
-}
-
bool IsApproxZero(float value) {
return std::abs(value) < kEpsilon;
}
@@ -83,25 +32,18 @@ gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) {
return vector;
}
-// Force loading of any necessary resources. This function is thread-safe.
-void EnsureResources() {
- g_overscroll_resources.Get();
-}
-
-} // namespace
-
-scoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled) {
- // Don't block the main thread with effect resource loading during creation.
- // Effect instantiation is deferred until the effect overscrolls, in which
- // case the main thread may block until the resource has loaded.
- if (enabled && g_overscroll_resources == NULL)
- base::WorkerPool::PostTask(FROM_HERE, base::Bind(EnsureResources), true);
+} // namespace
- return make_scoped_ptr(new OverscrollGlow(enabled));
+scoped_ptr<OverscrollGlow> OverscrollGlow::Create(
+ ui::SystemUIResourceManager* resource_manager) {
+ return make_scoped_ptr(new OverscrollGlow(resource_manager));
}
-OverscrollGlow::OverscrollGlow(bool enabled)
- : enabled_(enabled), initialized_(false) {}
+OverscrollGlow::OverscrollGlow(ui::SystemUIResourceManager* resource_manager)
+ : enabled_(true), initialized_(false), resource_manager_(resource_manager) {
+ DCHECK(resource_manager_);
+ EdgeEffect::PreloadResources(resource_manager_);
+}
OverscrollGlow::~OverscrollGlow() {
Detach();
@@ -222,6 +164,9 @@ void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) {
if (root_layer_->parent() != parent)
parent->AddChild(root_layer_);
+
+ for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i)
+ edge_effects_[i]->SetParent(root_layer_);
}
void OverscrollGlow::Detach() {
@@ -234,22 +179,10 @@ bool OverscrollGlow::InitializeIfNecessary() {
if (initialized_)
return true;
- const SkBitmap& edge = g_overscroll_resources.Get().edge_bitmap();
- const SkBitmap& glow = g_overscroll_resources.Get().glow_bitmap();
- if (edge.isNull() || glow.isNull()) {
- Disable();
- return false;
- }
-
DCHECK(!root_layer_);
root_layer_ = cc::Layer::Create();
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
- scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge);
- scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow);
- root_layer_->AddChild(edge_layer);
- root_layer_->AddChild(glow_layer);
- edge_effects_[i] = make_scoped_ptr(new EdgeEffect(edge_layer, glow_layer));
- }
+ for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i)
+ edge_effects_[i] = make_scoped_ptr(new EdgeEffect(resource_manager_));
initialized_ = true;
return true;
diff --git a/content/browser/android/overscroll_glow.h b/content/browser/android/overscroll_glow.h
index 0a555d4..7500940 100644
--- a/content/browser/android/overscroll_glow.h
+++ b/content/browser/android/overscroll_glow.h
@@ -14,8 +14,8 @@
class SkBitmap;
-namespace cc {
-class Layer;
+namespace ui {
+class SystemUIResourceManager;
}
namespace content {
@@ -26,11 +26,11 @@ namespace content {
*/
class OverscrollGlow {
public:
- // Create a new effect. If |enabled| is false, the effect will remain
- // deactivated until explicitly enabled.
- // Note: No resources will be allocated until the effect is both
- // enabled and an overscroll event has occurred.
- static scoped_ptr<OverscrollGlow> Create(bool enabled);
+ // Create a new effect. |resource_manager| provides the resource for the
+ // effect. |resource_manager| must outlive the effect. The effect is
+ // activated by default.
+ static scoped_ptr<OverscrollGlow> Create(
+ ui::SystemUIResourceManager* resource_manager);
~OverscrollGlow();
@@ -70,7 +70,7 @@ class OverscrollGlow {
private:
enum Axis { AXIS_X, AXIS_Y };
- OverscrollGlow(bool enabled);
+ explicit OverscrollGlow(ui::SystemUIResourceManager* resource_manager);
// Returns whether the effect is initialized.
bool InitializeIfNecessary();
@@ -94,6 +94,7 @@ class OverscrollGlow {
bool initialized_;
scoped_refptr<cc::Layer> root_layer_;
+ ui::SystemUIResourceManager* resource_manager_;
DISALLOW_COPY_AND_ASSIGN(OverscrollGlow);
};
diff --git a/content/browser/android/system_ui_resource_manager_impl.cc b/content/browser/android/system_ui_resource_manager_impl.cc
new file mode 100644
index 0000000..6da221b
--- /dev/null
+++ b/content/browser/android/system_ui_resource_manager_impl.cc
@@ -0,0 +1,137 @@
+// Copyright 2014 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 "content/browser/android/system_ui_resource_manager_impl.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/observer_list.h"
+#include "base/threading/worker_pool.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "content/public/browser/android/ui_resource_client_android.h"
+#include "content/public/browser/android/ui_resource_provider.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/android/java_bitmap.h"
+
+namespace content {
+
+class SystemUIResourceManagerImpl::Entry
+ : public content::UIResourceClientAndroid {
+ public:
+ explicit Entry(UIResourceProvider* provider) : id_(0), provider_(provider) {
+ DCHECK(provider);
+ }
+
+ virtual ~Entry() {
+ if (id_)
+ provider_->DeleteUIResource(id_);
+ id_ = 0;
+ }
+
+ void SetBitmap(const SkBitmap& bitmap) {
+ DCHECK(bitmap_.empty());
+ DCHECK(!bitmap.empty());
+ DCHECK(!id_);
+ bitmap_ = bitmap;
+ }
+
+ cc::UIResourceId GetUIResourceId() {
+ if (bitmap_.empty())
+ return 0;
+ if (!id_)
+ id_ = provider_->CreateUIResource(this);
+ return id_;
+ }
+
+ // content::UIResourceClient implementation.
+ virtual cc::UIResourceBitmap GetBitmap(cc::UIResourceId uid,
+ bool resource_lost) OVERRIDE {
+ DCHECK(!bitmap_.empty());
+ return cc::UIResourceBitmap(bitmap_);
+ }
+
+ // content::UIResourceClientAndroid implementation.
+ virtual void UIResourceIsInvalid() OVERRIDE { id_ = 0; }
+
+ const SkBitmap& bitmap() const { return bitmap_; }
+
+ private:
+ SkBitmap bitmap_;
+ cc::UIResourceId id_;
+ UIResourceProvider* provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(Entry);
+};
+
+SystemUIResourceManagerImpl::SystemUIResourceManagerImpl(
+ UIResourceProvider* ui_resource_provider)
+ : ui_resource_provider_(ui_resource_provider), weak_factory_(this) {
+}
+
+SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() {
+}
+
+void SystemUIResourceManagerImpl::PreloadResource(ResourceType type) {
+ GetEntry(type);
+}
+
+cc::UIResourceId SystemUIResourceManagerImpl::GetUIResourceId(
+ ResourceType type) {
+ return GetEntry(type)->GetUIResourceId();
+}
+
+SystemUIResourceManagerImpl::Entry* SystemUIResourceManagerImpl::GetEntry(
+ ResourceType type) {
+ DCHECK_GE(type, RESOURCE_TYPE_FIRST);
+ DCHECK_LE(type, RESOURCE_TYPE_LAST);
+ if (!resource_map_[type]) {
+ resource_map_[type].reset(new Entry(ui_resource_provider_));
+ // Lazily build the resource.
+ BuildResource(type);
+ }
+ return resource_map_[type].get();
+}
+
+void SystemUIResourceManagerImpl::BuildResource(ResourceType type) {
+ DCHECK(GetEntry(type)->bitmap().empty());
+
+ // Instead of blocking the main thread, we post a task to load the bitmap.
+ SkBitmap* bitmap = new SkBitmap();
+ base::Closure load_bitmap =
+ base::Bind(&SystemUIResourceManagerImpl::LoadBitmap, type, bitmap);
+ base::Closure finished_load =
+ base::Bind(&SystemUIResourceManagerImpl::OnFinishedLoadBitmap,
+ weak_factory_.GetWeakPtr(),
+ type,
+ base::Owned(bitmap));
+ base::WorkerPool::PostTaskAndReply(
+ FROM_HERE, load_bitmap, finished_load, true);
+}
+
+void SystemUIResourceManagerImpl::LoadBitmap(ResourceType type,
+ SkBitmap* bitmap_holder) {
+ SkBitmap bitmap;
+ switch (type) {
+ case ui::SystemUIResourceManager::OVERSCROLL_EDGE:
+ bitmap = gfx::CreateSkBitmapFromAndroidResource(
+ "android:drawable/overscroll_edge", gfx::Size(128, 12));
+ break;
+ case ui::SystemUIResourceManager::OVERSCROLL_GLOW:
+ bitmap = gfx::CreateSkBitmapFromAndroidResource(
+ "android:drawable/overscroll_glow", gfx::Size(128, 64));
+ break;
+ }
+ bitmap.setImmutable();
+ *bitmap_holder = bitmap;
+}
+
+void SystemUIResourceManagerImpl::OnFinishedLoadBitmap(
+ ResourceType type,
+ SkBitmap* bitmap_holder) {
+ DCHECK(bitmap_holder);
+ GetEntry(type)->SetBitmap(*bitmap_holder);
+}
+
+} // namespace content
diff --git a/content/browser/android/system_ui_resource_manager_impl.h b/content/browser/android/system_ui_resource_manager_impl.h
new file mode 100644
index 0000000..c5792a1
--- /dev/null
+++ b/content/browser/android/system_ui_resource_manager_impl.h
@@ -0,0 +1,55 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "ui/base/android/system_ui_resource_manager.h"
+
+class SkBitmap;
+
+namespace cc {
+class UIResourceBitmap;
+}
+
+namespace content {
+
+class UIResourceProvider;
+
+class CONTENT_EXPORT SystemUIResourceManagerImpl
+ : public ui::SystemUIResourceManager {
+ public:
+ explicit SystemUIResourceManagerImpl(
+ UIResourceProvider* ui_resource_provider);
+ virtual ~SystemUIResourceManagerImpl();
+
+ virtual void PreloadResource(ResourceType type) OVERRIDE;
+ virtual cc::UIResourceId GetUIResourceId(ResourceType type) OVERRIDE;
+
+ private:
+ friend class TestSystemUIResourceManagerImpl;
+ class Entry;
+
+ // Start loading the resource bitmap. virtual for testing.
+ virtual void BuildResource(ResourceType type);
+
+ Entry* GetEntry(ResourceType type);
+ static void LoadBitmap(ResourceType, SkBitmap* bitmap_holder);
+ void OnFinishedLoadBitmap(ResourceType, SkBitmap* bitmap_holder);
+
+ scoped_ptr<Entry> resource_map_[RESOURCE_TYPE_LAST + 1];
+ UIResourceProvider* ui_resource_provider_;
+
+ base::WeakPtrFactory<SystemUIResourceManagerImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemUIResourceManagerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_IMPL_H_
diff --git a/content/browser/android/system_ui_resource_manager_impl_unittest.cc b/content/browser/android/system_ui_resource_manager_impl_unittest.cc
new file mode 100644
index 0000000..95a7e9b
--- /dev/null
+++ b/content/browser/android/system_ui_resource_manager_impl_unittest.cc
@@ -0,0 +1,167 @@
+// Copyright 2014 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 "content/browser/android/system_ui_resource_manager_impl.h"
+#include "content/public/browser/android/ui_resource_client_android.h"
+#include "content/public/browser/android/ui_resource_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+
+namespace content {
+
+class TestSystemUIResourceManagerImpl
+ : public content::SystemUIResourceManagerImpl {
+ public:
+ TestSystemUIResourceManagerImpl(content::UIResourceProvider* provider)
+ : SystemUIResourceManagerImpl(provider) {}
+
+ virtual ~TestSystemUIResourceManagerImpl() {}
+
+ virtual void BuildResource(
+ ui::SystemUIResourceManager::ResourceType type) OVERRIDE {}
+
+ void SetResourceAsLoaded(ui::SystemUIResourceManager::ResourceType type) {
+ SkBitmap small_bitmap;
+ SkCanvas canvas(small_bitmap);
+ small_bitmap.allocPixels(
+ SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
+ canvas.drawColor(SK_ColorWHITE);
+ small_bitmap.setImmutable();
+ OnFinishedLoadBitmap(type, &small_bitmap);
+ }
+};
+
+namespace {
+
+const ui::SystemUIResourceManager::ResourceType TEST_RESOURCE_TYPE =
+ ui::SystemUIResourceManager::OVERSCROLL_GLOW;
+
+class MockUIResourceProvider : public content::UIResourceProvider {
+ public:
+ MockUIResourceProvider()
+ : next_ui_resource_id_(1),
+ has_layer_tree_host_(true),
+ system_ui_resource_manager_(this) {}
+
+ virtual ~MockUIResourceProvider() {}
+
+ virtual cc::UIResourceId CreateUIResource(
+ content::UIResourceClientAndroid* client) OVERRIDE {
+ if (!has_layer_tree_host_)
+ return 0;
+ cc::UIResourceId id = next_ui_resource_id_++;
+ client->GetBitmap(id, false);
+ ui_resource_client_map_[id] = client;
+ return id;
+ }
+
+ virtual void DeleteUIResource(cc::UIResourceId id) OVERRIDE {
+ CHECK(has_layer_tree_host_);
+ ui_resource_client_map_.erase(id);
+ }
+
+ void LayerTreeHostCleared() {
+ has_layer_tree_host_ = false;
+ UIResourceClientMap client_map = ui_resource_client_map_;
+ ui_resource_client_map_.clear();
+ for (UIResourceClientMap::iterator iter = client_map.begin();
+ iter != client_map.end();
+ iter++) {
+ iter->second->UIResourceIsInvalid();
+ }
+ }
+
+ void LayerTreeHostReturned() { has_layer_tree_host_ = true; }
+
+ TestSystemUIResourceManagerImpl& GetSystemUIResourceManager() {
+ return system_ui_resource_manager_;
+ }
+
+ cc::UIResourceId next_ui_resource_id() const { return next_ui_resource_id_; }
+
+ private:
+ typedef base::hash_map<cc::UIResourceId, content::UIResourceClientAndroid*>
+ UIResourceClientMap;
+
+ cc::UIResourceId next_ui_resource_id_;
+ UIResourceClientMap ui_resource_client_map_;
+ bool has_layer_tree_host_;
+
+ // The UIResourceProvider owns the SystemUIResourceManager.
+ TestSystemUIResourceManagerImpl system_ui_resource_manager_;
+};
+
+} // namespace
+
+class SystemUIResourceManagerImplTest : public testing::Test {
+ public:
+ void PreloadResource(ui::SystemUIResourceManager::ResourceType type) {
+ ui_resource_provider_.GetSystemUIResourceManager().PreloadResource(type);
+ }
+
+ cc::UIResourceId GetUIResourceId(
+ ui::SystemUIResourceManager::ResourceType type) {
+ return ui_resource_provider_.GetSystemUIResourceManager().GetUIResourceId(
+ type);
+ }
+
+ void LayerTreeHostCleared() { ui_resource_provider_.LayerTreeHostCleared(); }
+
+ void LayerTreeHostReturned() {
+ ui_resource_provider_.LayerTreeHostReturned();
+ }
+
+ void SetResourceAsLoaded(ui::SystemUIResourceManager::ResourceType type) {
+ ui_resource_provider_.GetSystemUIResourceManager().SetResourceAsLoaded(
+ type);
+ }
+
+ cc::UIResourceId GetNextUIResourceId() const {
+ return ui_resource_provider_.next_ui_resource_id();
+ }
+
+ private:
+ MockUIResourceProvider ui_resource_provider_;
+};
+
+TEST_F(SystemUIResourceManagerImplTest, GetResourceAfterBitmapLoaded) {
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+}
+
+TEST_F(SystemUIResourceManagerImplTest, GetResourceBeforeLoadBitmap) {
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+}
+
+TEST_F(SystemUIResourceManagerImplTest, PreloadEnsureResource) {
+ // Preloading the resource should trigger bitmap loading, but the actual
+ // resource id will not be generated until it is explicitly requested.
+ cc::UIResourceId first_resource_id = GetNextUIResourceId();
+ PreloadResource(TEST_RESOURCE_TYPE);
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_EQ(first_resource_id, GetNextUIResourceId());
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ EXPECT_NE(first_resource_id, GetNextUIResourceId());
+}
+
+TEST_F(SystemUIResourceManagerImplTest, ResetLayerTreeHost) {
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostCleared();
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostReturned();
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostCleared();
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostReturned();
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+}
+
+} // namespace content
diff --git a/content/browser/android/ui_resource_provider_impl.cc b/content/browser/android/ui_resource_provider_impl.cc
index f97975c..d26d42f 100644
--- a/content/browser/android/ui_resource_provider_impl.cc
+++ b/content/browser/android/ui_resource_provider_impl.cc
@@ -10,7 +10,8 @@
namespace content {
-UIResourceProviderImpl::UIResourceProviderImpl() : host_(NULL) {
+UIResourceProviderImpl::UIResourceProviderImpl()
+ : system_ui_resource_manager_(this), host_(NULL) {
}
UIResourceProviderImpl::~UIResourceProviderImpl() {
@@ -57,4 +58,9 @@ void UIResourceProviderImpl::DeleteUIResource(cc::UIResourceId ui_resource_id) {
host_->DeleteUIResource(ui_resource_id);
}
+ui::SystemUIResourceManager&
+UIResourceProviderImpl::GetSystemUIResourceManager() {
+ return system_ui_resource_manager_;
+}
+
} // namespace content
diff --git a/content/browser/android/ui_resource_provider_impl.h b/content/browser/android/ui_resource_provider_impl.h
index 79c2301..57c9ab8 100644
--- a/content/browser/android/ui_resource_provider_impl.h
+++ b/content/browser/android/ui_resource_provider_impl.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_ANDROID_UI_RESOURCE_PROVIDER_IMPL_H_
#include "base/containers/hash_tables.h"
+#include "content/browser/android/system_ui_resource_manager_impl.h"
#include "content/public/browser/android/ui_resource_provider.h"
namespace cc {
@@ -31,11 +32,13 @@ class UIResourceProviderImpl : public UIResourceProvider {
virtual void DeleteUIResource(cc::UIResourceId resource_id) OVERRIDE;
+ ui::SystemUIResourceManager& GetSystemUIResourceManager();
+
private:
typedef base::hash_map<cc::UIResourceId, UIResourceClientAndroid*>
UIResourceClientMap;
UIResourceClientMap ui_resource_client_map_;
-
+ SystemUIResourceManagerImpl system_ui_resource_manager_;
cc::LayerTreeHost* host_;
DISALLOW_COPY_AND_ASSIGN(UIResourceProviderImpl);
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 70ebbfe..d704f28 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -340,6 +340,10 @@ UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
return ui_resource_provider_;
}
+ui::SystemUIResourceManager& CompositorImpl::GetSystemUIResourceManager() {
+ return ui_resource_provider_.GetSystemUIResourceManager();
+}
+
void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
if (subroot_layer_) {
subroot_layer_->RemoveFromParent();
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 4792d90..9b75bd9 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -8,10 +8,8 @@
#include "base/basictypes.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "cc/resources/ui_resource_client.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "content/browser/android/ui_resource_provider_impl.h"
@@ -19,6 +17,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/android/compositor.h"
#include "third_party/khronos/GLES2/gl2.h"
+#include "ui/base/android/system_ui_resource_manager.h"
#include "ui/base/android/window_android_compositor.h"
class SkBitmap;
@@ -98,6 +97,7 @@ class CONTENT_EXPORT CompositorImpl
virtual void OnVSync(base::TimeTicks frame_time,
base::TimeDelta vsync_period) OVERRIDE;
virtual void SetNeedsAnimate() OVERRIDE;
+ virtual ui::SystemUIResourceManager& GetSystemUIResourceManager() OVERRIDE;
enum CompositingTrigger {
DO_NOT_COMPOSITE,
@@ -127,9 +127,6 @@ class CONTENT_EXPORT CompositorImpl
composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
will_composite_immediately_ = false;
}
- cc::UIResourceId GenerateUIResourceFromUIResourceBitmap(
- const cc::UIResourceBitmap& bitmap,
- bool is_transient);
void OnGpuChannelEstablished();
// root_layer_ is the persistent internal root layer, while subroot_layer_
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index e43f452..c52e845 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -192,7 +192,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
weak_ptr_factory_(this),
overscroll_effect_enabled_(!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableOverscrollEdgeEffect)),
- overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)),
gesture_provider_(CreateGestureProviderConfig(), this),
gesture_text_selector_(this),
touch_scrolling_(false),
@@ -368,7 +367,7 @@ void RenderWidgetHostViewAndroid::MovePluginWindows(
void RenderWidgetHostViewAndroid::Focus() {
host_->Focus();
host_->SetInputMethodActive(true);
- if (overscroll_effect_enabled_)
+ if (overscroll_effect_)
overscroll_effect_->Enable();
}
@@ -376,7 +375,8 @@ void RenderWidgetHostViewAndroid::Blur() {
host_->ExecuteEditCommand("Unselect", "");
host_->SetInputMethodActive(false);
host_->Blur();
- overscroll_effect_->Disable();
+ if (overscroll_effect_)
+ overscroll_effect_->Disable();
}
bool RenderWidgetHostViewAndroid::HasFocus() const {
@@ -929,8 +929,10 @@ void RenderWidgetHostViewAndroid::ComputeContentsSize(
gfx::Size(texture_size_in_layer_.width() - offset.x(),
texture_size_in_layer_.height() - offset.y());
- overscroll_effect_->UpdateDisplayParameters(
- CreateOverscrollDisplayParameters(frame_metadata));
+ if (overscroll_effect_) {
+ overscroll_effect_->UpdateDisplayParameters(
+ CreateOverscrollDisplayParameters(frame_metadata));
+ }
}
void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
@@ -1143,7 +1145,7 @@ void RenderWidgetHostViewAndroid::AttachLayers() {
return;
content_view_core_->AttachLayer(layer_);
- if (overscroll_effect_enabled_)
+ if (overscroll_effect_)
overscroll_effect_->Enable();
layer_->SetHideLayerAndSubtree(!is_showing_);
}
@@ -1156,11 +1158,13 @@ void RenderWidgetHostViewAndroid::RemoveLayers() {
return;
content_view_core_->RemoveLayer(layer_);
- overscroll_effect_->Disable();
+ if (overscroll_effect_)
+ overscroll_effect_->Disable();
}
bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
- bool needs_animate = overscroll_effect_->Animate(frame_time);
+ bool needs_animate =
+ overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
if (selection_controller_)
needs_animate |= selection_controller_->Animate(frame_time);
return needs_animate;
@@ -1361,8 +1365,8 @@ void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
void RenderWidgetHostViewAndroid::SendGestureEvent(
const blink::WebGestureEvent& event) {
// Sending a gesture that may trigger overscroll should resume the effect.
- if (overscroll_effect_enabled_)
- overscroll_effect_->Enable();
+ if (overscroll_effect_)
+ overscroll_effect_->Enable();
if (host_)
host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
@@ -1408,7 +1412,9 @@ void RenderWidgetHostViewAndroid::DidOverscroll(
return;
const float device_scale_factor = content_view_core_->GetDpiScale();
- if (overscroll_effect_->OnOverscrolled(
+
+ if (overscroll_effect_ &&
+ overscroll_effect_->OnOverscrolled(
content_view_core_->GetLayer(),
base::TimeTicks::Now(),
gfx::ScaleVector2d(params.accumulated_overscroll,
@@ -1475,6 +1481,16 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
if (!selection_controller_)
selection_controller_.reset(new TouchSelectionController(this));
+
+ if (!content_view_core_) {
+ overscroll_effect_.reset();
+ } else if (overscroll_effect_enabled_ && !overscroll_effect_) {
+ DCHECK(content_view_core_->GetWindowAndroid()->GetCompositor());
+ overscroll_effect_ =
+ OverscrollGlow::Create(&content_view_core_->GetWindowAndroid()
+ ->GetCompositor()
+ ->GetSystemUIResourceManager());
+ }
}
void RenderWidgetHostViewAndroid::RunAckCallbacks() {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index e52652a..91f9d48 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -355,7 +355,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const bool overscroll_effect_enabled_;
// Used to render overscroll overlays.
- // Note: |overscroll_effect_| will never be NULL, even if it's never enabled.
scoped_ptr<OverscrollGlow> overscroll_effect_;
// Provides gesture synthesis given a stream of touch events (derived from
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index bd2476f..46b7ca7 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -313,6 +313,8 @@
'browser/android/popup_touch_handle_drawable.h',
'browser/android/surface_texture_peer_browser_impl.cc',
'browser/android/surface_texture_peer_browser_impl.h',
+ 'browser/android/system_ui_resource_manager_impl.cc',
+ 'browser/android/system_ui_resource_manager_impl.h',
'browser/android/tracing_controller_android.cc',
'browser/android/tracing_controller_android.h',
'browser/android/web_contents_observer_android.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index b15c5d7..f7a3c38 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -901,6 +901,7 @@
'browser/android/java/gin_java_method_invocation_helper_unittest.cc',
'browser/android/java/java_type_unittest.cc',
'browser/android/java/jni_helper_unittest.cc',
+ 'browser/android/system_ui_resource_manager_impl_unittest.cc',
'renderer/java/gin_java_bridge_value_converter_unittest.cc',
],
'sources!': [
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index ddadf1b..76dcaa4 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -21,6 +21,7 @@ component("base") {
"accelerators/platform_accelerator.h",
"accelerators/platform_accelerator_cocoa.h",
"accelerators/platform_accelerator_cocoa.mm",
+ "android/system_ui_resource_manager.h",
"android/ui_base_jni_registrar.cc",
"android/ui_base_jni_registrar.h",
"android/view_android.cc",
diff --git a/ui/base/android/system_ui_resource_manager.h b/ui/base/android/system_ui_resource_manager.h
new file mode 100644
index 0000000..03a112d
--- /dev/null
+++ b/ui/base/android/system_ui_resource_manager.h
@@ -0,0 +1,41 @@
+// Copyright 2014 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 UI_BASE_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_H_
+#define UI_BASE_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_H_
+
+#include "cc/resources/ui_resource_client.h"
+#include "ui/base/ui_base_export.h"
+
+namespace ui {
+
+// Interface for loading and accessing shared system UI resources.
+class UI_BASE_EXPORT SystemUIResourceManager {
+ public:
+ enum ResourceType {
+ OVERSCROLL_EDGE = 0,
+ OVERSCROLL_GLOW,
+ RESOURCE_TYPE_FIRST = OVERSCROLL_EDGE,
+ RESOURCE_TYPE_LAST = OVERSCROLL_GLOW
+ };
+
+ virtual ~SystemUIResourceManager() {}
+
+ // Optionally trigger bitmap loading for a given |resource|, if necessary.
+ // Note that this operation may be asynchronous, and subsequent queries to
+ // |GetUIResourceId()| will yield a valid result only after loading finishes.
+ // This method is particularly useful for idly loading a resource before an
+ // explicit cc::UIResourceId is required. Repeated calls will be ignored.
+ virtual void PreloadResource(ResourceType resource) = 0;
+
+ // Return the resource id associated with |resource|. If loading hasn't yet
+ // begun for the given |resource|, it will be triggered immediately. If
+ // loading is asynchronous, 0 will be returned until loading has finished, and
+ // the caller is responsible for re-querying until a valid id is returned.
+ virtual cc::UIResourceId GetUIResourceId(ResourceType resource) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_H_
diff --git a/ui/base/android/window_android_compositor.h b/ui/base/android/window_android_compositor.h
index eb55a7b..eee3357 100644
--- a/ui/base/android/window_android_compositor.h
+++ b/ui/base/android/window_android_compositor.h
@@ -6,6 +6,7 @@
#define UI_BASE_ANDROID_WINDOW_ANDROID_COMPOSITOR_H_
#include "cc/output/copy_output_request.h"
+#include "ui/base/android/system_ui_resource_manager.h"
#include "ui/base/ui_base_export.h"
namespace cc {
@@ -25,6 +26,7 @@ class UI_BASE_EXPORT WindowAndroidCompositor {
virtual void OnVSync(base::TimeTicks frame_time,
base::TimeDelta vsync_period) = 0;
virtual void SetNeedsAnimate() = 0;
+ virtual SystemUIResourceManager& GetSystemUIResourceManager() = 0;
};
} // namespace ui
diff --git a/ui/base/ui_base.gyp b/ui/base/ui_base.gyp
index 6e6a316..887e8e4 100644
--- a/ui/base/ui_base.gyp
+++ b/ui/base/ui_base.gyp
@@ -47,6 +47,7 @@
'accelerators/platform_accelerator.h',
'accelerators/platform_accelerator_cocoa.h',
'accelerators/platform_accelerator_cocoa.mm',
+ 'android/system_ui_resource_manager.h',
'android/ui_base_jni_registrar.cc',
'android/ui_base_jni_registrar.h',
'android/view_android.cc',
diff --git a/ui/gfx/android/java_bitmap.cc b/ui/gfx/android/java_bitmap.cc
index 5988befe..d1f644f 100644
--- a/ui/gfx/android/java_bitmap.cc
+++ b/ui/gfx/android/java_bitmap.cc
@@ -9,6 +9,7 @@
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "jni/BitmapHelper_jni.h"
+#include "skia/ext/image_operations.h"
#include "ui/gfx/size.h"
using base::android::AttachCurrentThread;
@@ -68,17 +69,6 @@ ScopedJavaLocalRef<jobject> CreateJavaBitmap(int width,
AttachCurrentThread(), width, height, java_bitmap_config);
}
-ScopedJavaLocalRef<jobject> CreateJavaBitmapFromAndroidResource(
- const char* name,
- gfx::Size size) {
- DCHECK(name);
- DCHECK(!size.IsEmpty());
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> jname(ConvertUTF8ToJavaString(env, name));
- return Java_BitmapHelper_decodeDrawableResource(
- env, jname.obj(), size.width(), size.height());
-}
-
ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(const SkBitmap* skbitmap) {
DCHECK(skbitmap);
DCHECK(!skbitmap->isNull());
@@ -96,6 +86,26 @@ ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(const SkBitmap* skbitmap) {
return jbitmap;
}
+SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) {
+ DCHECK(name);
+ DCHECK(!size.IsEmpty());
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jname(ConvertUTF8ToJavaString(env, name));
+ base::android::ScopedJavaLocalRef<jobject> jobj =
+ Java_BitmapHelper_decodeDrawableResource(
+ env, jname.obj(), size.width(), size.height());
+
+ if (jobj.is_null())
+ return SkBitmap();
+
+ SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj()));
+ if (bitmap.isNull())
+ return bitmap;
+
+ return skia::ImageOperations::Resize(
+ bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
+}
+
SkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap) {
// TODO(jdduke): Convert to DCHECK's when sufficient data has been capture for
// crbug.com/341406.
diff --git a/ui/gfx/android/java_bitmap.h b/ui/gfx/android/java_bitmap.h
index befb09b..34cd26a 100644
--- a/ui/gfx/android/java_bitmap.h
+++ b/ui/gfx/android/java_bitmap.h
@@ -57,12 +57,12 @@ GFX_EXPORT base::android::ScopedJavaLocalRef<jobject> CreateJavaBitmap(
int height,
SkColorType color_type);
-// Loads a Java-backed bitmap (android.graphics.Bitmap) from the provided
-// drawable resource identifier (e.g., android:drawable/overscroll_glow). If the
-// resource loads successfully, it will be integrally scaled down, preserving
-// aspect ratio, to a size no smaller than |size|. Otherwise, null is returned.
-GFX_EXPORT base::android::ScopedJavaLocalRef<jobject>
- CreateJavaBitmapFromAndroidResource(const char* name, gfx::Size size);
+// Loads an SkBitmap from the provided drawable resource identifier (e.g.,
+// android:drawable/overscroll_glow). If the resource loads successfully, it
+// will be integrally scaled down, preserving aspect ratio, to a size no smaller
+// than |size|. Otherwise, an empty bitmap is returned.
+GFX_EXPORT SkBitmap
+ CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size);
// Converts |skbitmap| to a Java-backed bitmap (android.graphics.Bitmap).
// Note: |skbitmap| is assumed to be non-null, non-empty and one of RGBA_8888 or