PatchCache.cpp revision 3b748a44c6bd2ea05fe16839caf73dbe50bd7ae9
1f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/* 2f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * Copyright (C) 2010 The Android Open Source Project 3f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * 4f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * you may not use this file except in compliance with the License. 6f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * You may obtain a copy of the License at 7f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * 8f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * http://www.apache.org/licenses/LICENSE-2.0 9f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * 10f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * Unless required by applicable law or agreed to in writing, software 11f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * See the License for the specific language governing permissions and 14f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy * limitations under the License. 15f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy */ 16f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 17f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#define LOG_TAG "OpenGLRenderer" 18f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <utils/JenkinsHash.h> 20f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#include <utils/Log.h> 21f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "Caches.h" 23f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#include "PatchCache.h" 24fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h" 25f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 26f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guynamespace android { 27f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guynamespace uirenderer { 28f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 29f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 30f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy// Constructors/destructor 31f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 32f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain GuyPatchCache::PatchCache(): mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity) { 343b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy char property[PROPERTY_VALUE_MAX]; 353b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, NULL) > 0) { 363b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy INIT_LOGD(" Setting patch cache size to %skB", property); 373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mMaxSize = KB(atoi(property)); 383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } else { 393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy INIT_LOGD(" Using default patch cache size of %.2fkB", DEFAULT_PATCH_CACHE_SIZE); 403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mMaxSize = KB(DEFAULT_PATCH_CACHE_SIZE); 413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mSize = 0; 43f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 44f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 45f7f93556c8fcc640ab5adef79d021a80a72a645aRomain GuyPatchCache::~PatchCache() { 46f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy clear(); 47f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 48f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid PatchCache::init(Caches& caches) { 503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glGenBuffers(1, &mMeshBuffer); 513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy caches.bindMeshBuffer(mMeshBuffer); 523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy caches.resetVertexPointers(); 533b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW); 553b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 57f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 58f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy// Caching 59f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy/////////////////////////////////////////////////////////////////////////////// 60f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyhash_t PatchCache::PatchDescription::hash() const { 623b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch)); 633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mBitmapWidth); 643b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mBitmapHeight); 653b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mPixelWidth); 663b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy hash = JenkinsHashMix(hash, mPixelHeight); 673b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return JenkinsHashWhiten(hash); 683b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 6913ba0054846ce630ca31e8f26169fd9388faee02Romain Guy 703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyint PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs, 713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const PatchCache::PatchDescription& rhs) { 723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return memcmp(&lhs, &rhs, sizeof(PatchDescription)); 7313ba0054846ce630ca31e8f26169fd9388faee02Romain Guy} 7413ba0054846ce630ca31e8f26169fd9388faee02Romain Guy 75f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guyvoid PatchCache::clear() { 763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glDeleteBuffers(1, &mMeshBuffer); 773b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy clearCache(); 783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mSize = 0; 793b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 803b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 813b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid PatchCache::clearCache() { 823b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy LruCache<PatchDescription, Patch*>::Iterator i(mCache); 833b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy while (i.next()) { 843b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGD("Delete %p", i.value()); 853b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy delete i.value(); 862728f961614a385df1f056fc24803a9f65c90fabRomain Guy } 87f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy mCache.clear(); 88f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 89f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 903b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyconst Patch* PatchCache::get(const AssetAtlas::Entry* entry, 913b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const uint32_t bitmapWidth, const uint32_t bitmapHeight, 923b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) { 934bb942083a0d4db746adf95349108dd8ef842e32Romain Guy 943b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch); 953b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const Patch* mesh = mCache.get(description); 964bb942083a0d4db746adf95349108dd8ef842e32Romain Guy 973b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (!mesh) { 983b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy Patch* newMesh = new Patch(); 993b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy TextureVertex* vertices; 1003b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1013b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (entry) { 1023b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy vertices = newMesh->createMesh(bitmapWidth, bitmapHeight, 1033b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 0.0f, 0.0f, pixelWidth, pixelHeight, entry->uvMapper, patch); 1043b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } else { 1053b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy vertices = newMesh->createMesh(bitmapWidth, bitmapHeight, 1063b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 0.0f, 0.0f, pixelWidth, pixelHeight, patch); 1074bb942083a0d4db746adf95349108dd8ef842e32Romain Guy } 1082728f961614a385df1f056fc24803a9f65c90fabRomain Guy 1093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (vertices) { 1103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy Caches& caches = Caches::getInstance(); 1113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy caches.bindMeshBuffer(mMeshBuffer); 1123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy caches.resetVertexPointers(); 1133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1143b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // TODO: Simply remove the oldest items until we have enough room 1153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // This will require to keep a list of free blocks in the VBO 1163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy uint32_t size = newMesh->getSize(); 1173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (mSize + size > mMaxSize) { 1183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy clearCache(); 1193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW); 1203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mSize = 0; 1213b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 122054dc1840941665e32036f9523df51720ad069c8Romain Guy 1233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy newMesh->offset = (GLintptr) mSize; 1243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy newMesh->textureOffset = newMesh->offset + gMeshTextureOffset; 1253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mSize += size; 1262728f961614a385df1f056fc24803a9f65c90fabRomain Guy 1273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices); 128f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 1293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy delete[] vertices; 1302728f961614a385df1f056fc24803a9f65c90fabRomain Guy } 1312728f961614a385df1f056fc24803a9f65c90fabRomain Guy 1323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mCache.put(description, newMesh); 1333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return newMesh; 134f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy } 135f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 136f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy return mesh; 137f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 138f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 139f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}; // namespace uirenderer 140f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy}; // namespace android 141