blob: c6ed275e3caee182d9a4ee67dbf0bb6ebd877398 [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 Guy7d9b1b32013-05-28 14:25:09 -070043 mMeshBuffer = 0;
Romain Guyf7f93552010-07-08 19:17:03 -070044}
45
46PatchCache::~PatchCache() {
47 clear();
48}
49
Romain Guy3b748a42013-04-17 18:54:38 -070050void PatchCache::init(Caches& caches) {
Romain Guy7d9b1b32013-05-28 14:25:09 -070051 bool created = false;
52 if (!mMeshBuffer) {
53 glGenBuffers(1, &mMeshBuffer);
54 created = true;
55 }
56
Romain Guy3b748a42013-04-17 18:54:38 -070057 caches.bindMeshBuffer(mMeshBuffer);
58 caches.resetVertexPointers();
59
Romain Guy7d9b1b32013-05-28 14:25:09 -070060 if (created) {
61 glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW);
62 }
Romain Guy3b748a42013-04-17 18:54:38 -070063}
64
Romain Guyf7f93552010-07-08 19:17:03 -070065///////////////////////////////////////////////////////////////////////////////
Romain Guyf7f93552010-07-08 19:17:03 -070066// Caching
67///////////////////////////////////////////////////////////////////////////////
68
Romain Guy3b748a42013-04-17 18:54:38 -070069hash_t PatchCache::PatchDescription::hash() const {
70 uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch));
71 hash = JenkinsHashMix(hash, mBitmapWidth);
72 hash = JenkinsHashMix(hash, mBitmapHeight);
73 hash = JenkinsHashMix(hash, mPixelWidth);
74 hash = JenkinsHashMix(hash, mPixelHeight);
75 return JenkinsHashWhiten(hash);
76}
Romain Guy13ba0052013-02-15 12:47:26 -080077
Romain Guy3b748a42013-04-17 18:54:38 -070078int PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs,
79 const PatchCache::PatchDescription& rhs) {
80 return memcmp(&lhs, &rhs, sizeof(PatchDescription));
Romain Guy13ba0052013-02-15 12:47:26 -080081}
82
Romain Guyf7f93552010-07-08 19:17:03 -070083void PatchCache::clear() {
Romain Guy3b748a42013-04-17 18:54:38 -070084 clearCache();
Romain Guy7d9b1b32013-05-28 14:25:09 -070085
86 if (mMeshBuffer) {
87 Caches::getInstance().unbindMeshBuffer();
88 glDeleteBuffers(1, &mMeshBuffer);
89 mMeshBuffer = 0;
90 mSize = 0;
91 }
Romain Guy3b748a42013-04-17 18:54:38 -070092}
93
94void PatchCache::clearCache() {
95 LruCache<PatchDescription, Patch*>::Iterator i(mCache);
96 while (i.next()) {
Romain Guy3b748a42013-04-17 18:54:38 -070097 delete i.value();
Romain Guy2728f962010-10-08 18:36:15 -070098 }
Romain Guyf7f93552010-07-08 19:17:03 -070099 mCache.clear();
Romain Guyf7f93552010-07-08 19:17:03 -0700100}
101
Romain Guy3b748a42013-04-17 18:54:38 -0700102const Patch* PatchCache::get(const AssetAtlas::Entry* entry,
103 const uint32_t bitmapWidth, const uint32_t bitmapHeight,
104 const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) {
Romain Guy4bb94202010-10-12 15:59:26 -0700105
Romain Guy3b748a42013-04-17 18:54:38 -0700106 const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch);
107 const Patch* mesh = mCache.get(description);
Romain Guy2728f962010-10-08 18:36:15 -0700108
Romain Guyf7f93552010-07-08 19:17:03 -0700109 if (!mesh) {
Romain Guy3b748a42013-04-17 18:54:38 -0700110 Patch* newMesh = new Patch();
111 TextureVertex* vertices;
Romain Guy2728f962010-10-08 18:36:15 -0700112
Romain Guy3b748a42013-04-17 18:54:38 -0700113 if (entry) {
114 vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
115 0.0f, 0.0f, pixelWidth, pixelHeight, entry->uvMapper, patch);
116 } else {
117 vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
118 0.0f, 0.0f, pixelWidth, pixelHeight, patch);
Romain Guy2728f962010-10-08 18:36:15 -0700119 }
120
Romain Guy3b748a42013-04-17 18:54:38 -0700121 if (vertices) {
Romain Guy7d9b1b32013-05-28 14:25:09 -0700122 // This call ensures the VBO exists and that it is bound
123 init(Caches::getInstance());
Romain Guy3b748a42013-04-17 18:54:38 -0700124
125 // TODO: Simply remove the oldest items until we have enough room
126 // This will require to keep a list of free blocks in the VBO
127 uint32_t size = newMesh->getSize();
128 if (mSize + size > mMaxSize) {
129 clearCache();
130 glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW);
131 mSize = 0;
132 }
133
134 newMesh->offset = (GLintptr) mSize;
135 newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
136 mSize += size;
137
138 glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
139
140 delete[] vertices;
141 }
142
143 mCache.put(description, newMesh);
144 return newMesh;
Romain Guyf7f93552010-07-08 19:17:03 -0700145 }
146
147 return mesh;
148}
149
150}; // namespace uirenderer
151}; // namespace android