blob: c2b28d196f46b9f849678975af1ba69a5349c159 [file] [log] [blame]
Romain Guyf7f93552010-07-08 19:17:03 -07001/*
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
Romain Guy3b748a42013-04-17 18:54:38 -070019#include <utils/JenkinsHash.h>
Romain Guyf7f93552010-07-08 19:17:03 -070020#include <utils/Log.h>
Romain Guyf7f93552010-07-08 19:17:03 -070021
Romain Guy3b748a42013-04-17 18:54:38 -070022#include "Caches.h"
Romain Guyf7f93552010-07-08 19:17:03 -070023#include "PatchCache.h"
Romain Guyfb8b7632010-08-23 21:05:08 -070024#include "Properties.h"
Romain Guyf7f93552010-07-08 19:17:03 -070025
26namespace android {
27namespace uirenderer {
28
29///////////////////////////////////////////////////////////////////////////////
30// Constructors/destructor
31///////////////////////////////////////////////////////////////////////////////
32
Romain Guy3b748a42013-04-17 18:54:38 -070033PatchCache::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;
Romain Guyf7f93552010-07-08 19:17:03 -070043}
44
45PatchCache::~PatchCache() {
46 clear();
47}
48
Romain Guy3b748a42013-04-17 18:54:38 -070049void 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
Romain Guyf7f93552010-07-08 19:17:03 -070057///////////////////////////////////////////////////////////////////////////////
Romain Guyf7f93552010-07-08 19:17:03 -070058// Caching
59///////////////////////////////////////////////////////////////////////////////
60
Romain Guy3b748a42013-04-17 18:54:38 -070061hash_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}
Romain Guy13ba0052013-02-15 12:47:26 -080069
Romain Guy3b748a42013-04-17 18:54:38 -070070int PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs,
71 const PatchCache::PatchDescription& rhs) {
72 return memcmp(&lhs, &rhs, sizeof(PatchDescription));
Romain Guy13ba0052013-02-15 12:47:26 -080073}
74
Romain Guyf7f93552010-07-08 19:17:03 -070075void PatchCache::clear() {
Romain Guy3b748a42013-04-17 18:54:38 -070076 glDeleteBuffers(1, &mMeshBuffer);
77 clearCache();
78 mSize = 0;
79}
80
81void PatchCache::clearCache() {
82 LruCache<PatchDescription, Patch*>::Iterator i(mCache);
83 while (i.next()) {
Romain Guy3b748a42013-04-17 18:54:38 -070084 delete i.value();
Romain Guy2728f962010-10-08 18:36:15 -070085 }
Romain Guyf7f93552010-07-08 19:17:03 -070086 mCache.clear();
Romain Guyf7f93552010-07-08 19:17:03 -070087}
88
Romain Guy3b748a42013-04-17 18:54:38 -070089const 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) {
Romain Guy4bb94202010-10-12 15:59:26 -070092
Romain Guy3b748a42013-04-17 18:54:38 -070093 const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch);
94 const Patch* mesh = mCache.get(description);
Romain Guy2728f962010-10-08 18:36:15 -070095
Romain Guyf7f93552010-07-08 19:17:03 -070096 if (!mesh) {
Romain Guy3b748a42013-04-17 18:54:38 -070097 Patch* newMesh = new Patch();
98 TextureVertex* vertices;
Romain Guy2728f962010-10-08 18:36:15 -070099
Romain Guy3b748a42013-04-17 18:54:38 -0700100 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);
Romain Guy2728f962010-10-08 18:36:15 -0700106 }
107
Romain Guy3b748a42013-04-17 18:54:38 -0700108 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;
Romain Guyf7f93552010-07-08 19:17:03 -0700133 }
134
135 return mesh;
136}
137
138}; // namespace uirenderer
139}; // namespace android