/* * Copyright 2015 Julian Harnath * All rights reserved. Distributed under the terms of the MIT license. */ #ifndef ALPHA_MASK_CACHE_H #define ALPHA_MASK_CACHE_H #include #include "ShapePrivate.h" #include #include class AlphaMask; class ShapeAlphaMask; class AlphaMaskCache { private: enum { kMaxCacheBytes = 8 * 1024 * 1024 // 8 MiB }; public: AlphaMaskCache(); ~AlphaMaskCache(); static AlphaMaskCache* Default(); status_t Put(ShapeAlphaMask* mask); ShapeAlphaMask* Get(const shape_data& shape, AlphaMask* previousMask, bool inverse); void Clear(); private: size_t _FindUncachedPreviousMasks(AlphaMask* mask, bool reference); void _PrintAndResetStatistics(); private: struct ShapeMaskElement { ShapeMaskElement(const shape_data* shape, ShapeAlphaMask* mask, AlphaMask* previousMask, bool inverse) : fShape(shape), fInverse(inverse), fMask(mask), fPreviousMask(previousMask) { } bool operator<(const ShapeMaskElement& other) const { if (fInverse != other.fInverse) return fInverse < other.fInverse; if (fPreviousMask != other.fPreviousMask) return fPreviousMask < other.fPreviousMask; // compare shapes if (fShape->ptCount != other.fShape->ptCount) return fShape->ptCount < other.fShape->ptCount; if (fShape->opCount != other.fShape->opCount) return fShape->opCount < other.fShape->opCount; int diff = memcmp(fShape->ptList, other.fShape->ptList, fShape->ptSize); if (diff != 0) return diff < 0; diff = memcmp(fShape->opList, other.fShape->opList, fShape->opSize); if (diff != 0) return diff < 0; // equal return false; } const shape_data* fShape; bool fInverse; ShapeAlphaMask* fMask; AlphaMask* fPreviousMask; }; private: typedef std::set ShapeMaskSet; static AlphaMaskCache sDefaultInstance; BLocker fLock; size_t fCurrentCacheBytes; ShapeMaskSet fShapeMasks; // Statistics counters uint32 fTooLargeMaskCount; uint32 fMasksReplacedCount; uint32 fHitCount; uint32 fMissCount; uint32 fLowerMaskReferencedCount; }; #endif // ALPHA_MASK_CACHE_H