Home | History | Annotate | Download | only in hwui
      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 
     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 
     39 ResourceCache::ResourceCache() {
     40     Mutex::Autolock _l(mLock);
     41     mCache = new KeyedVector<void*, ResourceReference*>();
     42 }
     43 
     44 ResourceCache::~ResourceCache() {
     45     Mutex::Autolock _l(mLock);
     46     delete mCache;
     47 }
     48 
     49 void ResourceCache::lock() {
     50     mLock.lock();
     51 }
     52 
     53 void ResourceCache::unlock() {
     54     mLock.unlock();
     55 }
     56 
     57 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
     58     Mutex::Autolock _l(mLock);
     59     incrementRefcountLocked(resource, resourceType);
     60 }
     61 
     62 void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
     63     SkSafeRef(bitmapResource->pixelRef());
     64     SkSafeRef(bitmapResource->getColorTable());
     65     incrementRefcount((void*) bitmapResource, kBitmap);
     66 }
     67 
     68 void ResourceCache::incrementRefcount(SkPath* pathResource) {
     69     incrementRefcount((void*) pathResource, kPath);
     70 }
     71 
     72 void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
     73     SkSafeRef(shaderResource->getSkShader());
     74     incrementRefcount((void*) shaderResource, kShader);
     75 }
     76 
     77 void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
     78     SkSafeRef(filterResource->getSkColorFilter());
     79     incrementRefcount((void*) filterResource, kColorFilter);
     80 }
     81 
     82 void ResourceCache::incrementRefcount(Layer* layerResource) {
     83     incrementRefcount((void*) layerResource, kLayer);
     84 }
     85 
     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 
     96 void ResourceCache::incrementRefcountLocked(SkBitmap* bitmapResource) {
     97     SkSafeRef(bitmapResource->pixelRef());
     98     SkSafeRef(bitmapResource->getColorTable());
     99     incrementRefcountLocked((void*) bitmapResource, kBitmap);
    100 }
    101 
    102 void ResourceCache::incrementRefcountLocked(SkPath* pathResource) {
    103     incrementRefcountLocked((void*) pathResource, kPath);
    104 }
    105 
    106 void ResourceCache::incrementRefcountLocked(SkiaShader* shaderResource) {
    107     SkSafeRef(shaderResource->getSkShader());
    108     incrementRefcountLocked((void*) shaderResource, kShader);
    109 }
    110 
    111 void ResourceCache::incrementRefcountLocked(SkiaColorFilter* filterResource) {
    112     SkSafeRef(filterResource->getSkColorFilter());
    113     incrementRefcountLocked((void*) filterResource, kColorFilter);
    114 }
    115 
    116 void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
    117     incrementRefcountLocked((void*) layerResource, kLayer);
    118 }
    119 
    120 void ResourceCache::decrementRefcount(void* resource) {
    121     Mutex::Autolock _l(mLock);
    122     decrementRefcountLocked(resource);
    123 }
    124 
    125 void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
    126     SkSafeUnref(bitmapResource->pixelRef());
    127     SkSafeUnref(bitmapResource->getColorTable());
    128     decrementRefcount((void*) bitmapResource);
    129 }
    130 
    131 void ResourceCache::decrementRefcount(SkPath* pathResource) {
    132     decrementRefcount((void*) pathResource);
    133 }
    134 
    135 void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
    136     SkSafeUnref(shaderResource->getSkShader());
    137     decrementRefcount((void*) shaderResource);
    138 }
    139 
    140 void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
    141     SkSafeUnref(filterResource->getSkColorFilter());
    142     decrementRefcount((void*) filterResource);
    143 }
    144 
    145 void ResourceCache::decrementRefcount(Layer* layerResource) {
    146     decrementRefcount((void*) layerResource);
    147 }
    148 
    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 
    162 void ResourceCache::decrementRefcountLocked(SkBitmap* bitmapResource) {
    163     SkSafeUnref(bitmapResource->pixelRef());
    164     SkSafeUnref(bitmapResource->getColorTable());
    165     decrementRefcountLocked((void*) bitmapResource);
    166 }
    167 
    168 void ResourceCache::decrementRefcountLocked(SkPath* pathResource) {
    169     decrementRefcountLocked((void*) pathResource);
    170 }
    171 
    172 void ResourceCache::decrementRefcountLocked(SkiaShader* shaderResource) {
    173     SkSafeUnref(shaderResource->getSkShader());
    174     decrementRefcountLocked((void*) shaderResource);
    175 }
    176 
    177 void ResourceCache::decrementRefcountLocked(SkiaColorFilter* filterResource) {
    178     SkSafeUnref(filterResource->getSkColorFilter());
    179     decrementRefcountLocked((void*) filterResource);
    180 }
    181 
    182 void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
    183     decrementRefcountLocked((void*) layerResource);
    184 }
    185 
    186 void ResourceCache::destructor(SkPath* resource) {
    187     Mutex::Autolock _l(mLock);
    188     destructorLocked(resource);
    189 }
    190 
    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 
    208 void ResourceCache::destructor(SkBitmap* resource) {
    209     Mutex::Autolock _l(mLock);
    210     destructorLocked(resource);
    211 }
    212 
    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 
    230 void ResourceCache::destructor(SkiaShader* resource) {
    231     Mutex::Autolock _l(mLock);
    232     destructorLocked(resource);
    233 }
    234 
    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 
    249 void ResourceCache::destructor(SkiaColorFilter* resource) {
    250     Mutex::Autolock _l(mLock);
    251     destructorLocked(resource);
    252 }
    253 
    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  */
    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  */
    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  */
    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