root/src/servers/app/drawing/AlphaMaskCache.h
/*
 * Copyright 2015 Julian Harnath <julian.harnath@rwth-aachen.de>
 * All rights reserved. Distributed under the terms of the MIT license.
 */
#ifndef ALPHA_MASK_CACHE_H
#define ALPHA_MASK_CACHE_H

#include <set>

#include "ShapePrivate.h"
#include <Locker.h>
#include <kernel/OS.h>


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<ShapeMaskElement> 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