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