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