ResourceCache.cpp revision fe48f65922d4a3cc4aefe058cee5acec51504a20
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    mCache = new KeyedVector<void *, ResourceReference *>();
41}
42
43ResourceCache::~ResourceCache() {
44    delete mCache;
45}
46
47void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
48    for (size_t i = 0; i < mCache->size(); ++i) {
49        void* ref = mCache->valueAt(i);
50    }
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
59void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
60    bitmapResource->pixelRef()->safeRef();
61    bitmapResource->getColorTable()->safeRef();
62    incrementRefcount((void*)bitmapResource, kBitmap);
63}
64
65void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
66    shaderResource->getSkShader()->safeRef();
67    incrementRefcount((void*)shaderResource, kShader);
68}
69
70void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
71    filterResource->getSkColorFilter()->safeRef();
72    incrementRefcount((void*)filterResource, kColorFilter);
73}
74
75void ResourceCache::decrementRefcount(void* resource) {
76    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
77    if (ref == NULL) {
78        // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
79        return;
80    }
81    ref->refCount--;
82    if (ref->refCount == 0) {
83        deleteResourceReference(resource, ref);
84    }
85}
86
87void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
88    bitmapResource->pixelRef()->safeUnref();
89    bitmapResource->getColorTable()->safeUnref();
90    decrementRefcount((void*)bitmapResource);
91}
92
93void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
94    shaderResource->getSkShader()->safeUnref();
95    decrementRefcount((void*)shaderResource);
96}
97
98void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
99    filterResource->getSkColorFilter()->safeUnref();
100    decrementRefcount((void*)filterResource);
101}
102
103void ResourceCache::recycle(SkBitmap* resource) {
104    if (mCache->indexOfKey(resource) < 0) {
105        // not tracking this resource; just recycle the pixel data
106        resource->setPixels(NULL, NULL);
107        return;
108    }
109    recycle((void*) resource);
110}
111
112void ResourceCache::recycle(void* resource) {
113    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
114    if (ref == NULL) {
115        // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
116        return;
117    }
118    ref->recycled = true;
119    if (ref->refCount == 0) {
120        deleteResourceReference(resource, ref);
121    }
122}
123
124void ResourceCache::destructor(SkBitmap* resource) {
125    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
126    if (ref == NULL) {
127        // If we're not tracking this resource, just delete it
128        if (Caches::hasInstance()) {
129            Caches::getInstance().textureCache.removeDeferred(resource);
130        }
131        delete resource;
132        return;
133    }
134    ref->destroyed = true;
135    if (ref->refCount == 0) {
136        deleteResourceReference(resource, ref);
137        return;
138    }
139}
140
141void ResourceCache::destructor(SkiaShader* resource) {
142    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
143    if (ref == NULL) {
144        // If we're not tracking this resource, just delete it
145        if (Caches::hasInstance()) {
146            Caches::getInstance().gradientCache.removeDeferred(resource->getSkShader());
147        }
148        delete resource;
149        return;
150    }
151    ref->destroyed = true;
152    if (ref->refCount == 0) {
153        deleteResourceReference(resource, ref);
154        return;
155    }
156}
157
158void ResourceCache::destructor(SkiaColorFilter* resource) {
159    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
160    if (ref == NULL) {
161        // If we're not tracking this resource, just delete it
162        delete resource;
163        return;
164    }
165    ref->destroyed = true;
166    if (ref->refCount == 0) {
167        deleteResourceReference(resource, ref);
168        return;
169    }
170}
171
172void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
173    if (ref->recycled && ref->resourceType == kBitmap) {
174        ((SkBitmap*) resource)->setPixels(NULL, NULL);
175    }
176    if (ref->destroyed) {
177        switch (ref->resourceType) {
178            case kBitmap:
179            {
180                SkBitmap* bitmap = (SkBitmap*)resource;
181                if (Caches::hasInstance()) {
182                    Caches::getInstance().textureCache.removeDeferred(bitmap);
183                }
184                delete bitmap;
185            }
186            break;
187            case kShader:
188            {
189                SkiaShader* shader = (SkiaShader*)resource;
190                if (Caches::hasInstance()) {
191                    Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader());
192                }
193                delete shader;
194            }
195            break;
196            case kColorFilter:
197            {
198                SkiaColorFilter* filter = (SkiaColorFilter*)resource;
199                delete filter;
200            }
201            break;
202        }
203    }
204    mCache->removeItem(resource);
205    delete ref;
206}
207
208}; // namespace uirenderer
209}; // namespace android
210