blob: 9efdebfb093a2cb72b9be37d0842478ab4c9986c [file] [log] [blame]
Robert Phillips5af44de2017-07-18 14:49:38 -04001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrResourceAllocator.h"
Robert Phillips5af44de2017-07-18 14:49:38 -04009
Adlai Hollerca1137b2021-04-08 11:39:55 -040010#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrGpuResourcePriv.h"
Greg Danielf41b2bd2019-08-22 16:19:24 -040012#include "src/gpu/GrOpsTask.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040013#include "src/gpu/GrRenderTargetProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrResourceProvider.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040015#include "src/gpu/GrSurfaceProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/GrSurfaceProxyPriv.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040017
Adlai Holler4cfbe532021-03-17 10:36:39 -040018#ifdef SK_DEBUG
19#include <atomic>
Mike Klein0ec1c572018-12-04 11:52:51 -050020
Adlai Holler4cfbe532021-03-17 10:36:39 -040021uint32_t GrResourceAllocator::Interval::CreateUniqueID() {
22 static std::atomic<uint32_t> nextID{1};
23 uint32_t id;
24 do {
25 id = nextID.fetch_add(1, std::memory_order_relaxed);
26 } while (id == SK_InvalidUniqueID);
27 return id;
28}
29
30uint32_t GrResourceAllocator::Register::CreateUniqueID() {
31 static std::atomic<uint32_t> nextID{1};
32 uint32_t id;
33 do {
34 id = nextID.fetch_add(1, std::memory_order_relaxed);
35 } while (id == SK_InvalidUniqueID);
36 return id;
37}
Robert Phillipsda1be462018-07-27 07:18:06 -040038#endif
39
Robert Phillips5b65a842017-11-13 15:48:12 -050040GrResourceAllocator::~GrResourceAllocator() {
Robert Phillips5b65a842017-11-13 15:48:12 -050041 SkASSERT(fIntvlList.empty());
42 SkASSERT(fActiveIntvls.empty());
43 SkASSERT(!fIntvlHash.count());
Robert Phillips5b65a842017-11-13 15:48:12 -050044}
45
Adlai Holler7f7a5df2021-02-09 17:41:10 +000046void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy, unsigned int start, unsigned int end,
47 ActualUse actualUse
Chris Dalton8816b932017-11-29 16:48:25 -070048 SkDEBUGCODE(, bool isDirectDstRead)) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040049 SkASSERT(start <= end);
50 SkASSERT(!fAssigned); // We shouldn't be adding any intervals after (or during) assignment
Robert Phillips5f78adf2019-04-22 12:41:39 -040051
Chris Dalton97155592019-06-13 13:40:20 -060052 if (proxy->canSkipResourceAllocator()) {
Robert Phillips5f78adf2019-04-22 12:41:39 -040053 return;
54 }
55
Brian Salomon9cadc312018-12-05 15:09:19 -050056 // If a proxy is read only it must refer to a texture with specific content that cannot be
57 // recycled. We don't need to assign a texture to it and no other proxy can be instantiated
58 // with the same texture.
59 if (proxy->readOnly()) {
Adlai Hollerca1137b2021-04-08 11:39:55 -040060 auto resourceProvider = fDContext->priv().resourceProvider();
61 if (proxy->isLazy() && !proxy->priv().doLazyInstantiation(resourceProvider)) {
Adlai Holler19fd5142021-03-08 10:19:30 -070062 fFailedInstantiation = true;
Brian Salomon9cadc312018-12-05 15:09:19 -050063 } else {
Brian Salomonbeb7f522019-08-30 16:19:42 -040064 // Since we aren't going to add an interval we won't revisit this proxy in assign(). So
65 // must already be instantiated or it must be a lazy proxy that we instantiated above.
66 SkASSERT(proxy->isInstantiated());
Brian Salomon9cadc312018-12-05 15:09:19 -050067 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040068 return;
69 }
Adlai Holler539db2f2021-03-16 09:45:05 -040070 uint32_t proxyID = proxy->uniqueID().asUInt();
71 if (Interval** intvlPtr = fIntvlHash.find(proxyID)) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040072 // Revise the interval for an existing use
Adlai Holler1143b1b2021-03-16 13:07:40 -040073 Interval* intvl = *intvlPtr;
Brian Salomonbeb7f522019-08-30 16:19:42 -040074#ifdef SK_DEBUG
Adlai Holler9e2c50e2021-02-09 14:41:52 -050075 if (0 == start && 0 == end) {
76 // This interval is for the initial upload to a deferred proxy. Due to the vagaries
77 // of how deferred proxies are collected they can appear as uploads multiple times
78 // in a single opsTasks' list and as uploads in several opsTasks.
79 SkASSERT(0 == intvl->start());
80 } else if (isDirectDstRead) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040081 // Direct reads from the render target itself should occur w/in the existing
82 // interval
83 SkASSERT(intvl->start() <= start && intvl->end() >= end);
84 } else {
85 SkASSERT(intvl->end() <= start && intvl->end() <= end);
86 }
87#endif
Adlai Holler7f7a5df2021-02-09 17:41:10 +000088 if (ActualUse::kYes == actualUse) {
89 intvl->addUse();
90 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040091 intvl->extendEnd(end);
92 return;
93 }
Adlai Holler4cfbe532021-03-17 10:36:39 -040094 Interval* newIntvl = fInternalAllocator.make<Interval>(proxy, start, end);
Brian Salomonc6093532018-12-05 21:34:36 +000095
Adlai Holler7f7a5df2021-02-09 17:41:10 +000096 if (ActualUse::kYes == actualUse) {
97 newIntvl->addUse();
98 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040099 fIntvlList.insertByIncreasingStart(newIntvl);
Adlai Holler539db2f2021-03-16 09:45:05 -0400100 fIntvlHash.set(proxyID, newIntvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400101}
102
Adlai Holler7df8d222021-03-19 12:27:49 -0400103bool GrResourceAllocator::Register::isRecyclable(const GrCaps& caps,
104 GrSurfaceProxy* proxy,
105 int knownUseCount) const {
106 if (!caps.reuseScratchTextures() && !proxy->asRenderTargetProxy()) {
107 // Tragically, scratch texture reuse is totally disabled in this case.
108 return false;
109 }
110
111 if (!this->scratchKey().isValid()) {
112 return false; // no scratch key, no free pool
113 }
114 if (this->uniqueKey().isValid()) {
115 return false; // rely on the resource cache to hold onto uniquely-keyed surfaces.
116 }
117 // If all the refs on the proxy are known to the resource allocator then no one
Adlai Holler1143b1b2021-03-16 13:07:40 -0400118 // should be holding onto it outside of Ganesh.
Adlai Holler7df8d222021-03-19 12:27:49 -0400119 return !proxy->refCntGreaterThan(knownUseCount);
120}
121
122bool GrResourceAllocator::Register::instantiateSurface(GrSurfaceProxy* proxy,
123 GrResourceProvider* resourceProvider) {
124 SkASSERT(!proxy->peekSurface());
125
126 sk_sp<GrSurface> surface;
127 if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
128 SkASSERT(uniqueKey == fOriginatingProxy->getUniqueKey());
129 // First try to reattach to a cached surface if the proxy is uniquely keyed
130 surface = resourceProvider->findByUniqueKey<GrSurface>(uniqueKey);
131 }
132 if (!surface) {
133 if (proxy == fOriginatingProxy) {
134 surface = proxy->priv().createSurface(resourceProvider);
135 } else {
136 surface = sk_ref_sp(fOriginatingProxy->peekSurface());
137 }
138 }
139 if (!surface) {
140 return false;
141 }
142
143 // Make surface budgeted if this proxy is budgeted.
144 if (SkBudgeted::kYes == proxy->isBudgeted() &&
145 GrBudgetedType::kBudgeted != surface->resourcePriv().budgetedType()) {
146 // This gets the job done but isn't quite correct. It would be better to try to
147 // match budgeted proxies w/ budgeted surfaces and unbudgeted w/ unbudgeted.
148 surface->resourcePriv().makeBudgeted();
149 }
150
151 // Propagate the proxy unique key to the surface if we have one.
152 if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
153 if (!surface->getUniqueKey().isValid()) {
154 resourceProvider->assignUniqueKeyToResource(uniqueKey, surface.get());
155 }
156 SkASSERT(surface->getUniqueKey() == uniqueKey);
157 }
158 proxy->priv().assign(std::move(surface));
159 return true;
Adlai Holler1143b1b2021-03-16 13:07:40 -0400160}
161
Robert Phillips5af44de2017-07-18 14:49:38 -0400162GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400163 SkDEBUGCODE(this->validate());
164
Robert Phillips5af44de2017-07-18 14:49:38 -0400165 Interval* temp = fHead;
166 if (temp) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500167 fHead = temp->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400168 if (!fHead) {
169 fTail = nullptr;
170 }
171 temp->setNext(nullptr);
Robert Phillips5af44de2017-07-18 14:49:38 -0400172 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400173
174 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400175 return temp;
176}
177
178// TODO: fuse this with insertByIncreasingEnd
179void GrResourceAllocator::IntervalList::insertByIncreasingStart(Interval* intvl) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400180 SkDEBUGCODE(this->validate());
181 SkASSERT(!intvl->next());
182
Robert Phillips5af44de2017-07-18 14:49:38 -0400183 if (!fHead) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400184 // 14%
185 fHead = fTail = intvl;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500186 } else if (intvl->start() <= fHead->start()) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400187 // 3%
Robert Phillipsf8e25022017-11-08 15:24:31 -0500188 intvl->setNext(fHead);
Robert Phillips5af44de2017-07-18 14:49:38 -0400189 fHead = intvl;
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400190 } else if (fTail->start() <= intvl->start()) {
191 // 83%
192 fTail->setNext(intvl);
193 fTail = intvl;
Robert Phillips5af44de2017-07-18 14:49:38 -0400194 } else {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400195 // almost never
Robert Phillips5af44de2017-07-18 14:49:38 -0400196 Interval* prev = fHead;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500197 Interval* next = prev->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400198 for (; intvl->start() > next->start(); prev = next, next = next->next()) {
Robert Phillips5af44de2017-07-18 14:49:38 -0400199 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400200
201 SkASSERT(next);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500202 intvl->setNext(next);
203 prev->setNext(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400204 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400205
206 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400207}
208
209// TODO: fuse this with insertByIncreasingStart
210void GrResourceAllocator::IntervalList::insertByIncreasingEnd(Interval* intvl) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400211 SkDEBUGCODE(this->validate());
212 SkASSERT(!intvl->next());
213
Robert Phillips5af44de2017-07-18 14:49:38 -0400214 if (!fHead) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400215 // 14%
216 fHead = fTail = intvl;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500217 } else if (intvl->end() <= fHead->end()) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400218 // 64%
Robert Phillipsf8e25022017-11-08 15:24:31 -0500219 intvl->setNext(fHead);
Robert Phillips5af44de2017-07-18 14:49:38 -0400220 fHead = intvl;
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400221 } else if (fTail->end() <= intvl->end()) {
222 // 3%
223 fTail->setNext(intvl);
224 fTail = intvl;
Robert Phillips5af44de2017-07-18 14:49:38 -0400225 } else {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400226 // 19% but 81% of those land right after the list's head
Robert Phillips5af44de2017-07-18 14:49:38 -0400227 Interval* prev = fHead;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500228 Interval* next = prev->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400229 for (; intvl->end() > next->end(); prev = next, next = next->next()) {
Robert Phillips5af44de2017-07-18 14:49:38 -0400230 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400231
232 SkASSERT(next);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500233 intvl->setNext(next);
234 prev->setNext(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400235 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400236
237 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400238}
239
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400240#ifdef SK_DEBUG
241void GrResourceAllocator::IntervalList::validate() const {
242 SkASSERT(SkToBool(fHead) == SkToBool(fTail));
243
244 Interval* prev = nullptr;
245 for (Interval* cur = fHead; cur; prev = cur, cur = cur->next()) {
246 }
247
248 SkASSERT(fTail == prev);
249}
250#endif
Robert Phillips4150eea2018-02-07 17:08:21 -0500251
Adlai Holler4cfbe532021-03-17 10:36:39 -0400252// First try to reuse one of the recently allocated/used registers in the free pool.
Adlai Holler7df8d222021-03-19 12:27:49 -0400253GrResourceAllocator::Register* GrResourceAllocator::findOrCreateRegisterFor(GrSurfaceProxy* proxy) {
254 // Handle uniquely keyed proxies
Adlai Hollercc119d92021-03-16 15:17:25 -0400255 if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
Adlai Holler7df8d222021-03-19 12:27:49 -0400256 if (auto p = fUniqueKeyRegisters.find(uniqueKey)) {
257 return *p;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400258 }
Adlai Holler7df8d222021-03-19 12:27:49 -0400259 // No need for a scratch key. These don't go in the free pool.
260 Register* r = fInternalAllocator.make<Register>(proxy, GrScratchKey());
261 fUniqueKeyRegisters.set(uniqueKey, r);
262 return r;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400263 }
264
Adlai Hollercc119d92021-03-16 15:17:25 -0400265 // Then look in the free pool
Adlai Holler7df8d222021-03-19 12:27:49 -0400266 GrScratchKey scratchKey;
Adlai Hollerca1137b2021-04-08 11:39:55 -0400267 proxy->priv().computeScratchKey(*fDContext->priv().caps(), &scratchKey);
Robert Phillips57aa3672017-07-21 11:38:13 -0400268
Adlai Holler4cfbe532021-03-17 10:36:39 -0400269 auto filter = [] (const Register* r) {
Robert Phillips10d17212019-04-24 14:09:10 -0400270 return true;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500271 };
Adlai Holler7df8d222021-03-19 12:27:49 -0400272 if (Register* r = fFreePool.findAndRemove(scratchKey, filter)) {
Adlai Holler4cfbe532021-03-17 10:36:39 -0400273 return r;
Robert Phillips57aa3672017-07-21 11:38:13 -0400274 }
275
Adlai Holler7df8d222021-03-19 12:27:49 -0400276 return fInternalAllocator.make<Register>(proxy, std::move(scratchKey));
Robert Phillips5af44de2017-07-18 14:49:38 -0400277}
278
Adlai Holler7df8d222021-03-19 12:27:49 -0400279// Remove any intervals that end before the current index. Add their registers
Robert Phillips39667382019-04-17 16:03:30 -0400280// to the free pool if possible.
Robert Phillips5af44de2017-07-18 14:49:38 -0400281void GrResourceAllocator::expire(unsigned int curIndex) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500282 while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->end() < curIndex) {
Adlai Holler729ba5e2021-03-15 12:34:31 -0400283 Interval* intvl = fActiveIntvls.popHead();
284 SkASSERT(!intvl->next());
Robert Phillips5b65a842017-11-13 15:48:12 -0500285
Adlai Holler7df8d222021-03-19 12:27:49 -0400286 Register* r = intvl->getRegister();
Adlai Hollerca1137b2021-04-08 11:39:55 -0400287 if (r && r->isRecyclable(*fDContext->priv().caps(), intvl->proxy(), intvl->uses())) {
Adlai Holler7df8d222021-03-19 12:27:49 -0400288#if GR_ALLOCATION_SPEW
289 SkDebugf("putting register %d back into pool\n", r->uniqueID());
290#endif
291 // TODO: fix this insertion so we get a more LRU-ish behavior
292 fFreePool.insert(r->scratchKey(), r);
Robert Phillips5b65a842017-11-13 15:48:12 -0500293 }
Adlai Holler7df8d222021-03-19 12:27:49 -0400294 fFinishedIntvls.insertByIncreasingStart(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400295 }
296}
297
Adlai Holler19fd5142021-03-08 10:19:30 -0700298bool GrResourceAllocator::assign() {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400299 fIntvlHash.reset(); // we don't need the interval hash anymore
300
Robert Phillips5af44de2017-07-18 14:49:38 -0400301 SkDEBUGCODE(fAssigned = true;)
302
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500303 if (fIntvlList.empty()) {
Adlai Holler19fd5142021-03-08 10:19:30 -0700304 return !fFailedInstantiation; // no resources to assign
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500305 }
306
Robert Phillips715d08c2018-07-18 13:56:48 -0400307#if GR_ALLOCATION_SPEW
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500308 SkDebugf("assigning %d ops\n", fNumOps);
Robert Phillips715d08c2018-07-18 13:56:48 -0400309 this->dumpIntervals();
310#endif
Robert Phillipseafd48a2017-11-16 07:52:08 -0500311
Adlai Holler1143b1b2021-03-16 13:07:40 -0400312 while (Interval* cur = fIntvlList.popHead()) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500313 this->expire(cur->start());
Robert Phillips57aa3672017-07-21 11:38:13 -0400314
Adlai Holler7df8d222021-03-19 12:27:49 -0400315 // Already-instantiated proxies and lazy proxies don't use registers.
316 // No need to compute scratch keys (or CANT, in the case of fully-lazy).
317 if (cur->proxy()->isInstantiated() || cur->proxy()->isLazy()) {
Robert Phillips57aa3672017-07-21 11:38:13 -0400318 fActiveIntvls.insertByIncreasingEnd(cur);
Robert Phillipseafd48a2017-11-16 07:52:08 -0500319
Robert Phillips57aa3672017-07-21 11:38:13 -0400320 continue;
321 }
322
Adlai Holler7df8d222021-03-19 12:27:49 -0400323 Register* r = this->findOrCreateRegisterFor(cur->proxy());
Robert Phillips715d08c2018-07-18 13:56:48 -0400324#if GR_ALLOCATION_SPEW
Adlai Holler7df8d222021-03-19 12:27:49 -0400325 SkDebugf("Assigning register %d to %d\n",
326 r->uniqueID(),
327 cur->proxy()->uniqueID().asUInt());
Robert Phillips715d08c2018-07-18 13:56:48 -0400328#endif
Adlai Holler7df8d222021-03-19 12:27:49 -0400329 SkASSERT(!cur->proxy()->peekSurface());
330 cur->setRegister(r);
Robert Phillipseafd48a2017-11-16 07:52:08 -0500331
Robert Phillips5af44de2017-07-18 14:49:38 -0400332 fActiveIntvls.insertByIncreasingEnd(cur);
333 }
Robert Phillips5b65a842017-11-13 15:48:12 -0500334
335 // expire all the remaining intervals to drain the active interval list
336 this->expire(std::numeric_limits<unsigned int>::max());
Adlai Holler7df8d222021-03-19 12:27:49 -0400337
338 // TODO: Return here and give the caller a chance to estimate memory cost and bail before
339 // instantiating anything.
340
341 // Instantiate surfaces
Adlai Hollerca1137b2021-04-08 11:39:55 -0400342 auto resourceProvider = fDContext->priv().resourceProvider();
Adlai Holler7df8d222021-03-19 12:27:49 -0400343 while (Interval* cur = fFinishedIntvls.popHead()) {
344 if (fFailedInstantiation) {
345 break;
346 }
347 if (cur->proxy()->isInstantiated()) {
348 continue;
349 }
350 if (cur->proxy()->isLazy()) {
Adlai Hollerca1137b2021-04-08 11:39:55 -0400351 fFailedInstantiation = !cur->proxy()->priv().doLazyInstantiation(resourceProvider);
Adlai Holler7df8d222021-03-19 12:27:49 -0400352 continue;
353 }
354 Register* r = cur->getRegister();
355 SkASSERT(r);
Adlai Hollerca1137b2021-04-08 11:39:55 -0400356 fFailedInstantiation = !r->instantiateSurface(cur->proxy(), resourceProvider);
Adlai Holler7df8d222021-03-19 12:27:49 -0400357 }
Adlai Holler19fd5142021-03-08 10:19:30 -0700358 return !fFailedInstantiation;
Robert Phillips5af44de2017-07-18 14:49:38 -0400359}
Robert Phillips715d08c2018-07-18 13:56:48 -0400360
361#if GR_ALLOCATION_SPEW
362void GrResourceAllocator::dumpIntervals() {
Robert Phillips715d08c2018-07-18 13:56:48 -0400363 // Print all the intervals while computing their range
Robert Phillips3bf3d4a2019-03-27 07:09:09 -0400364 SkDebugf("------------------------------------------------------------\n");
365 unsigned int min = std::numeric_limits<unsigned int>::max();
Robert Phillips715d08c2018-07-18 13:56:48 -0400366 unsigned int max = 0;
367 for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
Greg Danielc61d7e32020-02-04 14:27:45 -0500368 SkDebugf("{ %3d,%3d }: [%2d, %2d] - refProxys:%d surfaceRefs:%d\n",
Robert Phillips715d08c2018-07-18 13:56:48 -0400369 cur->proxy()->uniqueID().asUInt(),
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400370 cur->proxy()->isInstantiated() ? cur->proxy()->underlyingUniqueID().asUInt() : -1,
Robert Phillips715d08c2018-07-18 13:56:48 -0400371 cur->start(),
372 cur->end(),
373 cur->proxy()->priv().getProxyRefCnt(),
Robert Phillipsb5204762019-06-19 14:12:13 -0400374 cur->proxy()->testingOnly_getBackingRefCnt());
Brian Osman788b9162020-02-07 10:36:46 -0500375 min = std::min(min, cur->start());
376 max = std::max(max, cur->end());
Robert Phillips715d08c2018-07-18 13:56:48 -0400377 }
378
379 // Draw a graph of the useage intervals
380 for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
381 SkDebugf("{ %3d,%3d }: ",
382 cur->proxy()->uniqueID().asUInt(),
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400383 cur->proxy()->isInstantiated() ? cur->proxy()->underlyingUniqueID().asUInt() : -1);
Robert Phillips715d08c2018-07-18 13:56:48 -0400384 for (unsigned int i = min; i <= max; ++i) {
385 if (i >= cur->start() && i <= cur->end()) {
386 SkDebugf("x");
387 } else {
388 SkDebugf(" ");
389 }
390 }
391 SkDebugf("\n");
392 }
393}
394#endif