1 /* 2 * Copyright 2017 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 "GrResourceAllocator.h" 9 10 #include "GrSurfaceProxy.h" 11 #include "GrSurfaceProxyPriv.h" 12 addInterval(GrSurfaceProxy * proxy,unsigned int start,unsigned int end)13void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy, 14 unsigned int start, unsigned int end) { 15 SkASSERT(start <= end); 16 SkASSERT(!fAssigned); // We shouldn't be adding any intervals after (or during) assignment 17 18 if (Interval* intvl = fIntvlHash.find(proxy->uniqueID().asUInt())) { 19 // Revise the interval for an existing use 20 SkASSERT(intvl->fEnd < start); 21 intvl->fEnd = end; 22 return; 23 } 24 25 // TODO: given the usage pattern an arena allocation scheme would work well here 26 Interval* newIntvl = new Interval(proxy, start, end); 27 28 fIntvlList.insertByIncreasingStart(newIntvl); 29 fIntvlHash.add(newIntvl); 30 } 31 popHead()32GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() { 33 Interval* temp = fHead; 34 if (temp) { 35 fHead = temp->fNext; 36 } 37 return temp; 38 } 39 40 // TODO: fuse this with insertByIncreasingEnd insertByIncreasingStart(Interval * intvl)41void GrResourceAllocator::IntervalList::insertByIncreasingStart(Interval* intvl) { 42 if (!fHead) { 43 intvl->fNext = nullptr; 44 fHead = intvl; 45 } else if (intvl->fStart <= fHead->fStart) { 46 intvl->fNext = fHead; 47 fHead = intvl; 48 } else { 49 Interval* prev = fHead; 50 Interval* next = prev->fNext; 51 for (; next && intvl->fStart > next->fStart; prev = next, next = next->fNext) { 52 } 53 intvl->fNext = next; 54 prev->fNext = intvl; 55 } 56 } 57 58 // TODO: fuse this with insertByIncreasingStart insertByIncreasingEnd(Interval * intvl)59void GrResourceAllocator::IntervalList::insertByIncreasingEnd(Interval* intvl) { 60 if (!fHead) { 61 intvl->fNext = nullptr; 62 fHead = intvl; 63 } else if (intvl->fEnd <= fHead->fEnd) { 64 intvl->fNext = fHead; 65 fHead = intvl; 66 } else { 67 Interval* prev = fHead; 68 Interval* next = prev->fNext; 69 for (; next && intvl->fEnd > next->fEnd; prev = next, next = next->fNext) { 70 } 71 intvl->fNext = next; 72 prev->fNext = intvl; 73 } 74 } 75 76 // 'surface' can be reused. Add it back to the free pool. freeUpSurface(GrSurface * surface)77void GrResourceAllocator::freeUpSurface(GrSurface* surface) { 78 // TODO: add free pool 79 } 80 81 // First try to reuse one of the recently allocated/used GrSurfaces in the free pool. 82 // If we can't find a useable one, create a new one. 83 // TODO: handle being overbudget findSurfaceFor(GrSurfaceProxy * proxy)84sk_sp<GrSurface> GrResourceAllocator::findSurfaceFor(GrSurfaceProxy* proxy) { 85 // TODO: add free pool 86 87 // Try to grab one from the resource cache 88 return proxy->priv().createSurface(fResourceProvider); 89 } 90 91 // Remove any intervals that end before the current index. Return their GrSurfaces 92 // to the free pool. expire(unsigned int curIndex)93void GrResourceAllocator::expire(unsigned int curIndex) { 94 while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->fEnd < curIndex) { 95 Interval* temp = fActiveIntvls.popHead(); 96 this->freeUpSurface(temp->fProxy->priv().peekSurface()); 97 delete temp; 98 } 99 } 100 assign()101void GrResourceAllocator::assign() { 102 fIntvlHash.reset(); // we don't need this anymore 103 SkDEBUGCODE(fAssigned = true;) 104 105 while (Interval* cur = fIntvlList.popHead()) { 106 this->expire(cur->fStart); 107 // TODO: add over budget handling here? 108 sk_sp<GrSurface> surface = this->findSurfaceFor(cur->fProxy); 109 if (surface) { 110 cur->fProxy->priv().assign(std::move(surface)); 111 } 112 // TODO: handle resouce allocation failure upstack 113 fActiveIntvls.insertByIncreasingEnd(cur); 114 } 115 } 116