blob: 99f9d2a8e309a691408203bc03d8b2a79118306c [file] [log] [blame]
Chris Dalton706a6ff2017-11-29 22:01:06 -07001/*
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 "Test.h"
9
Chris Dalton706a6ff2017-11-29 22:01:06 -070010#include "GrClip.h"
11#include "GrContextPriv.h"
Robert Phillips7c525e62018-06-12 10:11:12 -040012#include "GrMemoryPool.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070013#include "GrOnFlushResourceProvider.h"
Robert Phillips7c525e62018-06-12 10:11:12 -040014#include "GrProxyProvider.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070015#include "GrRenderTargetContext.h"
16#include "GrRenderTargetContextPriv.h"
17#include "GrSurfaceProxy.h"
Greg Daniel94a6ce82018-01-16 16:14:41 -050018#include "GrSurfaceProxyPriv.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070019#include "GrTexture.h"
20#include "GrTextureProxy.h"
21#include "GrTextureProxyPriv.h"
22#include "SkMakeUnique.h"
Mike Reed274218e2018-01-08 15:05:02 -050023#include "SkRectPriv.h"
Greg Daniel4684f822018-03-08 15:27:36 -050024#include "mock/GrMockGpu.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070025#include "mock/GrMockTypes.h"
26
27// This test verifies that lazy proxy callbacks get invoked during flush, after onFlush callbacks,
28// but before Ops are executed. It also ensures that lazy proxy callbacks are invoked both for
29// regular Ops and for clips.
30class LazyProxyTest final : public GrOnFlushCallbackObject {
31public:
32 LazyProxyTest(skiatest::Reporter* reporter)
33 : fReporter(reporter)
34 , fHasOpTexture(false)
35 , fHasClipTexture(false) {
36 }
37
38 ~LazyProxyTest() override {
39 REPORTER_ASSERT(fReporter, fHasOpTexture);
40 REPORTER_ASSERT(fReporter, fHasClipTexture);
41 }
42
43 void preFlush(GrOnFlushResourceProvider*, const uint32_t*, int,
44 SkTArray<sk_sp<GrRenderTargetContext>>*) override {
45 REPORTER_ASSERT(fReporter, !fHasOpTexture);
46 REPORTER_ASSERT(fReporter, !fHasClipTexture);
47 }
48
49 void postFlush(GrDeferredUploadToken, const uint32_t* opListIDs, int numOpListIDs) override {
50 REPORTER_ASSERT(fReporter, fHasOpTexture);
51 REPORTER_ASSERT(fReporter, fHasClipTexture);
52 }
53
54 class Op final : public GrDrawOp {
55 public:
56 DEFINE_OP_CLASS_ID
57
Robert Phillips88a32ef2018-06-07 11:05:56 -040058 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
59 GrProxyProvider* proxyProvider,
60 LazyProxyTest* test,
61 bool nullTexture) {
Robert Phillipsc994a932018-06-19 13:09:54 -040062 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
63
64 return pool->allocate<Op>(proxyProvider, test, nullTexture);
Robert Phillips88a32ef2018-06-07 11:05:56 -040065 }
66
67 void visitProxies(const VisitProxyFunc& func) const override {
68 func(fProxy.get());
69 }
70
71 void onExecute(GrOpFlushState*) override {
72 REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
73 REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
74 }
75
76 private:
Robert Phillips7c525e62018-06-12 10:11:12 -040077 friend class GrOpMemoryPool; // for ctor
78
Robert Phillips777707b2018-01-17 11:40:14 -050079 Op(GrProxyProvider* proxyProvider, LazyProxyTest* test, bool nullTexture)
80 : GrDrawOp(ClassID()), fTest(test) {
Chris Dalton4c458b12018-06-16 17:22:59 -060081 fProxy = GrProxyProvider::MakeFullyLazyProxy(
82 [this, nullTexture](GrResourceProvider* rp) {
83 if (!rp) {
84 return sk_sp<GrTexture>();
85 }
86 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture);
87 fTest->fHasOpTexture = true;
88 if (nullTexture) {
89 return sk_sp<GrTexture>();
90 } else {
91 GrSurfaceDesc desc;
92 desc.fWidth = 1234;
93 desc.fHeight = 567;
94 desc.fConfig = kRGB_565_GrPixelConfig;
95 sk_sp<GrTexture> texture = rp->createTexture(desc, SkBudgeted::kYes);
96 REPORTER_ASSERT(fTest->fReporter, texture);
97 return texture;
98 }
99 },
100 GrProxyProvider::Renderable::kNo, kTopLeft_GrSurfaceOrigin,
101 kRGB_565_GrPixelConfig, *proxyProvider->caps());
102
103 this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo,
104 GrOp::IsZeroArea::kNo);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700105 }
106
Chris Dalton706a6ff2017-11-29 22:01:06 -0700107 const char* name() const override { return "LazyProxyTest::Op"; }
108 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman532b3f92018-07-11 10:02:07 -0400109 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
Chris Dalton706a6ff2017-11-29 22:01:06 -0700110 return RequiresDstTexture::kNo;
111 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700112 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; }
113 void onPrepare(GrOpFlushState*) override {}
114
115 LazyProxyTest* const fTest;
116 sk_sp<GrTextureProxy> fProxy;
117 };
118
119 class ClipFP : public GrFragmentProcessor {
120 public:
Robert Phillips777707b2018-01-17 11:40:14 -0500121 ClipFP(GrProxyProvider* proxyProvider, LazyProxyTest* test, GrTextureProxy* atlas)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700122 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
Robert Phillips777707b2018-01-17 11:40:14 -0500123 , fProxyProvider(proxyProvider)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700124 , fTest(test)
125 , fAtlas(atlas) {
Chris Dalton4c458b12018-06-16 17:22:59 -0600126 fLazyProxy = GrProxyProvider::MakeFullyLazyProxy(
Robert Phillipsce5209a2018-02-13 11:13:51 -0500127 [this](GrResourceProvider* rp) {
128 if (!rp) {
129 return sk_sp<GrTexture>();
130 }
131 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
132 fTest->fHasClipTexture = true;
133 fAtlas->instantiate(rp);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400134 return sk_ref_sp(fAtlas->peekTexture());
Robert Phillipsce5209a2018-02-13 11:13:51 -0500135 },
136 GrProxyProvider::Renderable::kYes,
137 kBottomLeft_GrSurfaceOrigin,
Chris Dalton4c458b12018-06-16 17:22:59 -0600138 kAlpha_half_GrPixelConfig, *proxyProvider->caps());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700139 fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
Brian Salomone782f842018-07-31 13:53:11 -0400140 GrSamplerState::WrapMode::kClamp);
Brian Salomonf7dcd762018-07-30 14:48:15 -0400141 this->setTextureSamplerCnt(1);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700142 }
143
144 private:
145 const char* name() const override { return "LazyProxyTest::ClipFP"; }
146 std::unique_ptr<GrFragmentProcessor> clone() const override {
Robert Phillips777707b2018-01-17 11:40:14 -0500147 return skstd::make_unique<ClipFP>(fProxyProvider, fTest, fAtlas);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700148 }
149 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
150 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
151 bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400152 const TextureSampler& onTextureSampler(int) const override { return fAccess; }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700153
Robert Phillips777707b2018-01-17 11:40:14 -0500154 GrProxyProvider* const fProxyProvider;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700155 LazyProxyTest* const fTest;
156 GrTextureProxy* const fAtlas;
157 sk_sp<GrTextureProxy> fLazyProxy;
158 TextureSampler fAccess;
159 };
160
161
162 class Clip : public GrClip {
163 public:
164 Clip(LazyProxyTest* test, GrTextureProxy* atlas)
165 : fTest(test)
166 , fAtlas(atlas) {}
167
168 private:
Robert Phillips777707b2018-01-17 11:40:14 -0500169 bool apply(GrContext* context, GrRenderTargetContext*, bool, bool, GrAppliedClip* out,
Chris Dalton706a6ff2017-11-29 22:01:06 -0700170 SkRect* bounds) const override {
Robert Phillips777707b2018-01-17 11:40:14 -0500171 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
172 out->addCoverageFP(skstd::make_unique<ClipFP>(proxyProvider, fTest, fAtlas));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700173 return true;
174 }
175 bool quickContains(const SkRect&) const final { return false; }
176 bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
177 void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
178 rect->set(0, 0, width, height);
179 if (iior) {
180 *iior = false;
181 }
182 }
183
184 LazyProxyTest* const fTest;
185 GrTextureProxy* fAtlas;
186 };
187
188private:
189 skiatest::Reporter* fReporter;
190 bool fHasOpTexture;
191 bool fHasClipTexture;
192};
193
194DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
195 GrMockOptions mockOptions;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500196 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderability =
197 GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700198 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true;
199 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips777707b2018-01-17 11:40:14 -0500200 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700201 for (bool nullTexture : {false, true}) {
202 LazyProxyTest test(reporter);
203 ctx->contextPriv().addOnFlushCallbackObject(&test);
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500204 sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext(
205 SkBackingFit::kExact, 100, 100,
206 kRGBA_8888_GrPixelConfig, nullptr);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700207 REPORTER_ASSERT(reporter, rtc);
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500208 sk_sp<GrRenderTargetContext> mockAtlas = ctx->contextPriv().makeDeferredRenderTargetContext(
209 SkBackingFit::kExact, 10, 10,
Chris Dalton706a6ff2017-11-29 22:01:06 -0700210 kAlpha_half_GrPixelConfig, nullptr);
211 REPORTER_ASSERT(reporter, mockAtlas);
212 rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
Robert Phillips88a32ef2018-06-07 11:05:56 -0400213 LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700214 ctx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
215 }
216}
217
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500218static const int kSize = 16;
219
Greg Daniel94a6ce82018-01-16 16:14:41 -0500220DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
221 GrMockOptions mockOptions;
222 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips777707b2018-01-17 11:40:14 -0500223 auto proxyProvider = ctx->contextPriv().proxyProvider();
Greg Daniel94a6ce82018-01-16 16:14:41 -0500224
225 GrSurfaceDesc desc;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500226 desc.fWidth = kSize;
227 desc.fHeight = kSize;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500228 desc.fConfig = kRGBA_8888_GrPixelConfig;
229
Greg Daniel457469c2018-02-08 15:05:44 -0500230 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500231 for (bool doInstantiate : {true, false}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500232 for (auto lazyType : {LazyInstantiationType::kSingleUse,
Greg Daniela8d92112018-03-09 12:05:04 -0500233 LazyInstantiationType::kMultipleUse,
234 LazyInstantiationType::kUninstantiate}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500235 int testCount = 0;
236 int* testCountPtr = &testCount;
237 sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
Robert Phillipsce5209a2018-02-13 11:13:51 -0500238 [testCountPtr](GrResourceProvider* resourceProvider) {
Greg Daniel457469c2018-02-08 15:05:44 -0500239 if (!resourceProvider) {
240 *testCountPtr = -1;
241 return sk_sp<GrTexture>();
242 }
243 *testCountPtr = 1;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500244 return sk_sp<GrTexture>();
Brian Salomon2a4f9832018-03-03 22:43:43 -0500245 },
Brian Salomon7226c232018-07-30 13:13:17 -0400246 desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrTextureType::k2D,
247 GrInternalSurfaceFlags::kNone, SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel94a6ce82018-01-16 16:14:41 -0500248
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400249 REPORTER_ASSERT(reporter, proxy.get());
Greg Daniel457469c2018-02-08 15:05:44 -0500250 REPORTER_ASSERT(reporter, 0 == testCount);
251
252 if (doInstantiate) {
253 proxy->priv().doLazyInstantiation(ctx->contextPriv().resourceProvider());
254 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
255 // In SingleUse we will call the cleanup and delete the callback in the
256 // doLazyInstantiationCall.
257 REPORTER_ASSERT(reporter, -1 == testCount);
258 } else {
259 REPORTER_ASSERT(reporter, 1 == testCount);
260 }
261 proxy.reset();
262 REPORTER_ASSERT(reporter, -1 == testCount);
263 } else {
264 proxy.reset();
265 REPORTER_ASSERT(reporter, -1 == testCount);
266 }
Greg Daniel94a6ce82018-01-16 16:14:41 -0500267 }
268 }
269}
270
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500271class LazyFailedInstantiationTestOp : public GrDrawOp {
272public:
273 DEFINE_OP_CLASS_ID
274
Robert Phillips88a32ef2018-06-07 11:05:56 -0400275 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
276 GrProxyProvider* proxyProvider,
277 int* testExecuteValue,
278 bool shouldFailInstantiation) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400279 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
280
281 return pool->allocate<LazyFailedInstantiationTestOp>(proxyProvider,
282 testExecuteValue,
283 shouldFailInstantiation);
Robert Phillips88a32ef2018-06-07 11:05:56 -0400284 }
285
286 void visitProxies(const VisitProxyFunc& func) const override {
287 func(fLazyProxy.get());
288 }
289
290private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400291 friend class GrOpMemoryPool; // for ctor
292
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500293 LazyFailedInstantiationTestOp(GrProxyProvider* proxyProvider, int* testExecuteValue,
294 bool shouldFailInstantiation)
295 : INHERITED(ClassID())
296 , fTestExecuteValue(testExecuteValue) {
297 GrSurfaceDesc desc;
298 desc.fWidth = kSize;
299 desc.fHeight = kSize;
300 desc.fConfig = kRGBA_8888_GrPixelConfig;
301
302 fLazyProxy = proxyProvider->createLazyProxy(
Brian Salomon2a4f9832018-03-03 22:43:43 -0500303 [testExecuteValue, shouldFailInstantiation, desc](GrResourceProvider* rp) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500304 if (!rp) {
305 return sk_sp<GrTexture>();
306 }
307 if (shouldFailInstantiation) {
308 *testExecuteValue = 1;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500309 return sk_sp<GrTexture>();
310 }
311 return rp->createTexture(desc, SkBudgeted::kNo);
Brian Salomon2a4f9832018-03-03 22:43:43 -0500312 },
Brian Salomon7226c232018-07-30 13:13:17 -0400313 desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrTextureType::k2D,
314 SkBackingFit::kExact, SkBudgeted::kNo);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500315
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400316 SkASSERT(fLazyProxy.get());
317
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500318 this->setBounds(SkRect::MakeIWH(kSize, kSize),
319 HasAABloat::kNo, IsZeroArea::kNo);
320 }
321
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500322 const char* name() const override { return "LazyFailedInstantiationTestOp"; }
323 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman532b3f92018-07-11 10:02:07 -0400324 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500325 return RequiresDstTexture::kNo;
326 }
327 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; }
328 void onPrepare(GrOpFlushState*) override {}
329 void onExecute(GrOpFlushState* state) override {
330 *fTestExecuteValue = 2;
331 }
332
333 int* fTestExecuteValue;
334 sk_sp<GrSurfaceProxy> fLazyProxy;
335
336 typedef GrDrawOp INHERITED;
337};
338
339// Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was
340// associated with.
341DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) {
342 GrMockOptions mockOptions;
343 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips4150eea2018-02-07 17:08:21 -0500344 GrResourceProvider* resourceProvider = ctx->contextPriv().resourceProvider();
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500345 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
346 for (bool failInstantiation : {false, true}) {
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500347 sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext(
348 SkBackingFit::kExact, 100, 100,
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500349 kRGBA_8888_GrPixelConfig, nullptr);
350 REPORTER_ASSERT(reporter, rtc);
351
352 rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes);
353
354 int executeTestValue = 0;
Robert Phillips88a32ef2018-06-07 11:05:56 -0400355 rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make(
356 ctx.get(), proxyProvider, &executeTestValue, failInstantiation));
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500357 ctx->flush();
358
359 if (failInstantiation) {
Robert Phillips4150eea2018-02-07 17:08:21 -0500360 if (resourceProvider->explicitlyAllocateGPUResources()) {
361 REPORTER_ASSERT(reporter, 1 == executeTestValue);
362 } else {
363 // When we disable explicit gpu resource allocation we don't throw away ops that
364 // have uninstantiated proxies.
365 REPORTER_ASSERT(reporter, 2 == executeTestValue);
366 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500367 } else {
368 REPORTER_ASSERT(reporter, 2 == executeTestValue);
369 }
370 }
Greg Daniel4684f822018-03-08 15:27:36 -0500371}
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500372
Greg Daniel4684f822018-03-08 15:27:36 -0500373class LazyUninstantiateTestOp : public GrDrawOp {
374public:
375 DEFINE_OP_CLASS_ID
376
Robert Phillips88a32ef2018-06-07 11:05:56 -0400377 static std::unique_ptr<GrDrawOp> Make(GrContext* context, sk_sp<GrTextureProxy> proxy) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400378 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
379
380 return pool->allocate<LazyUninstantiateTestOp>(std::move(proxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500381 }
382
383 void visitProxies(const VisitProxyFunc& func) const override {
384 func(fLazyProxy.get());
385 }
386
387private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400388 friend class GrOpMemoryPool; // for ctor
389
Robert Phillips88a32ef2018-06-07 11:05:56 -0400390 LazyUninstantiateTestOp(sk_sp<GrTextureProxy> proxy)
391 : INHERITED(ClassID())
392 , fLazyProxy(std::move(proxy)) {
393 this->setBounds(SkRect::MakeIWH(kSize, kSize), HasAABloat::kNo, IsZeroArea::kNo);
394 }
395
Greg Daniel4684f822018-03-08 15:27:36 -0500396 const char* name() const override { return "LazyUninstantiateTestOp"; }
397 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman532b3f92018-07-11 10:02:07 -0400398 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
Greg Daniel4684f822018-03-08 15:27:36 -0500399 return RequiresDstTexture::kNo;
400 }
401 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; }
402 void onPrepare(GrOpFlushState*) override {}
403 void onExecute(GrOpFlushState* state) override {}
404
405 sk_sp<GrSurfaceProxy> fLazyProxy;
406
407 typedef GrDrawOp INHERITED;
408};
409
410static void UninstantiateReleaseProc(void* releaseValue) {
411 (*static_cast<int*>(releaseValue))++;
412}
413
414// Test that lazy proxies with the Uninstantiate LazyCallbackType are uninstantiated and released as
415// expected.
416DEF_GPUTEST(LazyProxyUninstantiateTest, reporter, /* options */) {
417 GrMockOptions mockOptions;
418 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
419 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
420 GrGpu* gpu = ctx->contextPriv().getGpu();
421
422 using LazyType = GrSurfaceProxy::LazyInstantiationType;
423 for (auto lazyType : {LazyType::kSingleUse, LazyType::kMultipleUse, LazyType::kUninstantiate}) {
424 sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext(
425 SkBackingFit::kExact, 100, 100,
426 kRGBA_8888_GrPixelConfig, nullptr);
427 REPORTER_ASSERT(reporter, rtc);
428
429 rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes);
430
431 int instantiateTestValue = 0;
432 int releaseTestValue = 0;
433 int* instantiatePtr = &instantiateTestValue;
434 int* releasePtr = &releaseTestValue;
435 GrSurfaceDesc desc;
436 desc.fWidth = kSize;
437 desc.fHeight = kSize;
438 desc.fConfig = kRGBA_8888_GrPixelConfig;
439
440 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
441 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, false, GrMipMapped::kNo);
442
443 sk_sp<GrTextureProxy> lazyProxy = proxyProvider->createLazyProxy(
444 [instantiatePtr, releasePtr, backendTex](GrResourceProvider* rp) {
445 if (!rp) {
446 return sk_sp<GrTexture>();
447 }
448
449 sk_sp<GrTexture> texture = rp->wrapBackendTexture(backendTex);
450 if (!texture) {
451 return sk_sp<GrTexture>();
452 }
453 (*instantiatePtr)++;
454 texture->setRelease(UninstantiateReleaseProc, releasePtr);
455 return texture;
456 },
Brian Salomon7226c232018-07-30 13:13:17 -0400457 desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrTextureType::k2D,
458 GrInternalSurfaceFlags::kNone, SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel4684f822018-03-08 15:27:36 -0500459
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400460 REPORTER_ASSERT(reporter, lazyProxy.get());
461
Robert Phillips88a32ef2018-06-07 11:05:56 -0400462 rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500463
464 ctx->flush();
465
466 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
467 if (LazyType::kUninstantiate == lazyType) {
468 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
469 } else {
470 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
471 }
472
473 // This should cause the uninstantiate proxies to be instantiated again but have no effect
474 // on the others
Robert Phillips88a32ef2018-06-07 11:05:56 -0400475 rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500476 // Add a second op to make sure we only instantiate once.
Robert Phillips88a32ef2018-06-07 11:05:56 -0400477 rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500478 ctx->flush();
479
480 if (LazyType::kUninstantiate == lazyType) {
481 REPORTER_ASSERT(reporter, 2 == instantiateTestValue);
482 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
483 } else {
484 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
485 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
486 }
487
488 lazyProxy.reset();
489 if (LazyType::kUninstantiate == lazyType) {
490 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
491 } else {
492 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
493 }
494
Brian Salomon26102cb2018-03-09 09:33:19 -0500495 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel4684f822018-03-08 15:27:36 -0500496 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500497}