LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkBitmapCache.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 193 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2014 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "SkBitmapCache.h"
       9             : #include "SkImage.h"
      10             : #include "SkResourceCache.h"
      11             : #include "SkMipMap.h"
      12             : #include "SkPixelRef.h"
      13             : #include "SkRect.h"
      14             : 
      15             : /**
      16             :  *  Use this for bitmapcache and mipmapcache entries.
      17             :  */
      18           0 : uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID) {
      19           0 :     uint64_t sharedID = SkSetFourByteTag('b', 'm', 'a', 'p');
      20           0 :     return (sharedID << 32) | bitmapGenID;
      21             : }
      22             : 
      23           0 : void SkNotifyBitmapGenIDIsStale(uint32_t bitmapGenID) {
      24           0 :     SkResourceCache::PostPurgeSharedID(SkMakeResourceCacheSharedIDForBitmap(bitmapGenID));
      25           0 : }
      26             : 
      27             : ///////////////////////////////////////////////////////////////////////////////////////////////////
      28             : 
      29             : /**
      30             :  This function finds the bounds of the bitmap *within its pixelRef*.
      31             :  If the bitmap lacks a pixelRef, it will return an empty rect, since
      32             :  that doesn't make sense.  This may be a useful enough function that
      33             :  it should be somewhere else (in SkBitmap?).
      34             :  */
      35           0 : static SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
      36           0 :     if (!(bm.pixelRef())) {
      37           0 :         return SkIRect::MakeEmpty();
      38             :     }
      39           0 :     SkIPoint origin = bm.pixelRefOrigin();
      40           0 :     return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
      41             : }
      42             : 
      43             : /**
      44             :  *  This function finds the bounds of the image. Today this is just the entire bounds,
      45             :  *  but in the future we may support subsets within an image, in which case this should
      46             :  *  return that subset (see get_bounds_from_bitmap).
      47             :  */
      48           0 : static SkIRect get_bounds_from_image(const SkImage* image) {
      49           0 :     SkASSERT(image->width() > 0 && image->height() > 0);
      50           0 :     return SkIRect::MakeWH(image->width(), image->height());
      51             : }
      52             : 
      53           0 : SkBitmapCacheDesc SkBitmapCacheDesc::Make(uint32_t imageID, int origWidth, int origHeight) {
      54           0 :     SkASSERT(imageID);
      55           0 :     SkASSERT(origWidth > 0 && origHeight > 0);
      56           0 :     return { imageID, 0, 0, {0, 0, origWidth, origHeight} };
      57             : }
      58             : 
      59           0 : SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkBitmap& bm, int scaledWidth, int scaledHeight) {
      60           0 :     SkASSERT(bm.width() > 0 && bm.height() > 0);
      61           0 :     SkASSERT(scaledWidth > 0 && scaledHeight > 0);
      62           0 :     SkASSERT(scaledWidth != bm.width() || scaledHeight != bm.height());
      63             : 
      64           0 :     return { bm.getGenerationID(), scaledWidth, scaledHeight, get_bounds_from_bitmap(bm) };
      65             : }
      66             : 
      67           0 : SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkBitmap& bm) {
      68           0 :     SkASSERT(bm.width() > 0 && bm.height() > 0);
      69           0 :     SkASSERT(bm.pixelRefOrigin() == SkIPoint::Make(0, 0));
      70             : 
      71           0 :     return { bm.getGenerationID(), 0, 0, get_bounds_from_bitmap(bm) };
      72             : }
      73             : 
      74           0 : SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkImage* image, int scaledWidth, int scaledHeight) {
      75           0 :     SkASSERT(image->width() > 0 && image->height() > 0);
      76           0 :     SkASSERT(scaledWidth > 0 && scaledHeight > 0);
      77             : 
      78             :     // If the dimensions are the same, should we set them to 0,0?
      79             :     //SkASSERT(scaledWidth != image->width() || scaledHeight != image->height());
      80             : 
      81           0 :     return { image->uniqueID(), scaledWidth, scaledHeight, get_bounds_from_image(image) };
      82             : }
      83             : 
      84           0 : SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkImage* image) {
      85           0 :     SkASSERT(image->width() > 0 && image->height() > 0);
      86             : 
      87           0 :     return { image->uniqueID(), 0, 0, get_bounds_from_image(image) };
      88             : }
      89             : 
      90             : namespace {
      91             : static unsigned gBitmapKeyNamespaceLabel;
      92             : 
      93             : struct BitmapKey : public SkResourceCache::Key {
      94             : public:
      95           0 :     BitmapKey(const SkBitmapCacheDesc& desc) : fDesc(desc) {
      96           0 :         this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fDesc.fImageID),
      97           0 :                    sizeof(fDesc));
      98           0 :     }
      99             : 
     100             :     void dump() const {
     101             :         SkDebugf("-- add [%d %d] %d [%d %d %d %d]\n",
     102             :                  fDesc.fScaledWidth, fDesc.fScaledHeight, fDesc.fImageID,
     103             :              fDesc.fSubset.x(), fDesc.fSubset.y(), fDesc.fSubset.width(), fDesc.fSubset.height());
     104             :     }
     105             : 
     106             :     const SkBitmapCacheDesc fDesc;
     107             : };
     108             : }
     109             : 
     110             : //////////////////////
     111             : #include "SkDiscardableMemory.h"
     112             : #include "SkNextID.h"
     113             : 
     114           0 : void SkBitmapCache_setImmutableWithID(SkPixelRef* pr, uint32_t id) {
     115           0 :     pr->setImmutableWithID(id);
     116           0 : }
     117             : 
     118             : //#define REC_TRACE   SkDebugf
     119           0 : static void REC_TRACE(const char format[], ...) {}
     120             : 
     121             : // for diagnostics
     122             : static int32_t gRecCounter;
     123             : 
     124             : class SkBitmapCache::Rec : public SkResourceCache::Rec {
     125             : public:
     126           0 :     Rec(const SkBitmapCacheDesc& desc, const SkImageInfo& info, size_t rowBytes,
     127             :         std::unique_ptr<SkDiscardableMemory> dm, void* block)
     128           0 :         : fKey(desc)
     129           0 :         , fDM(std::move(dm))
     130             :         , fMalloc(block)
     131             :         , fInfo(info)
     132             :         , fRowBytes(rowBytes)
     133           0 :         , fExternalCounter(kBeforeFirstInstall_ExternalCounter)
     134             :     {
     135           0 :         SkASSERT(!(fDM && fMalloc));    // can't have both
     136             : 
     137             :         // We need an ID to return with the bitmap/pixelref.
     138             :         // If they are not scaling, we can return the same ID as the key/desc
     139             :         // If they are scaling, we need a new ID
     140           0 :         if (desc.fScaledWidth == 0 && desc.fScaledHeight == 0) {
     141           0 :             fPrUniqueID = desc.fImageID;
     142             :         } else {
     143           0 :             fPrUniqueID = SkNextID::ImageID();
     144             :         }
     145           0 :         REC_TRACE(" Rec(%d): [%d %d] %d\n",
     146           0 :                   sk_atomic_inc(&gRecCounter), fInfo.width(), fInfo.height(), fPrUniqueID);
     147           0 :     }
     148             : 
     149           0 :     ~Rec() override {
     150           0 :         SkASSERT(0 == fExternalCounter || kBeforeFirstInstall_ExternalCounter == fExternalCounter);
     151           0 :         if (fDM && kBeforeFirstInstall_ExternalCounter == fExternalCounter) {
     152             :             // we never installed, so we need to unlock before we destroy the DM
     153           0 :             SkASSERT(fDM->data());
     154           0 :             fDM->unlock();
     155             :         }
     156           0 :         REC_TRACE("~Rec(%d): [%d %d] %d\n",
     157           0 :                   sk_atomic_dec(&gRecCounter) - 1, fInfo.width(), fInfo.height(), fPrUniqueID);
     158           0 :         sk_free(fMalloc);   // may be null
     159           0 :     }
     160             : 
     161           0 :     const Key& getKey() const override { return fKey; }
     162           0 :     size_t bytesUsed() const override {
     163           0 :         return sizeof(fKey) + fInfo.getSafeSize(fRowBytes);
     164             :     }
     165           0 :     bool canBePurged() override {
     166           0 :         SkAutoMutexAcquire ama(fMutex);
     167           0 :         return fExternalCounter == 0;
     168             :     }
     169           0 :     void postAddInstall(void* payload) override {
     170           0 :         SkAssertResult(this->install(static_cast<SkBitmap*>(payload)));
     171           0 :     }
     172             : 
     173           0 :     const char* getCategory() const override { return "bitmap"; }
     174           0 :     SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
     175           0 :         return fDM.get();
     176             :     }
     177             : 
     178           0 :     static void ReleaseProc(void* addr, void* ctx) {
     179           0 :         Rec* rec = static_cast<Rec*>(ctx);
     180           0 :         SkAutoMutexAcquire ama(rec->fMutex);
     181             : 
     182           0 :         REC_TRACE(" Rec: [%d] releaseproc\n", rec->fPrUniqueID);
     183             : 
     184           0 :         SkASSERT(rec->fExternalCounter > 0);
     185           0 :         rec->fExternalCounter -= 1;
     186           0 :         if (rec->fDM) {
     187           0 :             SkASSERT(rec->fMalloc == nullptr);
     188           0 :             if (rec->fExternalCounter == 0) {
     189           0 :                 REC_TRACE(" Rec [%d] unlock\n", rec->fPrUniqueID);
     190           0 :                 rec->fDM->unlock();
     191             :             }
     192             :         } else {
     193           0 :             SkASSERT(rec->fMalloc != nullptr);
     194             :         }
     195           0 :     }
     196             :     
     197           0 :     bool install(SkBitmap* bitmap) {
     198           0 :         SkAutoMutexAcquire ama(fMutex);
     199             : 
     200             :         // are we still valid
     201           0 :         if (!fDM && !fMalloc) {
     202           0 :             REC_TRACE(" Rec: [%d] invalid\n", fPrUniqueID);
     203           0 :             return false;
     204             :         }
     205             : 
     206             :         /*
     207             :             constructor      fExternalCount < 0     fDM->data()
     208             :             after install    fExternalCount > 0     fDM->data()
     209             :             after Release    fExternalCount == 0    !fDM->data()
     210             :         */
     211           0 :         if (fDM) {
     212           0 :             if (kBeforeFirstInstall_ExternalCounter == fExternalCounter) {
     213           0 :                 SkASSERT(fDM->data());
     214           0 :             } else if (fExternalCounter > 0) {
     215           0 :                 SkASSERT(fDM->data());
     216             :             } else {
     217           0 :                 SkASSERT(fExternalCounter == 0);
     218           0 :                 if (!fDM->lock()) {
     219           0 :                     REC_TRACE(" Rec [%d] re-lock failed\n", fPrUniqueID);
     220           0 :                     fDM.reset(nullptr);
     221           0 :                     return false;
     222             :                 }
     223           0 :                 REC_TRACE(" Rec [%d] re-lock succeeded\n", fPrUniqueID);
     224             :             }
     225           0 :             SkASSERT(fDM->data());
     226             :         }
     227             : 
     228           0 :         bitmap->installPixels(fInfo, fDM ? fDM->data() : fMalloc, fRowBytes, nullptr,
     229           0 :                               ReleaseProc, this);
     230           0 :         SkBitmapCache_setImmutableWithID(bitmap->pixelRef(), fPrUniqueID);
     231             : 
     232           0 :         REC_TRACE(" Rec: [%d] install new pr\n", fPrUniqueID);
     233             : 
     234           0 :         if (kBeforeFirstInstall_ExternalCounter == fExternalCounter) {
     235           0 :             fExternalCounter = 1;
     236             :         } else {
     237           0 :             fExternalCounter += 1;
     238             :         }
     239           0 :         SkASSERT(fExternalCounter > 0);
     240           0 :         return true;
     241             :     }
     242             : 
     243           0 :     static bool Finder(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
     244           0 :         Rec* rec = (Rec*)&baseRec;
     245           0 :         SkBitmap* result = (SkBitmap*)contextBitmap;
     246           0 :         REC_TRACE(" Rec: [%d] found\n", rec->fPrUniqueID);
     247           0 :         return rec->install(result);
     248             :     }
     249             : 
     250             : private:
     251             :     BitmapKey   fKey;
     252             : 
     253             :     SkMutex     fMutex;
     254             : 
     255             :     // either fDM or fMalloc can be non-null, but not both
     256             :     std::unique_ptr<SkDiscardableMemory> fDM;
     257             :     void*       fMalloc;
     258             : 
     259             :     SkImageInfo fInfo;
     260             :     size_t      fRowBytes;
     261             :     uint32_t    fPrUniqueID;
     262             : 
     263             :     // This field counts the number of external pixelrefs we have created. They notify us when
     264             :     // they are destroyed so we can decrement this.
     265             :     //
     266             :     //  > 0     we have outstanding pixelrefs
     267             :     // == 0     we have no outstanding pixelrefs, and can be safely purged
     268             :     //  < 0     we have been created, but not yet "installed" the first time.
     269             :     //
     270             :     int         fExternalCounter;
     271             : 
     272             :     enum {
     273             :         kBeforeFirstInstall_ExternalCounter = -1
     274             :     };
     275             : };
     276             : 
     277           0 : void SkBitmapCache::PrivateDeleteRec(Rec* rec) { delete rec; }
     278             : 
     279           0 : SkBitmapCache::RecPtr SkBitmapCache::Alloc(const SkBitmapCacheDesc& desc, const SkImageInfo& info,
     280             :                                            SkPixmap* pmap) {
     281             :     // Ensure that the caller is self-consistent:
     282             :     //  - if they are scaling, the info matches the scaled size
     283             :     //  - if they are not, the info matches the subset (i.e. the subset is the entire image)
     284           0 :     if (desc.fScaledWidth == 0 && desc.fScaledHeight == 0) {
     285           0 :         SkASSERT(info.width() == desc.fSubset.width());
     286           0 :         SkASSERT(info.height() == desc.fSubset.height());
     287             :     } else {
     288           0 :         SkASSERT(info.width() == desc.fScaledWidth);
     289           0 :         SkASSERT(info.height() == desc.fScaledHeight);
     290             :     }
     291             : 
     292           0 :     const size_t rb = info.minRowBytes();
     293           0 :     size_t size = info.getSafeSize(rb);
     294           0 :     if (0 == size) {
     295           0 :         return nullptr;
     296             :     }
     297             : 
     298           0 :     std::unique_ptr<SkDiscardableMemory> dm;
     299           0 :     void* block = nullptr;
     300             : 
     301           0 :     auto factory = SkResourceCache::GetDiscardableFactory();
     302           0 :     if (factory) {
     303           0 :         dm.reset(factory(size));
     304             :     } else {
     305           0 :         block = sk_malloc_flags(size, 0);
     306             :     }
     307           0 :     if (!dm && !block) {
     308           0 :         return nullptr;
     309             :     }
     310           0 :     *pmap = SkPixmap(info, dm ? dm->data() : block, rb);
     311           0 :     return RecPtr(new Rec(desc, info, rb, std::move(dm), block));
     312             : }
     313             : 
     314           0 : void SkBitmapCache::Add(RecPtr rec, SkBitmap* bitmap) {
     315           0 :     SkResourceCache::Add(rec.release(), bitmap);
     316           0 : }
     317             : 
     318           0 : bool SkBitmapCache::Find(const SkBitmapCacheDesc& desc, SkBitmap* result) {
     319           0 :     desc.validate();
     320           0 :     return SkResourceCache::Find(BitmapKey(desc), SkBitmapCache::Rec::Finder, result);
     321             : }
     322             : 
     323             : //////////////////////////////////////////////////////////////////////////////////////////
     324             : //////////////////////////////////////////////////////////////////////////////////////////
     325             : 
     326             : #define CHECK_LOCAL(localCache, localName, globalName, ...) \
     327             :     ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
     328             : 
     329             : namespace {
     330             : static unsigned gMipMapKeyNamespaceLabel;
     331             : 
     332             : struct MipMapKey : public SkResourceCache::Key {
     333             : public:
     334           0 :     MipMapKey(uint32_t imageID, const SkIRect& subset, SkDestinationSurfaceColorMode colorMode)
     335           0 :         : fImageID(imageID)
     336           0 :         , fColorMode(static_cast<uint32_t>(colorMode))
     337           0 :         , fSubset(subset)
     338             :     {
     339           0 :         SkASSERT(fImageID);
     340           0 :         SkASSERT(!subset.isEmpty());
     341           0 :         this->init(&gMipMapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fImageID),
     342           0 :                    sizeof(fImageID) + sizeof(fColorMode) + sizeof(fSubset));
     343           0 :     }
     344             : 
     345             :     uint32_t    fImageID;
     346             :     uint32_t    fColorMode;
     347             :     SkIRect     fSubset;
     348             : };
     349             : 
     350             : struct MipMapRec : public SkResourceCache::Rec {
     351           0 :     MipMapRec(uint32_t imageID, const SkIRect& subset, SkDestinationSurfaceColorMode colorMode,
     352             :               const SkMipMap* result)
     353           0 :         : fKey(imageID, subset, colorMode)
     354           0 :         , fMipMap(result)
     355             :     {
     356           0 :         fMipMap->attachToCacheAndRef();
     357           0 :     }
     358             : 
     359           0 :     ~MipMapRec() override {
     360           0 :         fMipMap->detachFromCacheAndUnref();
     361           0 :     }
     362             : 
     363           0 :     const Key& getKey() const override { return fKey; }
     364           0 :     size_t bytesUsed() const override { return sizeof(fKey) + fMipMap->size(); }
     365           0 :     const char* getCategory() const override { return "mipmap"; }
     366           0 :     SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
     367           0 :         return fMipMap->diagnostic_only_getDiscardable();
     368             :     }
     369             : 
     370           0 :     static bool Finder(const SkResourceCache::Rec& baseRec, void* contextMip) {
     371           0 :         const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
     372           0 :         const SkMipMap* mm = SkRef(rec.fMipMap);
     373             :         // the call to ref() above triggers a "lock" in the case of discardable memory,
     374             :         // which means we can now check for null (in case the lock failed).
     375           0 :         if (nullptr == mm->data()) {
     376           0 :             mm->unref();    // balance our call to ref()
     377           0 :             return false;
     378             :         }
     379             :         // the call must call unref() when they are done.
     380           0 :         *(const SkMipMap**)contextMip = mm;
     381           0 :         return true;
     382             :     }
     383             : 
     384             : private:
     385             :     MipMapKey       fKey;
     386             :     const SkMipMap* fMipMap;
     387             : };
     388             : }
     389             : 
     390           0 : const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmapCacheDesc& desc,
     391             :                                           SkDestinationSurfaceColorMode colorMode,
     392             :                                           SkResourceCache* localCache) {
     393           0 :     SkASSERT(desc.fScaledWidth == 0);
     394           0 :     SkASSERT(desc.fScaledHeight == 0);
     395           0 :     MipMapKey key(desc.fImageID, desc.fSubset, colorMode);
     396             :     const SkMipMap* result;
     397             : 
     398           0 :     if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Finder, &result)) {
     399           0 :         result = nullptr;
     400             :     }
     401           0 :     return result;
     402             : }
     403             : 
     404           0 : static SkResourceCache::DiscardableFactory get_fact(SkResourceCache* localCache) {
     405           0 :     return localCache ? localCache->GetDiscardableFactory()
     406           0 :                       : SkResourceCache::GetDiscardableFactory();
     407             : }
     408             : 
     409           0 : const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src,
     410             :                                          SkDestinationSurfaceColorMode colorMode,
     411             :                                          SkResourceCache* localCache) {
     412           0 :     SkMipMap* mipmap = SkMipMap::Build(src, colorMode, get_fact(localCache));
     413           0 :     if (mipmap) {
     414           0 :         MipMapRec* rec = new MipMapRec(src.getGenerationID(), get_bounds_from_bitmap(src),
     415           0 :                                        colorMode, mipmap);
     416           0 :         CHECK_LOCAL(localCache, add, Add, rec);
     417           0 :         src.pixelRef()->notifyAddedToCache();
     418             :     }
     419           0 :     return mipmap;
     420             : }

Generated by: LCOV version 1.13