GradientCache.h revision 96a5c4c7bab6718524de7253da8309143ab48bef
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 30namespace android { 31namespace uirenderer { 32 33class Texture; 34 35struct GradientCacheEntry { 36 GradientCacheEntry() { 37 count = 0; 38 colors = nullptr; 39 positions = nullptr; 40 } 41 42 GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) { 43 copy(colors, positions, count); 44 } 45 46 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 74private: 75 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 88inline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 89 return GradientCacheEntry::compare(lhs, rhs) < 0; 90} 91 92inline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 93 return GradientCacheEntry::compare(lhs, rhs); 94} 95 96inline 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 */ 105class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> { 106public: 107 GradientCache(); 108 GradientCache(uint32_t maxByteSize); 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 * Sets the maximum size of the cache in bytes. 129 */ 130 void setMaxSize(uint32_t maxSize); 131 /** 132 * Returns the maximum size of the cache in bytes. 133 */ 134 uint32_t getMaxSize(); 135 /** 136 * Returns the current size of the cache in bytes. 137 */ 138 uint32_t getSize(); 139 140private: 141 /** 142 * Adds a new linear gradient to the cache. The generated texture is 143 * returned. 144 */ 145 Texture* addLinearGradient(GradientCacheEntry& gradient, 146 uint32_t* colors, float* positions, int count); 147 148 void generateTexture(uint32_t* colors, float* positions, Texture* texture); 149 150 struct GradientInfo { 151 uint32_t width; 152 bool hasAlpha; 153 }; 154 155 void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info); 156 157 size_t bytesPerPixel() const; 158 159 struct GradientColor { 160 float r; 161 float g; 162 float b; 163 float a; 164 }; 165 166 typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor, 167 GradientColor& outColor) const; 168 169 void splitToBytes(uint32_t inColor, GradientColor& outColor) const; 170 void splitToFloats(uint32_t inColor, GradientColor& outColor) const; 171 172 typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end, 173 float amount, uint8_t*& dst) const; 174 175 void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const; 176 void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const; 177 178 LruCache<GradientCacheEntry, Texture*> mCache; 179 180 uint32_t mSize; 181 uint32_t mMaxSize; 182 183 GLint mMaxTextureSize; 184 bool mUseFloatTexture; 185 bool mHasNpot; 186 187 Vector<SkShader*> mGarbage; 188 mutable Mutex mLock; 189}; // class GradientCache 190 191}; // namespace uirenderer 192}; // namespace android 193 194#endif // ANDROID_HWUI_GRADIENT_CACHE_H 195