Commit c8d99c55 authored by jdduke@chromium.org's avatar jdduke@chromium.org

[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

Review URL: https://codereview.chromium.org/422013003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288095 0039d316-1c4b-4281-b951-d872f2087c98
parent fad702ab
......@@ -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
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 UpdateLayer(cc::Layer* layer,
EdgeEffect::Edge edge,
void Disable() { ui_resource_layer_->SetIsDrawable(false); }
void Update(EdgeEffect::Edge edge,
const gfx::SizeF& window_size,
int offset,
int height,
float opacity) {
DCHECK(layer);
layer->SetIsDrawable(true);
ui_resource_layer_->SetUIResourceId(
resource_manager_->GetUIResourceId(resource_type_));
ui_resource_layer_->SetIsDrawable(true);
gfx::Size bounds = ComputeBounds(edge, window_size, height);
layer->SetTransformOrigin(
ui_resource_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));
}
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
scoped_refptr<cc::UIResourceLayer> ui_resource_layer_;
ui::SystemUIResourceManager::ResourceType resource_type_;
ui::SystemUIResourceManager* resource_manager_;
DISALLOW_COPY_AND_ASSIGN(EffectLayer);
};
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());
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_);
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
......@@ -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_;
......
......@@ -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);
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;
......
......@@ -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);
};
......
// 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
// 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_
// 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
......@@ -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
......@@ -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);
......
......@@ -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();
......
......@@ -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_
......
......@@ -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,6 +375,7 @@ void RenderWidgetHostViewAndroid::Blur() {
host_->ExecuteEditCommand("Unselect", "");
host_->SetInputMethodActive(false);
host_->Blur();
if (overscroll_effect_)
overscroll_effect_->Disable();
}
......@@ -929,8 +929,10 @@ void RenderWidgetHostViewAndroid::ComputeContentsSize(
gfx::Size(texture_size_in_layer_.width() - offset.x(),
texture_size_in_layer_.height() - offset.y());
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_);
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,7 +1365,7 @@ 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_)
if (overscroll_effect_)
overscroll_effect_->Enable();
if (host_)
......@@ -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() {
......
......@@ -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
......
......@@ -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',
......
......@@ -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!': [
......
......@@ -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",
......
// 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_
......@@ -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
......
......@@ -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',
......
......@@ -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.
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment