• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <SkPixelRef.h>
18 #include "ResourceCache.h"
19 #include "Caches.h"
20 
21 namespace android {
22 namespace uirenderer {
23 
24 ///////////////////////////////////////////////////////////////////////////////
25 // Resource cache
26 ///////////////////////////////////////////////////////////////////////////////
27 
logCache()28 void ResourceCache::logCache() {
29     ALOGD("ResourceCache: cacheReport:");
30     for (size_t i = 0; i < mCache->size(); ++i) {
31         ResourceReference* ref = mCache->valueAt(i);
32         ALOGD("  ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
33                 i, mCache->keyAt(i), mCache->valueAt(i));
34         ALOGD("  ResourceCache: mCache(%d): refCount, recycled, destroyed, type = %d, %d, %d, %d",
35                 i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType);
36     }
37 }
38 
ResourceCache()39 ResourceCache::ResourceCache() {
40     Mutex::Autolock _l(mLock);
41     mCache = new KeyedVector<void*, ResourceReference*>();
42 }
43 
~ResourceCache()44 ResourceCache::~ResourceCache() {
45     Mutex::Autolock _l(mLock);
46     delete mCache;
47 }
48 
lock()49 void ResourceCache::lock() {
50     mLock.lock();
51 }
52 
unlock()53 void ResourceCache::unlock() {
54     mLock.unlock();
55 }
56 
incrementRefcount(void * resource,ResourceType resourceType)57 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
58     Mutex::Autolock _l(mLock);
59     incrementRefcountLocked(resource, resourceType);
60 }
61 
incrementRefcount(SkBitmap * bitmapResource)62 void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
63     SkSafeRef(bitmapResource->pixelRef());
64     SkSafeRef(bitmapResource->getColorTable());
65     incrementRefcount((void*) bitmapResource, kBitmap);
66 }
67 
incrementRefcount(SkPath * pathResource)68 void ResourceCache::incrementRefcount(SkPath* pathResource) {
69     incrementRefcount((void*) pathResource, kPath);
70 }
71 
incrementRefcount(SkiaShader * shaderResource)72 void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
73     SkSafeRef(shaderResource->getSkShader());
74     incrementRefcount((void*) shaderResource, kShader);
75 }
76 
incrementRefcount(SkiaColorFilter * filterResource)77 void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
78     SkSafeRef(filterResource->getSkColorFilter());
79     incrementRefcount((void*) filterResource, kColorFilter);
80 }
81 
incrementRefcount(Layer * layerResource)82 void ResourceCache::incrementRefcount(Layer* layerResource) {
83     incrementRefcount((void*) layerResource, kLayer);
84 }
85 
incrementRefcountLocked(void * resource,ResourceType resourceType)86 void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
87     ssize_t index = mCache->indexOfKey(resource);
88     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
89     if (ref == NULL || mCache->size() == 0) {
90         ref = new ResourceReference(resourceType);
91         mCache->add(resource, ref);
92     }
93     ref->refCount++;
94 }
95 
incrementRefcountLocked(SkBitmap * bitmapResource)96 void ResourceCache::incrementRefcountLocked(SkBitmap* bitmapResource) {
97     SkSafeRef(bitmapResource->pixelRef());
98     SkSafeRef(bitmapResource->getColorTable());
99     incrementRefcountLocked((void*) bitmapResource, kBitmap);
100 }
101 
incrementRefcountLocked(SkPath * pathResource)102 void ResourceCache::incrementRefcountLocked(SkPath* pathResource) {
103     incrementRefcountLocked((void*) pathResource, kPath);
104 }
105 
incrementRefcountLocked(SkiaShader * shaderResource)106 void ResourceCache::incrementRefcountLocked(SkiaShader* shaderResource) {
107     SkSafeRef(shaderResource->getSkShader());
108     incrementRefcountLocked((void*) shaderResource, kShader);
109 }
110 
incrementRefcountLocked(SkiaColorFilter * filterResource)111 void ResourceCache::incrementRefcountLocked(SkiaColorFilter* filterResource) {
112     SkSafeRef(filterResource->getSkColorFilter());
113     incrementRefcountLocked((void*) filterResource, kColorFilter);
114 }
115 
incrementRefcountLocked(Layer * layerResource)116 void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
117     incrementRefcountLocked((void*) layerResource, kLayer);
118 }
119 
decrementRefcount(void * resource)120 void ResourceCache::decrementRefcount(void* resource) {
121     Mutex::Autolock _l(mLock);
122     decrementRefcountLocked(resource);
123 }
124 
decrementRefcount(SkBitmap * bitmapResource)125 void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
126     SkSafeUnref(bitmapResource->pixelRef());
127     SkSafeUnref(bitmapResource->getColorTable());
128     decrementRefcount((void*) bitmapResource);
129 }
130 
decrementRefcount(SkPath * pathResource)131 void ResourceCache::decrementRefcount(SkPath* pathResource) {
132     decrementRefcount((void*) pathResource);
133 }
134 
decrementRefcount(SkiaShader * shaderResource)135 void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
136     SkSafeUnref(shaderResource->getSkShader());
137     decrementRefcount((void*) shaderResource);
138 }
139 
decrementRefcount(SkiaColorFilter * filterResource)140 void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
141     SkSafeUnref(filterResource->getSkColorFilter());
142     decrementRefcount((void*) filterResource);
143 }
144 
decrementRefcount(Layer * layerResource)145 void ResourceCache::decrementRefcount(Layer* layerResource) {
146     decrementRefcount((void*) layerResource);
147 }
148 
decrementRefcountLocked(void * resource)149 void ResourceCache::decrementRefcountLocked(void* resource) {
150     ssize_t index = mCache->indexOfKey(resource);
151     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
152     if (ref == NULL) {
153         // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
154         return;
155     }
156     ref->refCount--;
157     if (ref->refCount == 0) {
158         deleteResourceReferenceLocked(resource, ref);
159     }
160 }
161 
decrementRefcountLocked(SkBitmap * bitmapResource)162 void ResourceCache::decrementRefcountLocked(SkBitmap* bitmapResource) {
163     SkSafeUnref(bitmapResource->pixelRef());
164     SkSafeUnref(bitmapResource->getColorTable());
165     decrementRefcountLocked((void*) bitmapResource);
166 }
167 
decrementRefcountLocked(SkPath * pathResource)168 void ResourceCache::decrementRefcountLocked(SkPath* pathResource) {
169     decrementRefcountLocked((void*) pathResource);
170 }
171 
decrementRefcountLocked(SkiaShader * shaderResource)172 void ResourceCache::decrementRefcountLocked(SkiaShader* shaderResource) {
173     SkSafeUnref(shaderResource->getSkShader());
174     decrementRefcountLocked((void*) shaderResource);
175 }
176 
decrementRefcountLocked(SkiaColorFilter * filterResource)177 void ResourceCache::decrementRefcountLocked(SkiaColorFilter* filterResource) {
178     SkSafeUnref(filterResource->getSkColorFilter());
179     decrementRefcountLocked((void*) filterResource);
180 }
181 
decrementRefcountLocked(Layer * layerResource)182 void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
183     decrementRefcountLocked((void*) layerResource);
184 }
185 
destructor(SkPath * resource)186 void ResourceCache::destructor(SkPath* resource) {
187     Mutex::Autolock _l(mLock);
188     destructorLocked(resource);
189 }
190 
destructorLocked(SkPath * resource)191 void ResourceCache::destructorLocked(SkPath* resource) {
192     ssize_t index = mCache->indexOfKey(resource);
193     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
194     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) {
204         deleteResourceReferenceLocked(resource, ref);
205     }
206 }
207 
destructor(SkBitmap * resource)208 void ResourceCache::destructor(SkBitmap* resource) {
209     Mutex::Autolock _l(mLock);
210     destructorLocked(resource);
211 }
212 
destructorLocked(SkBitmap * resource)213 void ResourceCache::destructorLocked(SkBitmap* resource) {
214     ssize_t index = mCache->indexOfKey(resource);
215     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
216     if (ref == NULL) {
217         // If we're not tracking this resource, just delete it
218         if (Caches::hasInstance()) {
219             Caches::getInstance().textureCache.removeDeferred(resource);
220         }
221         delete resource;
222         return;
223     }
224     ref->destroyed = true;
225     if (ref->refCount == 0) {
226         deleteResourceReferenceLocked(resource, ref);
227     }
228 }
229 
destructor(SkiaShader * resource)230 void ResourceCache::destructor(SkiaShader* resource) {
231     Mutex::Autolock _l(mLock);
232     destructorLocked(resource);
233 }
234 
destructorLocked(SkiaShader * resource)235 void ResourceCache::destructorLocked(SkiaShader* resource) {
236     ssize_t index = mCache->indexOfKey(resource);
237     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
238     if (ref == NULL) {
239         // If we're not tracking this resource, just delete it
240         delete resource;
241         return;
242     }
243     ref->destroyed = true;
244     if (ref->refCount == 0) {
245         deleteResourceReferenceLocked(resource, ref);
246     }
247 }
248 
destructor(SkiaColorFilter * resource)249 void ResourceCache::destructor(SkiaColorFilter* resource) {
250     Mutex::Autolock _l(mLock);
251     destructorLocked(resource);
252 }
253 
destructorLocked(SkiaColorFilter * resource)254 void ResourceCache::destructorLocked(SkiaColorFilter* resource) {
255     ssize_t index = mCache->indexOfKey(resource);
256     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
257     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) {
264         deleteResourceReferenceLocked(resource, ref);
265     }
266 }
267 
268 /**
269  * Return value indicates whether resource was actually recycled, which happens when RefCnt
270  * reaches 0.
271  */
recycle(SkBitmap * resource)272 bool ResourceCache::recycle(SkBitmap* resource) {
273     Mutex::Autolock _l(mLock);
274     return recycleLocked(resource);
275 }
276 
277 /**
278  * Return value indicates whether resource was actually recycled, which happens when RefCnt
279  * reaches 0.
280  */
recycleLocked(SkBitmap * resource)281 bool ResourceCache::recycleLocked(SkBitmap* resource) {
282     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);
286         return true;
287     }
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
291         return true;
292     }
293     ref->recycled = true;
294     if (ref->refCount == 0) {
295         deleteResourceReferenceLocked(resource, ref);
296         return true;
297     }
298     // Still referring to resource, don't recycle yet
299     return false;
300 }
301 
302 /**
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  */
deleteResourceReferenceLocked(void * resource,ResourceReference * ref)306 void ResourceCache::deleteResourceReferenceLocked(void* resource, ResourceReference* ref) {
307     if (ref->recycled && ref->resourceType == kBitmap) {
308         ((SkBitmap*) resource)->setPixels(NULL, NULL);
309     }
310     if (ref->destroyed || ref->resourceType == kLayer) {
311         switch (ref->resourceType) {
312             case kBitmap: {
313                 SkBitmap* bitmap = (SkBitmap*) resource;
314                 if (Caches::hasInstance()) {
315                     Caches::getInstance().textureCache.removeDeferred(bitmap);
316                 }
317                 delete bitmap;
318             }
319             break;
320             case kPath: {
321                 SkPath* path = (SkPath*) resource;
322                 if (Caches::hasInstance()) {
323                     Caches::getInstance().pathCache.removeDeferred(path);
324                 }
325                 delete path;
326             }
327             break;
328             case kShader: {
329                 SkiaShader* shader = (SkiaShader*) resource;
330                 delete shader;
331             }
332             break;
333             case kColorFilter: {
334                 SkiaColorFilter* filter = (SkiaColorFilter*) resource;
335                 delete filter;
336             }
337             break;
338             case kLayer: {
339                 Layer* layer = (Layer*) resource;
340                 Caches::getInstance().deleteLayerDeferred(layer);
341             }
342             break;
343         }
344     }
345     mCache->removeItem(resource);
346     delete ref;
347 }
348 
349 }; // namespace uirenderer
350 }; // namespace android
351