ResourceCache.cpp revision e7d2295c06ef9b9df6336cbff23007a13fb3f6e4
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 bitmapResource->pixelRef()->safeRef(); 64 bitmapResource->getColorTable()->safeRef(); 65 incrementRefcount((void*)bitmapResource, kBitmap); 66} 67 68void ResourceCache::incrementRefcount(SkiaShader* shaderResource) { 69 shaderResource->getSkShader()->safeRef(); 70 incrementRefcount((void*)shaderResource, kShader); 71} 72 73void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) { 74 filterResource->getSkColorFilter()->safeRef(); 75 incrementRefcount((void*)filterResource, kColorFilter); 76} 77 78void ResourceCache::decrementRefcount(void* resource) { 79 Mutex::Autolock _l(mLock); 80 ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; 81 if (ref == NULL) { 82 // Should not get here - shouldn't get a call to decrement if we're not yet tracking it 83 return; 84 } 85 ref->refCount--; 86 if (ref->refCount == 0) { 87 deleteResourceReference(resource, ref); 88 } 89} 90 91void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) { 92 bitmapResource->pixelRef()->safeUnref(); 93 bitmapResource->getColorTable()->safeUnref(); 94 decrementRefcount((void*)bitmapResource); 95} 96 97void ResourceCache::decrementRefcount(SkiaShader* shaderResource) { 98 shaderResource->getSkShader()->safeUnref(); 99 decrementRefcount((void*)shaderResource); 100} 101 102void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) { 103 filterResource->getSkColorFilter()->safeUnref(); 104 decrementRefcount((void*)filterResource); 105} 106 107void ResourceCache::recycle(SkBitmap* resource) { 108 Mutex::Autolock _l(mLock); 109 if (mCache->indexOfKey(resource) < 0) { 110 // not tracking this resource; just recycle the pixel data 111 resource->setPixels(NULL, NULL); 112 return; 113 } 114 recycle((void*) resource); 115} 116 117void ResourceCache::recycle(void* resource) { 118 Mutex::Autolock _l(mLock); 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 130void ResourceCache::destructor(SkBitmap* 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().textureCache.removeDeferred(resource); 137 } 138 delete resource; 139 return; 140 } 141 ref->destroyed = true; 142 if (ref->refCount == 0) { 143 deleteResourceReference(resource, ref); 144 return; 145 } 146} 147 148void ResourceCache::destructor(SkiaShader* resource) { 149 Mutex::Autolock _l(mLock); 150 ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; 151 if (ref == NULL) { 152 // If we're not tracking this resource, just delete it 153 if (Caches::hasInstance()) { 154 Caches::getInstance().gradientCache.removeDeferred(resource->getSkShader()); 155 } 156 delete resource; 157 return; 158 } 159 ref->destroyed = true; 160 if (ref->refCount == 0) { 161 deleteResourceReference(resource, ref); 162 return; 163 } 164} 165 166void ResourceCache::destructor(SkiaColorFilter* resource) { 167 Mutex::Autolock _l(mLock); 168 ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; 169 if (ref == NULL) { 170 // If we're not tracking this resource, just delete it 171 delete resource; 172 return; 173 } 174 ref->destroyed = true; 175 if (ref->refCount == 0) { 176 deleteResourceReference(resource, ref); 177 return; 178 } 179} 180 181/** 182 * This method should only be called while the mLock mutex is held (that mutex is grabbed 183 * by the various destructor() and recycle() methods which call this method). 184 */ 185void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) { 186 if (ref->recycled && ref->resourceType == kBitmap) { 187 ((SkBitmap*) resource)->setPixels(NULL, NULL); 188 } 189 if (ref->destroyed) { 190 switch (ref->resourceType) { 191 case kBitmap: 192 { 193 SkBitmap* bitmap = (SkBitmap*)resource; 194 if (Caches::hasInstance()) { 195 Caches::getInstance().textureCache.removeDeferred(bitmap); 196 } 197 delete bitmap; 198 } 199 break; 200 case kShader: 201 { 202 SkiaShader* shader = (SkiaShader*)resource; 203 if (Caches::hasInstance()) { 204 Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader()); 205 } 206 delete shader; 207 } 208 break; 209 case kColorFilter: 210 { 211 SkiaColorFilter* filter = (SkiaColorFilter*)resource; 212 delete filter; 213 } 214 break; 215 } 216 } 217 mCache->removeItem(resource); 218 delete ref; 219} 220 221}; // namespace uirenderer 222}; // namespace android 223