140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2010 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */
840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkBitmapCache.h"
1140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstruct SkBitmapCache::Entry {
1340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    Entry*      fPrev;
1440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    Entry*      fNext;
1540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void*       fBuffer;
1740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    size_t      fSize;
1840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkBitmap    fBitmap;
1940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Entry(const void* buffer, size_t size, const SkBitmap& bm)
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            : fPrev(NULL),
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              fNext(NULL),
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              fBitmap(bm) {
2440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fBuffer = sk_malloc_throw(size);
2540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fSize = size;
2640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        memcpy(fBuffer, buffer, size);
2740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
2840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
2940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    ~Entry() { sk_free(fBuffer); }
3040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
3140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    bool equals(const void* buffer, size_t size) const {
3240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return (fSize == size) && !memcmp(fBuffer, buffer, size);
3340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
3440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
3540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
3640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkBitmapCache::SkBitmapCache(int max) : fMaxEntries(max) {
3740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fEntryCount = 0;
3840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fHead = fTail = NULL;
3940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->validate();
4140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
4240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkBitmapCache::~SkBitmapCache() {
4440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->validate();
4540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    Entry* entry = fHead;
4740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    while (entry) {
4840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        Entry* next = entry->fNext;
4940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        delete entry;
5040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        entry = next;
5140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
5240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
5340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkBitmapCache::Entry* SkBitmapCache::detach(Entry* entry) const {
5540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (entry->fPrev) {
5640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(fHead != entry);
5740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        entry->fPrev->fNext = entry->fNext;
5840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
5940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(fHead == entry);
6040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fHead = entry->fNext;
6140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
6240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (entry->fNext) {
6340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(fTail != entry);
6440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        entry->fNext->fPrev = entry->fPrev;
6540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
6640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(fTail == entry);
6740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fTail = entry->fPrev;
6840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
6940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return entry;
7040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
7140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkBitmapCache::attachToHead(Entry* entry) const {
7340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    entry->fPrev = NULL;
7440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    entry->fNext = fHead;
7540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fHead) {
7640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fHead->fPrev = entry;
7740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
7840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fTail = entry;
7940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
8040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fHead = entry;
8140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
8240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerbool SkBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
8440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    AutoValidate av(this);
8540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    Entry* entry = fHead;
8740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    while (entry) {
8840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (entry->equals(buffer, size)) {
8940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (bm) {
9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                *bm = entry->fBitmap;
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
9240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            // move to the head of our list, so we purge it last
9340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            this->detach(entry);
9440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            this->attachToHead(entry);
9540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            return true;
9640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
9740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        entry = entry->fNext;
9840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
9940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return false;
10040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
10140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
10340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    AutoValidate av(this);
10440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fEntryCount == fMaxEntries) {
10640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(fTail);
10740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        delete this->detach(fTail);
10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fEntryCount -= 1;
10940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    Entry* entry = new Entry(buffer, len, bm);
11240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->attachToHead(entry);
11340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fEntryCount += 1;
11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifdef SK_DEBUG
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkBitmapCache::validate() const {
12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
12240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fEntryCount > 0) {
12440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(NULL == fHead->fPrev);
12540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(NULL == fTail->fNext);
12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (fEntryCount == 1) {
12840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkASSERT(fHead == fTail);
12940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
13040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkASSERT(fHead != fTail);
13140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        Entry* entry = fHead;
13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        int count = 0;
13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        while (entry) {
13640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            count += 1;
13740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            entry = entry->fNext;
13840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
13940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(count == fEntryCount);
14040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        entry = fTail;
14240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        while (entry) {
14340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            count -= 1;
14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            entry = entry->fPrev;
14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(0 == count);
14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(NULL == fHead);
14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(NULL == fTail);
15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
15340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
155