Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2010 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkStrikeCache_DEFINED
      9 #define SkStrikeCache_DEFINED
     10 
     11 #include <unordered_map>
     12 #include <unordered_set>
     13 
     14 #include "SkDescriptor.h"
     15 #include "SkStrike.h"
     16 #include "SkSpinlock.h"
     17 #include "SkTemplates.h"
     18 
     19 class SkStrike;
     20 class SkTraceMemoryDump;
     21 
     22 #ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
     23     #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT   2048
     24 #endif
     25 
     26 #ifndef SK_DEFAULT_FONT_CACHE_LIMIT
     27     #define SK_DEFAULT_FONT_CACHE_LIMIT     (2 * 1024 * 1024)
     28 #endif
     29 
     30 #ifndef SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT
     31     #define SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT  256
     32 #endif
     33 
     34 ///////////////////////////////////////////////////////////////////////////////
     35 
     36 class SkStrikePinner {
     37 public:
     38     virtual ~SkStrikePinner() = default;
     39     virtual bool canDelete() = 0;
     40 };
     41 
     42 class SkStrikeCache {
     43     class Node;
     44 
     45 public:
     46     SkStrikeCache() = default;
     47     ~SkStrikeCache();
     48 
     49     class ExclusiveStrikePtr {
     50     public:
     51         explicit ExclusiveStrikePtr(Node*);
     52         ExclusiveStrikePtr();
     53         ExclusiveStrikePtr(const ExclusiveStrikePtr&) = delete;
     54         ExclusiveStrikePtr& operator = (const ExclusiveStrikePtr&) = delete;
     55         ExclusiveStrikePtr(ExclusiveStrikePtr&&);
     56         ExclusiveStrikePtr& operator = (ExclusiveStrikePtr&&);
     57         ~ExclusiveStrikePtr();
     58 
     59         SkStrike* get() const;
     60         SkStrike* operator -> () const;
     61         SkStrike& operator *  () const;
     62         explicit operator bool () const;
     63         friend bool operator == (const ExclusiveStrikePtr&, const ExclusiveStrikePtr&);
     64         friend bool operator == (const ExclusiveStrikePtr&, decltype(nullptr));
     65         friend bool operator == (decltype(nullptr), const ExclusiveStrikePtr&);
     66 
     67     private:
     68         Node* fNode;
     69     };
     70 
     71     static SkStrikeCache* GlobalStrikeCache();
     72 
     73     static ExclusiveStrikePtr FindStrikeExclusive(const SkDescriptor&);
     74     ExclusiveStrikePtr findStrikeExclusive(const SkDescriptor&);
     75     Node* findAndDetachStrike(const SkDescriptor&);
     76 
     77     static ExclusiveStrikePtr CreateStrikeExclusive(
     78             const SkDescriptor& desc,
     79             std::unique_ptr<SkScalerContext> scaler,
     80             SkFontMetrics* maybeMetrics = nullptr,
     81             std::unique_ptr<SkStrikePinner> = nullptr);
     82 
     83     ExclusiveStrikePtr createStrikeExclusive(
     84             const SkDescriptor& desc,
     85             std::unique_ptr<SkScalerContext> scaler,
     86             SkFontMetrics* maybeMetrics = nullptr,
     87             std::unique_ptr<SkStrikePinner> = nullptr);
     88 
     89     Node* createStrike(
     90             const SkDescriptor& desc,
     91             std::unique_ptr<SkScalerContext> scaler,
     92             SkFontMetrics* maybeMetrics = nullptr,
     93             std::unique_ptr<SkStrikePinner> = nullptr);
     94 
     95     static ExclusiveStrikePtr FindOrCreateStrikeExclusive(
     96             const SkDescriptor& desc,
     97             const SkScalerContextEffects& effects,
     98             const SkTypeface& typeface);
     99 
    100     ExclusiveStrikePtr findOrCreateStrikeExclusive(
    101             const SkDescriptor& desc,
    102             const SkScalerContextEffects& effects,
    103             const SkTypeface& typeface);
    104 
    105     Node* findOrCreateStrike(
    106             const SkDescriptor& desc,
    107             const SkScalerContextEffects& effects,
    108             const SkTypeface& typeface);
    109 
    110     // Routines to find suitable data when working in a remote cache situation. These are
    111     // suitable as substitutes for similar calls in SkScalerContext.
    112     bool desperationSearchForImage(const SkDescriptor& desc,
    113                                    SkGlyph* glyph,
    114                                    SkStrike* targetCache);
    115     bool desperationSearchForPath(const SkDescriptor& desc, SkGlyphID glyphID, SkPath* path);
    116 
    117     static ExclusiveStrikePtr FindOrCreateStrikeExclusive(
    118             const SkFont& font,
    119             const SkPaint& paint,
    120             const SkSurfaceProps& surfaceProps,
    121             SkScalerContextFlags scalerContextFlags,
    122             const SkMatrix& deviceMatrix);
    123 
    124     Node* findOrCreateStrike(
    125             const SkFont& font,
    126             const SkPaint& paint,
    127             const SkSurfaceProps& surfaceProps,
    128             SkScalerContextFlags scalerContextFlags,
    129             const SkMatrix& deviceMatrix);
    130 
    131     // cons up a default paint, which is only needed for patheffects/maskfilter
    132     static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont&);
    133 
    134     static ExclusiveStrikePtr FindOrCreateStrikeWithNoDeviceExclusive(const SkFont& font,
    135                                                                       const SkPaint& paint);
    136 
    137     static std::unique_ptr<SkScalerContext> CreateScalerContext(
    138             const SkDescriptor&, const SkScalerContextEffects&, const SkTypeface&);
    139 
    140     static void PurgeAll();
    141     static void ValidateGlyphCacheDataSize();
    142     static void Dump();
    143 
    144     // Dump memory usage statistics of all the attaches caches in the process using the
    145     // SkTraceMemoryDump interface.
    146     static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
    147 
    148     // call when a glyphcache is available for caching (i.e. not in use)
    149     void attachNode(Node* node);
    150 
    151     void purgeAll(); // does not change budget
    152 
    153     int getCacheCountLimit() const;
    154     int setCacheCountLimit(int limit);
    155     int getCacheCountUsed() const;
    156 
    157     size_t getCacheSizeLimit() const;
    158     size_t setCacheSizeLimit(size_t limit);
    159     size_t getTotalMemoryUsed() const;
    160 
    161     int  getCachePointSizeLimit() const;
    162     int  setCachePointSizeLimit(int limit);
    163 
    164 #ifdef SK_DEBUG
    165     // A simple accounting of what each glyph cache reports and the strike cache total.
    166     void validate() const;
    167     // Make sure that each glyph cache's memory tracking and actual memory used are in sync.
    168     void validateGlyphCacheDataSize() const;
    169 #else
    170     void validate() const {}
    171     void validateGlyphCacheDataSize() const {}
    172 #endif
    173 
    174 private:
    175 
    176     // The following methods can only be called when mutex is already held.
    177     Node* internalGetHead() const { return fHead; }
    178     Node* internalGetTail() const { return fTail; }
    179     void internalDetachCache(Node*);
    180     void internalAttachToHead(Node*);
    181 
    182     // Checkout budgets, modulated by the specified min-bytes-needed-to-purge,
    183     // and attempt to purge caches to match.
    184     // Returns number of bytes freed.
    185     size_t internalPurge(size_t minBytesNeeded = 0);
    186 
    187     void forEachStrike(std::function<void(const SkStrike&)> visitor) const;
    188 
    189     mutable SkSpinlock fLock;
    190     Node*              fHead{nullptr};
    191     Node*              fTail{nullptr};
    192     size_t             fTotalMemoryUsed{0};
    193     size_t             fCacheSizeLimit{SK_DEFAULT_FONT_CACHE_LIMIT};
    194     int32_t            fCacheCountLimit{SK_DEFAULT_FONT_CACHE_COUNT_LIMIT};
    195     int32_t            fCacheCount{0};
    196     int32_t            fPointSizeLimit{SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT};
    197 };
    198 
    199 using SkExclusiveStrikePtr = SkStrikeCache::ExclusiveStrikePtr;
    200 
    201 #endif  // SkStrikeCache_DEFINED
    202