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#include <utils/Vector.h> 29fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 30c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace android { 31c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace uirenderer { 32c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 332dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudsonclass Texture; 342dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson 356203f6c8147069976342be8f42add797a50f9557Romain Guystruct GradientCacheEntry { 366203f6c8147069976342be8f42add797a50f9557Romain Guy GradientCacheEntry() { 376203f6c8147069976342be8f42add797a50f9557Romain Guy count = 0; 38e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik colors = nullptr; 39e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik positions = nullptr; 406203f6c8147069976342be8f42add797a50f9557Romain Guy } 416203f6c8147069976342be8f42add797a50f9557Romain Guy 42059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) { 4342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy copy(colors, positions, count); 446203f6c8147069976342be8f42add797a50f9557Romain Guy } 456203f6c8147069976342be8f42add797a50f9557Romain Guy 466203f6c8147069976342be8f42add797a50f9557Romain Guy GradientCacheEntry(const GradientCacheEntry& entry) { 4751d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik copy(entry.colors.get(), entry.positions.get(), entry.count); 48e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 49e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 50e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy GradientCacheEntry& operator=(const GradientCacheEntry& entry) { 51e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy if (this != &entry) { 5251d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik copy(entry.colors.get(), entry.positions.get(), entry.count); 53e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 54e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 55e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy return *this; 566203f6c8147069976342be8f42add797a50f9557Romain Guy } 576203f6c8147069976342be8f42add797a50f9557Romain Guy 58059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy hash_t hash() const; 59059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 60059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs); 61059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 62059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy bool operator==(const GradientCacheEntry& other) const { 63059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return compare(*this, other) == 0; 64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy } 65059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 66059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy bool operator!=(const GradientCacheEntry& other) const { 67059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return compare(*this, other) != 0; 686203f6c8147069976342be8f42add797a50f9557Romain Guy } 696203f6c8147069976342be8f42add797a50f9557Romain Guy 7051d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<uint32_t[]> colors; 7151d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<float[]> positions; 72059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy uint32_t count; 736203f6c8147069976342be8f42add797a50f9557Romain Guy 74e5df231434357424cea8d2b8d0cdf31253a98110Romain Guyprivate: 75059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy void copy(uint32_t* colors, float* positions, uint32_t count) { 76e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy this->count = count; 7751d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->colors.reset(new uint32_t[count]); 7851d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->positions.reset(new float[count]); 79e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 8051d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->colors.get(), colors, count * sizeof(uint32_t)); 8151d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->positions.get(), positions, count * sizeof(float)); 82e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 83e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 846203f6c8147069976342be8f42add797a50f9557Romain Guy}; // GradientCacheEntry 856203f6c8147069976342be8f42add797a50f9557Romain Guy 86059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Caching support 87059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 88059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 89059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs) < 0; 90059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 91059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 92059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 93059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs); 94059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 95059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 96059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline hash_t hash_type(const GradientCacheEntry& entry) { 97059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return entry.hash(); 98059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 99059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 100c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/** 101c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * A simple LRU gradient cache. The cache has a maximum size expressed in bytes. 102c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Any texture added to the cache causing the cache to grow beyond the maximum 103c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * allowed size will also cause the oldest texture to be kicked out. 104c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 1056203f6c8147069976342be8f42add797a50f9557Romain Guyclass GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> { 106c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guypublic: 107117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik GradientCache(Extensions& extensions); 108c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy ~GradientCache(); 109c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 110c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 111c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Used as a callback when an entry is removed from the cache. 112c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Do not invoke directly. 113c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 114e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik void operator()(GradientCacheEntry& shader, Texture*& texture) override; 115c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 116c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 117c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the texture associated with the specified shader. 118c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 11942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy Texture* get(uint32_t* colors, float* positions, int count); 12042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 121fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy /** 122c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Clears the cache. This causes all textures to be deleted. 123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy void clear(); 125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 126c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 127c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Sets the maximum size of the cache in bytes. 128c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy void setMaxSize(uint32_t maxSize); 130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 131c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the maximum size of the cache in bytes. 132c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 133c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getMaxSize(); 134c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 135c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the current size of the cache in bytes. 136c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 137c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getSize(); 138c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 139c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyprivate: 1406203f6c8147069976342be8f42add797a50f9557Romain Guy /** 1416203f6c8147069976342be8f42add797a50f9557Romain Guy * Adds a new linear gradient to the cache. The generated texture is 1426203f6c8147069976342be8f42add797a50f9557Romain Guy * returned. 1436203f6c8147069976342be8f42add797a50f9557Romain Guy */ 1446203f6c8147069976342be8f42add797a50f9557Romain Guy Texture* addLinearGradient(GradientCacheEntry& gradient, 14542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t* colors, float* positions, int count); 14642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 147e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik void generateTexture(uint32_t* colors, float* positions, 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 186fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy Vector<SkShader*> mGarbage; 187a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy mutable Mutex mLock; 188c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // class GradientCache 189c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 190c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace uirenderer 191c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace android 192c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 1935b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_GRADIENT_CACHE_H 194