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