blob: 8a68bf76fa20e2ff37806ff39bcf875223834773 [file] [log] [blame]
// 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 "ui/android/resources/resource_manager_impl.h"
#include <stddef.h>
#include <utility>
#include <vector>
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/trace_event/trace_event.h"
#include "cc/resources/scoped_ui_resource.h"
#include "jni/ResourceManager_jni.h"
#include "ui/android/resources/ui_resource_provider.h"
#include "ui/android/window_android.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/geometry/rect.h"
using base::android::JavaArrayOfIntArrayToIntVector;
using base::android::JavaRef;
namespace ui {
// static
ResourceManagerImpl* ResourceManagerImpl::FromJavaObject(jobject jobj) {
return reinterpret_cast<ResourceManagerImpl*>(
Java_ResourceManager_getNativePtr(base::android::AttachCurrentThread(),
jobj));
}
ResourceManagerImpl::ResourceManagerImpl(gfx::NativeWindow native_window)
: host_(nullptr) {
JNIEnv* env = base::android::AttachCurrentThread();
java_obj_.Reset(env, Java_ResourceManager_create(
env, native_window->GetJavaObject().obj(),
reinterpret_cast<intptr_t>(this))
.obj());
DCHECK(!java_obj_.is_null());
}
ResourceManagerImpl::~ResourceManagerImpl() {
Java_ResourceManager_destroy(base::android::AttachCurrentThread(),
java_obj_.obj());
}
void ResourceManagerImpl::Init(cc::LayerTreeHost* host) {
DCHECK(!host_);
DCHECK(host);
host_ = host;
}
base::android::ScopedJavaLocalRef<jobject>
ResourceManagerImpl::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
}
ResourceManager::Resource* ResourceManagerImpl::GetResource(
AndroidResourceType res_type,
int res_id) {
DCHECK_GE(res_type, ANDROID_RESOURCE_TYPE_FIRST);
DCHECK_LE(res_type, ANDROID_RESOURCE_TYPE_LAST);
Resource* resource = resources_[res_type].Lookup(res_id);
if (!resource || res_type == ANDROID_RESOURCE_TYPE_DYNAMIC ||
res_type == ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP) {
RequestResourceFromJava(res_type, res_id);
resource = resources_[res_type].Lookup(res_id);
}
return resource;
}
void ResourceManagerImpl::PreloadResource(AndroidResourceType res_type,
int res_id) {
DCHECK_GE(res_type, ANDROID_RESOURCE_TYPE_FIRST);
DCHECK_LE(res_type, ANDROID_RESOURCE_TYPE_LAST);
// Don't send out a query if the resource is already loaded.
if (resources_[res_type].Lookup(res_id))
return;
PreloadResourceFromJava(res_type, res_id);
}
void ResourceManagerImpl::OnResourceReady(JNIEnv* env,
const JavaRef<jobject>& jobj,
jint res_type,
jint res_id,
const JavaRef<jobject>& bitmap,
jint padding_left,
jint padding_top,
jint padding_right,
jint padding_bottom,
jint aperture_left,
jint aperture_top,
jint aperture_right,
jint aperture_bottom) {
DCHECK_GE(res_type, ANDROID_RESOURCE_TYPE_FIRST);
DCHECK_LE(res_type, ANDROID_RESOURCE_TYPE_LAST);
TRACE_EVENT2("ui", "ResourceManagerImpl::OnResourceReady",
"resource_type", res_type,
"resource_id", res_id);
Resource* resource = resources_[res_type].Lookup(res_id);
if (!resource) {
resource = new Resource();
resources_[res_type].AddWithID(resource, res_id);
}
gfx::JavaBitmap jbitmap(bitmap.obj());
resource->size = jbitmap.size();
resource->padding.SetRect(padding_left, padding_top,
padding_right - padding_left,
padding_bottom - padding_top);
resource->aperture.SetRect(aperture_left, aperture_top,
aperture_right - aperture_left,
aperture_bottom - aperture_top);
SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(jbitmap);
skbitmap.setImmutable();
resource->ui_resource =
cc::ScopedUIResource::Create(host_, cc::UIResourceBitmap(skbitmap));
}
CrushedSpriteResource* ResourceManagerImpl::GetCrushedSpriteResource(
int bitmap_res_id, int metadata_res_id) {
CrushedSpriteResource* resource =
crushed_sprite_resources_.Lookup(bitmap_res_id);
if (!resource) {
RequestCrushedSpriteResourceFromJava(bitmap_res_id, metadata_res_id, false);
resource = crushed_sprite_resources_.Lookup(bitmap_res_id);
} else if (resource->BitmapHasBeenEvictedFromMemory()) {
RequestCrushedSpriteResourceFromJava(bitmap_res_id, metadata_res_id, true);
}
return resource;
}
void ResourceManagerImpl::OnCrushedSpriteResourceReady(
JNIEnv* env,
const JavaRef<jobject>& jobj,
jint bitmap_res_id,
const JavaRef<jobject>& bitmap,
const JavaRef<jobjectArray>& frame_rects,
jint unscaled_sprite_width,
jint unscaled_sprite_height,
jfloat scaled_sprite_width,
jfloat scaled_sprite_height) {
// Construct source and destination rectangles for each frame from
// |frame_rects|.
std::vector<std::vector<int>> all_frame_rects_vector;
JavaArrayOfIntArrayToIntVector(env, frame_rects.obj(),
&all_frame_rects_vector);
CrushedSpriteResource::SrcDstRects src_dst_rects =
ProcessCrushedSpriteFrameRects(all_frame_rects_vector);
SkBitmap skbitmap =
gfx::CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(bitmap.obj()));
CrushedSpriteResource* resource = new CrushedSpriteResource(
skbitmap,
src_dst_rects,
gfx::Size(unscaled_sprite_width, unscaled_sprite_height),
gfx::Size(scaled_sprite_width, scaled_sprite_height));
if (crushed_sprite_resources_.Lookup(bitmap_res_id)) {
crushed_sprite_resources_.Replace(bitmap_res_id, resource);
} else {
crushed_sprite_resources_.AddWithID(resource, bitmap_res_id);
}
}
CrushedSpriteResource::SrcDstRects
ResourceManagerImpl::ProcessCrushedSpriteFrameRects(
std::vector<std::vector<int>> frame_rects_vector) {
CrushedSpriteResource::SrcDstRects src_dst_rects;
for (size_t i = 0; i < frame_rects_vector.size(); ++i) {
std::vector<int> frame_ints = frame_rects_vector[i];
CrushedSpriteResource::FrameSrcDstRects frame_src_dst_rects;
// Create source and destination gfx::Rect's for each rectangle in
// |frame_ints|. Each rectangle consists of 6 values:
// i: destination x i+1: destination y i+2: source x i+3: source y
// i+4: width i+5: height
for (size_t j = 0; j < frame_ints.size(); j += 6) {
gfx::Rect sprite_rect_destination(frame_ints[j],
frame_ints[j+1],
frame_ints[j+4],
frame_ints[j+5]);
gfx::Rect sprite_rect_source(frame_ints[j+2],
frame_ints[j+3],
frame_ints[j+4],
frame_ints[j+5]);
frame_src_dst_rects.push_back(std::pair<gfx::Rect, gfx::Rect>(
sprite_rect_source, sprite_rect_destination));
}
src_dst_rects.push_back(frame_src_dst_rects);
}
return src_dst_rects;
}
void ResourceManagerImpl::OnCrushedSpriteResourceReloaded(
JNIEnv* env,
const JavaRef<jobject>& jobj,
jint bitmap_res_id,
const JavaRef<jobject>& bitmap) {
CrushedSpriteResource* resource =
crushed_sprite_resources_.Lookup(bitmap_res_id);
if (!resource) {
// Cannot reload a resource that has not been previously loaded.
return;
}
SkBitmap skbitmap =
gfx::CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(bitmap.obj()));
resource->SetBitmap(skbitmap);
}
// static
bool ResourceManagerImpl::RegisterResourceManager(JNIEnv* env) {
return RegisterNativesImpl(env);
}
void ResourceManagerImpl::PreloadResourceFromJava(AndroidResourceType res_type,
int res_id) {
TRACE_EVENT2("ui", "ResourceManagerImpl::PreloadResourceFromJava",
"resource_type", res_type,
"resource_id", res_id);
Java_ResourceManager_preloadResource(base::android::AttachCurrentThread(),
java_obj_.obj(), res_type, res_id);
}
void ResourceManagerImpl::RequestResourceFromJava(AndroidResourceType res_type,
int res_id) {
TRACE_EVENT2("ui", "ResourceManagerImpl::RequestResourceFromJava",
"resource_type", res_type,
"resource_id", res_id);
Java_ResourceManager_resourceRequested(base::android::AttachCurrentThread(),
java_obj_.obj(), res_type, res_id);
}
void ResourceManagerImpl::RequestCrushedSpriteResourceFromJava(
int bitmap_res_id, int metadata_res_id, bool reloading) {
TRACE_EVENT2("ui",
"ResourceManagerImpl::RequestCrushedSpriteResourceFromJava",
"bitmap_res_id", bitmap_res_id,
"metadata_res_id", metadata_res_id);
Java_ResourceManager_crushedSpriteResourceRequested(
base::android::AttachCurrentThread(), java_obj_.obj(),
bitmap_res_id, metadata_res_id, reloading);
}
} // namespace ui