| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 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 |  | 
 | 8 | // This is a GPU-backend specific test. | 
 | 9 |  | 
 | 10 | #include "Test.h" | 
 | 11 |  | 
 | 12 | #if SK_SUPPORT_GPU | 
 | 13 |  | 
 | 14 | #include "GrBackendSurface.h" | 
 | 15 | #include "GrContextPriv.h" | 
 | 16 | #include "GrResourceCache.h" | 
 | 17 | #include "GrResourceProvider.h" | 
 | 18 | #include "GrTest.h" | 
 | 19 | #include "GrTexture.h" | 
 | 20 | #include "GrTextureProxy.h" | 
 | 21 |  | 
 | 22 | #include "SkGr.h" | 
 | 23 | #include "SkImage.h" | 
 | 24 |  | 
 | 25 | int GrResourceCache::numUniqueKeyProxies_TestOnly() const { | 
 | 26 |     return fUniquelyKeyedProxies.count(); | 
 | 27 | } | 
 | 28 |  | 
 | 29 | static GrSurfaceDesc make_desc(GrSurfaceFlags flags) { | 
 | 30 |     GrSurfaceDesc desc; | 
 | 31 |     desc.fFlags = flags; | 
 | 32 |     desc.fOrigin = kBottomLeft_GrSurfaceOrigin; | 
 | 33 |     desc.fWidth = 64; | 
 | 34 |     desc.fHeight = 64; | 
 | 35 |     desc.fConfig = kRGBA_8888_GrPixelConfig; | 
 | 36 |     desc.fSampleCnt = 0; | 
 | 37 |  | 
 | 38 |     return desc; | 
 | 39 | } | 
 | 40 |  | 
 | 41 | /////////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 42 | // Basic test | 
 | 43 |  | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 44 | static sk_sp<GrTextureProxy> deferred_tex(skiatest::Reporter* reporter, | 
 | 45 |                                           GrResourceProvider* provider, SkBackingFit fit) { | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 46 |     GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags); | 
 | 47 |  | 
 | 48 |     // Only budgeted & wrapped external proxies get to carry uniqueKeys | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 49 |     sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit, | 
 | 50 |                                                                SkBudgeted::kYes); | 
 | 51 |     REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid()); | 
 | 52 |     return proxy; | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 53 | } | 
 | 54 |  | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 55 | static sk_sp<GrTextureProxy> deferred_texRT(skiatest::Reporter* reporter, | 
 | 56 |                                             GrResourceProvider* provider, SkBackingFit fit) { | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 57 |     GrSurfaceDesc desc = make_desc(kRenderTarget_GrSurfaceFlag); | 
 | 58 |  | 
 | 59 |     // Only budgeted & wrapped external proxies get to carry uniqueKeys | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 60 |     sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit, | 
 | 61 |                                                                SkBudgeted::kYes); | 
 | 62 |     REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid()); | 
 | 63 |     return proxy; | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 64 | } | 
 | 65 |  | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 66 | static sk_sp<GrTextureProxy> wrapped(skiatest::Reporter* reporter, | 
 | 67 |                                      GrResourceProvider* provider, SkBackingFit fit) { | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 68 |     GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags); | 
 | 69 |  | 
 | 70 |     sk_sp<GrTexture> tex; | 
 | 71 |     if (SkBackingFit::kApprox == fit) { | 
 | 72 |         tex = sk_sp<GrTexture>(provider->createApproxTexture(desc, 0)); | 
 | 73 |     } else { | 
 | 74 |         // Only budgeted & wrapped external proxies get to carry uniqueKeys | 
 | 75 |         tex = provider->createTexture(desc, SkBudgeted::kYes); | 
 | 76 |     } | 
 | 77 |  | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 78 |     sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex), | 
 | 79 |                                                               kBottomLeft_GrSurfaceOrigin); | 
 | 80 |     REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid()); | 
 | 81 |     return proxy; | 
 | 82 | } | 
 | 83 |  | 
 | 84 | static sk_sp<GrTextureProxy> wrapped_with_key(skiatest::Reporter* reporter, | 
 | 85 |                                               GrResourceProvider* provider, SkBackingFit fit) { | 
 | 86 |     static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain(); | 
 | 87 |     static int kUniqueKeyData = 0; | 
 | 88 |  | 
 | 89 |     GrUniqueKey key; | 
 | 90 |  | 
 | 91 |     GrUniqueKey::Builder builder(&key, d, 1, nullptr); | 
 | 92 |     builder[0] = kUniqueKeyData++; | 
 | 93 |     builder.finish(); | 
 | 94 |  | 
 | 95 |     GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags); | 
 | 96 |  | 
 | 97 |     sk_sp<GrTexture> tex; | 
 | 98 |     if (SkBackingFit::kApprox == fit) { | 
 | 99 |         tex = sk_sp<GrTexture>(provider->createApproxTexture(desc, 0)); | 
 | 100 |     } else { | 
 | 101 |         // Only budgeted & wrapped external proxies get to carry uniqueKeys | 
 | 102 |         tex = provider->createTexture(desc, SkBudgeted::kYes); | 
 | 103 |     } | 
 | 104 |  | 
 | 105 |     tex->resourcePriv().setUniqueKey(key); | 
 | 106 |  | 
 | 107 |     sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex), | 
 | 108 |                                                               kBottomLeft_GrSurfaceOrigin); | 
 | 109 |     REPORTER_ASSERT(reporter, proxy->getUniqueKey().isValid()); | 
 | 110 |     return proxy; | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 111 | } | 
 | 112 |  | 
 | 113 | static sk_sp<GrTextureProxy> create_wrapped_backend(GrContext* context, SkBackingFit fit, | 
 | 114 |                                                     sk_sp<GrTexture>* backingSurface) { | 
 | 115 |     GrResourceProvider* provider = context->resourceProvider(); | 
 | 116 |  | 
| Robert Phillips | b67821d | 2017-12-13 15:00:45 -0500 | [diff] [blame] | 117 |     const GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags); | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 118 |  | 
 | 119 |     *backingSurface = provider->createTexture(desc, SkBudgeted::kNo); | 
 | 120 |     if (!(*backingSurface)) { | 
 | 121 |         return nullptr; | 
 | 122 |     } | 
 | 123 |  | 
