blob: f7c9a7a119faf6d1ab3d23e8dd85fe30a4d5981e [file] [log] [blame]
bsalomonc8dc1f72014-08-21 13:02:13 -07001
2/*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "GrResourceCache2.h"
bsalomonbcf0a522014-10-08 08:40:09 -070011#include "GrGpuResource.h"
bsalomonc8dc1f72014-08-21 13:02:13 -070012
bsalomonfe369ee2014-11-10 11:59:06 -080013GrResourceKey& GrResourceKey::NullScratchKey() {
14 static const GrCacheID::Key kBogusKey = { { {0} } };
15 static GrCacheID kBogusID(ScratchDomain(), kBogusKey);
16 static GrResourceKey kNullScratchKey(kBogusID, NoneResourceType(), 0);
17 return kNullScratchKey;
18}
19
20GrResourceKey::ResourceType GrResourceKey::NoneResourceType() {
21 static const ResourceType gNoneResourceType = GenerateResourceType();
22 return gNoneResourceType;
23}
24
25GrCacheID::Domain GrResourceKey::ScratchDomain() {
26 static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain();
27 return gDomain;
28}
29
30//////////////////////////////////////////////////////////////////////////////
31
bsalomonc8dc1f72014-08-21 13:02:13 -070032GrResourceCache2::~GrResourceCache2() {
33 this->releaseAll();
34}
35
36void GrResourceCache2::insertResource(GrGpuResource* resource) {
bsalomon49f085d2014-09-05 13:34:00 -070037 SkASSERT(resource);
bsalomonc8dc1f72014-08-21 13:02:13 -070038 SkASSERT(!resource->wasDestroyed());
bsalomon16961262014-08-26 14:01:07 -070039 SkASSERT(!this->isInCache(resource));
bsalomonc8dc1f72014-08-21 13:02:13 -070040 fResources.addToHead(resource);
41 ++fCount;
bsalomon744998e2014-08-28 09:54:34 -070042 if (!resource->getScratchKey().isNullScratch()) {
bsalomon8b79d232014-11-10 10:19:06 -080043 // TODO(bsalomon): Make this assertion possible.
44 // SkASSERT(!resource->isWrapped());
bsalomon744998e2014-08-28 09:54:34 -070045 fScratchMap.insert(resource->getScratchKey(), resource);
46 }
bsalomonc8dc1f72014-08-21 13:02:13 -070047}
48
49void GrResourceCache2::removeResource(GrGpuResource* resource) {
bsalomon16961262014-08-26 14:01:07 -070050 SkASSERT(this->isInCache(resource));
bsalomon744998e2014-08-28 09:54:34 -070051 fResources.remove(resource);
52 if (!resource->getScratchKey().isNullScratch()) {
53 fScratchMap.remove(resource->getScratchKey(), resource);
54 }
bsalomon8b79d232014-11-10 10:19:06 -080055 if (const GrResourceKey* contentKey = resource->getContentKey()) {
56 fContentHash.remove(*contentKey);
57 }
bsalomonc8dc1f72014-08-21 13:02:13 -070058 --fCount;
59}
60
61void GrResourceCache2::abandonAll() {
62 while (GrGpuResource* head = fResources.head()) {
63 SkASSERT(!head->wasDestroyed());
64 head->abandon();
65 // abandon should have already removed this from the list.
66 SkASSERT(head != fResources.head());
67 }
bsalomon744998e2014-08-28 09:54:34 -070068 SkASSERT(!fScratchMap.count());
bsalomon8b79d232014-11-10 10:19:06 -080069 SkASSERT(!fContentHash.count());
bsalomonc8dc1f72014-08-21 13:02:13 -070070 SkASSERT(!fCount);
71}
72
73void GrResourceCache2::releaseAll() {
74 while (GrGpuResource* head = fResources.head()) {
75 SkASSERT(!head->wasDestroyed());
76 head->release();
77 // release should have already removed this from the list.
78 SkASSERT(head != fResources.head());
79 }
bsalomon744998e2014-08-28 09:54:34 -070080 SkASSERT(!fScratchMap.count());
bsalomonc8dc1f72014-08-21 13:02:13 -070081 SkASSERT(!fCount);
82}
bsalomonbcf0a522014-10-08 08:40:09 -070083
84class GrResourceCache2::AvailableForScratchUse {
85public:
bsalomon000f8292014-10-15 19:04:14 -070086 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendingIO) { }
bsalomonbcf0a522014-10-08 08:40:09 -070087
88 bool operator()(const GrGpuResource* resource) const {
bsalomon000f8292014-10-15 19:04:14 -070089 if (!resource->reffedOnlyByCache() || !resource->isScratch()) {
90 return false;
bsalomonbcf0a522014-10-08 08:40:09 -070091 }
bsalomon000f8292014-10-15 19:04:14 -070092
93 return !fRejectPendingIO || !resource->internalHasPendingIO();
bsalomonbcf0a522014-10-08 08:40:09 -070094 }
bsalomon1e2530b2014-10-09 09:57:18 -070095
bsalomonbcf0a522014-10-08 08:40:09 -070096private:
bsalomon000f8292014-10-15 19:04:14 -070097 bool fRejectPendingIO;
bsalomonbcf0a522014-10-08 08:40:09 -070098};
99
100GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey& scratchKey,
bsalomon000f8292014-10-15 19:04:14 -0700101 uint32_t flags) {
bsalomonbcf0a522014-10-08 08:40:09 -0700102 SkASSERT(scratchKey.isScratch());
bsalomon000f8292014-10-15 19:04:14 -0700103
104 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) {
105 GrGpuResource* resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
106 if (resource) {
107 return SkRef(resource);
108 } else if (flags & kRequireNoPendingIO_ScratchFlag) {
109 return NULL;
110 }
111 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io,
112 // but there is still space in our budget for the resource.
113 }
114 return SkSafeRef(fScratchMap.find(scratchKey, AvailableForScratchUse(false)));
bsalomonbcf0a522014-10-08 08:40:09 -0700115}
bsalomon8b79d232014-11-10 10:19:06 -0800116
117void GrResourceCache2::willRemoveContentKey(const GrGpuResource* resource) {
118 SkASSERT(resource);
119 SkASSERT(resource->getContentKey());
120 SkDEBUGCODE(GrGpuResource* res = fContentHash.find(*resource->getContentKey()));
121 SkASSERT(res == resource);
122
123 fContentHash.remove(*resource->getContentKey());
124}
125
126bool GrResourceCache2::didAddContentKey(GrGpuResource* resource) {
127 SkASSERT(resource);
128 SkASSERT(resource->getContentKey());
129
130 GrGpuResource* res = fContentHash.find(*resource->getContentKey());
131 if (NULL != res) {
132 return false;
133 }
134
135 fContentHash.add(resource);
136 return true;
137}