blob: 5ebd2c0a14baba3beb944c8381ec2fba8c94b6f8 [file] [log] [blame]
Chet Haase5c13d892010-10-08 08:37:55 -07001/*
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() {
Chet Haasee7d22952010-11-11 16:30:16 -080040 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -070041 mCache = new KeyedVector<void *, ResourceReference *>();
42}
43
44ResourceCache::~ResourceCache() {
Chet Haasee7d22952010-11-11 16:30:16 -080045 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -070046 delete mCache;
47}
48
49void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
Chet Haasee7d22952010-11-11 16:30:16 -080050 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -070051 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
Chet Haase5c13d892010-10-08 08:37:55 -070068void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
69 shaderResource->getSkShader()->safeRef();
70 incrementRefcount((void*)shaderResource, kShader);
71}
72
Chet Haasead93c2b2010-10-22 16:17:12 -070073void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
74 filterResource->getSkColorFilter()->safeRef();
75 incrementRefcount((void*)filterResource, kColorFilter);
76}
77
Chet Haase5c13d892010-10-08 08:37:55 -070078void ResourceCache::decrementRefcount(void* resource) {
Chet Haasee7d22952010-11-11 16:30:16 -080079 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -070080 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
Chet Haasead93c2b2010-10-22 16:17:12 -0700102void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
103 filterResource->getSkColorFilter()->safeUnref();
104 decrementRefcount((void*)filterResource);
105}
106
Chet Haase5c13d892010-10-08 08:37:55 -0700107void ResourceCache::recycle(SkBitmap* resource) {
Chet Haasee7d22952010-11-11 16:30:16 -0800108 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -0700109 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) {
Chet Haasee7d22952010-11-11 16:30:16 -0800118 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -0700119 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) {
Chet Haasee7d22952010-11-11 16:30:16 -0800131 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -0700132 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()) {
Romain Guyfe48f652010-11-11 15:36:56 -0800136 Caches::getInstance().textureCache.removeDeferred(resource);
Chet Haase5c13d892010-10-08 08:37:55 -0700137 }
138 delete resource;
139 return;
140 }
141 ref->destroyed = true;
142 if (ref->refCount == 0) {
143 deleteResourceReference(resource, ref);
144 return;
145 }
146}
147
Chet Haase5c13d892010-10-08 08:37:55 -0700148void ResourceCache::destructor(SkiaShader* resource) {
Chet Haasee7d22952010-11-11 16:30:16 -0800149 Mutex::Autolock _l(mLock);
Chet Haase5c13d892010-10-08 08:37:55 -0700150 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()) {
Romain Guyfe48f652010-11-11 15:36:56 -0800154 Caches::getInstance().gradientCache.removeDeferred(resource->getSkShader());
Chet Haase5c13d892010-10-08 08:37:55 -0700155 }
156 delete resource;
157 return;
158 }
159 ref->destroyed = true;
160 if (ref->refCount == 0) {
161 deleteResourceReference(resource, ref);
162 return;
163 }
164}
165
Chet Haasead93c2b2010-10-22 16:17:12 -0700166void ResourceCache::destructor(SkiaColorFilter* resource) {
Chet Haasee7d22952010-11-11 16:30:16 -0800167 Mutex::Autolock _l(mLock);
Chet Haasead93c2b2010-10-22 16:17:12 -0700168 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
Chet Haasee7d22952010-11-11 16:30:16 -0800181/**
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 */
Chet Haase5c13d892010-10-08 08:37:55 -0700185void 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()) {
Romain Guyfe48f652010-11-11 15:36:56 -0800195 Caches::getInstance().textureCache.removeDeferred(bitmap);
Chet Haase5c13d892010-10-08 08:37:55 -0700196 }
197 delete bitmap;
198 }
199 break;
Chet Haase5c13d892010-10-08 08:37:55 -0700200 case kShader:
Chet Haasead93c2b2010-10-22 16:17:12 -0700201 {
Chet Haase5c13d892010-10-08 08:37:55 -0700202 SkiaShader* shader = (SkiaShader*)resource;
203 if (Caches::hasInstance()) {
Romain Guyfe48f652010-11-11 15:36:56 -0800204 Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader());
Chet Haase5c13d892010-10-08 08:37:55 -0700205 }
206 delete shader;
Chet Haasead93c2b2010-10-22 16:17:12 -0700207 }
208 break;
209 case kColorFilter:
210 {
211 SkiaColorFilter* filter = (SkiaColorFilter*)resource;
212 delete filter;
213 }
214 break;
Chet Haase5c13d892010-10-08 08:37:55 -0700215 }
216 }
217 mCache->removeItem(resource);
218 delete ref;
219}
220
221}; // namespace uirenderer
222}; // namespace android