| /* | 
 |  * Copyright (C) 2010 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #ifndef ANDROID_HWUI_GRADIENT_CACHE_H | 
 | #define ANDROID_HWUI_GRADIENT_CACHE_H | 
 |  | 
 | #include <memory> | 
 |  | 
 | #include <GLES3/gl3.h> | 
 |  | 
 | #include <SkShader.h> | 
 |  | 
 | #include <utils/LruCache.h> | 
 | #include <utils/Mutex.h> | 
 |  | 
 | #include "FloatColor.h" | 
 |  | 
 | namespace android { | 
 | namespace uirenderer { | 
 |  | 
 | class Texture; | 
 |  | 
 | struct GradientCacheEntry { | 
 |     GradientCacheEntry() { | 
 |         count = 0; | 
 |         colors = nullptr; | 
 |         positions = nullptr; | 
 |     } | 
 |  | 
 |     GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) { | 
 |         copy(colors, positions, count); | 
 |     } | 
 |  | 
 |     GradientCacheEntry(const GradientCacheEntry& entry) { | 
 |         copy(entry.colors.get(), entry.positions.get(), entry.count); | 
 |     } | 
 |  | 
 |     GradientCacheEntry& operator=(const GradientCacheEntry& entry) { | 
 |         if (this != &entry) { | 
 |             copy(entry.colors.get(), entry.positions.get(), entry.count); | 
 |         } | 
 |  | 
 |         return *this; | 
 |     } | 
 |  | 
 |     hash_t hash() const; | 
 |  | 
 |     static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs); | 
 |  | 
 |     bool operator==(const GradientCacheEntry& other) const { | 
 |         return compare(*this, other) == 0; | 
 |     } | 
 |  | 
 |     bool operator!=(const GradientCacheEntry& other) const { | 
 |         return compare(*this, other) != 0; | 
 |     } | 
 |  | 
 |     std::unique_ptr<uint32_t[]> colors; | 
 |     std::unique_ptr<float[]> positions; | 
 |     uint32_t count; | 
 |  | 
 | private: | 
 |     void copy(uint32_t* colors, float* positions, uint32_t count) { | 
 |         this->count = count; | 
 |         this->colors.reset(new uint32_t[count]); | 
 |         this->positions.reset(new float[count]); | 
 |  | 
 |         memcpy(this->colors.get(), colors, count * sizeof(uint32_t)); | 
 |         memcpy(this->positions.get(), positions, count * sizeof(float)); | 
 |     } | 
 |  | 
 | }; // GradientCacheEntry | 
 |  | 
 | // Caching support | 
 |  | 
 | inline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { | 
 |     return GradientCacheEntry::compare(lhs, rhs) < 0; | 
 | } | 
 |  | 
 | inline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) { | 
 |     return GradientCacheEntry::compare(lhs, rhs); | 
 | } | 
 |  | 
 | inline hash_t hash_type(const GradientCacheEntry& entry) { | 
 |     return entry.hash(); | 
 | } | 
 |  | 
 | /** | 
 |  * A simple LRU gradient cache. The cache has a maximum size expressed in bytes. | 
 |  * Any texture added to the cache causing the cache to grow beyond the maximum | 
 |  * allowed size will also cause the oldest texture to be kicked out. | 
 |  */ | 
 | class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> { | 
 | public: | 
 |     explicit GradientCache(Extensions& extensions); | 
 |     ~GradientCache(); | 
 |  | 
 |     /** | 
 |      * Used as a callback when an entry is removed from the cache. | 
 |      * Do not invoke directly. | 
 |      */ | 
 |     void operator()(GradientCacheEntry& shader, Texture*& texture) override; | 
 |  | 
 |     /** | 
 |      * Returns the texture associated with the specified shader. | 
 |      */ | 
 |     Texture* get(uint32_t* colors, float* positions, int count); | 
 |  | 
 |     /** | 
 |      * Clears the cache. This causes all textures to be deleted. | 
 |      */ | 
 |     void clear(); | 
 |  | 
 |     /** | 
 |      * Returns the maximum size of the cache in bytes. | 
 |      */ | 
 |     uint32_t getMaxSize(); | 
 |     /** | 
 |      * Returns the current size of the cache in bytes. | 
 |      */ | 
 |     uint32_t getSize(); | 
 |  | 
 | private: | 
 |     /** | 
 |      * Adds a new linear gradient to the cache. The generated texture is | 
 |      * returned. | 
 |      */ | 
 |     Texture* addLinearGradient(GradientCacheEntry& gradient, | 
 |             uint32_t* colors, float* positions, int count); | 
 |  | 
 |     void generateTexture(uint32_t* colors, float* positions, | 
 |             const uint32_t width, const uint32_t height, Texture* texture); | 
 |  | 
 |     struct GradientInfo { | 
 |         uint32_t width; | 
 |         bool hasAlpha; | 
 |     }; | 
 |  | 
 |     void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info); | 
 |  | 
 |     size_t bytesPerPixel() const; | 
 |     size_t sourceBytesPerPixel() const; | 
 |  | 
 |     typedef void (GradientCache::*ChannelMixer)(const FloatColor& start, const FloatColor& end, | 
 |             float amount, uint8_t*& dst) const; | 
 |  | 
 |     void mixBytes(const FloatColor& start, const FloatColor& end, | 
 |             float amount, uint8_t*& dst) const; | 
 |     void mixFloats(const FloatColor& start, const FloatColor& end, | 
 |             float amount, uint8_t*& dst) const; | 
 |  | 
 |     LruCache<GradientCacheEntry, Texture*> mCache; | 
 |  | 
 |     uint32_t mSize; | 
 |     const uint32_t mMaxSize; | 
 |  | 
 |     GLint mMaxTextureSize; | 
 |     bool mUseFloatTexture; | 
 |     bool mHasNpot; | 
 |     bool mHasLinearBlending; | 
 |  | 
 |     mutable Mutex mLock; | 
 | }; // class GradientCache | 
 |  | 
 | }; // namespace uirenderer | 
 | }; // namespace android | 
 |  | 
 | #endif // ANDROID_HWUI_GRADIENT_CACHE_H |