blob: f95d2be3acf99ffa3caf279e70369a11e14da65c [file] [log] [blame]
Romain Guy1e45aae2010-08-13 19:39:53 -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#define LOG_TAG "OpenGLRenderer"
18
19#include "TextDropShadowCache.h"
20
21namespace android {
22namespace uirenderer {
23
24///////////////////////////////////////////////////////////////////////////////
25// Constructors/destructor
26///////////////////////////////////////////////////////////////////////////////
27
Romain Guyfb8b7632010-08-23 21:05:08 -070028TextDropShadowCache::TextDropShadowCache():
29 mCache(GenerationCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity),
30 mSize(0), mMaxSize(MB(DEFAULT_DROP_SHADOW_CACHE_SIZE)) {
31 char property[PROPERTY_VALUE_MAX];
32 if (property_get(PROPERTY_DROP_SHADOW_CACHE_SIZE, property, NULL) > 0) {
33 LOGD(" Setting drop shadow cache size to %sMB", property);
34 setMaxSize(MB(atof(property)));
35 } else {
36 LOGD(" Using default drop shadow cache size of %.2fMB", DEFAULT_DROP_SHADOW_CACHE_SIZE);
37 }
38
39 mCache.setOnEntryRemovedListener(this);
40}
41
Romain Guy1e45aae2010-08-13 19:39:53 -070042TextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize):
43 mCache(GenerationCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity),
44 mSize(0), mMaxSize(maxByteSize) {
45 mCache.setOnEntryRemovedListener(this);
46}
47
48TextDropShadowCache::~TextDropShadowCache() {
49 mCache.clear();
50}
51
52///////////////////////////////////////////////////////////////////////////////
53// Size management
54///////////////////////////////////////////////////////////////////////////////
55
56uint32_t TextDropShadowCache::getSize() {
57 return mSize;
58}
59
60uint32_t TextDropShadowCache::getMaxSize() {
61 return mMaxSize;
62}
63
64void TextDropShadowCache::setMaxSize(uint32_t maxSize) {
65 mMaxSize = maxSize;
66 while (mSize > mMaxSize) {
67 mCache.removeOldest();
68 }
69}
70
71///////////////////////////////////////////////////////////////////////////////
72// Callbacks
73///////////////////////////////////////////////////////////////////////////////
74
75void TextDropShadowCache::operator()(ShadowText& text, ShadowTexture*& texture) {
76 const uint32_t size = texture->width * texture->height;
77 mSize -= size;
78
79 if (texture) {
80 glDeleteTextures(1, &texture->id);
81 delete texture;
82 }
83}
84
85///////////////////////////////////////////////////////////////////////////////
86// Caching
87///////////////////////////////////////////////////////////////////////////////
88
89void TextDropShadowCache::clear() {
90 mCache.clear();
91}
92
93ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
94 int numGlyphs, uint32_t radius) {
95 ShadowText entry(paint, radius, len, text);
96 ShadowTexture* texture = mCache.get(entry);
97
98 if (!texture) {
99 FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0,
100 len, numGlyphs, radius);
101
102 texture = new ShadowTexture;
103 texture->left = shadow.penX;
104 texture->top = shadow.penY;
105 texture->width = shadow.width;
106 texture->height = shadow.height;
107 texture->generation = 0;
108 texture->blend = true;
109
110 const uint32_t size = shadow.width * shadow.height;
111 // Don't even try to cache a bitmap that's bigger than the cache
112 if (size < mMaxSize) {
113 while (mSize + size > mMaxSize) {
114 mCache.removeOldest();
115 }
116 }
117
118 glGenTextures(1, &texture->id);
119
120 glBindTexture(GL_TEXTURE_2D, texture->id);
121 // Textures are Alpha8
122 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
123
124 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
125 GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image);
126
127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
129
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
132
133 if (size < mMaxSize) {
134 mSize += size;
135 mCache.put(entry, texture);
136 } else {
137 texture->cleanup = true;
138 }
139
140 // Cleanup shadow
141 delete[] shadow.image;
142 }
143
144 return texture;
145}
146
147}; // namespace uirenderer
148}; // namespace android