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 #ifndef ANDROID_HWUI_GRADIENT_CACHE_H
18 #define ANDROID_HWUI_GRADIENT_CACHE_H
19
20 #include <memory>
21
22 #include <GLES3/gl3.h>
23
24 #include <SkShader.h>
25
26 #include <utils/LruCache.h>
27 #include <utils/Mutex.h>
28 #include <utils/Vector.h>
29
30 namespace android {
31 namespace uirenderer {
32
33 class Texture;
34
35 struct GradientCacheEntry {
GradientCacheEntryGradientCacheEntry36 GradientCacheEntry() {
37 count = 0;
38 colors = nullptr;
39 positions = nullptr;
40 }
41
GradientCacheEntryGradientCacheEntry42 GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) {
43 copy(colors, positions, count);
44 }
45
GradientCacheEntryGradientCacheEntry46 GradientCacheEntry(const GradientCacheEntry& entry) {
47 copy(entry.colors.get(), entry.positions.get(), entry.count);
48 }
49
50 GradientCacheEntry& operator=(const GradientCacheEntry& entry) {
51 if (this != &entry) {
52 copy(entry.colors.get(), entry.positions.get(), entry.count);
53 }
54
55 return *this;
56 }
57
58 hash_t hash() const;
59
60 static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs);
61
62 bool operator==(const GradientCacheEntry& other) const {
63 return compare(*this, other) == 0;
64 }
65
66 bool operator!=(const GradientCacheEntry& other) const {
67 return compare(*this, other) != 0;
68 }
69
70 std::unique_ptr<uint32_t[]> colors;
71 std::unique_ptr<float[]> positions;
72 uint32_t count;
73
74 private:
copyGradientCacheEntry75 void copy(uint32_t* colors, float* positions, uint32_t count) {
76 this->count = count;
77 this->colors.reset(new uint32_t[count]);
78 this->positions.reset(new float[count]);
79
80 memcpy(this->colors.get(), colors, count * sizeof(uint32_t));
81 memcpy(this->positions.get(), positions, count * sizeof(float));
82 }
83
84 }; // GradientCacheEntry
85
86 // Caching support
87
strictly_order_type(const GradientCacheEntry & lhs,const GradientCacheEntry & rhs)88 inline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
89 return GradientCacheEntry::compare(lhs, rhs) < 0;
90 }
91
compare_type(const GradientCacheEntry & lhs,const GradientCacheEntry & rhs)92 inline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
93 return GradientCacheEntry::compare(lhs, rhs);
94 }
95
hash_type(const GradientCacheEntry & entry)96 inline hash_t hash_type(const GradientCacheEntry& entry) {
97 return entry.hash();
98 }
99
100 /**
101 * A simple LRU gradient cache. The cache has a maximum size expressed in bytes.
102 * Any texture added to the cache causing the cache to grow beyond the maximum
103 * allowed size will also cause the oldest texture to be kicked out.
104 */
105 class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
106 public:
107 GradientCache(Extensions& extensions);
108 ~GradientCache();
109
110 /**
111 * Used as a callback when an entry is removed from the cache.
112 * Do not invoke directly.
113 */
114 void operator()(GradientCacheEntry& shader, Texture*& texture) override;
115
116 /**
117 * Returns the texture associated with the specified shader.
118 */
119 Texture* get(uint32_t* colors, float* positions, int count);
120
121 /**
122 * Clears the cache. This causes all textures to be deleted.
123 */
124 void clear();
125
126 /**
127 * Sets the maximum size of the cache in bytes.
128 */
129 void setMaxSize(uint32_t maxSize);
130 /**
131 * Returns the maximum size of the cache in bytes.
132 */
133 uint32_t getMaxSize();
134 /**
135 * Returns the current size of the cache in bytes.
136 */
137 uint32_t getSize();
138
139 private:
140 /**
141 * Adds a new linear gradient to the cache. The generated texture is
142 * returned.
143 */
144 Texture* addLinearGradient(GradientCacheEntry& gradient,
145 uint32_t* colors, float* positions, int count);
146
147 void generateTexture(uint32_t* colors, float* positions, Texture* texture);
148
149 struct GradientInfo {
150 uint32_t width;
151 bool hasAlpha;
152 };
153
154 void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
155
156 size_t bytesPerPixel() const;
157
158 struct GradientColor {
159 float r;
160 float g;
161 float b;
162 float a;
163 };
164
165 typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor,
166 GradientColor& outColor) const;
167
168 void splitToBytes(uint32_t inColor, GradientColor& outColor) const;
169 void splitToFloats(uint32_t inColor, GradientColor& outColor) const;
170
171 typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end,
172 float amount, uint8_t*& dst) const;
173
174 void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
175 void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
176
177 LruCache<GradientCacheEntry, Texture*> mCache;
178
179 uint32_t mSize;
180 uint32_t mMaxSize;
181
182 GLint mMaxTextureSize;
183 bool mUseFloatTexture;
184 bool mHasNpot;
185
186 Vector<SkShader*> mGarbage;
187 mutable Mutex mLock;
188 }; // class GradientCache
189
190 }; // namespace uirenderer
191 }; // namespace android
192
193 #endif // ANDROID_HWUI_GRADIENT_CACHE_H
194