blob: a4b93c8d7a5767cab5f457cde0fc70ee40418d8a [file] [log] [blame]
Robert Phillipsae7d3f32017-09-21 08:26:08 -04001/*
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
25int GrResourceCache::numUniqueKeyProxies_TestOnly() const {
26 return fUniquelyKeyedProxies.count();
27}
28
29static 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 Danielcd871402017-09-26 12:49:26 -040044static sk_sp<GrTextureProxy> deferred_tex(skiatest::Reporter* reporter,
45 GrResourceProvider* provider, SkBackingFit fit) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -040046 GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
47
48 // Only budgeted & wrapped external proxies get to carry uniqueKeys
Greg Danielcd871402017-09-26 12:49:26 -040049 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit,
50 SkBudgeted::kYes);
51 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
52 return proxy;
Robert Phillipsae7d3f32017-09-21 08:26:08 -040053}
54
Greg Danielcd871402017-09-26 12:49:26 -040055static sk_sp<GrTextureProxy> deferred_texRT(skiatest::Reporter* reporter,
56 GrResourceProvider* provider, SkBackingFit fit) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -040057 GrSurfaceDesc desc = make_desc(kRenderTarget_GrSurfaceFlag);
58
59 // Only budgeted & wrapped external proxies get to carry uniqueKeys
Greg Danielcd871402017-09-26 12:49:26 -040060 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit,
61 SkBudgeted::kYes);
62 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
63 return proxy;
Robert Phillipsae7d3f32017-09-21 08:26:08 -040064}
65
Greg Danielcd871402017-09-26 12:49:26 -040066static sk_sp<GrTextureProxy> wrapped(skiatest::Reporter* reporter,
67 GrResourceProvider* provider, SkBackingFit fit) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -040068 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 Danielcd871402017-09-26 12:49:26 -040078 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex),
79 kBottomLeft_GrSurfaceOrigin);
80 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
81 return proxy;
82}
83
84static 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 Phillipsae7d3f32017-09-21 08:26:08 -0400111}
112
113static sk_sp<GrTextureProxy> create_wrapped_backend(GrContext* context, SkBackingFit fit,
114 sk_sp<GrTexture>* backingSurface) {
115 GrResourceProvider* provider = context->resourceProvider();
116
117 GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
118
119 *backingSurface = provider->createTexture(desc, SkBudgeted::kNo);
120 if (!(*backingSurface)) {
121 return nullptr;
122 }
123
124 GrBackendTexture backendTex =
125 GrTest::CreateBackendTexture(context->contextPriv().getBackend(),
126 64, 64,
127 kRGBA_8888_GrPixelConfig,
Greg Daniel177e6952017-10-12 12:27:11 -0400128 GrMipMapped::kNo,
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400129 (*backingSurface)->getTextureHandle());
130
131 return GrSurfaceProxy::MakeWrappedBackend(context, backendTex, kBottomLeft_GrSurfaceOrigin);
132}
133
134
135// This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning
136// and looking them up work, etc.
137static void basic_test(GrContext* context,
138 skiatest::Reporter* reporter,
139 sk_sp<GrTextureProxy> proxy, bool proxyIsCached) {
140 static int id = 1;
141
142 GrResourceProvider* provider = context->resourceProvider();
143 GrResourceCache* cache = context->getResourceCache();
144
145 int startCacheCount = cache->getResourceCount();
146
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400147 GrUniqueKey key;
Greg Danielcd871402017-09-26 12:49:26 -0400148 if (proxy->getUniqueKey().isValid()) {
149 key = proxy->getUniqueKey();
150 } else {
151 GrMakeKeyFromImageID(&key, id, SkIRect::MakeWH(64, 64));
152 ++id;
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400153
Greg Danielcd871402017-09-26 12:49:26 -0400154 // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation
155 REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
156 provider->assignUniqueKeyToProxy(key, proxy.get());
157 }
158
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400159 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
160 REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount());
161
162 // setUniqueKey had better stick
163 REPORTER_ASSERT(reporter, key == proxy->getUniqueKey());
164
165 // We just added it, surely we can find it
Greg Danielcd871402017-09-26 12:49:26 -0400166 REPORTER_ASSERT(reporter, provider->findOrCreateProxyByUniqueKey(key,
167 kBottomLeft_GrSurfaceOrigin));
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400168 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
169
170 // Once instantiated, the backing resource should have the same key
171 SkAssertResult(proxy->instantiate(provider));
172 const GrUniqueKey& texKey = proxy->priv().peekSurface()->getUniqueKey();
173 REPORTER_ASSERT(reporter, texKey.isValid());
174 REPORTER_ASSERT(reporter, key == texKey);
175 if (proxyIsCached) {
176 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
177 }
178
179 // deleting the proxy should delete it from the hash but not the cache
180 proxy = nullptr;
181 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
182 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
183
184 // If the proxy was cached refinding it should bring it back to life
Greg Danielcd871402017-09-26 12:49:26 -0400185 proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400186 if (proxyIsCached) {
187 REPORTER_ASSERT(reporter, proxy);
188 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
189 } else {
190 REPORTER_ASSERT(reporter, !proxy);
191 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
192 }
193 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
194
195 // Mega-purging it should remove it from both the hash and the cache
196 proxy = nullptr;
197 cache->purgeAllUnlocked();
198 if (proxyIsCached) {
199 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
200 } else {
201 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
202 }
203
204 // We can bring neither the texture nor proxy back from perma-death
Greg Danielcd871402017-09-26 12:49:26 -0400205 proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400206 REPORTER_ASSERT(reporter, !proxy);
207 if (proxyIsCached) {
208 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
209 } else {
210 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
211 }
212}
213
214///////////////////////////////////////////////////////////////////////////////////////////////////
215// Invalidation test
216
217// Test if invalidating unique ids operates as expected for texture proxies.
218static void invalidation_test(GrContext* context, skiatest::Reporter* reporter) {
219
220 GrResourceCache* cache = context->getResourceCache();
221 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
222
223 sk_sp<SkImage> rasterImg;
224
225 {
226 SkImageInfo ii = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
227
228 SkBitmap bm;
229 bm.allocPixels(ii);
230
231 rasterImg = SkImage::MakeFromBitmap(bm);
232 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
233 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
234 }
235
236 sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(context, nullptr);
237 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
238 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
239
240 rasterImg = nullptr; // this invalidates the uniqueKey
241
242 // this forces the cache to respond to the inval msg
243 int maxNum;
244 size_t maxBytes;
245 context->getResourceCacheLimits(&maxNum, &maxBytes);
246 context->setResourceCacheLimits(maxNum-1, maxBytes);
247
248 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
249 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
250
251 textureImg = nullptr;
252 context->purgeAllUnlockedResources();
253
254 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
255 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
256}
257
Robert Phillipsfa8c0802017-10-04 08:42:28 -0400258#ifndef SK_DISABLE_DEFERRED_PROXIES
Brian Osman28c434b2017-09-27 13:11:16 -0400259// Test if invalidating unique ids prior to instantiating operates as expected
260static void invalidation_and_instantiation_test(GrContext* context, skiatest::Reporter* reporter) {
261 GrResourceProvider* provider = context->resourceProvider();
262 GrResourceCache* cache = context->getResourceCache();
263 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
264
265 static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
266 GrUniqueKey key;
267 GrUniqueKey::Builder builder(&key, d, 1, nullptr);
268 builder[0] = 0;
269 builder.finish();
270
271 // Create proxy, assign unique key
272 sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, provider, SkBackingFit::kExact);
273 provider->assignUniqueKeyToProxy(key, proxy.get());
274
275 // Send an invalidation message, which will be sitting in the cache's inbox
276 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(GrUniqueKeyInvalidatedMessage(key));
277
278 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
279 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
280
281 // Instantiate the proxy. This will trigger the message to be processed, so the resulting
282 // texture should *not* have the unique key on it!
283 SkAssertResult(proxy->instantiate(provider));
284
285 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
286 REPORTER_ASSERT(reporter, !proxy->priv().peekTexture()->getUniqueKey().isValid());
287 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
288 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
289
290 proxy = nullptr;
291 context->purgeAllUnlockedResources();
292
293 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
294 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
295}
Robert Phillips73f7e1d2017-10-02 14:05:46 -0400296#endif
Brian Osman28c434b2017-09-27 13:11:16 -0400297
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400298DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureProxyTest, reporter, ctxInfo) {
299 GrContext* context = ctxInfo.grContext();
300 GrResourceProvider* provider = context->resourceProvider();
301 GrResourceCache* cache = context->getResourceCache();
302
303 REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
304 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
305
306 for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
Greg Danielcd871402017-09-26 12:49:26 -0400307 for (auto create : { deferred_tex, deferred_texRT, wrapped, wrapped_with_key }) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400308 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
Greg Danielcd871402017-09-26 12:49:26 -0400309 basic_test(context, reporter, create(reporter, provider, fit), true);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400310 }
311
312 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
313 sk_sp<GrTexture> backingTex;
314 sk_sp<GrTextureProxy> proxy = create_wrapped_backend(context, fit, &backingTex);
315 basic_test(context, reporter, std::move(proxy), false);
316
317 backingTex = nullptr;
318 cache->purgeAllUnlocked();
319 }
320
321 invalidation_test(context, reporter);
Robert Phillipsfa8c0802017-10-04 08:42:28 -0400322#ifndef SK_DISABLE_DEFERRED_PROXIES
323 invalidation_and_instantiation_test(context, reporter);
324#endif
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400325}
326
327#endif