TextureProxyTest.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. // This is a GPU-backend specific test.
  8. #include "tests/Test.h"
  9. #include "include/gpu/GrBackendSurface.h"
  10. #include "include/gpu/GrTexture.h"
  11. #include "src/gpu/GrContextPriv.h"
  12. #include "src/gpu/GrProxyProvider.h"
  13. #include "src/gpu/GrResourceCache.h"
  14. #include "src/gpu/GrResourceProvider.h"
  15. #include "src/gpu/GrTextureProxy.h"
  16. #include "include/core/SkImage.h"
  17. #include "src/gpu/SkGr.h"
  18. int GrProxyProvider::numUniqueKeyProxies_TestOnly() const {
  19. return fUniquelyKeyedProxies.count();
  20. }
  21. static GrSurfaceDesc make_desc() {
  22. GrSurfaceDesc desc;
  23. desc.fWidth = 64;
  24. desc.fHeight = 64;
  25. desc.fConfig = kRGBA_8888_GrPixelConfig;
  26. return desc;
  27. }
  28. ///////////////////////////////////////////////////////////////////////////////////////////////////
  29. // Basic test
  30. static sk_sp<GrTextureProxy> deferred_tex(skiatest::Reporter* reporter, GrContext* ctx,
  31. GrProxyProvider* proxyProvider, SkBackingFit fit) {
  32. const GrSurfaceDesc desc = make_desc();
  33. GrBackendFormat format =
  34. ctx->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
  35. sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(format, desc, GrRenderable::kNo, 1,
  36. kBottomLeft_GrSurfaceOrigin, fit,
  37. SkBudgeted::kYes, GrProtected::kNo);
  38. // Only budgeted & wrapped external proxies get to carry uniqueKeys
  39. REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
  40. return proxy;
  41. }
  42. static sk_sp<GrTextureProxy> deferred_texRT(skiatest::Reporter* reporter, GrContext* ctx,
  43. GrProxyProvider* proxyProvider, SkBackingFit fit) {
  44. const GrSurfaceDesc desc = make_desc();
  45. GrBackendFormat format =
  46. ctx->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
  47. sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(format, desc, GrRenderable::kYes, 1,
  48. kBottomLeft_GrSurfaceOrigin, fit,
  49. SkBudgeted::kYes, GrProtected::kNo);
  50. // Only budgeted & wrapped external proxies get to carry uniqueKeys
  51. REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
  52. return proxy;
  53. }
  54. static sk_sp<GrTextureProxy> wrapped(skiatest::Reporter* reporter, GrContext* ctx,
  55. GrProxyProvider* proxyProvider, SkBackingFit fit) {
  56. const GrSurfaceDesc desc = make_desc();
  57. sk_sp<GrTextureProxy> proxy = proxyProvider->testingOnly_createInstantiatedProxy(
  58. desc, GrRenderable::kNo, 1, kBottomLeft_GrSurfaceOrigin, fit, SkBudgeted::kYes,
  59. GrProtected::kNo);
  60. // Only budgeted & wrapped external proxies get to carry uniqueKeys
  61. REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
  62. return proxy;
  63. }
  64. static sk_sp<GrTextureProxy> wrapped_with_key(skiatest::Reporter* reporter, GrContext* ctx,
  65. GrProxyProvider* proxyProvider, SkBackingFit fit) {
  66. static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
  67. static int kUniqueKeyData = 0;
  68. GrUniqueKey key;
  69. GrUniqueKey::Builder builder(&key, d, 1, nullptr);
  70. builder[0] = kUniqueKeyData++;
  71. builder.finish();
  72. const GrSurfaceDesc desc = make_desc();
  73. // Only budgeted & wrapped external proxies get to carry uniqueKeys
  74. sk_sp<GrTextureProxy> proxy = proxyProvider->testingOnly_createInstantiatedProxy(
  75. desc, GrRenderable::kNo, 1, kBottomLeft_GrSurfaceOrigin, fit, SkBudgeted::kYes,
  76. GrProtected::kNo);
  77. SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get()));
  78. REPORTER_ASSERT(reporter, proxy->getUniqueKey().isValid());
  79. return proxy;
  80. }
  81. static sk_sp<GrTextureProxy> create_wrapped_backend(GrContext* context, SkBackingFit fit,
  82. sk_sp<GrTexture>* backingSurface) {
  83. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  84. GrResourceProvider* resourceProvider = context->priv().resourceProvider();
  85. const GrSurfaceDesc desc = make_desc();
  86. *backingSurface = resourceProvider->createTexture(desc, GrRenderable::kNo, 1, SkBudgeted::kNo,
  87. GrProtected::kNo,
  88. GrResourceProvider::Flags::kNoPendingIO);
  89. if (!(*backingSurface)) {
  90. return nullptr;
  91. }
  92. GrBackendTexture backendTex = (*backingSurface)->getBackendTexture();
  93. backendTex.setPixelConfig(desc.fConfig);
  94. return proxyProvider->wrapBackendTexture(backendTex, GrColorType::kRGBA_8888,
  95. kBottomLeft_GrSurfaceOrigin, kBorrow_GrWrapOwnership,
  96. GrWrapCacheable::kYes, kRead_GrIOType);
  97. }
  98. // This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning
  99. // and looking them up work, etc.
  100. static void basic_test(GrContext* context,
  101. skiatest::Reporter* reporter,
  102. sk_sp<GrTextureProxy> proxy) {
  103. static int id = 1;
  104. GrResourceProvider* resourceProvider = context->priv().resourceProvider();
  105. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  106. GrResourceCache* cache = context->priv().getResourceCache();
  107. int startCacheCount = cache->getResourceCount();
  108. GrUniqueKey key;
  109. if (proxy->getUniqueKey().isValid()) {
  110. key = proxy->getUniqueKey();
  111. } else {
  112. GrMakeKeyFromImageID(&key, id, SkIRect::MakeWH(64, 64));
  113. ++id;
  114. // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation
  115. REPORTER_ASSERT(reporter, !proxyProvider->numUniqueKeyProxies_TestOnly());
  116. SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get()));
  117. }
  118. REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
  119. REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount());
  120. // setUniqueKey had better stick
  121. REPORTER_ASSERT(reporter, key == proxy->getUniqueKey());
  122. // We just added it, surely we can find it
  123. REPORTER_ASSERT(reporter, proxyProvider->findOrCreateProxyByUniqueKey(
  124. key, kBottomLeft_GrSurfaceOrigin));
  125. REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
  126. int expectedCacheCount = startCacheCount + (proxy->isInstantiated() ? 0 : 1);
  127. // Once instantiated, the backing resource should have the same key
  128. SkAssertResult(proxy->instantiate(resourceProvider));
  129. const GrUniqueKey texKey = proxy->peekSurface()->getUniqueKey();
  130. REPORTER_ASSERT(reporter, texKey.isValid());
  131. REPORTER_ASSERT(reporter, key == texKey);
  132. // An Unbudgeted-cacheable resource will not get purged when a proxy with the same key is
  133. // deleted.
  134. bool expectResourceToOutliveProxy = proxy->peekSurface()->resourcePriv().budgetedType() ==
  135. GrBudgetedType::kUnbudgetedCacheable;
  136. // An Unbudgeted-uncacheable resource is never kept alive if it's ref cnt reaches zero even if
  137. // it has a key.
  138. bool expectDeletingProxyToDeleteResource =
  139. proxy->peekSurface()->resourcePriv().budgetedType() ==
  140. GrBudgetedType::kUnbudgetedUncacheable;
  141. // deleting the proxy should delete it from the hash but not the cache
  142. proxy = nullptr;
  143. if (expectDeletingProxyToDeleteResource) {
  144. expectedCacheCount -= 1;
  145. }
  146. REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
  147. REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
  148. // If the proxy was cached refinding it should bring it back to life
  149. proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
  150. REPORTER_ASSERT(reporter, proxy);
  151. REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
  152. REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
  153. // Mega-purging it should remove it from both the hash and the cache
  154. proxy = nullptr;
  155. cache->purgeAllUnlocked();
  156. if (!expectResourceToOutliveProxy) {
  157. expectedCacheCount--;
  158. }
  159. REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
  160. // If the texture was deleted then the proxy should no longer be findable. Otherwise, it should
  161. // be.
  162. proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
  163. REPORTER_ASSERT(reporter, expectResourceToOutliveProxy ? (bool)proxy : !proxy);
  164. REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
  165. if (expectResourceToOutliveProxy) {
  166. proxy.reset();
  167. GrUniqueKeyInvalidatedMessage msg(texKey, context->priv().contextID());
  168. SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(msg);
  169. cache->purgeAsNeeded();
  170. expectedCacheCount--;
  171. proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
  172. REPORTER_ASSERT(reporter, !proxy);
  173. REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
  174. }
  175. }
  176. ///////////////////////////////////////////////////////////////////////////////////////////////////
  177. // Invalidation test
  178. // Test if invalidating unique ids operates as expected for texture proxies.
  179. static void invalidation_test(GrContext* context, skiatest::Reporter* reporter) {
  180. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  181. GrResourceCache* cache = context->priv().getResourceCache();
  182. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  183. sk_sp<SkImage> rasterImg;
  184. {
  185. SkImageInfo ii = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
  186. SkBitmap bm;
  187. bm.allocPixels(ii);
  188. rasterImg = SkImage::MakeFromBitmap(bm);
  189. REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
  190. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  191. }
  192. sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(context, nullptr);
  193. REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
  194. REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
  195. rasterImg = nullptr; // this invalidates the uniqueKey
  196. // this forces the cache to respond to the inval msg
  197. int maxNum;
  198. size_t maxBytes;
  199. context->getResourceCacheLimits(&maxNum, &maxBytes);
  200. context->setResourceCacheLimits(maxNum-1, maxBytes);
  201. REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
  202. REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
  203. textureImg = nullptr;
  204. context->priv().testingOnly_purgeAllUnlockedResources();
  205. REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
  206. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  207. }
  208. // Test if invalidating unique ids prior to instantiating operates as expected
  209. static void invalidation_and_instantiation_test(GrContext* context, skiatest::Reporter* reporter) {
  210. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  211. GrResourceProvider* resourceProvider = context->priv().resourceProvider();
  212. GrResourceCache* cache = context->priv().getResourceCache();
  213. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  214. static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
  215. GrUniqueKey key;
  216. GrUniqueKey::Builder builder(&key, d, 1, nullptr);
  217. builder[0] = 0;
  218. builder.finish();
  219. // Create proxy, assign unique key
  220. sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, context, proxyProvider,
  221. SkBackingFit::kExact);
  222. SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get()));
  223. // Send an invalidation message, which will be sitting in the cache's inbox
  224. SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(
  225. GrUniqueKeyInvalidatedMessage(key, context->priv().contextID()));
  226. REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
  227. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  228. // Instantiate the proxy. This will trigger the message to be processed, so the resulting
  229. // texture should *not* have the unique key on it!
  230. SkAssertResult(proxy->instantiate(resourceProvider));
  231. REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
  232. REPORTER_ASSERT(reporter, !proxy->peekTexture()->getUniqueKey().isValid());
  233. REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
  234. REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
  235. proxy = nullptr;
  236. context->priv().testingOnly_purgeAllUnlockedResources();
  237. REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
  238. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  239. }
  240. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureProxyTest, reporter, ctxInfo) {
  241. GrContext* context = ctxInfo.grContext();
  242. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  243. GrResourceCache* cache = context->priv().getResourceCache();
  244. REPORTER_ASSERT(reporter, !proxyProvider->numUniqueKeyProxies_TestOnly());
  245. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  246. for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
  247. for (auto create : { deferred_tex, deferred_texRT, wrapped, wrapped_with_key }) {
  248. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  249. basic_test(context, reporter, create(reporter, context, proxyProvider, fit));
  250. }
  251. REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
  252. sk_sp<GrTexture> backingTex;
  253. sk_sp<GrTextureProxy> proxy = create_wrapped_backend(context, fit, &backingTex);
  254. basic_test(context, reporter, std::move(proxy));
  255. backingTex = nullptr;
  256. cache->purgeAllUnlocked();
  257. }
  258. invalidation_test(context, reporter);
  259. invalidation_and_instantiation_test(context, reporter);
  260. }