• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)13 void 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()32 GrResourceAllocator::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)41 void 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)59 void 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)77 void 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)84 sk_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)93 void 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()101 void 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