• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
PathTexturePathTexture62      PathTexture(Caches& caches): Texture(caches) {
63      }
64  
~PathTexturePathTexture65      ~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  
taskPathTexture82      sp<Task<SkBitmap*> > task() const {
83          return mTask;
84      }
85  
setTaskPathTexture86      void setTask(const sp<Task<SkBitmap*> >& task) {
87          mTask = task;
88      }
89  
clearTaskPathTexture90      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  
get(const PathDescription & entry)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  
checkTextureSize(uint32_t width,uint32_t height)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:
PathTask(const SkPath * path,const SkPaint * paint,PathTexture * texture)274          PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture):
275              path(*path), paint(*paint), texture(texture) {
276          }
277  
~PathTask()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);
~PathProcessor()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