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