1602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com/*
2602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com * Copyright 2013 Google Inc.
3602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com *
4602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com * Use of this source code is governed by a BSD-style license that can be
5602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com * found in the LICENSE file.
6602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com */
7602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
8602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#include "SkScaledImageCache.h"
9d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com#include "SkMipMap.h"
10602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#include "SkPixelRef.h"
11602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#include "SkRect.h"
12602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
13e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com// This can be defined by the caller's build system
14e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com//#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE
15e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
16e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com#ifndef SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT
17e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com#   define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT   1024
18e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com#endif
19e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
20602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT
21602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    #define SK_DEFAULT_IMAGE_CACHE_LIMIT     (2 * 1024 * 1024)
22602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#endif
23602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
247585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic inline SkScaledImageCache::ID* rec_to_id(SkScaledImageCache::Rec* rec) {
257585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return reinterpret_cast<SkScaledImageCache::ID*>(rec);
267585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
277585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
287585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic inline SkScaledImageCache::Rec* id_to_rec(SkScaledImageCache::ID* id) {
297585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return reinterpret_cast<SkScaledImageCache::Rec*>(id);
307585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
315d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com
32602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com // Implemented from en.wikipedia.org/wiki/MurmurHash.
33602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comstatic uint32_t compute_hash(const uint32_t data[], int count) {
34602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    uint32_t hash = 0;
357f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
36602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    for (int i = 0; i < count; ++i) {
37602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        uint32_t k = data[i];
38602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        k *= 0xcc9e2d51;
39602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        k = (k << 15) | (k >> 17);
40602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        k *= 0x1b873593;
417f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
42602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        hash ^= k;
43602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        hash = (hash << 13) | (hash >> 19);
44602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        hash *= 5;
45602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        hash += 0xe6546b64;
46602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
477f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
48602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    //    hash ^= size;
49602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    hash ^= hash >> 16;
50602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    hash *= 0x85ebca6b;
51602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    hash ^= hash >> 13;
52602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    hash *= 0xc2b2ae35;
53602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    hash ^= hash >> 16;
547f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
55602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    return hash;
56602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
57602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
58d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comstruct SkScaledImageCache::Key {
597585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Key(uint32_t genID,
607585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkScalar scaleX,
617585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkScalar scaleY,
627585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkIRect  bounds)
637585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        : fGenID(genID)
647585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        , fScaleX(scaleX)
657585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        , fScaleY(scaleY)
667585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        , fBounds(bounds) {
67602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        fHash = compute_hash(&fGenID, 7);
68602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
69602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
705d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    bool operator<(const Key& other) const {
71602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        const uint32_t* a = &fGenID;
72602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        const uint32_t* b = &other.fGenID;
73602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        for (int i = 0; i < 7; ++i) {
74602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            if (a[i] < b[i]) {
75602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                return true;
76602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            }
77602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            if (a[i] > b[i]) {
78602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                return false;
79602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            }
80602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        }
81602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        return false;
82602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
83602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
845d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    bool operator==(const Key& other) const {
85602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        const uint32_t* a = &fHash;
86602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        const uint32_t* b = &other.fHash;
87602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        for (int i = 0; i < 8; ++i) {
88602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            if (a[i] != b[i]) {
89602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                return false;
90602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            }
91602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        }
92602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        return true;
93602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
94602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
95602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    uint32_t    fHash;
96602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    uint32_t    fGenID;
97602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    float       fScaleX;
98602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    float       fScaleY;
99602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkIRect     fBounds;
100602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com};
101602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
102602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comstruct SkScaledImageCache::Rec {
103602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec(const Key& key, const SkBitmap& bm) : fKey(key), fBitmap(bm) {
104602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        fLockCount = 1;
105d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        fMip = NULL;
106602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
1075c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com
108d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    Rec(const Key& key, const SkMipMap* mip) : fKey(key) {
109d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        fLockCount = 1;
110d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        fMip = mip;
111d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        mip->ref();
112d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    }
1135c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com
114d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    ~Rec() {
115d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        SkSafeUnref(fMip);
116d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    }
1175c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com
11855bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org    static const Key& GetKey(const Rec& rec) { return rec.fKey; }
11955bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org    static uint32_t Hash(const Key& key) { return key.fHash; }
12055bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org
121602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    size_t bytesUsed() const {
122d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        return fMip ? fMip->getSize() : fBitmap.getSize();
123602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
124602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
125602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec*    fNext;
126602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec*    fPrev;
127602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
128602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    // this guy wants to be 64bit aligned
129602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Key     fKey;
130602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
131602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    int32_t fLockCount;
1325c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com
133d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    // we use either fBitmap or fMip, but not both
134602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkBitmap fBitmap;
135d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    const SkMipMap* fMip;
136602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com};
137602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
1385d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#include "SkTDynamicHash.h"
1395d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com
14055bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.orgclass SkScaledImageCache::Hash :
14155bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org    public SkTDynamicHash<SkScaledImageCache::Rec, SkScaledImageCache::Key> {};
142158f64626f8dae7e8437744184860d0110b88609commit-bot@chromium.org
1435d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com
1445d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com///////////////////////////////////////////////////////////////////////////////
1455d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com
146b8d17fef261eb70305105dddc4089aa744accfcereed@google.com// experimental hash to speed things up
147ea348cb4352cfa09fb060854057dc89ae102a976reed@google.com#define USE_HASH
1485d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com
1497585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#if !defined(USE_HASH)
1507585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic inline SkScaledImageCache::Rec* find_rec_in_list(
1517585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkScaledImageCache::Rec* head, const Key & key) {
1527585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkScaledImageCache::Rec* rec = head;
1537585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    while ((rec != NULL) && (rec->fKey != key)) {
1547585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        rec = rec->fNext;
1557585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
1567585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return rec;
1577585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
1587585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#endif
1597585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
160e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comvoid SkScaledImageCache::init() {
161602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    fHead = NULL;
162602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    fTail = NULL;
1635d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#ifdef USE_HASH
1645d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    fHash = new Hash;
1655d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#else
1665d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    fHash = NULL;
1675d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#endif
1684e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fTotalBytesUsed = 0;
169602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    fCount = 0;
1704e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fSingleAllocationByteLimit = 0;
171e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    fAllocator = NULL;
172e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
173e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    // One of these should be explicit set by the caller after we return.
1744e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fTotalByteLimit = 0;
175e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    fDiscardableFactory = NULL;
176e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
177e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
178e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com#include "SkDiscardableMemory.h"
179e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
180e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comclass SkOneShotDiscardablePixelRef : public SkPixelRef {
181e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.compublic:
182227c24673196f5f06bee85e7e9aa067be90e1359commit-bot@chromium.org    SK_DECLARE_INST_COUNT(SkOneShotDiscardablePixelRef)
183e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    // Ownership of the discardablememory is transfered to the pixelref
184e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_t rowBytes);
185e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    ~SkOneShotDiscardablePixelRef();
186e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
187e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SK_DECLARE_UNFLATTENABLE_OBJECT()
188e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
189e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comprotected:
190d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
191e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    virtual void onUnlockPixels() SK_OVERRIDE;
192e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
193e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
194e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comprivate:
195e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkDiscardableMemory* fDM;
196e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    size_t               fRB;
197e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    bool                 fFirstTime;
198e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
199e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    typedef SkPixelRef INHERITED;
200e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com};
201e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
202e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comSkOneShotDiscardablePixelRef::SkOneShotDiscardablePixelRef(const SkImageInfo& info,
203e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com                                             SkDiscardableMemory* dm,
204e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com                                             size_t rowBytes)
205e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    : INHERITED(info)
206e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    , fDM(dm)
207e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    , fRB(rowBytes)
208e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com{
209e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkASSERT(dm->data());
210e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    fFirstTime = true;
211e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
212e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
213e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comSkOneShotDiscardablePixelRef::~SkOneShotDiscardablePixelRef() {
214e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkDELETE(fDM);
215e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
216e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
217d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.combool SkOneShotDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
218e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    if (fFirstTime) {
219e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        // we're already locked
220c83a91f4721739f05f9df51d496d50b5d028b132reed@google.com        SkASSERT(fDM->data());
221e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        fFirstTime = false;
222d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com        goto SUCCESS;
223e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    }
224281713e4d4d77e086a0053351da6f7358d3cf4b6commit-bot@chromium.org
225fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    // A previous call to onUnlock may have deleted our DM, so check for that
226fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    if (NULL == fDM) {
227d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com        return false;
228fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    }
229fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com
230fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    if (!fDM->lock()) {
231fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com        // since it failed, we delete it now, to free-up the resource
232fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com        delete fDM;
233fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com        fDM = NULL;
234d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com        return false;
235fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    }
236d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com
237d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.comSUCCESS:
238d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    rec->fPixels = fDM->data();
239d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    rec->fColorTable = NULL;
240d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    rec->fRowBytes = fRB;
241d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    return true;
242e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
243e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
244e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comvoid SkOneShotDiscardablePixelRef::onUnlockPixels() {
245e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkASSERT(!fFirstTime);
246c83a91f4721739f05f9df51d496d50b5d028b132reed@google.com    fDM->unlock();
247e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
248e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
249e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comsize_t SkOneShotDiscardablePixelRef::getAllocatedSizeInBytes() const {
250d0419b1fe781ed21d4aa0dc80df6b3e79ed37e46reed@google.com    return this->info().getSafeSize(fRB);
251e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
252e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
253e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comclass SkScaledImageCacheDiscardableAllocator : public SkBitmap::Allocator {
254e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.compublic:
255e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkScaledImageCacheDiscardableAllocator(
256e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com                            SkScaledImageCache::DiscardableFactory factory) {
257e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        SkASSERT(factory);
258e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        fFactory = factory;
259e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    }
260e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
261e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE;
262cf0803b46f60d9fcb5ad9a376b638c4c32b655deskia.committer@gmail.com
263e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comprivate:
264e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkScaledImageCache::DiscardableFactory fFactory;
265e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com};
266e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
267e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.combool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
268e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com                                                       SkColorTable* ctable) {
269e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    size_t size = bitmap->getSize();
2704e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    uint64_t size64 = bitmap->computeSize64();
2714e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    if (0 == size || size64 > (uint64_t)size) {
272e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        return false;
273e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    }
274e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
275e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkDiscardableMemory* dm = fFactory(size);
276e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    if (NULL == dm) {
277e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        return false;
278e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    }
279e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
280900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    // can we relax this?
28128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    if (kN32_SkColorType != bitmap->colorType()) {
282e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        return false;
283e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    }
284e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
285900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    SkImageInfo info = bitmap->info();
286e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    bitmap->setPixelRef(SkNEW_ARGS(SkOneShotDiscardablePixelRef,
287e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com                                   (info, dm, bitmap->rowBytes())))->unref();
288e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    bitmap->lockPixels();
289e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    return bitmap->readyToDraw();
290e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
291e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
292e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comSkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) {
293e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    this->init();
294e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    fDiscardableFactory = factory;
295e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
296e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    fAllocator = SkNEW_ARGS(SkScaledImageCacheDiscardableAllocator, (factory));
297e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
298e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
299e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comSkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
300e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    this->init();
3014e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fTotalByteLimit = byteLimit;
302602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
303602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
304602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comSkScaledImageCache::~SkScaledImageCache() {
305e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkSafeUnref(fAllocator);
306e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
307602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec* rec = fHead;
308602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    while (rec) {
309602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        Rec* next = rec->fNext;
310602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkDELETE(rec);
311602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        rec = next;
312602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
3135d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    delete fHash;
314602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
315602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
3167585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
3177585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
318d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
3197585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgSkScaledImageCache::Rec* SkScaledImageCache::findAndLock(uint32_t genID,
320602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                        SkScalar scaleX,
3217585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                        SkScalar scaleY,
3227585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                        const SkIRect& bounds) {
323d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    const Key key(genID, scaleX, scaleY, bounds);
324d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    return this->findAndLock(key);
325d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com}
326d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
327d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com/**
328d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com   This private method is the fully general record finder. All other
329d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com   record finders should call this function or the one above. */
330d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comSkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkScaledImageCache::Key& key) {
331d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    if (key.fBounds.isEmpty()) {
332602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        return NULL;
333602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
3345d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#ifdef USE_HASH
3355d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    Rec* rec = fHash->find(key);
3365d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#else
3377585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Rec* rec = find_rec_in_list(fHead, key);
3385d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#endif
3395d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    if (rec) {
3405d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com        this->moveToHead(rec);  // for our LRU
3415d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com        rec->fLockCount += 1;
3425d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    }
3435d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com    return rec;
344602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
345602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
3467585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
3477585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org   This function finds the bounds of the bitmap *within its pixelRef*.
3487585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org   If the bitmap lacks a pixelRef, it will return an empty rect, since
3497585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org   that doesn't make sense.  This may be a useful enough function that
3507585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org   it should be somewhere else (in SkBitmap?). */
3517585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
3527585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (!(bm.pixelRef())) {
3537585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return SkIRect::MakeEmpty();
3547585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
355672588b684d484dce6ae251e9e163e4a46924322reed@google.com    SkIPoint origin = bm.pixelRefOrigin();
356672588b684d484dce6ae251e9e163e4a46924322reed@google.com    return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
3577585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
3587585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
3597585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
3607585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgSkScaledImageCache::ID* SkScaledImageCache::findAndLock(uint32_t genID,
3617585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                        int32_t width,
3627585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                        int32_t height,
3637585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                        SkBitmap* bitmap) {
3647585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Rec* rec = this->findAndLock(genID, SK_Scalar1, SK_Scalar1,
3657585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                 SkIRect::MakeWH(width, height));
3667585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (rec) {
3677585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkASSERT(NULL == rec->fMip);
3687585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkASSERT(rec->fBitmap.pixelRef());
3697585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        *bitmap = rec->fBitmap;
3707585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
3717585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return rec_to_id(rec);
3727585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
3737585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
374d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.comSkScaledImageCache::ID* SkScaledImageCache::findAndLock(const SkBitmap& orig,
375d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com                                                        SkScalar scaleX,
376d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com                                                        SkScalar scaleY,
377d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com                                                        SkBitmap* scaled) {
378d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    if (0 == scaleX || 0 == scaleY) {
379d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        // degenerate, and the key we use for mipmaps
380d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        return NULL;
381d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    }
3827585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Rec* rec = this->findAndLock(orig.getGenerationID(), scaleX,
3837585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                 scaleY, get_bounds_from_bitmap(orig));
384d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    if (rec) {
385d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        SkASSERT(NULL == rec->fMip);
386d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        SkASSERT(rec->fBitmap.pixelRef());
387d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        *scaled = rec->fBitmap;
388d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    }
3897585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return rec_to_id(rec);
390d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com}
391d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com
392d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.comSkScaledImageCache::ID* SkScaledImageCache::findAndLockMip(const SkBitmap& orig,
393d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com                                                           SkMipMap const ** mip) {
394b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com    Rec* rec = this->findAndLock(orig.getGenerationID(), 0, 0,
3957585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                 get_bounds_from_bitmap(orig));
396d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    if (rec) {
397d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        SkASSERT(rec->fMip);
398d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        SkASSERT(NULL == rec->fBitmap.pixelRef());
399d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        *mip = rec->fMip;
400d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    }
4017585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return rec_to_id(rec);
4027585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
4037585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
4047585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
4057585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
4067585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
4077585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org   This private method is the fully general record adder. All other
4087585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org   record adders should call this funtion. */
409d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comSkScaledImageCache::ID* SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) {
4107585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkASSERT(rec);
411d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    // See if we already have this key (racy inserts, etc.)
412d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    Rec* existing = this->findAndLock(rec->fKey);
4135db04dfad7dae105adcb82caf013f4775bfe1257robertphillips@google.com    if (NULL != existing) {
4145db04dfad7dae105adcb82caf013f4775bfe1257robertphillips@google.com        // Since we already have a matching entry, just delete the new one and return.
4155db04dfad7dae105adcb82caf013f4775bfe1257robertphillips@google.com        // Call sites cannot assume the passed in object will live past this call.
4165e4112b33aeecbb773ed4c8e33994dec14becb84commit-bot@chromium.org        existing->fBitmap = rec->fBitmap;
4175db04dfad7dae105adcb82caf013f4775bfe1257robertphillips@google.com        SkDELETE(rec);
418d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        return rec_to_id(existing);
419d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    }
420d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
4217585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    this->addToHead(rec);
4227585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkASSERT(1 == rec->fLockCount);
4237585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#ifdef USE_HASH
4247585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkASSERT(fHash);
4257585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    fHash->add(rec);
4267585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#endif
4277585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    // We may (now) be overbudget, so see if we need to purge something.
4287585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    this->purgeAsNeeded();
429d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    return rec_to_id(rec);
4307585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
4317585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
4327585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgSkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID,
4337585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                       int32_t width,
4347585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                       int32_t height,
4357585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                                       const SkBitmap& bitmap) {
4367585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Key key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height));
4377585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Rec* rec = SkNEW_ARGS(Rec, (key, bitmap));
438d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    return this->addAndLock(rec);
439d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com}
440d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com
441602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comSkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig,
442602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                       SkScalar scaleX,
443602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                       SkScalar scaleY,
444602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                       const SkBitmap& scaled) {
445d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    if (0 == scaleX || 0 == scaleY) {
446d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        // degenerate, and the key we use for mipmaps
447d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        return NULL;
448d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    }
4497585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkIRect bounds = get_bounds_from_bitmap(orig);
4507585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (bounds.isEmpty()) {
451602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        return NULL;
452602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
4537585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Key key(orig.getGenerationID(), scaleX, scaleY, bounds);
454602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec* rec = SkNEW_ARGS(Rec, (key, scaled));
455d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    return this->addAndLock(rec);
456d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com}
457602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
458d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.comSkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig,
459d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com                                                          const SkMipMap* mip) {
4607585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkIRect bounds = get_bounds_from_bitmap(orig);
4617585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (bounds.isEmpty()) {
462d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com        return NULL;
463d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    }
4647585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Key key(orig.getGenerationID(), 0, 0, bounds);
465d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    Rec* rec = SkNEW_ARGS(Rec, (key, mip));
466d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    return this->addAndLock(rec);
467602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
468602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
469602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comvoid SkScaledImageCache::unlock(SkScaledImageCache::ID* id) {
470602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(id);
471602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
472602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#ifdef SK_DEBUG
473602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    {
474602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        bool found = false;
475602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        Rec* rec = fHead;
476602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        while (rec != NULL) {
4777585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org            if (rec == id_to_rec(id)) {
478602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                found = true;
479602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                break;
480602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            }
481602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            rec = rec->fNext;
482602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        }
483602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkASSERT(found);
484602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
485602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#endif
4867585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    Rec* rec = id_to_rec(id);
487602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(rec->fLockCount > 0);
488602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    rec->fLockCount -= 1;
489602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
490602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    // we may have been over-budget, but now have released something, so check
491602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    // if we should purge.
492602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (0 == rec->fLockCount) {
493602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        this->purgeAsNeeded();
494602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
495602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
496602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
497602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comvoid SkScaledImageCache::purgeAsNeeded() {
498e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    size_t byteLimit;
499e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    int    countLimit;
500e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
501e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    if (fDiscardableFactory) {
502e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        countLimit = SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT;
503e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        byteLimit = SK_MaxU32;  // no limit based on bytes
504e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    } else {
505e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        countLimit = SK_MaxS32; // no limit based on count
5064e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger        byteLimit = fTotalByteLimit;
507e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    }
5087f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
5094e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    size_t bytesUsed = fTotalBytesUsed;
510e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    int    countUsed = fCount;
511cf0803b46f60d9fcb5ad9a376b638c4c32b655deskia.committer@gmail.com
512602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec* rec = fTail;
513602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    while (rec) {
514e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com        if (bytesUsed < byteLimit && countUsed < countLimit) {
515602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            break;
516602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        }
517e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
518602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        Rec* prev = rec->fPrev;
519602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        if (0 == rec->fLockCount) {
520602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            size_t used = rec->bytesUsed();
521602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            SkASSERT(used <= bytesUsed);
522602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            this->detach(rec);
5235d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#ifdef USE_HASH
5245d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com            fHash->remove(rec->fKey);
5255d1e5589fe446a59372debd8c7221170e21ec2b8reed@google.com#endif
526956b310f13c7412c035406c658ff16ca85eac656skia.committer@gmail.com
527602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com            SkDELETE(rec);
528e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
529e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com            bytesUsed -= used;
530e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com            countUsed -= 1;
531602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        }
532602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        rec = prev;
533602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
534e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
5354e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fTotalBytesUsed = bytesUsed;
536e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    fCount = countUsed;
537602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
538602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
5394e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::setTotalByteLimit(size_t newLimit) {
5404e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    size_t prevLimit = fTotalByteLimit;
5414e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fTotalByteLimit = newLimit;
542602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (newLimit < prevLimit) {
543602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        this->purgeAsNeeded();
544602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
545602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    return prevLimit;
546602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
547602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
548602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com///////////////////////////////////////////////////////////////////////////////
549602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
550602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comvoid SkScaledImageCache::detach(Rec* rec) {
551602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec* prev = rec->fPrev;
552602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    Rec* next = rec->fNext;
5537f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
554602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (!prev) {
555602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkASSERT(fHead == rec);
556602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        fHead = next;
557602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    } else {
558602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        prev->fNext = next;
559602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
5607f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
561602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (!next) {
562602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        fTail = prev;
563602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    } else {
564602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        next->fPrev = prev;
565602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
5667f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
567602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    rec->fNext = rec->fPrev = NULL;
568602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
569602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
570602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comvoid SkScaledImageCache::moveToHead(Rec* rec) {
571602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (fHead == rec) {
572602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        return;
573602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
574602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
575602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(fHead);
576602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(fTail);
577602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
578602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    this->validate();
579602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
580602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    this->detach(rec);
581602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
582602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    fHead->fPrev = rec;
583602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    rec->fNext = fHead;
584602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    fHead = rec;
5857f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
586602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    this->validate();
587602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
588602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
589602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comvoid SkScaledImageCache::addToHead(Rec* rec) {
590602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    this->validate();
591602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
592602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    rec->fPrev = NULL;
593602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    rec->fNext = fHead;
594602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (fHead) {
595602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        fHead->fPrev = rec;
596602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
597602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    fHead = rec;
598602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (!fTail) {
599602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        fTail = rec;
600602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
6014e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fTotalBytesUsed += rec->bytesUsed();
602602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    fCount += 1;
603602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
604602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    this->validate();
605602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
606602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
607fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com///////////////////////////////////////////////////////////////////////////////
608fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com
609602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#ifdef SK_DEBUG
610602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comvoid SkScaledImageCache::validate() const {
611602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (NULL == fHead) {
612602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkASSERT(NULL == fTail);
6134e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger        SkASSERT(0 == fTotalBytesUsed);
614602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        return;
615602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
616602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
617602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    if (fHead == fTail) {
618602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkASSERT(NULL == fHead->fPrev);
619602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkASSERT(NULL == fHead->fNext);
6204e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger        SkASSERT(fHead->bytesUsed() == fTotalBytesUsed);
621602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        return;
622602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
623602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
624602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(NULL == fHead->fPrev);
625602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(NULL != fHead->fNext);
626602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(NULL == fTail->fNext);
627602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(NULL != fTail->fPrev);
628602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
629602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    size_t used = 0;
630602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    int count = 0;
631602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    const Rec* rec = fHead;
632602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    while (rec) {
633602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        count += 1;
634602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        used += rec->bytesUsed();
6354e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger        SkASSERT(used <= fTotalBytesUsed);
636602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        rec = rec->fNext;
637602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
638602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(fCount == count);
639602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
640602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    rec = fTail;
641602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    while (rec) {
642602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkASSERT(count > 0);
643602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        count -= 1;
644602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        SkASSERT(used >= rec->bytesUsed());
645602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        used -= rec->bytesUsed();
646602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com        rec = rec->fPrev;
647602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    }
6487f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
649602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(0 == count);
650602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkASSERT(0 == used);
651602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
652602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#endif
653602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
654fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.comvoid SkScaledImageCache::dump() const {
655fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    this->validate();
656fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com
657fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    const Rec* rec = fHead;
658fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    int locked = 0;
659fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    while (rec) {
660fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com        locked += rec->fLockCount > 0;
661fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com        rec = rec->fNext;
662fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    }
663fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com
664fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    SkDebugf("SkScaledImageCache: count=%d bytes=%d locked=%d %s\n",
6654e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger             fCount, fTotalBytesUsed, locked,
666fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com             fDiscardableFactory ? "discardable" : "malloc");
667fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com}
668fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com
6694e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::setSingleAllocationByteLimit(size_t newLimit) {
6704e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    size_t oldLimit = fSingleAllocationByteLimit;
6714e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    fSingleAllocationByteLimit = newLimit;
6724e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return oldLimit;
6734e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger}
6744e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger
6754e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::getSingleAllocationByteLimit() const {
6764e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return fSingleAllocationByteLimit;
6774e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger}
6784e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger
679602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com///////////////////////////////////////////////////////////////////////////////
680602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
681602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#include "SkThread.h"
682602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
683be19dbe488e21cd9dc8c7adfbbd13602ee67a326reed@google.comSK_DECLARE_STATIC_MUTEX(gMutex);
684709ca75f032d7c60eb53c5840524a875a3a6cdb1commit-bot@chromium.orgstatic SkScaledImageCache* gScaledImageCache = NULL;
68577ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtkleinstatic void cleanup_gScaledImageCache() {
68677ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein    // We'll clean this up in our own tests, but disable for clients.
68777ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein    // Chrome seems to have funky multi-process things going on in unit tests that
68877ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein    // makes this unsafe to delete when the main process atexit()s.
68977ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein    // SkLazyPtr does the same sort of thing.
69077ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein#if SK_DEVELOPER
69177ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein    SkDELETE(gScaledImageCache);
69277ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein#endif
69377ec7a6f44ccfdacc9c3422516f09720ca17f9e2mtklein}
694602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
69560c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.org/** Must hold gMutex when calling. */
69660c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.orgstatic SkScaledImageCache* get_cache() {
69760c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.org    // gMutex is always held when this is called, so we don't need to be fancy in here.
698b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein    gMutex.assertHeld();
69960c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.org    if (NULL == gScaledImageCache) {
700e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
70160c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.org        gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
702e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com#else
70360c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.org        gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
704e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com#endif
70560c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.org        atexit(cleanup_gScaledImageCache);
70660c8d24f84105dd341e36a7fc97e25f88ceef309commit-bot@chromium.org    }
707709ca75f032d7c60eb53c5840524a875a3a6cdb1commit-bot@chromium.org    return gScaledImageCache;
708602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
709602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
7107585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
7117585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgSkScaledImageCache::ID* SkScaledImageCache::FindAndLock(
7127585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                uint32_t pixelGenerationID,
7137585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                int32_t width,
7147585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                int32_t height,
7157585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                SkBitmap* scaled) {
7167585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkAutoMutexAcquire am(gMutex);
7177585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return get_cache()->findAndLock(pixelGenerationID, width, height, scaled);
7187585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
7197585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
7207585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgSkScaledImageCache::ID* SkScaledImageCache::AddAndLock(
7217585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                               uint32_t pixelGenerationID,
7227585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                               int32_t width,
7237585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                               int32_t height,
7247585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                               const SkBitmap& scaled) {
7257585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkAutoMutexAcquire am(gMutex);
7267585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return get_cache()->addAndLock(pixelGenerationID, width, height, scaled);
7277585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
7287585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
7297585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
730602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comSkScaledImageCache::ID* SkScaledImageCache::FindAndLock(const SkBitmap& orig,
731602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                        SkScalar scaleX,
732602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                        SkScalar scaleY,
733602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                        SkBitmap* scaled) {
734602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkAutoMutexAcquire am(gMutex);
735602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    return get_cache()->findAndLock(orig, scaleX, scaleY, scaled);
736602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
737602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
738d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.comSkScaledImageCache::ID* SkScaledImageCache::FindAndLockMip(const SkBitmap& orig,
739d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com                                                       SkMipMap const ** mip) {
740d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    SkAutoMutexAcquire am(gMutex);
741d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    return get_cache()->findAndLockMip(orig, mip);
742d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com}
743d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com
744602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comSkScaledImageCache::ID* SkScaledImageCache::AddAndLock(const SkBitmap& orig,
745602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                       SkScalar scaleX,
746602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                       SkScalar scaleY,
747602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com                                                       const SkBitmap& scaled) {
748602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkAutoMutexAcquire am(gMutex);
749602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    return get_cache()->addAndLock(orig, scaleX, scaleY, scaled);
750602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
751602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
752d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.comSkScaledImageCache::ID* SkScaledImageCache::AddAndLockMip(const SkBitmap& orig,
753d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com                                                          const SkMipMap* mip) {
754d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    SkAutoMutexAcquire am(gMutex);
755d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com    return get_cache()->addAndLockMip(orig, mip);
756d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com}
757d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com
758602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.comvoid SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) {
759602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkAutoMutexAcquire am(gMutex);
760fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    get_cache()->unlock(id);
761fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com
762fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com//    get_cache()->dump();
763602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
764602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
7654e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::GetTotalBytesUsed() {
766602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkAutoMutexAcquire am(gMutex);
7674e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return get_cache()->getTotalBytesUsed();
768602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
769602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
7704e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::GetTotalByteLimit() {
771602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkAutoMutexAcquire am(gMutex);
7724e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return get_cache()->getTotalByteLimit();
773602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
774602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
7754e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::SetTotalByteLimit(size_t newLimit) {
776602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com    SkAutoMutexAcquire am(gMutex);
7774e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return get_cache()->setTotalByteLimit(newLimit);
778602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
779602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
780e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.comSkBitmap::Allocator* SkScaledImageCache::GetAllocator() {
781e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    SkAutoMutexAcquire am(gMutex);
782e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com    return get_cache()->allocator();
783e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com}
784e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com
785fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.comvoid SkScaledImageCache::Dump() {
786fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    SkAutoMutexAcquire am(gMutex);
787fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com    get_cache()->dump();
788fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com}
789fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com
7904e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::SetSingleAllocationByteLimit(size_t size) {
7914e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    SkAutoMutexAcquire am(gMutex);
7924e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return get_cache()->setSingleAllocationByteLimit(size);
7934e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger}
7944e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger
7954e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkScaledImageCache::GetSingleAllocationByteLimit() {
7964e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    SkAutoMutexAcquire am(gMutex);
7974e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return get_cache()->getSingleAllocationByteLimit();
7984e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger}
7994e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger
800602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com///////////////////////////////////////////////////////////////////////////////
801602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
802602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#include "SkGraphics.h"
803602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
8044e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkGraphics::GetImageCacheTotalBytesUsed() {
8054e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return SkScaledImageCache::GetTotalBytesUsed();
8064e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger}
8074e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger
8084e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkGraphics::GetImageCacheTotalByteLimit() {
8094e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return SkScaledImageCache::GetTotalByteLimit();
810602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
811602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
8124e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkGraphics::SetImageCacheTotalByteLimit(size_t newLimit) {
8134e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return SkScaledImageCache::SetTotalByteLimit(newLimit);
814602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
815602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com
8164e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkGraphics::GetImageCacheSingleAllocationByteLimit() {
8174e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return SkScaledImageCache::GetSingleAllocationByteLimit();
818602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com}
8194e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger
8204e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergersize_t SkGraphics::SetImageCacheSingleAllocationByteLimit(size_t newLimit) {
8214e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger    return SkScaledImageCache::SetSingleAllocationByteLimit(newLimit);
8224e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger}
8234e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger
824