blob: 347bd78ca93b1a61c02f6170077cb08afa1f3af8 [file] [log] [blame]
Chet Haase5c13d892010-10-08 08:37:55 -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#include <SkPixelRef.h>
18#include "ResourceCache.h"
19#include "Caches.h"
20
21namespace android {
22namespace uirenderer {
23
24///////////////////////////////////////////////////////////////////////////////
25// Resource cache
26///////////////////////////////////////////////////////////////////////////////
27
28void ResourceCache::logCache() {
Steve Block5baa3a62011-12-20 16:23:08 +000029 ALOGD("ResourceCache: cacheReport:");
Chet Haase5c13d892010-10-08 08:37:55 -070030 for (size_t i = 0; i < mCache->size(); ++i) {
31 ResourceReference* ref = mCache->valueAt(i);
Steve Block5baa3a62011-12-20 16:23:08 +000032 ALOGD(" ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
Chet Haase5c13d892010-10-08 08:37:55 -070033 i, mCache->keyAt(i), mCache->valueAt(i));
Steve Block5baa3a62011-12-20 16:23:08 +000034 ALOGD(" ResourceCache: mCache(%d): refCount, recycled, destroyed, type = %d, %d, %d, %d",
Chet Haase5c13d892010-10-08 08:37:55 -070035 i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType);
36 }
37}
38
39ResourceCache::ResourceCache() {
Chet Haasee7d22952010-11-11 16:30:16 -080040 Mutex::Autolock _l(mLock);
Romain Guy58ecc202012-09-07 11:58:36 -070041 mCache = new KeyedVector<void*, ResourceReference*>();
Chet Haase5c13d892010-10-08 08:37:55 -070042}
43
44ResourceCache::~ResourceCache() {
Chet Haasee7d22952010-11-11 16:30:16 -080045 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -070046 delete mCache;
47}
48
Romain Guy58ecc202012-09-07 11:58:36 -070049void ResourceCache::lock() {
50 mLock.lock();
51}
52
53void ResourceCache::unlock() {
54 mLock.unlock();
55}
56
Chet Haase5c13d892010-10-08 08:37:55 -070057void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
Chet Haasee7d22952010-11-11 16:30:16 -080058 Mutex::Autolock _l(mLock);
Romain Guy58ecc202012-09-07 11:58:36 -070059 incrementRefcountLocked(resource, resourceType);
Chet Haase5c13d892010-10-08 08:37:55 -070060}
61
62void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
Derek Sollenberger6062c592011-02-22 13:55:04 -050063 SkSafeRef(bitmapResource->pixelRef());
64 SkSafeRef(bitmapResource->getColorTable());
Romain Guy49c5fc02012-05-15 11:10:01 -070065 incrementRefcount((void*) bitmapResource, kBitmap);
Chet Haase5c13d892010-10-08 08:37:55 -070066}
67
Chet Haase5a7e8282011-02-04 12:50:55 -080068void ResourceCache::incrementRefcount(SkPath* pathResource) {
Romain Guy49c5fc02012-05-15 11:10:01 -070069 incrementRefcount((void*) pathResource, kPath);
Chet Haase5a7e8282011-02-04 12:50:55 -080070}
71
Chet Haase5c13d892010-10-08 08:37:55 -070072void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
Derek Sollenberger6062c592011-02-22 13:55:04 -050073 SkSafeRef(shaderResource->getSkShader());
Romain Guy43ccf462011-01-14 18:51:01 -080074 incrementRefcount((void*) shaderResource, kShader);
Chet Haase5c13d892010-10-08 08:37:55 -070075}
76
Chet Haasead93c2b2010-10-22 16:17:12 -070077void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
Derek Sollenberger6062c592011-02-22 13:55:04 -050078 SkSafeRef(filterResource->getSkColorFilter());
Romain Guy43ccf462011-01-14 18:51:01 -080079 incrementRefcount((void*) filterResource, kColorFilter);
Chet Haasead93c2b2010-10-22 16:17:12 -070080}
81
Chet Haase603f6de2012-09-14 15:31:25 -070082void ResourceCache::incrementRefcount(Layer* layerResource) {
83 incrementRefcount((void*) layerResource, kLayer);
84}
85
Romain Guy58ecc202012-09-07 11:58:36 -070086void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
Romain Guy8dcfd5e2012-07-20 11:36:03 -070087 ssize_t index = mCache->indexOfKey(resource);
88 ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
Romain Guy58ecc202012-09-07 11:58:36 -070089 if (ref == NULL || mCache->size() == 0) {
90 ref = new ResourceReference(resourceType);
91 mCache->add(resource, ref);
Chet Haase5c13d892010-10-08 08:37:55 -070092 }
Romain Guy58ecc202012-09-07 11:58:36 -070093 ref->refCount++;
94}
95
96void ResourceCache::incrementRefcountLocked(SkBitmap* bitmapResource) {
97 SkSafeRef(bitmapResource->pixelRef());
98 SkSafeRef(bitmapResource->getColorTable());
99 incrementRefcountLocked((void*) bitmapResource, kBitmap);
100}
101
102void ResourceCache::incrementRefcountLocked(SkPath* pathResource) {
103 incrementRefcountLocked((void*) pathResource, kPath);
104}
105
106void ResourceCache::incrementRefcountLocked(SkiaShader* shaderResource) {
107 SkSafeRef(shaderResource->getSkShader());
108 incrementRefcountLocked((void*) shaderResource, kShader);
109}
110
111void ResourceCache::incrementRefcountLocked(SkiaColorFilter* filterResource) {
112 SkSafeRef(filterResource->getSkColorFilter());
113 incrementRefcountLocked((void*) filterResource, kColorFilter);
114}
115
Chet Haase603f6de2012-09-14 15:31:25 -0700116void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
117 incrementRefcountLocked((void*) layerResource, kLayer);
118}
119
Romain Guy58ecc202012-09-07 11:58:36 -0700120void ResourceCache::decrementRefcount(void* resource) {
121 Mutex::Autolock _l(mLock);
122 decrementRefcountLocked(resource);
Chet Haase5c13d892010-10-08 08:37:55 -0700123}
124
125void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
Derek Sollenberger6062c592011-02-22 13:55:04 -0500126 SkSafeUnref(bitmapResource->pixelRef());
127 SkSafeUnref(bitmapResource->getColorTable());
Romain Guy43ccf462011-01-14 18:51:01 -0800128 decrementRefcount((void*) bitmapResource);
Chet Haase5c13d892010-10-08 08:37:55 -0700129}
130
Chet Haase5a7e8282011-02-04 12:50:55 -0800131void ResourceCache::decrementRefcount(SkPath* pathResource) {
132 decrementRefcount((void*) pathResource);
133}
134
Chet Haase5c13d892010-10-08 08:37:55 -0700135void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
Derek Sollenberger6062c592011-02-22 13:55:04 -0500136 SkSafeUnref(shaderResource->getSkShader());
Romain Guy43ccf462011-01-14 18:51:01 -0800137 decrementRefcount((void*) shaderResource);
Chet Haase5c13d892010-10-08 08:37:55 -0700138}
139
Chet Haasead93c2b2010-10-22 16:17:12 -0700140void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
Derek Sollenberger6062c592011-02-22 13:55:04 -0500141 SkSafeUnref(filterResource->getSkColorFilter());
Romain Guy43ccf462011-01-14 18:51:01 -0800142 decrementRefcount((void*) filterResource);
Chet Haasead93c2b2010-10-22 16:17:12 -0700143}
144
Chet Haase603f6de2012-09-14 15:31:25 -0700145void ResourceCache::decrementRefcount(Layer* layerResource) {
146 decrementRefcount((void*) layerResource);
147}
148
Romain Guy58ecc202012-09-07 11:58:36 -0700149void ResourceCache::decrementRefcountLocked(void* resource) {
Romain Guy8dcfd5e2012-07-20 11:36:03 -0700150 ssize_t index = mCache->indexOfKey(resource);
Romain Guy58ecc202012-09-07 11:58:36 -0700151 ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
Chet Haase5c13d892010-10-08 08:37:55 -0700152 if (ref == NULL) {
Romain Guy58ecc202012-09-07 11:58:36 -0700153 // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
Chet Haase5c13d892010-10-08 08:37:55 -0700154 return;
155 }
Romain Guy58ecc202012-09-07 11:58:36 -0700156 ref->refCount--;
Chet Haase5c13d892010-10-08 08:37:55 -0700157 if (ref->refCount == 0) {
Romain Guy97dc9172012-09-23 17:46:45 -0700158 deleteResourceReferenceLocked(resource, ref);
Chet Haase5c13d892010-10-08 08:37:55 -0700159 }
160}
161
Romain Guy58ecc202012-09-07 11:58:36 -0700162void ResourceCache::decrementRefcountLocked(SkBitmap* bitmapResource) {
163 SkSafeUnref(bitmapResource->pixelRef());
164 SkSafeUnref(bitmapResource->getColorTable());
165 decrementRefcountLocked((void*) bitmapResource);
166}
167
168void ResourceCache::decrementRefcountLocked(SkPath* pathResource) {
169 decrementRefcountLocked((void*) pathResource);
170}
171
172void ResourceCache::decrementRefcountLocked(SkiaShader* shaderResource) {
173 SkSafeUnref(shaderResource->getSkShader());
174 decrementRefcountLocked((void*) shaderResource);
175}
176
177void ResourceCache::decrementRefcountLocked(SkiaColorFilter* filterResource) {
178 SkSafeUnref(filterResource->getSkColorFilter());
179 decrementRefcountLocked((void*) filterResource);
180}
181
Chet Haase603f6de2012-09-14 15:31:25 -0700182void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
183 decrementRefcountLocked((void*) layerResource);
184}
185
Chet Haase5a7e8282011-02-04 12:50:55 -0800186void ResourceCache::destructor(SkPath* resource) {
187 Mutex::Autolock _l(mLock);
Romain Guy58ecc202012-09-07 11:58:36 -0700188 destructorLocked(resource);
189}
190
191void ResourceCache::destructorLocked(SkPath* resource) {
Romain Guy8dcfd5e2012-07-20 11:36:03 -0700192 ssize_t index = mCache->indexOfKey(resource);
193 ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
Chet Haase5a7e8282011-02-04 12:50:55 -0800194 if (ref == NULL) {
195 // If we're not tracking this resource, just delete it
196 if (Caches::hasInstance()) {
197 Caches::getInstance().pathCache.removeDeferred(resource);
198 }
199 delete resource;
200 return;
201 }
202 ref->destroyed = true;
203 if (ref->refCount == 0) {
Romain Guy97dc9172012-09-23 17:46:45 -0700204 deleteResourceReferenceLocked(resource, ref);
Chet Haase5a7e8282011-02-04 12:50:55 -0800205 }
206}
207
Chet Haase5c13d892010-10-08 08:37:55 -0700208void ResourceCache::destructor(SkBitmap* resource) {
Chet Haasee7d22952010-11-11 16:30:16 -0800209 Mutex::Autolock _l(mLock);
Romain Guy58ecc202012-09-07 11:58:36 -0700210 destructorLocked(resource);
211}
212
213void ResourceCache::destructorLocked(SkBitmap* resource) {
Romain Guy8dcfd5e2012-07-20 11:36:03 -0700214 ssize_t index = mCache->indexOfKey(resource);
215 ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
Chet Haase5c13d892010-10-08 08:37:55 -0700216 if (ref == NULL) {
217 // If we're not tracking this resource, just delete it
218 if (Caches::hasInstance()) {
Romain Guyfe48f652010-11-11 15:36:56 -0800219 Caches::getInstance().textureCache.removeDeferred(resource);
Chet Haase5c13d892010-10-08 08:37:55 -0700220 }
221 delete resource;
222 return;
223 }
224 ref->destroyed = true;
225 if (ref->refCount == 0) {
Romain Guy97dc9172012-09-23 17:46:45 -0700226 deleteResourceReferenceLocked(resource, ref);
Chet Haase5c13d892010-10-08 08:37:55 -0700227 }
228}
229
Chet Haase5c13d892010-10-08 08:37:55 -0700230void ResourceCache::destructor(SkiaShader* resource) {
Chet Haasee7d22952010-11-11 16:30:16 -0800231 Mutex::Autolock _l(mLock);
Romain Guy58ecc202012-09-07 11:58:36 -0700232 destructorLocked(resource);
233}
234
235void ResourceCache::destructorLocked(SkiaShader* resource) {
Romain Guy8dcfd5e2012-07-20 11:36:03 -0700236 ssize_t index = mCache->indexOfKey(resource);
237 ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
Chet Haase5c13d892010-10-08 08:37:55 -0700238 if (ref == NULL) {
239 // If we're not tracking this resource, just delete it
Chet Haase5c13d892010-10-08 08:37:55 -0700240 delete resource;
241 return;
242 }
243 ref->destroyed = true;
244 if (ref->refCount == 0) {
Romain Guy97dc9172012-09-23 17:46:45 -0700245 deleteResourceReferenceLocked(resource, ref);
Chet Haase5c13d892010-10-08 08:37:55 -0700246 }
247}
248
Chet Haasead93c2b2010-10-22 16:17:12 -0700249void ResourceCache::destructor(SkiaColorFilter* resource) {
Chet Haasee7d22952010-11-11 16:30:16 -0800250 Mutex::Autolock _l(mLock);
Romain Guy58ecc202012-09-07 11:58:36 -0700251 destructorLocked(resource);
252}
253
254void ResourceCache::destructorLocked(SkiaColorFilter* resource) {
Romain Guy8dcfd5e2012-07-20 11:36:03 -0700255 ssize_t index = mCache->indexOfKey(resource);
256 ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
Chet Haasead93c2b2010-10-22 16:17:12 -0700257 if (ref == NULL) {
258 // If we're not tracking this resource, just delete it
259 delete resource;
260 return;
261 }
262 ref->destroyed = true;
263 if (ref->refCount == 0) {
Romain Guy97dc9172012-09-23 17:46:45 -0700264 deleteResourceReferenceLocked(resource, ref);
Chet Haasead93c2b2010-10-22 16:17:12 -0700265 }
266}
267
Chet Haase547e6652012-10-22 15:07:26 -0700268/**
269 * Return value indicates whether resource was actually recycled, which happens when RefCnt
270 * reaches 0.
271 */
272bool ResourceCache::recycle(SkBitmap* resource) {
Romain Guy58ecc202012-09-07 11:58:36 -0700273 Mutex::Autolock _l(mLock);
Chet Haase547e6652012-10-22 15:07:26 -0700274 return recycleLocked(resource);
Romain Guy58ecc202012-09-07 11:58:36 -0700275}
276
Chet Haase547e6652012-10-22 15:07:26 -0700277/**
278 * Return value indicates whether resource was actually recycled, which happens when RefCnt
279 * reaches 0.
280 */
281bool ResourceCache::recycleLocked(SkBitmap* resource) {
Romain Guy58ecc202012-09-07 11:58:36 -0700282 ssize_t index = mCache->indexOfKey(resource);
283 if (index < 0) {
284 // not tracking this resource; just recycle the pixel data
285 resource->setPixels(NULL, NULL);
Chet Haase547e6652012-10-22 15:07:26 -0700286 return true;
Romain Guy58ecc202012-09-07 11:58:36 -0700287 }
288 ResourceReference* ref = mCache->valueAt(index);
289 if (ref == NULL) {
290 // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
Chet Haase547e6652012-10-22 15:07:26 -0700291 return true;
Romain Guy58ecc202012-09-07 11:58:36 -0700292 }
293 ref->recycled = true;
294 if (ref->refCount == 0) {
Romain Guy97dc9172012-09-23 17:46:45 -0700295 deleteResourceReferenceLocked(resource, ref);
Chet Haase547e6652012-10-22 15:07:26 -0700296 return true;
Romain Guy58ecc202012-09-07 11:58:36 -0700297 }
Chet Haase547e6652012-10-22 15:07:26 -0700298 // Still referring to resource, don't recycle yet
299 return false;
Romain Guy58ecc202012-09-07 11:58:36 -0700300}
301
Chet Haasee7d22952010-11-11 16:30:16 -0800302/**
303 * This method should only be called while the mLock mutex is held (that mutex is grabbed
304 * by the various destructor() and recycle() methods which call this method).
305 */
Romain Guy97dc9172012-09-23 17:46:45 -0700306void ResourceCache::deleteResourceReferenceLocked(void* resource, ResourceReference* ref) {
Chet Haase5c13d892010-10-08 08:37:55 -0700307 if (ref->recycled && ref->resourceType == kBitmap) {
308 ((SkBitmap*) resource)->setPixels(NULL, NULL);
309 }
Chet Haase603f6de2012-09-14 15:31:25 -0700310 if (ref->destroyed || ref->resourceType == kLayer) {
Chet Haase5c13d892010-10-08 08:37:55 -0700311 switch (ref->resourceType) {
Romain Guyd586ad92011-06-22 16:14:36 -0700312 case kBitmap: {
313 SkBitmap* bitmap = (SkBitmap*) resource;
Chet Haase5c13d892010-10-08 08:37:55 -0700314 if (Caches::hasInstance()) {
Romain Guyfe48f652010-11-11 15:36:56 -0800315 Caches::getInstance().textureCache.removeDeferred(bitmap);
Chet Haase5c13d892010-10-08 08:37:55 -0700316 }
317 delete bitmap;
318 }
319 break;
Romain Guyd586ad92011-06-22 16:14:36 -0700320 case kPath: {
321 SkPath* path = (SkPath*) resource;
Chet Haase5a7e8282011-02-04 12:50:55 -0800322 if (Caches::hasInstance()) {
323 Caches::getInstance().pathCache.removeDeferred(path);
324 }
325 delete path;
326 }
327 break;
Romain Guyd586ad92011-06-22 16:14:36 -0700328 case kShader: {
329 SkiaShader* shader = (SkiaShader*) resource;
Chet Haase5c13d892010-10-08 08:37:55 -0700330 delete shader;
Chet Haasead93c2b2010-10-22 16:17:12 -0700331 }
332 break;
Romain Guyd586ad92011-06-22 16:14:36 -0700333 case kColorFilter: {
334 SkiaColorFilter* filter = (SkiaColorFilter*) resource;
Chet Haasead93c2b2010-10-22 16:17:12 -0700335 delete filter;
336 }
337 break;
Chet Haase603f6de2012-09-14 15:31:25 -0700338 case kLayer: {
Dave Burke56257af2012-09-25 20:30:09 -0700339 Layer* layer = (Layer*) resource;
Mathias Agopian54643d72012-09-25 21:30:22 -0700340 Caches::getInstance().deleteLayerDeferred(layer);
Chet Haase603f6de2012-09-14 15:31:25 -0700341 }
342 break;
Chet Haase5c13d892010-10-08 08:37:55 -0700343 }
344 }
345 mCache->removeItem(resource);
346 delete ref;
347}
348
349}; // namespace uirenderer
350}; // namespace android