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