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 631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck bool operator==(const GradientCacheEntry& other) const { return compare(*this, other) == 0; } 64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck bool operator!=(const GradientCacheEntry& other) const { return compare(*this, other) != 0; } 666203f6c8147069976342be8f42add797a50f9557Romain Guy 6751d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<uint32_t[]> colors; 6851d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<float[]> positions; 69059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy uint32_t count; 706203f6c8147069976342be8f42add797a50f9557Romain Guy 71e5df231434357424cea8d2b8d0cdf31253a98110Romain Guyprivate: 72059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy void copy(uint32_t* colors, float* positions, uint32_t count) { 73e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy this->count = count; 7451d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->colors.reset(new uint32_t[count]); 7551d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik this->positions.reset(new float[count]); 76e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 7751d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->colors.get(), colors, count * sizeof(uint32_t)); 7851d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik memcpy(this->positions.get(), positions, count * sizeof(float)); 79e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy } 80e5df231434357424cea8d2b8d0cdf31253a98110Romain Guy 811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}; // GradientCacheEntry 826203f6c8147069976342be8f42add797a50f9557Romain Guy 83059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Caching support 84059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 85059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 86059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs) < 0; 87059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 88059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 89059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { 90059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return GradientCacheEntry::compare(lhs, rhs); 91059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 92059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 93059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline hash_t hash_type(const GradientCacheEntry& entry) { 94059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy return entry.hash(); 95059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy} 96059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy 97c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy/** 98c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * A simple LRU gradient cache. The cache has a maximum size expressed in bytes. 99c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Any texture added to the cache causing the cache to grow beyond the maximum 100c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * allowed size will also cause the oldest texture to be kicked out. 101c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 1021bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckclass GradientCache : public OnEntryRemoved<GradientCacheEntry, Texture*> { 103c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guypublic: 1048dc02f99d09130ace2ee738c2e689db1b3f33181John Reck explicit GradientCache(const Extensions& extensions); 105c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy ~GradientCache(); 106c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 108c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Used as a callback when an entry is removed from the cache. 109c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Do not invoke directly. 110c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 111e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik void operator()(GradientCacheEntry& shader, Texture*& texture) override; 112c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 113c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the texture associated with the specified shader. 115c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 11642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy Texture* get(uint32_t* colors, float* positions, int count); 11742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 118fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy /** 119c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Clears the cache. This causes all textures to be deleted. 120c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 121c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy void clear(); 122c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the maximum size of the cache in bytes. 125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 126c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getMaxSize(); 127c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy /** 128c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy * Returns the current size of the cache in bytes. 129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy */ 130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t getSize(); 131c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 132c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guyprivate: 1336203f6c8147069976342be8f42add797a50f9557Romain Guy /** 1346203f6c8147069976342be8f42add797a50f9557Romain Guy * Adds a new linear gradient to the cache. The generated texture is 1356203f6c8147069976342be8f42add797a50f9557Romain Guy * returned. 1366203f6c8147069976342be8f42add797a50f9557Romain Guy */ 1371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Texture* addLinearGradient(GradientCacheEntry& gradient, uint32_t* colors, float* positions, 1381bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int count); 13942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 1401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck void generateTexture(uint32_t* colors, float* positions, const uint32_t width, 1411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const uint32_t height, Texture* texture); 14242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy 14342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy struct GradientInfo { 14442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy uint32_t width; 14542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy bool hasAlpha; 14642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy }; 1476203f6c8147069976342be8f42add797a50f9557Romain Guy 14842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info); 149c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 150b48800428906ae455c2b63acacd44e390e1fee49Romain Guy size_t bytesPerPixel() const; 151253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy size_t sourceBytesPerPixel() const; 152b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 1538762e332e3797fb41929a1c6069207f4906ca329Romain Guy typedef void (GradientCache::*ChannelMixer)(const FloatColor& start, const FloatColor& end, 1541bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck float amount, uint8_t*& dst) const; 155b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 1561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck void mixBytes(const FloatColor& start, const FloatColor& end, float amount, 1571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck uint8_t*& dst) const; 1581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck void mixFloats(const FloatColor& start, const FloatColor& end, float amount, 1591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck uint8_t*& dst) const; 160b48800428906ae455c2b63acacd44e390e1fee49Romain Guy 161059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy LruCache<GradientCacheEntry, Texture*> mCache; 162c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 163c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy uint32_t mSize; 16448a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik const uint32_t mMaxSize; 165a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 1668dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy GLint mMaxTextureSize; 167b48800428906ae455c2b63acacd44e390e1fee49Romain Guy bool mUseFloatTexture; 168b48800428906ae455c2b63acacd44e390e1fee49Romain Guy bool mHasNpot; 169efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy bool mHasLinearBlending; 1708dcfd5e836341b4a803b04d104a930bb312182d3Romain Guy 171a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy mutable Mutex mLock; 1721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}; // class GradientCache 173c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 1741bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}; // namespace uirenderer 1751bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}; // namespace android 176c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 1771bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#endif // ANDROID_HWUI_GRADIENT_CACHE_H 178