| Robert Phillips | b67821d | 2017-12-13 15:00:45 -0500 | [diff] [blame] | 124 |     GrBackendTexture backendTex = (*backingSurface)->getBackendTexture(); | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 125 |  | 
 | 126 |     return GrSurfaceProxy::MakeWrappedBackend(context, backendTex, kBottomLeft_GrSurfaceOrigin); | 
 | 127 | } | 
 | 128 |  | 
 | 129 |  | 
 | 130 | // This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning | 
 | 131 | // and looking them up work, etc. | 
 | 132 | static void basic_test(GrContext* context, | 
 | 133 |                        skiatest::Reporter* reporter, | 
 | 134 |                        sk_sp<GrTextureProxy> proxy, bool proxyIsCached) { | 
 | 135 |     static int id = 1; | 
 | 136 |  | 
 | 137 |     GrResourceProvider* provider = context->resourceProvider(); | 
 | 138 |     GrResourceCache* cache = context->getResourceCache(); | 
 | 139 |  | 
 | 140 |     int startCacheCount = cache->getResourceCount(); | 
 | 141 |  | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 142 |     GrUniqueKey key; | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 143 |     if (proxy->getUniqueKey().isValid()) { | 
 | 144 |         key = proxy->getUniqueKey(); | 
 | 145 |     } else { | 
 | 146 |         GrMakeKeyFromImageID(&key, id, SkIRect::MakeWH(64, 64)); | 
 | 147 |         ++id; | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 148 |  | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 149 |         // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation | 
 | 150 |         REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly()); | 
 | 151 |         provider->assignUniqueKeyToProxy(key, proxy.get()); | 
 | 152 |     } | 
 | 153 |  | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 154 |     REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 155 |     REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount()); | 
 | 156 |  | 
 | 157 |     // setUniqueKey had better stick | 
 | 158 |     REPORTER_ASSERT(reporter, key == proxy->getUniqueKey()); | 
 | 159 |  | 
 | 160 |     // We just added it, surely we can find it | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 161 |     REPORTER_ASSERT(reporter, provider->findOrCreateProxyByUniqueKey(key, | 
 | 162 |                                                                      kBottomLeft_GrSurfaceOrigin)); | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 163 |     REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 164 |  | 
 | 165 |     // Once instantiated, the backing resource should have the same key | 
 | 166 |     SkAssertResult(proxy->instantiate(provider)); | 
 | 167 |     const GrUniqueKey& texKey = proxy->priv().peekSurface()->getUniqueKey(); | 
 | 168 |     REPORTER_ASSERT(reporter, texKey.isValid()); | 
 | 169 |     REPORTER_ASSERT(reporter, key == texKey); | 
 | 170 |     if (proxyIsCached) { | 
 | 171 |         REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 172 |     } | 
 | 173 |  | 
 | 174 |     // deleting the proxy should delete it from the hash but not the cache | 
 | 175 |     proxy = nullptr; | 
 | 176 |     REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 177 |     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 178 |  | 
 | 179 |     // If the proxy was cached refinding it should bring it back to life | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 180 |     proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin); | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 181 |     if (proxyIsCached) { | 
 | 182 |         REPORTER_ASSERT(reporter, proxy); | 
 | 183 |         REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 184 |     } else { | 
 | 185 |         REPORTER_ASSERT(reporter, !proxy); | 
 | 186 |         REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 187 |     } | 
 | 188 |     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 189 |  | 
 | 190 |     // Mega-purging it should remove it from both the hash and the cache | 
 | 191 |     proxy = nullptr; | 
 | 192 |     cache->purgeAllUnlocked(); | 
 | 193 |     if (proxyIsCached) { | 
 | 194 |         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 195 |     } else { | 
 | 196 |         REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 197 |     } | 
 | 198 |  | 
 | 199 |     // We can bring neither the texture nor proxy back from perma-death | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 200 |     proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin); | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 201 |     REPORTER_ASSERT(reporter, !proxy); | 
 | 202 |     if (proxyIsCached) { | 
 | 203 |         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 204 |     } else { | 
 | 205 |         REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 206 |     } | 
 | 207 | } | 
 | 208 |  | 
 | 209 | /////////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 210 | // Invalidation test | 
 | 211 |  | 
 | 212 | // Test if invalidating unique ids operates as expected for texture proxies. | 
 | 213 | static void invalidation_test(GrContext* context, skiatest::Reporter* reporter) { | 
 | 214 |  | 
 | 215 |     GrResourceCache* cache = context->getResourceCache(); | 
 | 216 |     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 217 |  | 
 | 218 |     sk_sp<SkImage> rasterImg; | 
 | 219 |  | 
 | 220 |     { | 
 | 221 |         SkImageInfo ii = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kOpaque_SkAlphaType); | 
 | 222 |  | 
 | 223 |         SkBitmap bm; | 
 | 224 |         bm.allocPixels(ii); | 
 | 225 |  | 
 | 226 |         rasterImg = SkImage::MakeFromBitmap(bm); | 
 | 227 |         REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 228 |         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 229 |     } | 
 | 230 |  | 
 | 231 |     sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(context, nullptr); | 
 | 232 |     REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 233 |     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 234 |  | 
 | 235 |     rasterImg = nullptr;        // this invalidates the uniqueKey | 
 | 236 |  | 
 | 237 |     // this forces the cache to respond to the inval msg | 
 | 238 |     int maxNum; | 
 | 239 |     size_t maxBytes; | 
 | 240 |     context->getResourceCacheLimits(&maxNum, &maxBytes); | 
 | 241 |     context->setResourceCacheLimits(maxNum-1, maxBytes); | 
 | 242 |  | 
 | 243 |     REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 244 |     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 245 |  | 
 | 246 |     textureImg = nullptr; | 
 | 247 |     context->purgeAllUnlockedResources(); | 
 | 248 |  | 
 | 249 |     REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 250 |     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 251 | } | 
 | 252 |  | 
