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