1 /* 2 * Copyright 2016 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 // This is a GPU-backend specific test. 9 10 #include "Test.h" 11 12 #if SK_SUPPORT_GPU 13 #include "GrRenderTargetPriv.h" 14 #include "GrRenderTargetProxy.h" 15 #include "GrResourceProvider.h" 16 #include "GrSurfaceProxy.h" 17 #include "GrTextureProxy.h" 18 19 int32_t GrIORefProxy::getProxyRefCnt_TestOnly() const { 20 return fRefCnt; 21 } 22 23 int32_t GrIORefProxy::getBackingRefCnt_TestOnly() const { 24 if (fTarget) { 25 return fTarget->fRefCnt; 26 } 27 28 return fRefCnt; 29 } 30 31 int32_t GrIORefProxy::getPendingReadCnt_TestOnly() const { 32 if (fTarget) { 33 SkASSERT(!fPendingReads); 34 return fTarget->fPendingReads; 35 } 36 37 return fPendingReads; 38 } 39 40 int32_t GrIORefProxy::getPendingWriteCnt_TestOnly() const { 41 if (fTarget) { 42 SkASSERT(!fPendingWrites); 43 return fTarget->fPendingWrites; 44 } 45 46 return fPendingWrites; 47 } 48 49 static const int kWidthHeight = 128; 50 51 static void check_refs(skiatest::Reporter* reporter, 52 GrSurfaceProxy* proxy, 53 int32_t expectedProxyRefs, 54 int32_t expectedBackingRefs, 55 int32_t expectedNumReads, 56 int32_t expectedNumWrites) { 57 REPORTER_ASSERT(reporter, proxy->getProxyRefCnt_TestOnly() == expectedProxyRefs); 58 REPORTER_ASSERT(reporter, proxy->getBackingRefCnt_TestOnly() == expectedBackingRefs); 59 REPORTER_ASSERT(reporter, proxy->getPendingReadCnt_TestOnly() == expectedNumReads); 60 REPORTER_ASSERT(reporter, proxy->getPendingWriteCnt_TestOnly() == expectedNumWrites); 61 62 SkASSERT(proxy->getProxyRefCnt_TestOnly() == expectedProxyRefs); 63 SkASSERT(proxy->getBackingRefCnt_TestOnly() == expectedBackingRefs); 64 SkASSERT(proxy->getPendingReadCnt_TestOnly() == expectedNumReads); 65 SkASSERT(proxy->getPendingWriteCnt_TestOnly() == expectedNumWrites); 66 } 67 68 static sk_sp<GrSurfaceProxy> make_deferred(GrResourceProvider* provider) { 69 GrSurfaceDesc desc; 70 desc.fFlags = kRenderTarget_GrSurfaceFlag; 71 desc.fWidth = kWidthHeight; 72 desc.fHeight = kWidthHeight; 73 desc.fConfig = kRGBA_8888_GrPixelConfig; 74 75 return GrSurfaceProxy::MakeDeferred(provider, desc, 76 SkBackingFit::kApprox, SkBudgeted::kYes); 77 } 78 79 static sk_sp<GrSurfaceProxy> make_wrapped(GrResourceProvider* provider) { 80 GrSurfaceDesc desc; 81 desc.fFlags = kRenderTarget_GrSurfaceFlag; 82 desc.fWidth = kWidthHeight; 83 desc.fHeight = kWidthHeight; 84 desc.fConfig = kRGBA_8888_GrPixelConfig; 85 86 sk_sp<GrTexture> tex(provider->createTexture(desc, SkBudgeted::kNo)); 87 88 // Flush the IOWrite from the initial discard or it will confuse the later ref count checks 89 tex->flushWrites(); 90 91 return GrSurfaceProxy::MakeWrapped(std::move(tex)); 92 } 93 94 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ProxyRefTest, reporter, ctxInfo) { 95 GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider(); 96 const GrCaps& caps = *ctxInfo.grContext()->caps(); 97 98 // Currently the op itself takes a pending write and the render target op list does as well. 99 static const int kWritesForDiscard = 2; 100 for (auto make : { make_deferred, make_wrapped }) { 101 // A single write 102 { 103 sk_sp<GrSurfaceProxy> sProxy((*make)(provider)); 104 105 GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fWrite(sProxy.get()); 106 107 check_refs(reporter, sProxy.get(), 1, 1, 0, 1); 108 109 // In the deferred case, the discard op created on instantiation adds an 110 // extra ref and write 111 bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() && 112 caps.discardRenderTargetSupport(); 113 int expectedWrites = 1 + (proxyGetsDiscardRef ? kWritesForDiscard : 0); 114 115 sProxy->instantiate(provider); 116 117 // In the deferred case, this checks that the refs transfered to the GrSurface 118 check_refs(reporter, sProxy.get(), 1, 1, 0, expectedWrites); 119 } 120 121 // A single read 122 { 123 sk_sp<GrSurfaceProxy> sProxy((*make)(provider)); 124 125 GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(sProxy.get()); 126 127 check_refs(reporter, sProxy.get(), 1, 1, 1, 0); 128 129 // In the deferred case, the discard op created on instantiation adds an 130 // extra ref and write 131 bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() && 132 caps.discardRenderTargetSupport(); 133 int expectedWrites = proxyGetsDiscardRef ? kWritesForDiscard : 0; 134 135 sProxy->instantiate(provider); 136 137 // In the deferred case, this checks that the refs transfered to the GrSurface 138 check_refs(reporter, sProxy.get(), 1, 1, 1, expectedWrites); 139 } 140 141 // A single read/write pair 142 { 143 sk_sp<GrSurfaceProxy> sProxy((*make)(provider)); 144 145 GrPendingIOResource<GrSurfaceProxy, kRW_GrIOType> fRW(sProxy.get()); 146 147 check_refs(reporter, sProxy.get(), 1, 1, 1, 1); 148 149 // In the deferred case, the discard op created on instantiation adds an 150 // extra ref and write 151 bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() && 152 caps.discardRenderTargetSupport(); 153 int expectedWrites = 1 + (proxyGetsDiscardRef ? kWritesForDiscard : 0); 154 155 sProxy->instantiate(provider); 156 157 // In the deferred case, this checks that the refs transferred to the GrSurface 158 check_refs(reporter, sProxy.get(), 1, 1, 1, expectedWrites); 159 } 160 161 // Multiple normal refs 162 { 163 sk_sp<GrSurfaceProxy> sProxy((*make)(provider)); 164 sProxy->ref(); 165 sProxy->ref(); 166 167 check_refs(reporter, sProxy.get(), 3, 3, 0, 0); 168 169 bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() && 170 caps.discardRenderTargetSupport(); 171 int expectedWrites = proxyGetsDiscardRef ? kWritesForDiscard : 0; 172 173 sProxy->instantiate(provider); 174 175 // In the deferred case, this checks that the refs transferred to the GrSurface 176 check_refs(reporter, sProxy.get(), 3, 3, 0, expectedWrites); 177 178 sProxy->unref(); 179 sProxy->unref(); 180 } 181 182 // Continue using (reffing) proxy after instantiation 183 { 184 sk_sp<GrSurfaceProxy> sProxy((*make)(provider)); 185 sProxy->ref(); 186 187 GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fWrite(sProxy.get()); 188 189 check_refs(reporter, sProxy.get(), 2, 2, 0, 1); 190 191 bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() && 192 caps.discardRenderTargetSupport(); 193 int expectedWrites = 1 + (proxyGetsDiscardRef ? kWritesForDiscard : 0); 194 195 sProxy->instantiate(provider); 196 197 // In the deferred case, this checks that the refs transfered to the GrSurface 198 check_refs(reporter, sProxy.get(), 2, 2, 0, expectedWrites); 199 200 sProxy->unref(); 201 check_refs(reporter, sProxy.get(), 1, 1, 0, expectedWrites); 202 203 GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(sProxy.get()); 204 check_refs(reporter, sProxy.get(), 1, 1, 1, expectedWrites); 205 } 206 } 207 } 208 #endif 209