| Robert Phillips | fa8c080 | 2017-10-04 08:42:28 -0400 | [diff] [blame] | 253 | #ifndef SK_DISABLE_DEFERRED_PROXIES | 
| Brian Osman | 28c434b | 2017-09-27 13:11:16 -0400 | [diff] [blame] | 254 | // Test if invalidating unique ids prior to instantiating operates as expected | 
 | 255 | static void invalidation_and_instantiation_test(GrContext* context, skiatest::Reporter* reporter) { | 
 | 256 |     GrResourceProvider* provider = context->resourceProvider(); | 
 | 257 |     GrResourceCache* cache = context->getResourceCache(); | 
 | 258 |     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 259 |  | 
 | 260 |     static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain(); | 
 | 261 |     GrUniqueKey key; | 
 | 262 |     GrUniqueKey::Builder builder(&key, d, 1, nullptr); | 
 | 263 |     builder[0] = 0; | 
 | 264 |     builder.finish(); | 
 | 265 |  | 
 | 266 |     // Create proxy, assign unique key | 
 | 267 |     sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, provider, SkBackingFit::kExact); | 
 | 268 |     provider->assignUniqueKeyToProxy(key, proxy.get()); | 
 | 269 |  | 
 | 270 |     // Send an invalidation message, which will be sitting in the cache's inbox | 
 | 271 |     SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(GrUniqueKeyInvalidatedMessage(key)); | 
 | 272 |  | 
 | 273 |     REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 274 |     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 275 |  | 
 | 276 |     // Instantiate the proxy. This will trigger the message to be processed, so the resulting | 
 | 277 |     // texture should *not* have the unique key on it! | 
 | 278 |     SkAssertResult(proxy->instantiate(provider)); | 
 | 279 |  | 
 | 280 |     REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid()); | 
 | 281 |     REPORTER_ASSERT(reporter, !proxy->priv().peekTexture()->getUniqueKey().isValid()); | 
 | 282 |     REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 283 |     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); | 
 | 284 |  | 
 | 285 |     proxy = nullptr; | 
 | 286 |     context->purgeAllUnlockedResources(); | 
 | 287 |  | 
 | 288 |     REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly()); | 
 | 289 |     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 290 | } | 
