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 29253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy#include "FloatColor.h" 30253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy 31c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace android { 32c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guynamespace uirenderer { 33c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 342dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudsonclass Texture; 352dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson 366203f6c8147069976342be8f42add797a50f9557Romain Guystruct GradientCacheEntry { 376203f6c8147069976342be8f42add797a50f9557Romain Guy GradientCacheEntry() { 386203f6c8147069976342be8f42add797a50f9557Romain Guy count = 0; 39e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik colors = nullptr; 40e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik positions = nullptr; 416203f6c8147069976342be8f42add797a50f9557Romain Guy } 426203f6c8147069976342be8f42add797a50f9557Romain Guy 43059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) { 4442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy copy(colors, positions, count); 456203f6c8147069976342be8f42add797a50f9557Romain Guy } 466203f6c8147069976342be8f42add797a50f9557Romain Guy 476203f6c8147069976342be8f42add797a50f9557Romain Guy GradientCacheEntry(const GradientCacheEntry& entry) { 4851d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik copy(entry.colors.get(), entry.positions.get(), entry.count); 49e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 50e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 51e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy GradientCacheEntry& operator=(const GradientCacheEntry& entry) { 52e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy if (this != &entry) { 5351d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik copy(entry.colors.get(), entry.positions.get(), entry.count); 54e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 55e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 56e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy return *this; 576203f6c8147069976342be8f42add797a50f9557Romain Guy } 586203f6c8147069976342be8f42add797a50f9557Romain Guy 59059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy hash_t hash() const; 60059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 61059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs); 62059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 63059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy bool operator==(const GradientCacheEntry& other) const { 64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return compare(*this, other) == 0; 65059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy } 66059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 67059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy bool operator!=(const GradientCacheEntry& other) const { 68059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return compare(*this, other) != 0; 696203f6c8147069976342be8f42add797a50f9557Romain Guy } 706203f6c8147069976342be8f42add797a50f9557Romain Guy 7151d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<uint32_t[]> colors; 7251d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<float[]> positions; 73059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy uint32_t count; 746203f6c8147069976342be8f42add797a50f9557Romain Guy 75e5df231434357424cea8d2b8d0cdf31253a98110Romain Guyprivate: 76059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy void copy(uint32_t* colors, float* positions, uint32_t count) { 77e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy this->count = count; 7851d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->colors.reset(new uint32_t[count]); 7951d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->positions.reset(new float[count]); 80e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 8151d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->colors.get(), colors, count * sizeof(uint32_t)); 8251d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->positions.get(), positions, count * sizeof(float)); 83e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 84e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 856203f6c8147069976342be8f42add797a50f9557Romain Guy}; // GradientCacheEntry 866203f6c8147069976342be8f42add797a50f9557Romain Guy 87059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Caching support 88059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 89059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 90059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs) < 0; 91059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 92059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 93059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 94059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs); 95059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 96059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 97059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline hash_t hash_type(const GradientCacheEntry& entry) { 98059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return entry.hash(); 99059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 100059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 101c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/** 102c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * A simple LRU gradient cache. The cache has a maximum size expressed in bytes. 103c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Any texture added to the cache causing the cache to grow beyond the maximum 104c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * allowed size will also cause the oldest texture to be kicked out. 105c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 1066203f6c8147069976342be8f42add797a50f9557Romain Guyclass GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> { 107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guypublic: 108faecb78a6b11c780db47bc940ca7662899ab5d5eChih-Hung Hsieh explicit GradientCache(Extensions& extensions); 109c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy ~GradientCache(); 110c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 111c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 112c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Used as a callback when an entry is removed from the cache. 113c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Do not invoke directly. 114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 115e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik void operator()(GradientCacheEntry& shader, Texture*& texture) override; 116c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 117c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 118c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the texture associated with the specified shader. 119c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 12042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy Texture* get(uint32_t* colors, float* positions, int count); 12142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 122fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy /** 123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Clears the cache. This causes all textures to be deleted. 124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy void clear(); 126c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 127c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 128c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the maximum size of the cache in bytes. 129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getMaxSize(); 131c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 132c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the current size of the cache in bytes. 133c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 134c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getSize(); 135c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 136c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyprivate: 1376203f6c8147069976342be8f42add797a50f9557Romain Guy /** 1386203f6c8147069976342be8f42add797a50f9557Romain Guy * Adds a new linear gradient to the cache. The generated texture is 1396203f6c8147069976342be8f42add797a50f9557Romain Guy * returned. 1406203f6c8147069976342be8f42add797a50f9557Romain Guy */ 1416203f6c8147069976342be8f42add797a50f9557Romain Guy Texture* addLinearGradient(GradientCacheEntry& gradient, 14242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t* colors, float* positions, int count); 14342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 14438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck void generateTexture(uint32_t* colors, float* positions, 14538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const uint32_t width, const uint32_t height, Texture* texture); 14642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 14742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy struct GradientInfo { 14842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t width; 14942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy bool hasAlpha; 15042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy }; 1516203f6c8147069976342be8f42add797a50f9557Romain Guy 15242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info); 153c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 154b48800428906ae455c2b63acacd44e390e1fee49Romain Guy size_t bytesPerPixel() const; 155253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy size_t sourceBytesPerPixel() const; 156b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 1578762e332e3797fb41929a1c6069207f4906ca329Romain Guy typedef void (GradientCache::*ChannelMixer)(const FloatColor& start, const FloatColor& end, 158b48800428906ae455c2b63acacd44e390e1fee49Romain Guy float amount, uint8_t*& dst) const; 159b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 1608762e332e3797fb41929a1c6069207f4906ca329Romain Guy void mixBytes(const FloatColor& start, const FloatColor& end, 1618762e332e3797fb41929a1c6069207f4906ca329Romain Guy float amount, uint8_t*& dst) const; 1628762e332e3797fb41929a1c6069207f4906ca329Romain Guy void mixFloats(const FloatColor& start, const FloatColor& end, 1638762e332e3797fb41929a1c6069207f4906ca329Romain Guy float amount, uint8_t*& dst) const; 164b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 165059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy LruCache<GradientCacheEntry, Texture*> mCache; 166c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 167c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t mSize; 16848a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik const uint32_t mMaxSize; 169a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 1708dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy GLint mMaxTextureSize; 171b48800428906ae455c2b63acacd44e390e1fee49Romain Guy bool mUseFloatTexture; 172b48800428906ae455c2b63acacd44e390e1fee49Romain Guy bool mHasNpot; 173efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy bool mHasLinearBlending; 1748dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy 175a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy mutable Mutex mLock; 176c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // class GradientCache 177c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 178c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace uirenderer 179c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy}; // namespace android 180c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 1815b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_GRADIENT_CACHE_H 182