180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2010 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBitmapCache.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct SkBitmapCache::Entry {
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Entry*      fPrev;
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Entry*      fNext;
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void*       fBuffer;
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t      fSize;
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap    fBitmap;
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Entry(const void* buffer, size_t size, const SkBitmap& bm)
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            : fPrev(NULL),
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru              fNext(NULL),
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru              fBitmap(bm) {
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBuffer = sk_malloc_throw(size);
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSize = size;
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(fBuffer, buffer, size);
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~Entry() { sk_free(fBuffer); }
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool equals(const void* buffer, size_t size) const {
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (fSize == size) && !memcmp(fBuffer, buffer, size);
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapCache::SkBitmapCache(int max) : fMaxEntries(max) {
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEntryCount = 0;
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fHead = fTail = NULL;
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapCache::~SkBitmapCache() {
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Entry* entry = fHead;
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (entry) {
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Entry* next = entry->fNext;
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete entry;
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry = next;
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapCache::Entry* SkBitmapCache::detach(Entry* entry) const {
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (entry->fPrev) {
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fHead != entry);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry->fPrev->fNext = entry->fNext;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fHead == entry);
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fHead = entry->fNext;
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (entry->fNext) {
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fTail != entry);
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry->fNext->fPrev = entry->fPrev;
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fTail == entry);
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTail = entry->fPrev;
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return entry;
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapCache::attachToHead(Entry* entry) const {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    entry->fPrev = NULL;
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    entry->fNext = fHead;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fHead) {
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fHead->fPrev = entry;
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTail = entry;
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fHead = entry;
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AutoValidate av(this);
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Entry* entry = fHead;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (entry) {
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (entry->equals(buffer, size)) {
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (bm) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *bm = entry->fBitmap;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // move to the head of our list, so we purge it last
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->detach(entry);
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->attachToHead(entry);
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry = entry->fNext;
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AutoValidate av(this);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fEntryCount == fMaxEntries) {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fTail);
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete this->detach(fTail);
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fEntryCount -= 1;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Entry* entry = SkNEW_ARGS(Entry, (buffer, len, bm));
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->attachToHead(entry);
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEntryCount += 1;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapCache::validate() const {
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fEntryCount > 0) {
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL == fHead->fPrev);
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL == fTail->fNext);
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fEntryCount == 1) {
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(fHead == fTail);
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(fHead != fTail);
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Entry* entry = fHead;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int count = 0;
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (entry) {
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            count += 1;
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            entry = entry->fNext;
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(count == fEntryCount);
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry = fTail;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (entry) {
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            count -= 1;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            entry = entry->fPrev;
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(0 == count);
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL == fHead);
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL == fTail);
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
154