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