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