Home | History | Annotate | Download | only in images
      1 #include "SkImageRefPool.h"
      2 #include "SkImageRef.h"
      3 #include "SkThread.h"
      4 
      5 SkImageRefPool::SkImageRefPool() {
      6     fRAMBudget = 0; // means no explicit limit
      7     fRAMUsed = 0;
      8     fCount = 0;
      9     fHead = fTail = NULL;
     10 }
     11 
     12 SkImageRefPool::~SkImageRefPool() {
     13     //    SkASSERT(NULL == fHead);
     14 }
     15 
     16 void SkImageRefPool::setRAMBudget(size_t size) {
     17     if (fRAMBudget != size) {
     18         fRAMBudget = size;
     19         this->purgeIfNeeded();
     20     }
     21 }
     22 
     23 void SkImageRefPool::justAddedPixels(SkImageRef* ref) {
     24 #ifdef DUMP_IMAGEREF_LIFECYCLE
     25     SkDebugf("=== ImagePool: add pixels %s [%d %d %d] bytes=%d heap=%d\n",
     26              ref->getURI(),
     27              ref->fBitmap.width(), ref->fBitmap.height(),
     28              ref->fBitmap.bytesPerPixel(),
     29              ref->fBitmap.getSize(), (int)fRAMUsed);
     30 #endif
     31     fRAMUsed += ref->ramUsed();
     32     this->purgeIfNeeded();
     33 }
     34 
     35 void SkImageRefPool::canLosePixels(SkImageRef* ref) {
     36     // the refs near fHead have recently been released (used)
     37     // if we purge, we purge from the tail
     38     this->detach(ref);
     39     this->addToHead(ref);
     40     this->purgeIfNeeded();
     41 }
     42 
     43 void SkImageRefPool::purgeIfNeeded() {
     44     // do nothing if we have a zero-budget (i.e. unlimited)
     45     if (fRAMBudget != 0) {
     46         this->setRAMUsed(fRAMBudget);
     47     }
     48 }
     49 
     50 void SkImageRefPool::setRAMUsed(size_t limit) {
     51     SkImageRef* ref = fTail;
     52 
     53     while (NULL != ref && fRAMUsed > limit) {
     54         // only purge it if its pixels are unlocked
     55         if (0 == ref->getLockCount() && ref->fBitmap.getPixels()) {
     56             size_t size = ref->ramUsed();
     57             SkASSERT(size <= fRAMUsed);
     58             fRAMUsed -= size;
     59 
     60 #ifdef DUMP_IMAGEREF_LIFECYCLE
     61             SkDebugf("=== ImagePool: purge %s [%d %d %d] bytes=%d heap=%d\n",
     62                      ref->getURI(),
     63                      ref->fBitmap.width(), ref->fBitmap.height(),
     64                      ref->fBitmap.bytesPerPixel(),
     65                      (int)size, (int)fRAMUsed);
     66 #endif
     67 
     68             // remember the bitmap config (don't call reset),
     69             // just clear the pixel memory
     70             ref->fBitmap.setPixels(NULL);
     71             SkASSERT(NULL == ref->fBitmap.getPixels());
     72         }
     73         ref = ref->fPrev;
     74     }
     75 }
     76 
     77 ///////////////////////////////////////////////////////////////////////////////
     78 
     79 void SkImageRefPool::addToHead(SkImageRef* ref) {
     80     ref->fNext = fHead;
     81     ref->fPrev = NULL;
     82 
     83     if (fHead) {
     84         SkASSERT(NULL == fHead->fPrev);
     85         fHead->fPrev = ref;
     86     }
     87     fHead = ref;
     88 
     89     if (NULL == fTail) {
     90         fTail = ref;
     91     }
     92     fCount += 1;
     93     SkASSERT(computeCount() == fCount);
     94 
     95     fRAMUsed += ref->ramUsed();
     96 }
     97 
     98 void SkImageRefPool::addToTail(SkImageRef* ref) {
     99     ref->fNext = NULL;
    100     ref->fPrev = fTail;
    101 
    102     if (fTail) {
    103         SkASSERT(NULL == fTail->fNext);
    104         fTail->fNext = ref;
    105     }
    106     fTail = ref;
    107 
    108     if (NULL == fHead) {
    109         fHead = ref;
    110     }
    111     fCount += 1;
    112     SkASSERT(computeCount() == fCount);
    113 
    114     fRAMUsed += ref->ramUsed();
    115 }
    116 
    117 void SkImageRefPool::detach(SkImageRef* ref) {
    118     SkASSERT(fCount > 0);
    119 
    120     if (fHead == ref) {
    121         fHead = ref->fNext;
    122     }
    123     if (fTail == ref) {
    124         fTail = ref->fPrev;
    125     }
    126     if (ref->fPrev) {
    127         ref->fPrev->fNext = ref->fNext;
    128     }
    129     if (ref->fNext) {
    130         ref->fNext->fPrev = ref->fPrev;
    131     }
    132 
    133     ref->fNext = ref->fPrev = NULL;
    134 
    135     fCount -= 1;
    136     SkASSERT(computeCount() == fCount);
    137 
    138     SkASSERT(fRAMUsed >= ref->ramUsed());
    139     fRAMUsed -= ref->ramUsed();
    140 }
    141 
    142 int SkImageRefPool::computeCount() const {
    143     SkImageRef* ref = fHead;
    144     int count = 0;
    145 
    146     while (ref != NULL) {
    147         count += 1;
    148         ref = ref->fNext;
    149     }
    150 
    151 #ifdef SK_DEBUG
    152     ref = fTail;
    153     int count2 = 0;
    154 
    155     while (ref != NULL) {
    156         count2 += 1;
    157         ref = ref->fPrev;
    158     }
    159     SkASSERT(count2 == count);
    160 #endif
    161 
    162     return count;
    163 }
    164 
    165 ///////////////////////////////////////////////////////////////////////////////
    166 
    167 #include "SkStream.h"
    168 
    169 void SkImageRefPool::dump() const {
    170 #if defined(SK_DEBUG) || defined(DUMP_IMAGEREF_LIFECYCLE)
    171     SkDebugf("ImagePool dump: bugdet: %d used: %d count: %d\n",
    172              (int)fRAMBudget, (int)fRAMUsed, fCount);
    173 
    174     SkImageRef* ref = fHead;
    175 
    176     while (ref != NULL) {
    177         SkDebugf("  [%3d %3d %d] ram=%d data=%d locks=%d %s\n", ref->fBitmap.width(),
    178                  ref->fBitmap.height(), ref->fBitmap.config(),
    179                  ref->ramUsed(), (int)ref->fStream->getLength(),
    180                  ref->getLockCount(), ref->getURI());
    181 
    182         ref = ref->fNext;
    183     }
    184 #endif
    185 }
    186 
    187