| Robert Phillips | 73f7e1d | 2017-10-02 14:05:46 -0400 | [diff] [blame] | 291 | #endif | 
| Brian Osman | 28c434b | 2017-09-27 13:11:16 -0400 | [diff] [blame] | 292 |  | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 293 | DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureProxyTest, reporter, ctxInfo) { | 
 | 294 |     GrContext* context = ctxInfo.grContext(); | 
 | 295 |     GrResourceProvider* provider = context->resourceProvider(); | 
 | 296 |     GrResourceCache* cache = context->getResourceCache(); | 
 | 297 |  | 
 | 298 |     REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly()); | 
 | 299 |     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 300 |  | 
 | 301 |     for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) { | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 302 |         for (auto create : { deferred_tex, deferred_texRT, wrapped, wrapped_with_key }) { | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 303 |             REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
| Greg Daniel | cd87140 | 2017-09-26 12:49:26 -0400 | [diff] [blame] | 304 |             basic_test(context, reporter, create(reporter, provider, fit), true); | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 305 |         } | 
 | 306 |  | 
 | 307 |         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); | 
 | 308 |         sk_sp<GrTexture> backingTex; | 
 | 309 |         sk_sp<GrTextureProxy> proxy = create_wrapped_backend(context, fit, &backingTex); | 
 | 310 |         basic_test(context, reporter, std::move(proxy), false); | 
 | 311 |  | 
 | 312 |         backingTex = nullptr; | 
 | 313 |         cache->purgeAllUnlocked(); | 
 | 314 |     } | 
 | 315 |  | 
 | 316 |     invalidation_test(context, reporter); | 
| Robert Phillips | fa8c080 | 2017-10-04 08:42:28 -0400 | [diff] [blame] | 317 | #ifndef SK_DISABLE_DEFERRED_PROXIES | 
 | 318 |     invalidation_and_instantiation_test(context, reporter); | 
 | 319 | #endif | 
| Robert Phillips | ae7d3f3 | 2017-09-21 08:26:08 -0400 | [diff] [blame] | 320 | } | 
 | 321 |  | 
 | 322 | #endif |