blob: 27e0e4ab749a97b15f194082007b49144f2b1931 [file] [log] [blame]
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 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.
bsalomon@google.com8fe72472011-03-30 21:26:44 +00006 */
7
bsalomon6d3fe022014-07-25 08:35:45 -07008#include "GrGpuResource.h"
kkinnunencabe20c2015-06-01 01:37:26 -07009#include "GrContext.h"
Robert Phillips6be756b2018-01-16 15:07:54 -050010#include "GrContextPriv.h"
bsalomon0ea80f42015-02-11 10:49:59 -080011#include "GrResourceCache.h"
bsalomon@google.com8fe72472011-03-30 21:26:44 +000012#include "GrGpu.h"
bsalomon3582d3e2015-02-13 14:20:05 -080013#include "GrGpuResourcePriv.h"
ericrk0a5fa482015-09-15 14:16:10 -070014#include "SkTraceMemoryDump.h"
bsalomon@google.com8fe72472011-03-30 21:26:44 +000015
bsalomon0ea80f42015-02-11 10:49:59 -080016static inline GrResourceCache* get_resource_cache(GrGpu* gpu) {
bsalomon49f085d2014-09-05 13:34:00 -070017 SkASSERT(gpu);
18 SkASSERT(gpu->getContext());
Robert Phillips6be756b2018-01-16 15:07:54 -050019 SkASSERT(gpu->getContext()->contextPriv().getResourceCache());
20 return gpu->getContext()->contextPriv().getResourceCache();
bsalomonc8dc1f72014-08-21 13:02:13 -070021}
22
kkinnunen2e6055b2016-04-22 01:48:29 -070023GrGpuResource::GrGpuResource(GrGpu* gpu)
bsalomone2e87f32016-09-22 12:42:11 -070024 : fExternalFlushCntWhenBecamePurgeable(0)
25 , fGpu(gpu)
bsalomon69ed47f2014-11-12 11:13:39 -080026 , fGpuMemorySize(kInvalidGpuMemorySize)
kkinnunen2e6055b2016-04-22 01:48:29 -070027 , fBudgeted(SkBudgeted::kNo)
28 , fRefsWrappedObjects(false)
bsalomon84c8e622014-11-17 09:33:27 -080029 , fUniqueID(CreateUniqueID()) {
bsalomon9f2d1572015-02-17 11:47:40 -080030 SkDEBUGCODE(fCacheArrayIndex = -1);
bsalomon16961262014-08-26 14:01:07 -070031}
32
kkinnunen2e6055b2016-04-22 01:48:29 -070033void GrGpuResource::registerWithCache(SkBudgeted budgeted) {
34 SkASSERT(fBudgeted == SkBudgeted::kNo);
35 fBudgeted = budgeted;
36 this->computeScratchKey(&fScratchKey);
37 get_resource_cache(fGpu)->resourceAccess().insertResource(this);
38}
39
40void GrGpuResource::registerWithCacheWrapped() {
41 SkASSERT(fBudgeted == SkBudgeted::kNo);
42 // Currently resources referencing wrapped objects are not budgeted.
43 fRefsWrappedObjects = true;
bsalomon0ea80f42015-02-11 10:49:59 -080044 get_resource_cache(fGpu)->resourceAccess().insertResource(this);
bsalomon@google.com8fe72472011-03-30 21:26:44 +000045}
46
bsalomon6d3fe022014-07-25 08:35:45 -070047GrGpuResource::~GrGpuResource() {
bsalomon12299ab2014-11-14 13:33:09 -080048 // The cache should have released or destroyed this resource.
commit-bot@chromium.org089a7802014-05-02 21:38:22 +000049 SkASSERT(this->wasDestroyed());
bsalomon@google.com76b7fcc2012-04-27 17:24:09 +000050}
51
halcanary9d524f22016-03-29 09:03:52 -070052void GrGpuResource::release() {
bsalomon12299ab2014-11-14 13:33:09 -080053 SkASSERT(fGpu);
54 this->onRelease();
bsalomon0ea80f42015-02-11 10:49:59 -080055 get_resource_cache(fGpu)->resourceAccess().removeResource(this);
halcanary96fcdcc2015-08-27 07:41:13 -070056 fGpu = nullptr;
bsalomon12299ab2014-11-14 13:33:09 -080057 fGpuMemorySize = 0;
bsalomon@google.com8fe72472011-03-30 21:26:44 +000058}
59
bsalomon6d3fe022014-07-25 08:35:45 -070060void GrGpuResource::abandon() {
bsalomonc6363ef2015-09-24 07:07:40 -070061 if (this->wasDestroyed()) {
62 return;
63 }
bsalomon12299ab2014-11-14 13:33:09 -080064 SkASSERT(fGpu);
65 this->onAbandon();
bsalomon0ea80f42015-02-11 10:49:59 -080066 get_resource_cache(fGpu)->resourceAccess().removeResource(this);
halcanary96fcdcc2015-08-27 07:41:13 -070067 fGpu = nullptr;
bsalomon12299ab2014-11-14 13:33:09 -080068 fGpuMemorySize = 0;
bsalomon@google.com8fe72472011-03-30 21:26:44 +000069}
bsalomon@google.comf7b5c1e2011-11-15 19:42:07 +000070
ericrk0a5fa482015-09-15 14:16:10 -070071void GrGpuResource::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
Eric Karlaf770022018-03-19 13:04:03 -070072 if (this->fRefsWrappedObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
73 return;
74 }
75
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -040076 this->dumpMemoryStatisticsPriv(traceMemoryDump, this->getResourceName(),
77 this->getResourceType(), this->gpuMemorySize());
78}
ericrk0a5fa482015-09-15 14:16:10 -070079
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -040080void GrGpuResource::dumpMemoryStatisticsPriv(SkTraceMemoryDump* traceMemoryDump,
81 const SkString& resourceName,
82 const char* type, size_t size) const {
83 const char* tag = "Scratch";
84 if (fUniqueKey.isValid()) {
85 tag = (fUniqueKey.tag() != nullptr) ? fUniqueKey.tag() : "Other";
ericrk0a5fa482015-09-15 14:16:10 -070086 }
87
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -040088 traceMemoryDump->dumpNumericValue(resourceName.c_str(), "size", "bytes", size);
89 traceMemoryDump->dumpStringValue(resourceName.c_str(), "type", type);
90 traceMemoryDump->dumpStringValue(resourceName.c_str(), "category", tag);
91 if (this->isPurgeable()) {
92 traceMemoryDump->dumpNumericValue(resourceName.c_str(), "purgeable_size", "bytes", size);
93 }
94
95 this->setMemoryBacking(traceMemoryDump, resourceName);
96}
97
98SkString GrGpuResource::getResourceName() const {
99 // Dump resource as "skia/gpu_resources/resource_#".
100 SkString resourceName("skia/gpu_resources/resource_");
101 resourceName.appendU32(this->uniqueID().asUInt());
102 return resourceName;
ericrk0a5fa482015-09-15 14:16:10 -0700103}
104
bsalomon6d3fe022014-07-25 08:35:45 -0700105const GrContext* GrGpuResource::getContext() const {
bsalomon49f085d2014-09-05 13:34:00 -0700106 if (fGpu) {
bsalomon@google.comf7b5c1e2011-11-15 19:42:07 +0000107 return fGpu->getContext();
108 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700109 return nullptr;
bsalomon@google.comf7b5c1e2011-11-15 19:42:07 +0000110 }
111}
112
bsalomon6d3fe022014-07-25 08:35:45 -0700113GrContext* GrGpuResource::getContext() {
bsalomon49f085d2014-09-05 13:34:00 -0700114 if (fGpu) {
bsalomon@google.comf7b5c1e2011-11-15 19:42:07 +0000115 return fGpu->getContext();
116 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700117 return nullptr;
bsalomon@google.comf7b5c1e2011-11-15 19:42:07 +0000118 }
119}
bsalomonc44be0e2014-07-25 07:32:33 -0700120
bsalomon8718aaf2015-02-19 07:24:21 -0800121void GrGpuResource::removeUniqueKey() {
bsalomonc6363ef2015-09-24 07:07:40 -0700122 if (this->wasDestroyed()) {
123 return;
124 }
bsalomon8718aaf2015-02-19 07:24:21 -0800125 SkASSERT(fUniqueKey.isValid());
bsalomonf99e9612015-02-19 08:24:16 -0800126 get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this);
bsalomon23e619c2015-02-06 11:54:28 -0800127}
128
bsalomonf99e9612015-02-19 08:24:16 -0800129void GrGpuResource::setUniqueKey(const GrUniqueKey& key) {
bsalomon6d4488c2014-11-11 07:27:16 -0800130 SkASSERT(this->internalHasRef());
bsalomon23e619c2015-02-06 11:54:28 -0800131 SkASSERT(key.isValid());
bsalomondace19e2014-11-17 07:34:06 -0800132
Brian Osman0562eb92017-05-08 11:16:39 -0400133 // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
134 // resources are a special case: the unique keys give us a weak ref so that we can reuse the
135 // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
136 // it will always be released - it is never converted to a scratch resource.
137 if (SkBudgeted::kNo == this->resourcePriv().isBudgeted() && !this->fRefsWrappedObjects) {
bsalomonf99e9612015-02-19 08:24:16 -0800138 return;
bsalomondace19e2014-11-17 07:34:06 -0800139 }
bsalomon84c8e622014-11-17 09:33:27 -0800140
bsalomonf99e9612015-02-19 08:24:16 -0800141 if (this->wasDestroyed()) {
142 return;
bsalomon8b79d232014-11-10 10:19:06 -0800143 }
144
bsalomonf99e9612015-02-19 08:24:16 -0800145 get_resource_cache(fGpu)->resourceAccess().changeUniqueKey(this, key);
bsalomon8b79d232014-11-10 10:19:06 -0800146}
147
bsalomon3f324322015-04-08 11:01:54 -0700148void GrGpuResource::notifyAllCntsAreZero(CntType lastCntTypeToReachZero) const {
bsalomon12299ab2014-11-14 13:33:09 -0800149 if (this->wasDestroyed()) {
150 // We've already been removed from the cache. Goodbye cruel world!
halcanary385fe4d2015-08-26 13:07:48 -0700151 delete this;
bsalomon3f324322015-04-08 11:01:54 -0700152 return;
bsalomonbcf0a522014-10-08 08:40:09 -0700153 }
bsalomon3f324322015-04-08 11:01:54 -0700154
155 // We should have already handled this fully in notifyRefCntIsZero().
156 SkASSERT(kRef_CntType != lastCntTypeToReachZero);
157
158 GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this);
159 static const uint32_t kFlag =
160 GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag;
161 get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, kFlag);
162}
163
164bool GrGpuResource::notifyRefCountIsZero() const {
165 if (this->wasDestroyed()) {
166 // handle this in notifyAllCntsAreZero().
167 return true;
168 }
169
170 GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this);
Robert Phillipsb6deea82017-05-11 14:14:30 -0400171 uint32_t flags = GrResourceCache::ResourceAccess::kRefCntReachedZero_RefNotificationFlag;
bsalomon3f324322015-04-08 11:01:54 -0700172 if (!this->internalHasPendingIO()) {
173 flags |= GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag;
174 }
175 get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, flags);
176
177 // There is no need to call our notifyAllCntsAreZero function at this point since we already
178 // told the cache about the state of cnts.
179 return false;
bsalomonbcf0a522014-10-08 08:40:09 -0700180}
181
bsalomon10e23ca2014-11-25 05:52:06 -0800182void GrGpuResource::removeScratchKey() {
bsalomon7775c852014-12-30 12:50:52 -0800183 if (!this->wasDestroyed() && fScratchKey.isValid()) {
bsalomon0ea80f42015-02-11 10:49:59 -0800184 get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this);
bsalomon7775c852014-12-30 12:50:52 -0800185 fScratchKey.reset();
bsalomon10e23ca2014-11-25 05:52:06 -0800186 }
187}
188
bsalomonafe30052015-01-16 07:32:33 -0800189void GrGpuResource::makeBudgeted() {
kkinnunen2e6055b2016-04-22 01:48:29 -0700190 if (!this->wasDestroyed() && SkBudgeted::kNo == fBudgeted) {
191 // Currently resources referencing wrapped objects are not budgeted.
192 SkASSERT(!fRefsWrappedObjects);
193 fBudgeted = SkBudgeted::kYes;
bsalomon0ea80f42015-02-11 10:49:59 -0800194 get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
bsalomonafe30052015-01-16 07:32:33 -0800195 }
196}
197
bsalomonc2f35b72015-01-23 07:19:22 -0800198void GrGpuResource::makeUnbudgeted() {
kkinnunen2e6055b2016-04-22 01:48:29 -0700199 if (!this->wasDestroyed() && SkBudgeted::kYes == fBudgeted &&
bsalomonc6363ef2015-09-24 07:07:40 -0700200 !fUniqueKey.isValid()) {
kkinnunen2e6055b2016-04-22 01:48:29 -0700201 fBudgeted = SkBudgeted::kNo;
bsalomon0ea80f42015-02-11 10:49:59 -0800202 get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
bsalomonc2f35b72015-01-23 07:19:22 -0800203 }
204}
205
bsalomon6d3fe022014-07-25 08:35:45 -0700206uint32_t GrGpuResource::CreateUniqueID() {
bsalomonc44be0e2014-07-25 07:32:33 -0700207 static int32_t gUniqueID = SK_InvalidUniqueID;
208 uint32_t id;
209 do {
210 id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1);
211 } while (id == SK_InvalidUniqueID);
212 return id;
213}