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