| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 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 |  | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 17 | #define LOG_TAG "OpenGLRenderer" | 
|  | 18 |  | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 19 | #include "ResourceCache.h" | 
|  | 20 | #include "Caches.h" | 
|  | 21 |  | 
|  | 22 | namespace android { | 
| John Reck | a35778c7 | 2014-11-06 09:45:10 -0800 | [diff] [blame] | 23 |  | 
| John Reck | a35778c7 | 2014-11-06 09:45:10 -0800 | [diff] [blame] | 24 | using namespace uirenderer; | 
|  | 25 | ANDROID_SINGLETON_STATIC_INSTANCE(ResourceCache); | 
| John Reck | a35778c7 | 2014-11-06 09:45:10 -0800 | [diff] [blame] | 26 |  | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 27 | namespace uirenderer { | 
|  | 28 |  | 
|  | 29 | /////////////////////////////////////////////////////////////////////////////// | 
|  | 30 | // Resource cache | 
|  | 31 | /////////////////////////////////////////////////////////////////////////////// | 
|  | 32 |  | 
|  | 33 | void ResourceCache::logCache() { | 
| Steve Block | 5baa3a6 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 34 | ALOGD("ResourceCache: cacheReport:"); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 35 | for (size_t i = 0; i < mCache->size(); ++i) { | 
|  | 36 | ResourceReference* ref = mCache->valueAt(i); | 
| Ashok Bhat | f5df700 | 2014-03-25 20:51:35 +0000 | [diff] [blame] | 37 | ALOGD("  ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p", | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 38 | i, mCache->keyAt(i), mCache->valueAt(i)); | 
| Derek Sollenberger | 3d4eed7 | 2014-12-04 15:20:29 -0500 | [diff] [blame] | 39 | ALOGD("  ResourceCache: mCache(%zu): refCount, destroyed, type = %d, %d, %d", | 
|  | 40 | i, ref->refCount, ref->destroyed, ref->resourceType); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 41 | } | 
|  | 42 | } | 
|  | 43 |  | 
|  | 44 | ResourceCache::ResourceCache() { | 
| Chet Haase | e7d2295 | 2010-11-11 16:30:16 -0800 | [diff] [blame] | 45 | Mutex::Autolock _l(mLock); | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 46 | mCache = new KeyedVector<const void*, ResourceReference*>(); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 47 | } | 
|  | 48 |  | 
|  | 49 | ResourceCache::~ResourceCache() { | 
| Chet Haase | e7d2295 | 2010-11-11 16:30:16 -0800 | [diff] [blame] | 50 | Mutex::Autolock _l(mLock); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 51 | delete mCache; | 
|  | 52 | } | 
|  | 53 |  | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 54 | void ResourceCache::lock() { | 
|  | 55 | mLock.lock(); | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | void ResourceCache::unlock() { | 
|  | 59 | mLock.unlock(); | 
|  | 60 | } | 
|  | 61 |  | 
| Derek Sollenberger | 3d4eed7 | 2014-12-04 15:20:29 -0500 | [diff] [blame] | 62 | const SkBitmap* ResourceCache::insert(const SkBitmap* bitmapResource) { | 
|  | 63 | Mutex::Autolock _l(mLock); | 
|  | 64 |  | 
|  | 65 | BitmapKey bitmapKey(bitmapResource); | 
|  | 66 | ssize_t index = mBitmapCache.indexOfKey(bitmapKey); | 
|  | 67 | if (index == NAME_NOT_FOUND) { | 
|  | 68 | SkBitmap* cachedBitmap = new SkBitmap(*bitmapResource); | 
|  | 69 | index = mBitmapCache.add(bitmapKey, cachedBitmap); | 
|  | 70 | return cachedBitmap; | 
|  | 71 | } | 
|  | 72 |  | 
|  | 73 | mBitmapCache.keyAt(index).mRefCount++; | 
|  | 74 | return mBitmapCache.valueAt(index); | 
|  | 75 | } | 
|  | 76 |  | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 77 | void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) { | 
| Chet Haase | e7d2295 | 2010-11-11 16:30:16 -0800 | [diff] [blame] | 78 | Mutex::Autolock _l(mLock); | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 79 | incrementRefcountLocked(resource, resourceType); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 80 | } | 
|  | 81 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 82 | void ResourceCache::incrementRefcount(const SkPath* pathResource) { | 
| Romain Guy | 49c5fc0 | 2012-05-15 11:10:01 -0700 | [diff] [blame] | 83 | incrementRefcount((void*) pathResource, kPath); | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 84 | } | 
|  | 85 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 86 | void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) { | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 87 | incrementRefcount((void*) patchResource, kNinePatch); | 
|  | 88 | } | 
|  | 89 |  | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 90 | void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) { | 
| Romain Guy | 8dcfd5e | 2012-07-20 11:36:03 -0700 | [diff] [blame] | 91 | ssize_t index = mCache->indexOfKey(resource); | 
| Chris Craik | d41c4d8 | 2015-01-05 15:51:13 -0800 | [diff] [blame] | 92 | ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; | 
|  | 93 | if (ref == nullptr || mCache->size() == 0) { | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 94 | ref = new ResourceReference(resourceType); | 
|  | 95 | mCache->add(resource, ref); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 96 | } | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 97 | ref->refCount++; | 
|  | 98 | } | 
|  | 99 |  | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 100 | void ResourceCache::decrementRefcount(void* resource) { | 
|  | 101 | Mutex::Autolock _l(mLock); | 
|  | 102 | decrementRefcountLocked(resource); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 103 | } | 
|  | 104 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 105 | void ResourceCache::decrementRefcount(const SkBitmap* bitmapResource) { | 
| Derek Sollenberger | 3d4eed7 | 2014-12-04 15:20:29 -0500 | [diff] [blame] | 106 | Mutex::Autolock _l(mLock); | 
|  | 107 | decrementRefcountLocked(bitmapResource); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 108 | } | 
|  | 109 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 110 | void ResourceCache::decrementRefcount(const SkPath* pathResource) { | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 111 | decrementRefcount((void*) pathResource); | 
|  | 112 | } | 
|  | 113 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 114 | void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) { | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 115 | decrementRefcount((void*) patchResource); | 
|  | 116 | } | 
|  | 117 |  | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 118 | void ResourceCache::decrementRefcountLocked(void* resource) { | 
| Romain Guy | 8dcfd5e | 2012-07-20 11:36:03 -0700 | [diff] [blame] | 119 | ssize_t index = mCache->indexOfKey(resource); | 
| Chris Craik | d41c4d8 | 2015-01-05 15:51:13 -0800 | [diff] [blame] | 120 | ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; | 
|  | 121 | if (ref == nullptr) { | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 122 | // Should not get here - shouldn't get a call to decrement if we're not yet tracking it | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 123 | return; | 
|  | 124 | } | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 125 | ref->refCount--; | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 126 | if (ref->refCount == 0) { | 
| Romain Guy | 97dc917 | 2012-09-23 17:46:45 -0700 | [diff] [blame] | 127 | deleteResourceReferenceLocked(resource, ref); | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 128 | } | 
|  | 129 | } | 
|  | 130 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 131 | void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) { | 
| Derek Sollenberger | 3d4eed7 | 2014-12-04 15:20:29 -0500 | [diff] [blame] | 132 | BitmapKey bitmapKey(bitmapResource); | 
|  | 133 | ssize_t index = mBitmapCache.indexOfKey(bitmapKey); | 
|  | 134 |  | 
|  | 135 | LOG_ALWAYS_FATAL_IF(index == NAME_NOT_FOUND, | 
|  | 136 | "Decrementing the reference of an untracked Bitmap"); | 
|  | 137 |  | 
|  | 138 | const BitmapKey& cacheEntry = mBitmapCache.keyAt(index); | 
|  | 139 | if (cacheEntry.mRefCount == 1) { | 
|  | 140 | // delete the bitmap and remove it from the cache | 
|  | 141 | delete mBitmapCache.valueAt(index); | 
|  | 142 | mBitmapCache.removeItemsAt(index); | 
|  | 143 | } else { | 
|  | 144 | cacheEntry.mRefCount--; | 
|  | 145 | } | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 146 | } | 
|  | 147 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 148 | void ResourceCache::decrementRefcountLocked(const SkPath* pathResource) { | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 149 | decrementRefcountLocked((void*) pathResource); | 
|  | 150 | } | 
|  | 151 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 152 | void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) { | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 153 | decrementRefcountLocked((void*) patchResource); | 
|  | 154 | } | 
|  | 155 |  | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 156 | void ResourceCache::destructor(SkPath* resource) { | 
|  | 157 | Mutex::Autolock _l(mLock); | 
| Romain Guy | 58ecc20 | 2012-09-07 11:58:36 -0700 | [diff] [blame] | 158 | destructorLocked(resource); | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | void ResourceCache::destructorLocked(SkPath* resource) { | 
| Romain Guy | 8dcfd5e | 2012-07-20 11:36:03 -0700 | [diff] [blame] | 162 | ssize_t index = mCache->indexOfKey(resource); | 
| Chris Craik | d41c4d8 | 2015-01-05 15:51:13 -0800 | [diff] [blame] | 163 | ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; | 
|  | 164 | if (ref == nullptr) { | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 165 | // If we're not tracking this resource, just delete it | 
|  | 166 | if (Caches::hasInstance()) { | 
|  | 167 | Caches::getInstance().pathCache.removeDeferred(resource); | 
| Sangkyu Lee | 36fad8f | 2014-01-09 14:11:57 +0900 | [diff] [blame] | 168 | } else { | 
|  | 169 | delete resource; | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 170 | } | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 171 | return; | 
|  | 172 | } | 
|  | 173 | ref->destroyed = true; | 
|  | 174 | if (ref->refCount == 0) { | 
| Romain Guy | 97dc917 | 2012-09-23 17:46:45 -0700 | [diff] [blame] | 175 | deleteResourceReferenceLocked(resource, ref); | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 176 | } | 
|  | 177 | } | 
|  | 178 |  | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 179 | void ResourceCache::destructor(Res_png_9patch* resource) { | 
|  | 180 | Mutex::Autolock _l(mLock); | 
|  | 181 | destructorLocked(resource); | 
|  | 182 | } | 
|  | 183 |  | 
|  | 184 | void ResourceCache::destructorLocked(Res_png_9patch* resource) { | 
|  | 185 | ssize_t index = mCache->indexOfKey(resource); | 
| Chris Craik | d41c4d8 | 2015-01-05 15:51:13 -0800 | [diff] [blame] | 186 | ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr; | 
|  | 187 | if (ref == nullptr) { | 
| Sangkyu Lee | 36fad8f | 2014-01-09 14:11:57 +0900 | [diff] [blame] | 188 | // If we're not tracking this resource, just delete it | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 189 | if (Caches::hasInstance()) { | 
|  | 190 | Caches::getInstance().patchCache.removeDeferred(resource); | 
| Sangkyu Lee | 36fad8f | 2014-01-09 14:11:57 +0900 | [diff] [blame] | 191 | } else { | 
|  | 192 | // A Res_png_9patch is actually an array of byte that's larger | 
|  | 193 | // than sizeof(Res_png_9patch). It must be freed as an array. | 
|  | 194 | delete[] (int8_t*) resource; | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 195 | } | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 196 | return; | 
|  | 197 | } | 
|  | 198 | ref->destroyed = true; | 
|  | 199 | if (ref->refCount == 0) { | 
|  | 200 | deleteResourceReferenceLocked(resource, ref); | 
|  | 201 | } | 
|  | 202 | } | 
|  | 203 |  | 
| Chet Haase | 547e665 | 2012-10-22 15:07:26 -0700 | [diff] [blame] | 204 | /** | 
| Chet Haase | e7d2295 | 2010-11-11 16:30:16 -0800 | [diff] [blame] | 205 | * This method should only be called while the mLock mutex is held (that mutex is grabbed | 
|  | 206 | * by the various destructor() and recycle() methods which call this method). | 
|  | 207 | */ | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 208 | void ResourceCache::deleteResourceReferenceLocked(const void* resource, ResourceReference* ref) { | 
| John Reck | 0e89e2b | 2014-10-31 14:49:06 -0700 | [diff] [blame] | 209 | if (ref->destroyed) { | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 210 | switch (ref->resourceType) { | 
| Romain Guy | d586ad9 | 2011-06-22 16:14:36 -0700 | [diff] [blame] | 211 | case kPath: { | 
|  | 212 | SkPath* path = (SkPath*) resource; | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 213 | if (Caches::hasInstance()) { | 
|  | 214 | Caches::getInstance().pathCache.removeDeferred(path); | 
| Sangkyu Lee | 36fad8f | 2014-01-09 14:11:57 +0900 | [diff] [blame] | 215 | } else { | 
|  | 216 | delete path; | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 217 | } | 
| Chet Haase | 5a7e828 | 2011-02-04 12:50:55 -0800 | [diff] [blame] | 218 | } | 
|  | 219 | break; | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 220 | case kNinePatch: { | 
|  | 221 | if (Caches::hasInstance()) { | 
|  | 222 | Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource); | 
| Sangkyu Lee | 36fad8f | 2014-01-09 14:11:57 +0900 | [diff] [blame] | 223 | } else { | 
|  | 224 | // A Res_png_9patch is actually an array of byte that's larger | 
|  | 225 | // than sizeof(Res_png_9patch). It must be freed as an array. | 
|  | 226 | int8_t* patch = (int8_t*) resource; | 
|  | 227 | delete[] patch; | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 228 | } | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 229 | } | 
|  | 230 | break; | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 231 | } | 
|  | 232 | } | 
|  | 233 | mCache->removeItem(resource); | 
|  | 234 | delete ref; | 
|  | 235 | } | 
|  | 236 |  | 
| Derek Sollenberger | 3d4eed7 | 2014-12-04 15:20:29 -0500 | [diff] [blame] | 237 | /////////////////////////////////////////////////////////////////////////////// | 
|  | 238 | // Bitmap Key | 
|  | 239 | /////////////////////////////////////////////////////////////////////////////// | 
|  | 240 |  | 
|  | 241 | void BitmapKey::operator=(const BitmapKey& other) { | 
|  | 242 | this->mRefCount = other.mRefCount; | 
|  | 243 | this->mBitmapDimensions = other.mBitmapDimensions; | 
|  | 244 | this->mPixelRefOrigin = other.mPixelRefOrigin; | 
|  | 245 | this->mPixelRefStableID = other.mPixelRefStableID; | 
|  | 246 | } | 
|  | 247 |  | 
|  | 248 | bool BitmapKey::operator==(const BitmapKey& other) const { | 
|  | 249 | return mPixelRefStableID == other.mPixelRefStableID && | 
|  | 250 | mPixelRefOrigin == other.mPixelRefOrigin && | 
|  | 251 | mBitmapDimensions == other.mBitmapDimensions; | 
|  | 252 | } | 
|  | 253 |  | 
|  | 254 | bool BitmapKey::operator<(const BitmapKey& other) const { | 
|  | 255 | if (mPixelRefStableID != other.mPixelRefStableID) { | 
|  | 256 | return mPixelRefStableID < other.mPixelRefStableID; | 
|  | 257 | } | 
|  | 258 | if (mPixelRefOrigin.x() != other.mPixelRefOrigin.x()) { | 
|  | 259 | return mPixelRefOrigin.x() < other.mPixelRefOrigin.x(); | 
|  | 260 | } | 
|  | 261 | if (mPixelRefOrigin.y() != other.mPixelRefOrigin.y()) { | 
|  | 262 | return mPixelRefOrigin.y() < other.mPixelRefOrigin.y(); | 
|  | 263 | } | 
|  | 264 | if (mBitmapDimensions.width() != other.mBitmapDimensions.width()) { | 
|  | 265 | return mBitmapDimensions.width() < other.mBitmapDimensions.width(); | 
|  | 266 | } | 
|  | 267 | return mBitmapDimensions.height() < other.mBitmapDimensions.height(); | 
|  | 268 | } | 
|  | 269 |  | 
| Chet Haase | 5c13d89 | 2010-10-08 08:37:55 -0700 | [diff] [blame] | 270 | }; // namespace uirenderer | 
|  | 271 | }; // namespace android |