• 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     LOGD("ResourceCache: cacheReport:");
30     for (size_t i = 0; i < mCache->size(); ++i) {
31         ResourceReference* ref = mCache->valueAt(i);
32         LOGD("  ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
33                 i, mCache->keyAt(i), mCache->valueAt(i));
34         LOGD("  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 
incrementRefcount(void * resource,ResourceType resourceType)49 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
50     Mutex::Autolock _l(mLock);
51     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
52     if (ref == NULL || mCache->size() == 0) {
53         ref = new ResourceReference(resourceType);
54         mCache->add(resource, ref);
55     }
56     ref->refCount++;
57 }
58 
incrementRefcount(SkBitmap * bitmapResource)59 void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
60     SkSafeRef(bitmapResource->pixelRef());
61     SkSafeRef(bitmapResource->getColorTable());
62     incrementRefcount((void*)bitmapResource, kBitmap);
63 }
64 
incrementRefcount(SkPath * pathResource)65 void ResourceCache::incrementRefcount(SkPath* pathResource) {
66     incrementRefcount((void*)pathResource, kPath);
67 }
68 
incrementRefcount(SkiaShader * shaderResource)69 void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
70     SkSafeRef(shaderResource->getSkShader());
71     incrementRefcount((void*) shaderResource, kShader);
72 }
73 
incrementRefcount(SkiaColorFilter * filterResource)74 void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
75     SkSafeRef(filterResource->getSkColorFilter());
76     incrementRefcount((void*) filterResource, kColorFilter);
77 }
78 
decrementRefcount(void * resource)79 void ResourceCache::decrementRefcount(void* resource) {
80     Mutex::Autolock _l(mLock);
81     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
82     if (ref == NULL) {
83         // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
84         return;
85     }
86     ref->refCount--;
87     if (ref->refCount == 0) {
88         deleteResourceReference(resource, ref);
89     }
90 }
91 
decrementRefcount(SkBitmap * bitmapResource)92 void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
93     SkSafeUnref(bitmapResource->pixelRef());
94     SkSafeUnref(bitmapResource->getColorTable());
95     decrementRefcount((void*) bitmapResource);
96 }
97 
decrementRefcount(SkPath * pathResource)98 void ResourceCache::decrementRefcount(SkPath* pathResource) {
99     decrementRefcount((void*) pathResource);
100 }
101 
decrementRefcount(SkiaShader * shaderResource)102 void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
103     SkSafeUnref(shaderResource->getSkShader());
104     decrementRefcount((void*) shaderResource);
105 }
106 
decrementRefcount(SkiaColorFilter * filterResource)107 void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
108     SkSafeUnref(filterResource->getSkColorFilter());
109     decrementRefcount((void*) filterResource);
110 }
111 
recycle(SkBitmap * resource)112 void ResourceCache::recycle(SkBitmap* resource) {
113     Mutex::Autolock _l(mLock);
114     if (mCache->indexOfKey(resource) < 0) {
115         // not tracking this resource; just recycle the pixel data
116         resource->setPixels(NULL, NULL);
117         return;
118     }
119     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
120     if (ref == NULL) {
121         // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
122         return;
123     }
124     ref->recycled = true;
125     if (ref->refCount == 0) {
126         deleteResourceReference(resource, ref);
127     }
128 }
129 
destructor(SkPath * resource)130 void ResourceCache::destructor(SkPath* resource) {
131     Mutex::Autolock _l(mLock);
132     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
133     if (ref == NULL) {
134         // If we're not tracking this resource, just delete it
135         if (Caches::hasInstance()) {
136             Caches::getInstance().pathCache.removeDeferred(resource);
137         }
138         delete resource;
139         return;
140     }
141     ref->destroyed = true;
142     if (ref->refCount == 0) {
143         deleteResourceReference(resource, ref);
144     }
145 }
146 
destructor(SkBitmap * resource)147 void ResourceCache::destructor(SkBitmap* resource) {
148     Mutex::Autolock _l(mLock);
149     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
150     if (ref == NULL) {
151         // If we're not tracking this resource, just delete it
152         if (Caches::hasInstance()) {
153             Caches::getInstance().textureCache.removeDeferred(resource);
154         }
155         delete resource;
156         return;
157     }
158     ref->destroyed = true;
159     if (ref->refCount == 0) {
160         deleteResourceReference(resource, ref);
161     }
162 }
163 
destructor(SkiaShader * resource)164 void ResourceCache::destructor(SkiaShader* resource) {
165     Mutex::Autolock _l(mLock);
166     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
167     if (ref == NULL) {
168         // If we're not tracking this resource, just delete it
169         delete resource;
170         return;
171     }
172     ref->destroyed = true;
173     if (ref->refCount == 0) {
174         deleteResourceReference(resource, ref);
175     }
176 }
177 
destructor(SkiaColorFilter * resource)178 void ResourceCache::destructor(SkiaColorFilter* resource) {
179     Mutex::Autolock _l(mLock);
180     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
181     if (ref == NULL) {
182         // If we're not tracking this resource, just delete it
183         delete resource;
184         return;
185     }
186     ref->destroyed = true;
187     if (ref->refCount == 0) {
188         deleteResourceReference(resource, ref);
189     }
190 }
191 
192 /**
193  * This method should only be called while the mLock mutex is held (that mutex is grabbed
194  * by the various destructor() and recycle() methods which call this method).
195  */
deleteResourceReference(void * resource,ResourceReference * ref)196 void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
197     if (ref->recycled && ref->resourceType == kBitmap) {
198         ((SkBitmap*) resource)->setPixels(NULL, NULL);
199     }
200     if (ref->destroyed) {
201         switch (ref->resourceType) {
202             case kBitmap: {
203                 SkBitmap* bitmap = (SkBitmap*) resource;
204                 if (Caches::hasInstance()) {
205                     Caches::getInstance().textureCache.removeDeferred(bitmap);
206                 }
207                 delete bitmap;
208             }
209             break;
210             case kPath: {
211                 SkPath* path = (SkPath*) resource;
212                 if (Caches::hasInstance()) {
213                     Caches::getInstance().pathCache.removeDeferred(path);
214                 }
215                 delete path;
216             }
217             break;
218             case kShader: {
219                 SkiaShader* shader = (SkiaShader*) resource;
220                 delete shader;
221             }
222             break;
223             case kColorFilter: {
224                 SkiaColorFilter* filter = (SkiaColorFilter*) resource;
225                 delete filter;
226             }
227             break;
228         }
229     }
230     mCache->removeItem(resource);
231     delete ref;
232 }
233 
234 }; // namespace uirenderer
235 }; // namespace android
236