Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ANDROID_HWUI_GRADIENT_CACHE_H
     18 #define ANDROID_HWUI_GRADIENT_CACHE_H
     19 
     20 #include <GLES3/gl3.h>
     21 
     22 #include <SkShader.h>
     23 
     24 #include <utils/LruCache.h>
     25 #include <utils/Mutex.h>
     26 #include <utils/Vector.h>
     27 
     28 #include "Texture.h"
     29 
     30 namespace android {
     31 namespace uirenderer {
     32 
     33 struct GradientCacheEntry {
     34     GradientCacheEntry() {
     35         count = 0;
     36         colors = NULL;
     37         positions = NULL;
     38     }
     39 
     40     GradientCacheEntry(uint32_t* colors, float* positions, uint32_t count) {
     41         copy(colors, positions, count);
     42     }
     43 
     44     GradientCacheEntry(const GradientCacheEntry& entry) {
     45         copy(entry.colors, entry.positions, entry.count);
     46     }
     47 
     48     ~GradientCacheEntry() {
     49         delete[] colors;
     50         delete[] positions;
     51     }
     52 
     53     GradientCacheEntry& operator=(const GradientCacheEntry& entry) {
     54         if (this != &entry) {
     55             delete[] colors;
     56             delete[] positions;
     57 
     58             copy(entry.colors, entry.positions, entry.count);
     59         }
     60 
     61         return *this;
     62     }
     63 
     64     hash_t hash() const;
     65 
     66     static int compare(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs);
     67 
     68     bool operator==(const GradientCacheEntry& other) const {
     69         return compare(*this, other) == 0;
     70     }
     71 
     72     bool operator!=(const GradientCacheEntry& other) const {
     73         return compare(*this, other) != 0;
     74     }
     75 
     76     uint32_t* colors;
     77     float* positions;
     78     uint32_t count;
     79 
     80 private:
     81     void copy(uint32_t* colors, float* positions, uint32_t count) {
     82         this->count = count;
     83         this->colors = new uint32_t[count];
     84         this->positions = new float[count];
     85 
     86         memcpy(this->colors, colors, count * sizeof(uint32_t));
     87         memcpy(this->positions, positions, count * sizeof(float));
     88     }
     89 
     90 }; // GradientCacheEntry
     91 
     92 // Caching support
     93 
     94 inline int strictly_order_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
     95     return GradientCacheEntry::compare(lhs, rhs) < 0;
     96 }
     97 
     98 inline int compare_type(const GradientCacheEntry& lhs, const GradientCacheEntry& rhs) {
     99     return GradientCacheEntry::compare(lhs, rhs);
    100 }
    101 
    102 inline hash_t hash_type(const GradientCacheEntry& entry) {
    103     return entry.hash();
    104 }
    105 
    106 /**
    107  * A simple LRU gradient cache. The cache has a maximum size expressed in bytes.
    108  * Any texture added to the cache causing the cache to grow beyond the maximum
    109  * allowed size will also cause the oldest texture to be kicked out.
    110  */
    111 class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
    112 public:
    113     GradientCache();
    114     GradientCache(uint32_t maxByteSize);
    115     ~GradientCache();
    116 
    117     /**
    118      * Used as a callback when an entry is removed from the cache.
    119      * Do not invoke directly.
    120      */
    121     void operator()(GradientCacheEntry& shader, Texture*& texture);
    122 
    123     /**
    124      * Returns the texture associated with the specified shader.
    125      */
    126     Texture* get(uint32_t* colors, float* positions, int count);
    127 
    128     /**
    129      * Clears the cache. This causes all textures to be deleted.
    130      */
    131     void clear();
    132 
    133     /**
    134      * Sets the maximum size of the cache in bytes.
    135      */
    136     void setMaxSize(uint32_t maxSize);
    137     /**
    138      * Returns the maximum size of the cache in bytes.
    139      */
    140     uint32_t getMaxSize();
    141     /**
    142      * Returns the current size of the cache in bytes.
    143      */
    144     uint32_t getSize();
    145 
    146 private:
    147     /**
    148      * Adds a new linear gradient to the cache. The generated texture is
    149      * returned.
    150      */
    151     Texture* addLinearGradient(GradientCacheEntry& gradient,
    152             uint32_t* colors, float* positions, int count);
    153 
    154     void generateTexture(uint32_t* colors, float* positions, Texture* texture);
    155 
    156     struct GradientInfo {
    157         uint32_t width;
    158         bool hasAlpha;
    159     };
    160 
    161     void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
    162 
    163     size_t bytesPerPixel() const;
    164 
    165     struct GradientColor {
    166         float r;
    167         float g;
    168         float b;
    169         float a;
    170     };
    171 
    172     typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor,
    173             GradientColor& outColor) const;
    174 
    175     void splitToBytes(uint32_t inColor, GradientColor& outColor) const;
    176     void splitToFloats(uint32_t inColor, GradientColor& outColor) const;
    177 
    178     typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end,
    179             float amount, uint8_t*& dst) const;
    180 
    181     void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
    182     void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
    183 
    184     LruCache<GradientCacheEntry, Texture*> mCache;
    185 
    186     uint32_t mSize;
    187     uint32_t mMaxSize;
    188 
    189     GLint mMaxTextureSize;
    190     bool mUseFloatTexture;
    191     bool mHasNpot;
    192 
    193     Vector<SkShader*> mGarbage;
    194     mutable Mutex mLock;
    195 }; // class GradientCache
    196 
    197 }; // namespace uirenderer
    198 }; // namespace android
    199 
    200 #endif // ANDROID_HWUI_GRADIENT_CACHE_H
    201