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 { 37 GradientCacheEntry() { 38 count = 0; 39 colors = nullptr; 40 positions = nullptr; 41 } 42 43 GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) { 44 copy(colors, positions, count); 45 } 46 47 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: 76 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 89 inline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 90 return GradientCacheEntry::compare(lhs, rhs) < 0; 91 } 92 93 inline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 94 return GradientCacheEntry::compare(lhs, rhs); 95 } 96 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