Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2013 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_PATH_CACHE_H
     18 #define ANDROID_HWUI_PATH_CACHE_H
     19 
     20 #include "Debug.h"
     21 #include "Texture.h"
     22 #include "hwui/Bitmap.h"
     23 #include "thread/Task.h"
     24 #include "thread/TaskProcessor.h"
     25 #include "utils/Macros.h"
     26 #include "utils/Pair.h"
     27 
     28 #include <GLES2/gl2.h>
     29 #include <SkPaint.h>
     30 #include <SkPath.h>
     31 #include <utils/LruCache.h>
     32 #include <utils/Mutex.h>
     33 
     34 #include <vector>
     35 
     36 class SkCanvas;
     37 class SkPaint;
     38 struct SkRect;
     39 
     40 namespace android {
     41 namespace uirenderer {
     42 
     43 class Caches;
     44 ///////////////////////////////////////////////////////////////////////////////
     45 // Defines
     46 ///////////////////////////////////////////////////////////////////////////////
     47 
     48 // Debug
     49 #if DEBUG_PATHS
     50 #define PATH_LOGD(...) ALOGD(__VA_ARGS__)
     51 #else
     52 #define PATH_LOGD(...)
     53 #endif
     54 
     55 ///////////////////////////////////////////////////////////////////////////////
     56 // Classes
     57 ///////////////////////////////////////////////////////////////////////////////
     58 
     59 struct PathTexture;
     60 class PathTask : public Task<sk_sp<Bitmap>> {
     61 public:
     62     PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture)
     63             : path(*path), paint(*paint), texture(texture) {}
     64 
     65     // copied, since input path not guaranteed to survive for duration of task
     66     const SkPath path;
     67 
     68     // copied, since input paint may not be immutable
     69     const SkPaint paint;
     70     PathTexture* texture;
     71 };
     72 
     73 /**
     74  * Alpha texture used to represent a path.
     75  */
     76 struct PathTexture : public Texture {
     77     PathTexture(Caches& caches, int generation) : Texture(caches) { this->generation = generation; }
     78 
     79     ~PathTexture() { clearTask(); }
     80 
     81     /**
     82      * Left coordinate of the path bounds.
     83      */
     84     float left = 0;
     85     /**
     86      * Top coordinate of the path bounds.
     87      */
     88     float top = 0;
     89     /**
     90      * Offset to draw the path at the correct origin.
     91      */
     92     float offset = 0;
     93 
     94     sp<PathTask> task() const { return mTask; }
     95 
     96     void setTask(const sp<PathTask>& task) { mTask = task; }
     97 
     98     void clearTask() {
     99         if (mTask != nullptr) {
    100             mTask.clear();
    101         }
    102     }
    103 
    104 private:
    105     sp<PathTask> mTask;
    106 };  // struct PathTexture
    107 
    108 enum class ShapeType { None, Rect, RoundRect, Circle, Oval, Arc, Path };
    109 
    110 struct PathDescription {
    111     HASHABLE_TYPE(PathDescription);
    112     ShapeType type;
    113     SkPaint::Join join;
    114     SkPaint::Cap cap;
    115     SkPaint::Style style;
    116     float miter;
    117     float strokeWidth;
    118     SkPathEffect* pathEffect;
    119     union Shape {
    120         struct Path {
    121             uint32_t mGenerationID;
    122         } path;
    123         struct RoundRect {
    124             float mWidth;
    125             float mHeight;
    126             float mRx;
    127             float mRy;
    128         } roundRect;
    129         struct Circle {
    130             float mRadius;
    131         } circle;
    132         struct Oval {
    133             float mWidth;
    134             float mHeight;
    135         } oval;
    136         struct Rect {
    137             float mWidth;
    138             float mHeight;
    139         } rect;
    140         struct Arc {
    141             float mWidth;
    142             float mHeight;
    143             float mStartAngle;
    144             float mSweepAngle;
    145             bool mUseCenter;
    146         } arc;
    147     } shape;
    148 
    149     PathDescription();
    150     PathDescription(ShapeType shapeType, const SkPaint* paint);
    151 };
    152 
    153 /**
    154  * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
    155  * Any texture added to the cache causing the cache to grow beyond the maximum
    156  * allowed size will also cause the oldest texture to be kicked out.
    157  */
    158 class PathCache : public OnEntryRemoved<PathDescription, PathTexture*> {
    159 public:
    160     PathCache();
    161     ~PathCache();
    162 
    163     /**
    164      * Used as a callback when an entry is removed from the cache.
    165      * Do not invoke directly.
    166      */
    167     void operator()(PathDescription& path, PathTexture*& texture) override;
    168 
    169     /**
    170      * Clears the cache. This causes all textures to be deleted.
    171      */
    172     void clear();
    173 
    174     /**
    175      * Returns the maximum size of the cache in bytes.
    176      */
    177     uint32_t getMaxSize();
    178     /**
    179      * Returns the current size of the cache in bytes.
    180      */
    181     uint32_t getSize();
    182 
    183     PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint);
    184     PathTexture* getCircle(float radius, const SkPaint* paint);
    185     PathTexture* getOval(float width, float height, const SkPaint* paint);
    186     PathTexture* getRect(float width, float height, const SkPaint* paint);
    187     PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
    188                         bool useCenter, const SkPaint* paint);
    189     PathTexture* get(const SkPath* path, const SkPaint* paint);
    190     void remove(const SkPath* path, const SkPaint* paint);
    191 
    192     /**
    193      * Removes the specified path. This is meant to be called from threads
    194      * that are not the EGL context thread.
    195      */
    196     ANDROID_API void removeDeferred(const SkPath* path);
    197     /**
    198      * Process deferred removals.
    199      */
    200     void clearGarbage();
    201     /**
    202      * Trims the contents of the cache, removing items until it's under its
    203      * specified limit.
    204      *
    205      * Trimming is used for caches that support pre-caching from a worker
    206      * thread. During pre-caching the maximum limit of the cache can be
    207      * exceeded for the duration of the frame. It is therefore required to
    208      * trim the cache at the end of the frame to keep the total amount of
    209      * memory used under control.
    210      */
    211     void trim();
    212 
    213     /**
    214      * Precaches the specified path using background threads.
    215      */
    216     void precache(const SkPath* path, const SkPaint* paint);
    217 
    218 private:
    219     PathTexture* addTexture(const PathDescription& entry, const SkPath* path, const SkPaint* paint);
    220 
    221     /**
    222      * Generates the texture from a bitmap into the specified texture structure.
    223      */
    224     void generateTexture(Bitmap& bitmap, Texture* texture);
    225     void generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture,
    226                          bool addToCache = true);
    227 
    228     PathTexture* get(const PathDescription& entry) { return mCache.get(entry); }
    229 
    230     /**
    231      * Ensures there is enough space in the cache for a texture of the specified
    232      * dimensions.
    233      */
    234     void purgeCache(uint32_t width, uint32_t height);
    235 
    236     void removeTexture(PathTexture* texture);
    237 
    238     void init();
    239 
    240     class PathProcessor : public TaskProcessor<sk_sp<Bitmap>> {
    241     public:
    242         explicit PathProcessor(Caches& caches);
    243         ~PathProcessor() {}
    244 
    245         virtual void onProcess(const sp<Task<sk_sp<Bitmap>>>& task) override;
    246 
    247     private:
    248         uint32_t mMaxTextureSize;
    249     };
    250 
    251     LruCache<PathDescription, PathTexture*> mCache;
    252     uint32_t mSize;
    253     const uint32_t mMaxSize;
    254     GLuint mMaxTextureSize;
    255 
    256     bool mDebugEnabled;
    257 
    258     sp<PathProcessor> mProcessor;
    259 
    260     std::vector<uint32_t> mGarbage;
    261     mutable Mutex mLock;
    262 };  // class PathCache
    263 
    264 };  // namespace uirenderer
    265 };  // namespace android
    266 
    267 #endif  // ANDROID_HWUI_PATH_CACHE_H
    268