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 <SkShader.h>
     21 
     22 #include <utils/Vector.h>
     23 
     24 #include "Texture.h"
     25 #include "utils/Compare.h"
     26 #include "utils/GenerationCache.h"
     27 
     28 namespace android {
     29 namespace uirenderer {
     30 
     31 struct GradientCacheEntry {
     32     GradientCacheEntry() {
     33         count = 0;
     34         colors = NULL;
     35         positions = NULL;
     36         tileMode = SkShader::kClamp_TileMode;
     37     }
     38 
     39     GradientCacheEntry(uint32_t* colors, float* positions, int count,
     40             SkShader::TileMode tileMode) {
     41         copy(colors, positions, count, tileMode);
     42     }
     43 
     44     GradientCacheEntry(const GradientCacheEntry& entry) {
     45         copy(entry.colors, entry.positions, entry.count, entry.tileMode);
     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, entry.tileMode);
     59         }
     60 
     61         return *this;
     62     }
     63 
     64     bool operator<(const GradientCacheEntry& r) const {
     65         const GradientCacheEntry& rhs = (const GradientCacheEntry&) r;
     66         LTE_INT(count) {
     67             LTE_INT(tileMode) {
     68                 int result = memcmp(colors, rhs.colors, count * sizeof(uint32_t));
     69                 if (result< 0) return true;
     70                 else if (result == 0) {
     71                     result = memcmp(positions, rhs.positions, count * sizeof(float));
     72                     if (result < 0) return true;
     73                 }
     74             }
     75         }
     76         return false;
     77     }
     78 
     79     uint32_t* colors;
     80     float* positions;
     81     int count;
     82     SkShader::TileMode tileMode;
     83 
     84 private:
     85 
     86     void copy(uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) {
     87         this->count = count;
     88         this->colors = new uint32_t[count];
     89         this->positions = new float[count];
     90         this->tileMode = tileMode;
     91 
     92         memcpy(this->colors, colors, count * sizeof(uint32_t));
     93         memcpy(this->positions, positions, count * sizeof(float));
     94     }
     95 
     96 }; // GradientCacheEntry
     97 
     98 /**
     99  * A simple LRU gradient cache. The cache has a maximum size expressed in bytes.
    100  * Any texture added to the cache causing the cache to grow beyond the maximum
    101  * allowed size will also cause the oldest texture to be kicked out.
    102  */
    103 class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
    104 public:
    105     GradientCache();
    106     GradientCache(uint32_t maxByteSize);
    107     ~GradientCache();
    108 
    109     /**
    110      * Used as a callback when an entry is removed from the cache.
    111      * Do not invoke directly.
    112      */
    113     void operator()(GradientCacheEntry& shader, Texture*& texture);
    114 
    115     /**
    116      * Returns the texture associated with the specified shader.
    117      */
    118     Texture* get(uint32_t* colors, float* positions,
    119             int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
    120     /**
    121      * Clears the cache. This causes all textures to be deleted.
    122      */
    123     void clear();
    124 
    125     /**
    126      * Sets the maximum size of the cache in bytes.
    127      */
    128     void setMaxSize(uint32_t maxSize);
    129     /**
    130      * Returns the maximum size of the cache in bytes.
    131      */
    132     uint32_t getMaxSize();
    133     /**
    134      * Returns the current size of the cache in bytes.
    135      */
    136     uint32_t getSize();
    137 
    138 private:
    139     /**
    140      * Adds a new linear gradient to the cache. The generated texture is
    141      * returned.
    142      */
    143     Texture* addLinearGradient(GradientCacheEntry& gradient,
    144             uint32_t* colors, float* positions, int count,
    145             SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
    146 
    147     void generateTexture(SkBitmap* bitmap, Texture* texture);
    148 
    149     GenerationCache<GradientCacheEntry, Texture*> mCache;
    150 
    151     uint32_t mSize;
    152     uint32_t mMaxSize;
    153 
    154     Vector<SkShader*> mGarbage;
    155     mutable Mutex mLock;
    156 }; // class GradientCache
    157 
    158 }; // namespace uirenderer
    159 }; // namespace android
    160 
    161 #endif // ANDROID_HWUI_GRADIENT_CACHE_H
    162