PatchCache.cpp revision 1f8a0db348f6c7bf2d1f55065472c913677f3d69
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "OpenGLRenderer" 18 19#include <utils/JenkinsHash.h> 20#include <utils/Log.h> 21 22#include "Caches.h" 23#include "PatchCache.h" 24#include "Properties.h" 25 26namespace android { 27namespace uirenderer { 28 29/////////////////////////////////////////////////////////////////////////////// 30// Constructors/destructor 31/////////////////////////////////////////////////////////////////////////////// 32 33PatchCache::PatchCache(): mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity) { 34 char property[PROPERTY_VALUE_MAX]; 35 if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, NULL) > 0) { 36 INIT_LOGD(" Setting patch cache size to %skB", property); 37 mMaxSize = KB(atoi(property)); 38 } else { 39 INIT_LOGD(" Using default patch cache size of %.2fkB", DEFAULT_PATCH_CACHE_SIZE); 40 mMaxSize = KB(DEFAULT_PATCH_CACHE_SIZE); 41 } 42 mSize = 0; 43} 44 45PatchCache::~PatchCache() { 46 clear(); 47} 48 49void PatchCache::init(Caches& caches) { 50 glGenBuffers(1, &mMeshBuffer); 51 caches.bindMeshBuffer(mMeshBuffer); 52 caches.resetVertexPointers(); 53 54 glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW); 55} 56 57/////////////////////////////////////////////////////////////////////////////// 58// Caching 59/////////////////////////////////////////////////////////////////////////////// 60 61hash_t PatchCache::PatchDescription::hash() const { 62 uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch)); 63 hash = JenkinsHashMix(hash, mBitmapWidth); 64 hash = JenkinsHashMix(hash, mBitmapHeight); 65 hash = JenkinsHashMix(hash, mPixelWidth); 66 hash = JenkinsHashMix(hash, mPixelHeight); 67 return JenkinsHashWhiten(hash); 68} 69 70int PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs, 71 const PatchCache::PatchDescription& rhs) { 72 return memcmp(&lhs, &rhs, sizeof(PatchDescription)); 73} 74 75void PatchCache::clear() { 76 glDeleteBuffers(1, &mMeshBuffer); 77 clearCache(); 78 mSize = 0; 79} 80 81void PatchCache::clearCache() { 82 LruCache<PatchDescription, Patch*>::Iterator i(mCache); 83 while (i.next()) { 84 delete i.value(); 85 } 86 mCache.clear(); 87} 88 89const Patch* PatchCache::get(const AssetAtlas::Entry* entry, 90 const uint32_t bitmapWidth, const uint32_t bitmapHeight, 91 const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) { 92 93 const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch); 94 const Patch* mesh = mCache.get(description); 95 96 if (!mesh) { 97 Patch* newMesh = new Patch(); 98 TextureVertex* vertices; 99 100 if (entry) { 101 vertices = newMesh->createMesh(bitmapWidth, bitmapHeight, 102 0.0f, 0.0f, pixelWidth, pixelHeight, entry->uvMapper, patch); 103 } else { 104 vertices = newMesh->createMesh(bitmapWidth, bitmapHeight, 105 0.0f, 0.0f, pixelWidth, pixelHeight, patch); 106 } 107 108 if (vertices) { 109 Caches& caches = Caches::getInstance(); 110 caches.bindMeshBuffer(mMeshBuffer); 111 caches.resetVertexPointers(); 112 113 // TODO: Simply remove the oldest items until we have enough room 114 // This will require to keep a list of free blocks in the VBO 115 uint32_t size = newMesh->getSize(); 116 if (mSize + size > mMaxSize) { 117 clearCache(); 118 glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW); 119 mSize = 0; 120 } 121 122 newMesh->offset = (GLintptr) mSize; 123 newMesh->textureOffset = newMesh->offset + gMeshTextureOffset; 124 mSize += size; 125 126 glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices); 127 128 delete[] vertices; 129 } 130 131 mCache.put(description, newMesh); 132 return newMesh; 133 } 134 135 return mesh; 136} 137 138}; // namespace uirenderer 139}; // namespace android 140