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 <GLES2/gl2.h>
     21 
     22 #include <utils/LruCache.h>
     23 #include <utils/Mutex.h>
     24 #include <utils/Vector.h>
     25 
     26 #include "Debug.h"
     27 #include "Properties.h"
     28 #include "Texture.h"
     29 #include "utils/Macros.h"
     30 #include "utils/Pair.h"
     31 
     32 class SkBitmap;
     33 class SkCanvas;
     34 class SkPaint;
     35 class SkPath;
     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): Texture(caches) {
     63     }
     64 
     65     ~PathTexture() {
     66         clearTask();
     67     }
     68 
     69     /**
     70      * Left coordinate of the path bounds.
     71      */
     72     float left;
     73     /**
     74      * Top coordinate of the path bounds.
     75      */
     76     float top;
     77     /**
     78      * Offset to draw the path at the correct origin.
     79      */
     80     float offset;
     81 
     82     sp<Task<SkBitmap*> > task() const {
     83         return mTask;
     84     }
     85 
     86     void setTask(const sp<Task<SkBitmap*> >& task) {
     87         mTask = task;
     88     }
     89 
     90     void clearTask() {
     91         if (mTask != NULL) {
     92             mTask.clear();
     93         }
     94     }
     95 
     96 private:
     97     sp<Task<SkBitmap*> > mTask;
     98 }; // struct PathTexture
     99 
    100 enum ShapeType {
    101     kShapeNone,
    102     kShapeRect,
    103     kShapeRoundRect,
    104     kShapeCircle,
    105     kShapeOval,
    106     kShapeArc,
    107     kShapePath
    108 };
    109 
    110 struct PathDescription {
    111     DESCRIPTION_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             const SkPath* mPath;
    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     hash_t hash() const;
    153 };
    154 
    155 /**
    156  * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
    157  * Any texture added to the cache causing the cache to grow beyond the maximum
    158  * allowed size will also cause the oldest texture to be kicked out.
    159  */
    160 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> {
    161 public:
    162     PathCache();
    163     ~PathCache();
    164 
    165     /**
    166      * Used as a callback when an entry is removed from the cache.
    167      * Do not invoke directly.
    168      */
    169     void operator()(PathDescription& path, PathTexture*& texture);
    170 
    171     /**
    172      * Clears the cache. This causes all textures to be deleted.
    173      */
    174     void clear();
    175 
    176     /**
    177      * Sets the maximum size of the cache in bytes.
    178      */
    179     void setMaxSize(uint32_t maxSize);
    180     /**
    181      * Returns the maximum size of the cache in bytes.
    182      */
    183     uint32_t getMaxSize();
    184     /**
    185      * Returns the current size of the cache in bytes.
    186      */
    187     uint32_t getSize();
    188 
    189     PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint);
    190     PathTexture* getCircle(float radius, const SkPaint* paint);
    191     PathTexture* getOval(float width, float height, const SkPaint* paint);
    192     PathTexture* getRect(float width, float height, const SkPaint* paint);
    193     PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
    194             bool useCenter, const SkPaint* paint);
    195     PathTexture* get(const SkPath* path, const SkPaint* paint);
    196 
    197     /**
    198      * Removes the specified path. This is meant to be called from threads
    199      * that are not the EGL context thread.
    200      */
    201     void removeDeferred(SkPath* path);
    202     /**
    203      * Process deferred removals.
    204      */
    205     void clearGarbage();
    206     /**
    207      * Trims the contents of the cache, removing items until it's under its
    208      * specified limit.
    209      *
    210      * Trimming is used for caches that support pre-caching from a worker
    211      * thread. During pre-caching the maximum limit of the cache can be
    212      * exceeded for the duration of the frame. It is therefore required to
    213      * trim the cache at the end of the frame to keep the total amount of
    214      * memory used under control.
    215      */
    216     void trim();
    217 
    218     /**
    219      * Precaches the specified path using background threads.
    220      */
    221     void precache(const SkPath* path, const SkPaint* paint);
    222 
    223     static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint);
    224     static void computePathBounds(const SkPath* path, const SkPaint* paint,
    225             float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
    226     static void computeBounds(const SkRect& bounds, const SkPaint* paint,
    227             float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
    228 
    229 private:
    230     typedef Pair<SkPath*, SkPath*> path_pair_t;
    231 
    232     PathTexture* addTexture(const PathDescription& entry,
    233             const SkPath *path, const SkPaint* paint);
    234     PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap);
    235 
    236     /**
    237      * Generates the texture from a bitmap into the specified texture structure.
    238      */
    239     void generateTexture(SkBitmap& bitmap, Texture* texture);
    240     void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture,
    241             bool addToCache = true);
    242 
    243     PathTexture* get(const PathDescription& entry) {
    244         return mCache.get(entry);
    245     }
    246 
    247     /**
    248      * Removes an entry.
    249      * The pair must define first=path, second=sourcePath
    250      */
    251     void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair);
    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 refcounted / guaranteed to survive for duration of task
    283         // TODO: avoid deep copy with refcounting
    284         const SkPath path;
    285 
    286         // copied, since input paint may not be immutable
    287         const SkPaint paint;
    288         PathTexture* texture;
    289     };
    290 
    291     class PathProcessor: public TaskProcessor<SkBitmap*> {
    292     public:
    293         PathProcessor(Caches& caches);
    294         ~PathProcessor() { }
    295 
    296         virtual void onProcess(const sp<Task<SkBitmap*> >& task);
    297 
    298     private:
    299         uint32_t mMaxTextureSize;
    300     };
    301 
    302     LruCache<PathDescription, PathTexture*> mCache;
    303     uint32_t mSize;
    304     uint32_t mMaxSize;
    305     GLuint mMaxTextureSize;
    306 
    307     bool mDebugEnabled;
    308 
    309     sp<PathProcessor> mProcessor;
    310 
    311     Vector<path_pair_t> mGarbage;
    312     mutable Mutex mLock;
    313 }; // class PathCache
    314 
    315 }; // namespace uirenderer
    316 }; // namespace android
    317 
    318 #endif // ANDROID_HWUI_PATH_CACHE_H
    319