GradientCache.h revision 38e0c32852e3b9d8ca4a9d3791577f52536419cb
1c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/* 2c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Copyright (C) 2010 The Android Open Source Project 3c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * 4c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * you may not use this file except in compliance with the License. 6c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * You may obtain a copy of the License at 7c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * 8c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * http://www.apache.org/licenses/LICENSE-2.0 9c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * 10c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Unless required by applicable law or agreed to in writing, software 11c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * See the License for the specific language governing permissions and 14c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * limitations under the License. 15c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 16c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#ifndef ANDROID_HWUI_GRADIENT_CACHE_H 185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#define ANDROID_HWUI_GRADIENT_CACHE_H 19c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 2096a5c4c7bab6718524de7253da8309143ab48befChris Craik#include <memory> 2196a5c4c7bab6718524de7253da8309143ab48befChris Craik 22b48800428906ae455c2b63acacd44e390e1fee49Romain Guy#include <GLES3/gl3.h> 238dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy 24c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#include <SkShader.h> 25c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 26059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy#include <utils/LruCache.h> 27029f64303b8fe506ef34c12777da86b830d3bf7aDerek Sollenberger#include <utils/Mutex.h> 28fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 29c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace android { 30c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace uirenderer { 31c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 322dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudsonclass Texture; 332dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson 346203f6c8147069976342be8f42add797a50f9557Romain Guystruct GradientCacheEntry { 356203f6c8147069976342be8f42add797a50f9557Romain Guy GradientCacheEntry() { 366203f6c8147069976342be8f42add797a50f9557Romain Guy count = 0; 37e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik colors = nullptr; 38e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik positions = nullptr; 396203f6c8147069976342be8f42add797a50f9557Romain Guy } 406203f6c8147069976342be8f42add797a50f9557Romain Guy 41059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) { 4242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy copy(colors, positions, count); 436203f6c8147069976342be8f42add797a50f9557Romain Guy } 446203f6c8147069976342be8f42add797a50f9557Romain Guy 456203f6c8147069976342be8f42add797a50f9557Romain Guy GradientCacheEntry(const GradientCacheEntry& entry) { 4651d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik copy(entry.colors.get(), entry.positions.get(), entry.count); 47e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 48e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 49e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy GradientCacheEntry& operator=(const GradientCacheEntry& entry) { 50e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy if (this != &entry) { 5151d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik copy(entry.colors.get(), entry.positions.get(), entry.count); 52e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 53e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 54e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy return *this; 556203f6c8147069976342be8f42add797a50f9557Romain Guy } 566203f6c8147069976342be8f42add797a50f9557Romain Guy 57059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy hash_t hash() const; 58059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 59059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs); 60059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 61059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy bool operator==(const GradientCacheEntry& other) const { 62059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return compare(*this, other) == 0; 63059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy } 64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 65059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy bool operator!=(const GradientCacheEntry& other) const { 66059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return compare(*this, other) != 0; 676203f6c8147069976342be8f42add797a50f9557Romain Guy } 686203f6c8147069976342be8f42add797a50f9557Romain Guy 6951d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<uint32_t[]> colors; 7051d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<float[]> positions; 71059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy uint32_t count; 726203f6c8147069976342be8f42add797a50f9557Romain Guy 73e5df231434357424cea8d2b8d0cdf31253a98110Romain Guyprivate: 74059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy void copy(uint32_t* colors, float* positions, uint32_t count) { 75e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy this->count = count; 7651d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->colors.reset(new uint32_t[count]); 7751d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->positions.reset(new float[count]); 78e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 7951d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->colors.get(), colors, count * sizeof(uint32_t)); 8051d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->positions.get(), positions, count * sizeof(float)); 81e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 82e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 836203f6c8147069976342be8f42add797a50f9557Romain Guy}; // GradientCacheEntry 846203f6c8147069976342be8f42add797a50f9557Romain Guy 85059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Caching support 86059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 87059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 88059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs) < 0; 89059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 90059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 91059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 92059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs); 93059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 94059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 95059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline hash_t hash_type(const GradientCacheEntry& entry) { 96059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return entry.hash(); 97059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 98059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 99c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/** 100c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * A simple LRU gradient cache. The cache has a maximum size expressed in bytes. 101c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Any texture added to the cache causing the cache to grow beyond the maximum 102c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * allowed size will also cause the oldest texture to be kicked out. 103c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 1046203f6c8147069976342be8f42add797a50f9557Romain Guyclass GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> { 105c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guypublic: 106117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik GradientCache(Extensions& extensions); 107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy ~GradientCache(); 108c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 109c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 110c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Used as a callback when an entry is removed from the cache. 111c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Do not invoke directly. 112c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 113e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik void operator()(GradientCacheEntry& shader, Texture*& texture) override; 114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 115c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 116c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the texture associated with the specified shader. 117c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 11842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy Texture* get(uint32_t* colors, float* positions, int count); 11942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 120fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy /** 121c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Clears the cache. This causes all textures to be deleted. 122c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy void clear(); 124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 126c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Sets the maximum size of the cache in bytes. 127c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 128c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy void setMaxSize(uint32_t maxSize); 129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the maximum size of the cache in bytes. 131c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 132c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getMaxSize(); 133c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 134c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the current size of the cache in bytes. 135c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 136c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getSize(); 137c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 138c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyprivate: 1396203f6c8147069976342be8f42add797a50f9557Romain Guy /** 1406203f6c8147069976342be8f42add797a50f9557Romain Guy * Adds a new linear gradient to the cache. The generated texture is 1416203f6c8147069976342be8f42add797a50f9557Romain Guy * returned. 1426203f6c8147069976342be8f42add797a50f9557Romain Guy */ 1436203f6c8147069976342be8f42add797a50f9557Romain Guy Texture* addLinearGradient(GradientCacheEntry& gradient, 14442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t* colors, float* positions, int count); 14542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 14638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck void generateTexture(uint32_t* colors, float* positions, 14738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const uint32_t width, const uint32_t height, Texture* texture); 14842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 14942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy struct GradientInfo { 15042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t width; 15142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy bool hasAlpha; 15242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy }; 1536203f6c8147069976342be8f42add797a50f9557Romain Guy 15442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info); 155c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 156b48800428906ae455c2b63acacd44e390e1fee49Romain Guy size_t bytesPerPixel() const; 157b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 158b48800428906ae455c2b63acacd44e390e1fee49Romain Guy struct GradientColor { 159b48800428906ae455c2b63acacd44e390e1fee49Romain Guy float r; 160b48800428906ae455c2b63acacd44e390e1fee49Romain Guy float g; 161b48800428906ae455c2b63acacd44e390e1fee49Romain Guy float b; 162b48800428906ae455c2b63acacd44e390e1fee49Romain Guy float a; 163b48800428906ae455c2b63acacd44e390e1fee49Romain Guy }; 164b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 165b48800428906ae455c2b63acacd44e390e1fee49Romain Guy typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor, 166b48800428906ae455c2b63acacd44e390e1fee49Romain Guy GradientColor& outColor) const; 167b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 168b48800428906ae455c2b63acacd44e390e1fee49Romain Guy void splitToBytes(uint32_t inColor, GradientColor& outColor) const; 169b48800428906ae455c2b63acacd44e390e1fee49Romain Guy void splitToFloats(uint32_t inColor, GradientColor& outColor) const; 170b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 171b48800428906ae455c2b63acacd44e390e1fee49Romain Guy typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end, 172b48800428906ae455c2b63acacd44e390e1fee49Romain Guy float amount, uint8_t*& dst) const; 173b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 174b48800428906ae455c2b63acacd44e390e1fee49Romain Guy void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const; 175b48800428906ae455c2b63acacd44e390e1fee49Romain Guy void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const; 176b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 177059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy LruCache<GradientCacheEntry, Texture*> mCache; 178c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 179c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t mSize; 180c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t mMaxSize; 181a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 1828dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy GLint mMaxTextureSize; 183b48800428906ae455c2b63acacd44e390e1fee49Romain Guy bool mUseFloatTexture; 184b48800428906ae455c2b63acacd44e390e1fee49Romain Guy bool mHasNpot; 1858dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy 186a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy mutable Mutex mLock; 187c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // class GradientCache 188c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 189c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace uirenderer 190c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace android 191c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 1925b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_GRADIENT_CACHE_H 193