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 #include "tests/Test.h"
9
10 #include "include/gpu/GrTexture.h"
11 #include "include/gpu/mock/GrMockTypes.h"
12 #include "src/core/SkExchange.h"
13 #include "src/core/SkMakeUnique.h"
14 #include "src/core/SkRectPriv.h"
15 #include "src/gpu/GrClip.h"
16 #include "src/gpu/GrContextPriv.h"
17 #include "src/gpu/GrMemoryPool.h"
18 #include "src/gpu/GrOnFlushResourceProvider.h"
19 #include "src/gpu/GrProxyProvider.h"
20 #include "src/gpu/GrRecordingContextPriv.h"
21 #include "src/gpu/GrRenderTargetContext.h"
22 #include "src/gpu/GrRenderTargetContextPriv.h"
23 #include "src/gpu/GrSurfaceProxy.h"
24 #include "src/gpu/GrSurfaceProxyPriv.h"
25 #include "src/gpu/GrTextureProxy.h"
26 #include "src/gpu/GrTextureProxyPriv.h"
27 #include "src/gpu/mock/GrMockGpu.h"
28
29 // This test verifies that lazy proxy callbacks get invoked during flush, after onFlush callbacks,
30 // but before Ops are executed. It also ensures that lazy proxy callbacks are invoked both for
31 // regular Ops and for clips.
32 class LazyProxyTest final : public GrOnFlushCallbackObject {
33 public:
LazyProxyTest(skiatest::Reporter * reporter)34 LazyProxyTest(skiatest::Reporter* reporter)
35 : fReporter(reporter)
36 , fHasOpTexture(false)
37 , fHasClipTexture(false) {
38 }
39
~LazyProxyTest()40 ~LazyProxyTest() override {
41 REPORTER_ASSERT(fReporter, fHasOpTexture);
42 REPORTER_ASSERT(fReporter, fHasClipTexture);
43 }
44
preFlush(GrOnFlushResourceProvider *,const uint32_t *,int,SkTArray<sk_sp<GrRenderTargetContext>> *)45 void preFlush(GrOnFlushResourceProvider*, const uint32_t*, int,
46 SkTArray<sk_sp<GrRenderTargetContext>>*) override {
47 REPORTER_ASSERT(fReporter, !fHasOpTexture);
48 REPORTER_ASSERT(fReporter, !fHasClipTexture);
49 }
50
postFlush(GrDeferredUploadToken,const uint32_t * opListIDs,int numOpListIDs)51 void postFlush(GrDeferredUploadToken, const uint32_t* opListIDs, int numOpListIDs) override {
52 REPORTER_ASSERT(fReporter, fHasOpTexture);
53 REPORTER_ASSERT(fReporter, fHasClipTexture);
54 }
55
56 class Op final : public GrDrawOp {
57 public:
58 DEFINE_OP_CLASS_ID
59
Make(GrRecordingContext * context,GrProxyProvider * proxyProvider,LazyProxyTest * test,bool nullTexture)60 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
61 GrProxyProvider* proxyProvider,
62 LazyProxyTest* test,
63 bool nullTexture) {
64 GrOpMemoryPool* pool = context->priv().opMemoryPool();
65
66 return pool->allocate<Op>(context, proxyProvider, test, nullTexture);
67 }
68
visitProxies(const VisitProxyFunc & func) const69 void visitProxies(const VisitProxyFunc& func) const override {
70 func(fProxy.get(), GrMipMapped::kNo);
71 }
72
onExecute(GrOpFlushState *,const SkRect & chainBounds)73 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override {
74 REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
75 REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
76 }
77
78 private:
79 friend class GrOpMemoryPool; // for ctor
80
Op(GrRecordingContext * ctx,GrProxyProvider * proxyProvider,LazyProxyTest * test,bool nullTexture)81 Op(GrRecordingContext* ctx, GrProxyProvider* proxyProvider,
82 LazyProxyTest* test, bool nullTexture)
83 : GrDrawOp(ClassID()), fTest(test) {
84 const GrBackendFormat format =
85 ctx->priv().caps()->getDefaultBackendFormat(GrColorType::kBGR_565,
86 GrRenderable::kNo);
87 fProxy = GrProxyProvider::MakeFullyLazyProxy(
88 [this, format, nullTexture](
89 GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
90 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture);
91 fTest->fHasOpTexture = true;
92 if (nullTexture) {
93 return {};
94 } else {
95 GrSurfaceDesc desc;
96 desc.fWidth = 1234;
97 desc.fHeight = 567;
98 desc.fConfig = kRGB_565_GrPixelConfig;
99 sk_sp<GrTexture> texture = rp->createTexture(
100 desc, format, GrRenderable::kNo, 1, SkBudgeted::kYes,
101 GrProtected::kNo, GrResourceProvider::Flags::kNoPendingIO);
102 REPORTER_ASSERT(fTest->fReporter, texture);
103 return texture;
104 }
105 },
106 format, GrRenderable::kNo, 1, GrProtected::kNo, kTopLeft_GrSurfaceOrigin,
107 kRGB_565_GrPixelConfig, *proxyProvider->caps());
108
109 this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo,
110 GrOp::IsZeroArea::kNo);
111 }
112
name() const113 const char* name() const override { return "LazyProxyTest::Op"; }
fixedFunctionFlags() const114 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
finalize(const GrCaps &,const GrAppliedClip * clip,bool hasMixedSampledCoverage,GrClampType)115 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip* clip,
116 bool hasMixedSampledCoverage, GrClampType) override {
117 return GrProcessorSet::EmptySetAnalysis();
118 }
onPrepare(GrOpFlushState *)119 void onPrepare(GrOpFlushState*) override {}
120
121 LazyProxyTest* const fTest;
122 sk_sp<GrTextureProxy> fProxy;
123 };
124
125 class ClipFP : public GrFragmentProcessor {
126 public:
ClipFP(GrRecordingContext * ctx,GrProxyProvider * proxyProvider,LazyProxyTest * test,GrTextureProxy * atlas)127 ClipFP(GrRecordingContext* ctx, GrProxyProvider* proxyProvider, LazyProxyTest* test,
128 GrTextureProxy* atlas)
129 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
130 , fContext(ctx)
131 , fProxyProvider(proxyProvider)
132 , fTest(test)
133 , fAtlas(atlas) {
134 const GrBackendFormat format =
135 ctx->priv().caps()->getDefaultBackendFormat(GrColorType::kAlpha_F16,
136 GrRenderable::kYes);
137 fLazyProxy = GrProxyProvider::MakeFullyLazyProxy(
138 [this](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
139 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
140 fTest->fHasClipTexture = true;
141 fAtlas->instantiate(rp);
142 return sk_ref_sp(fAtlas->peekTexture());
143 },
144 format, GrRenderable::kYes, 1, GrProtected::kNo, kBottomLeft_GrSurfaceOrigin,
145 kAlpha_half_GrPixelConfig, *proxyProvider->caps());
146 fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
147 GrSamplerState::WrapMode::kClamp);
148 this->setTextureSamplerCnt(1);
149 }
150
151 private:
name() const152 const char* name() const override { return "LazyProxyTest::ClipFP"; }
clone() const153 std::unique_ptr<GrFragmentProcessor> clone() const override {
154 return skstd::make_unique<ClipFP>(fContext, fProxyProvider, fTest, fAtlas);
155 }
onCreateGLSLInstance() const156 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder *) const157 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
onIsEqual(const GrFragmentProcessor &) const158 bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
onTextureSampler(int) const159 const TextureSampler& onTextureSampler(int) const override { return fAccess; }
160
161 GrRecordingContext* const fContext;
162 GrProxyProvider* const fProxyProvider;
163 LazyProxyTest* const fTest;
164 GrTextureProxy* const fAtlas;
165 sk_sp<GrTextureProxy> fLazyProxy;
166 TextureSampler fAccess;
167 };
168
169
170 class Clip : public GrClip {
171 public:
Clip(LazyProxyTest * test,GrTextureProxy * atlas)172 Clip(LazyProxyTest* test, GrTextureProxy* atlas)
173 : fTest(test)
174 , fAtlas(atlas) {}
175
176 private:
apply(GrRecordingContext * context,GrRenderTargetContext *,bool useHWAA,bool hasUserStencilSettings,GrAppliedClip * out,SkRect * bounds) const177 bool apply(GrRecordingContext* context, GrRenderTargetContext*, bool useHWAA,
178 bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override {
179 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
180 out->addCoverageFP(skstd::make_unique<ClipFP>(context, proxyProvider, fTest, fAtlas));
181 return true;
182 }
quickContains(const SkRect &) const183 bool quickContains(const SkRect&) const final { return false; }
isRRect(const SkRect & rtBounds,SkRRect * rr,GrAA *) const184 bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
getConservativeBounds(int width,int height,SkIRect * rect,bool * iior) const185 void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
186 rect->set(0, 0, width, height);
187 if (iior) {
188 *iior = false;
189 }
190 }
191
192 LazyProxyTest* const fTest;
193 GrTextureProxy* fAtlas;
194 };
195
196 private:
197 skiatest::Reporter* fReporter;
198 bool fHasOpTexture;
199 bool fHasClipTexture;
200 };
201
202 DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
203 GrMockOptions mockOptions;
204 mockOptions.fConfigOptions[(int)GrColorType::kAlpha_F16].fRenderability =
205 GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
206 mockOptions.fConfigOptions[(int)GrColorType::kAlpha_F16].fTexturable = true;
207 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
208 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
209 for (bool nullTexture : {false, true}) {
210 LazyProxyTest test(reporter);
211 ctx->priv().addOnFlushCallbackObject(&test);
212 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
213 SkBackingFit::kExact, 100, 100, GrColorType::kRGBA_8888, nullptr);
214 REPORTER_ASSERT(reporter, rtc);
215 sk_sp<GrRenderTargetContext> mockAtlas = ctx->priv().makeDeferredRenderTargetContext(
216 SkBackingFit::kExact, 10, 10, GrColorType::kAlpha_F16, nullptr);
217 REPORTER_ASSERT(reporter, mockAtlas);
218 rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
219 LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
220 ctx->priv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
221 }
222 }
223
224 static const int kSize = 16;
225
226 DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
227 GrMockOptions mockOptions;
228 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
229 auto proxyProvider = ctx->priv().proxyProvider();
230 const GrCaps* caps = ctx->priv().caps();
231
232 GrSurfaceDesc desc;
233 desc.fWidth = kSize;
234 desc.fHeight = kSize;
235 desc.fConfig = kRGBA_8888_GrPixelConfig;
236
237 GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
238 GrRenderable::kNo);
239
240 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
241 using LazyInstantiationResult = GrSurfaceProxy::LazyInstantiationResult;
242 for (bool doInstantiate : {true, false}) {
243 for (auto lazyType : {LazyInstantiationType::kSingleUse,
244 LazyInstantiationType::kMultipleUse,
245 LazyInstantiationType::kDeinstantiate}) {
246 int testCount = 0;
247 // Sets an integer to 1 when the callback is called and -1 when it is deleted.
248 class TestCallback {
249 public:
TestCallback(int * value)250 TestCallback(int* value) : fValue(value) {}
TestCallback(const TestCallback & that)251 TestCallback(const TestCallback& that) { SkASSERT(0); }
TestCallback(TestCallback && that)252 TestCallback(TestCallback&& that) : fValue(that.fValue) { that.fValue = nullptr; }
253
~TestCallback()254 ~TestCallback() { fValue ? (void)(*fValue = -1) : void(); }
255
operator =(TestCallback && that)256 TestCallback& operator=(TestCallback&& that) {
257 fValue = skstd::exchange(that.fValue, nullptr);
258 return *this;
259 }
260 TestCallback& operator=(const TestCallback& that) = delete;
261
operator ()(GrResourceProvider * resourceProvider) const262 LazyInstantiationResult operator()(GrResourceProvider* resourceProvider) const {
263 *fValue = 1;
264 return {};
265 }
266
267 private:
268 int* fValue = nullptr;
269 };
270 sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
271 TestCallback(&testCount), format, desc, GrRenderable::kNo, 1,
272 kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated,
273 GrInternalSurfaceFlags::kNone, SkBackingFit::kExact, SkBudgeted::kNo,
274 GrProtected::kNo, lazyType);
275
276 REPORTER_ASSERT(reporter, proxy.get());
277 REPORTER_ASSERT(reporter, 0 == testCount);
278
279 if (doInstantiate) {
280 proxy->priv().doLazyInstantiation(ctx->priv().resourceProvider());
281 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
282 // In SingleUse we will call the cleanup and delete the callback in the
283 // doLazyInstantiationCall.
284 REPORTER_ASSERT(reporter, -1 == testCount);
285 } else {
286 REPORTER_ASSERT(reporter, 1 == testCount);
287 }
288 proxy.reset();
289 REPORTER_ASSERT(reporter, -1 == testCount);
290 } else {
291 proxy.reset();
292 REPORTER_ASSERT(reporter, -1 == testCount);
293 }
294 }
295 }
296 }
297
298 class LazyFailedInstantiationTestOp : public GrDrawOp {
299 public:
300 DEFINE_OP_CLASS_ID
301
Make(GrContext * context,GrProxyProvider * proxyProvider,int * testExecuteValue,bool shouldFailInstantiation)302 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
303 GrProxyProvider* proxyProvider,
304 int* testExecuteValue,
305 bool shouldFailInstantiation) {
306 GrOpMemoryPool* pool = context->priv().opMemoryPool();
307
308 return pool->allocate<LazyFailedInstantiationTestOp>(context, proxyProvider,
309 testExecuteValue,
310 shouldFailInstantiation);
311 }
312
visitProxies(const VisitProxyFunc & func) const313 void visitProxies(const VisitProxyFunc& func) const override {
314 func(fLazyProxy.get(), GrMipMapped::kNo);
315 }
316
317 private:
318 friend class GrOpMemoryPool; // for ctor
319
LazyFailedInstantiationTestOp(GrContext * ctx,GrProxyProvider * proxyProvider,int * testExecuteValue,bool shouldFailInstantiation)320 LazyFailedInstantiationTestOp(GrContext* ctx, GrProxyProvider* proxyProvider,
321 int* testExecuteValue, bool shouldFailInstantiation)
322 : INHERITED(ClassID())
323 , fTestExecuteValue(testExecuteValue) {
324 GrSurfaceDesc desc;
325 desc.fWidth = kSize;
326 desc.fHeight = kSize;
327 desc.fConfig = kRGBA_8888_GrPixelConfig;
328 GrBackendFormat format =
329 ctx->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
330 GrRenderable::kNo);
331
332 fLazyProxy = proxyProvider->createLazyProxy(
333 [testExecuteValue, shouldFailInstantiation, desc,
334 format](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
335 if (shouldFailInstantiation) {
336 *testExecuteValue = 1;
337 return {};
338 }
339 return {rp->createTexture(desc, format, GrRenderable::kNo, 1, SkBudgeted::kNo,
340 GrProtected::kNo,
341 GrResourceProvider::Flags::kNoPendingIO),
342 GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced};
343 },
344 format, desc, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
345 GrMipMapsStatus::kNotAllocated, SkBackingFit::kExact, SkBudgeted::kNo,
346 GrProtected::kNo);
347
348 SkASSERT(fLazyProxy.get());
349
350 this->setBounds(SkRect::MakeIWH(kSize, kSize),
351 HasAABloat::kNo, IsZeroArea::kNo);
352 }
353
name() const354 const char* name() const override { return "LazyFailedInstantiationTestOp"; }
fixedFunctionFlags() const355 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
finalize(const GrCaps &,const GrAppliedClip *,bool hasMixedSampledCoverage,GrClampType)356 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
357 bool hasMixedSampledCoverage, GrClampType) override {
358 return GrProcessorSet::EmptySetAnalysis();
359 }
onPrepare(GrOpFlushState *)360 void onPrepare(GrOpFlushState*) override {}
onExecute(GrOpFlushState * state,const SkRect & chainBounds)361 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
362 *fTestExecuteValue = 2;
363 }
364
365 int* fTestExecuteValue;
366 sk_sp<GrSurfaceProxy> fLazyProxy;
367
368 typedef GrDrawOp INHERITED;
369 };
370
371 // Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was
372 // associated with.
373 DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) {
374 GrMockOptions mockOptions;
375 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
376 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
377 for (bool failInstantiation : {false, true}) {
378 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
379 SkBackingFit::kExact, 100, 100, GrColorType::kRGBA_8888, nullptr);
380 REPORTER_ASSERT(reporter, rtc);
381
382 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
383 GrRenderTargetContext::CanClearFullscreen::kYes);
384
385 int executeTestValue = 0;
386 rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make(
387 ctx.get(), proxyProvider, &executeTestValue, failInstantiation));
388 ctx->flush();
389
390 if (failInstantiation) {
391 REPORTER_ASSERT(reporter, 1 == executeTestValue);
392 } else {
393 REPORTER_ASSERT(reporter, 2 == executeTestValue);
394 }
395 }
396 }
397
398 class LazyDeinstantiateTestOp : public GrDrawOp {
399 public:
400 DEFINE_OP_CLASS_ID
401
Make(GrContext * context,sk_sp<GrTextureProxy> proxy)402 static std::unique_ptr<GrDrawOp> Make(GrContext* context, sk_sp<GrTextureProxy> proxy) {
403 GrOpMemoryPool* pool = context->priv().opMemoryPool();
404
405 return pool->allocate<LazyDeinstantiateTestOp>(std::move(proxy));
406 }
407
visitProxies(const VisitProxyFunc & func) const408 void visitProxies(const VisitProxyFunc& func) const override {
409 func(fLazyProxy.get(), GrMipMapped::kNo);
410 }
411
412 private:
413 friend class GrOpMemoryPool; // for ctor
414
LazyDeinstantiateTestOp(sk_sp<GrTextureProxy> proxy)415 LazyDeinstantiateTestOp(sk_sp<GrTextureProxy> proxy)
416 : INHERITED(ClassID()), fLazyProxy(std::move(proxy)) {
417 this->setBounds(SkRect::MakeIWH(kSize, kSize), HasAABloat::kNo, IsZeroArea::kNo);
418 }
419
name() const420 const char* name() const override { return "LazyDeinstantiateTestOp"; }
fixedFunctionFlags() const421 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
finalize(const GrCaps &,const GrAppliedClip *,bool hasMixedSampledCoverage,GrClampType)422 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
423 bool hasMixedSampledCoverage, GrClampType) override {
424 return GrProcessorSet::EmptySetAnalysis();
425 }
onPrepare(GrOpFlushState *)426 void onPrepare(GrOpFlushState*) override {}
onExecute(GrOpFlushState * state,const SkRect & chainBounds)427 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {}
428
429 sk_sp<GrSurfaceProxy> fLazyProxy;
430
431 typedef GrDrawOp INHERITED;
432 };
433
DeinstantiateReleaseProc(void * releaseValue)434 static void DeinstantiateReleaseProc(void* releaseValue) { (*static_cast<int*>(releaseValue))++; }
435
436 // Test that lazy proxies with the Deinstantiate LazyCallbackType are deinstantiated and released as
437 // expected.
438 DEF_GPUTEST(LazyProxyDeinstantiateTest, reporter, /* options */) {
439 GrMockOptions mockOptions;
440 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
441 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
442
443 GrBackendFormat format =
444 ctx->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
445 GrRenderable::kNo);
446
447 using LazyType = GrSurfaceProxy::LazyInstantiationType;
448 for (auto lazyType : {LazyType::kSingleUse, LazyType::kMultipleUse, LazyType::kDeinstantiate}) {
449 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
450 SkBackingFit::kExact, 100, 100, GrColorType::kRGBA_8888, nullptr);
451 REPORTER_ASSERT(reporter, rtc);
452
453 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
454 GrRenderTargetContext::CanClearFullscreen::kYes);
455
456 int instantiateTestValue = 0;
457 int releaseTestValue = 0;
458 int* instantiatePtr = &instantiateTestValue;
459 int* releasePtr = &releaseTestValue;
460 GrSurfaceDesc desc;
461 desc.fWidth = kSize;
462 desc.fHeight = kSize;
463 desc.fConfig = kRGBA_8888_GrPixelConfig;
464
465 GrBackendTexture backendTex = ctx->createBackendTexture(
466 kSize, kSize, kRGBA_8888_SkColorType, SkColors::kTransparent,
467 GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
468
469 sk_sp<GrTextureProxy> lazyProxy = proxyProvider->createLazyProxy(
470 [instantiatePtr, releasePtr,
__anonfa3c11a50402(GrResourceProvider* rp) 471 backendTex](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
472 sk_sp<GrTexture> texture =
473 rp->wrapBackendTexture(backendTex, GrColorType::kRGBA_8888,
474 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
475 kRead_GrIOType);
476 if (!texture) {
477 return {};
478 }
479 (*instantiatePtr)++;
480 texture->setRelease(DeinstantiateReleaseProc, releasePtr);
481 return texture;
482 },
483 format, desc, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
484 GrMipMapsStatus::kNotAllocated, GrInternalSurfaceFlags::kReadOnly,
485 SkBackingFit::kExact, SkBudgeted::kNo, GrProtected::kNo, lazyType);
486
487 REPORTER_ASSERT(reporter, lazyProxy.get());
488
489 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
490
491 ctx->flush();
492
493 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
494 if (LazyType::kDeinstantiate == lazyType) {
495 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
496 } else {
497 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
498 }
499
500 // This should cause the uninstantiate proxies to be instantiated again but have no effect
501 // on the others
502 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
503 // Add a second op to make sure we only instantiate once.
504 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
505 ctx->flush();
506
507 if (LazyType::kDeinstantiate == lazyType) {
508 REPORTER_ASSERT(reporter, 2 == instantiateTestValue);
509 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
510 } else {
511 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
512 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
513 }
514
515 lazyProxy.reset();
516 if (LazyType::kDeinstantiate == lazyType) {
517 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
518 } else {
519 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
520 }
521
522 ctx->deleteBackendTexture(backendTex);
523 }
524 }
525