blob: eb2520d114a33dee905fd57092b3d9b092581646 [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
Greg Daniel4065d452018-11-16 15:43:41 -050064 return pool->allocate<Op>(context, proxyProvider, test, nullTexture);
Robert Phillips88a32ef2018-06-07 11:05:56 -040065 }
66
Brian Salomon7d94bb52018-10-12 14:37:19 -040067 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillips88a32ef2018-06-07 11:05:56 -040068 func(fProxy.get());
69 }
70
Brian Salomon588cec72018-11-14 13:56:37 -050071 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override {
Robert Phillips88a32ef2018-06-07 11:05:56 -040072 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
Greg Daniel4065d452018-11-16 15:43:41 -050079 Op(GrContext* ctx, GrProxyProvider* proxyProvider, LazyProxyTest* test, bool nullTexture)
Robert Phillips777707b2018-01-17 11:40:14 -050080 : GrDrawOp(ClassID()), fTest(test) {
Greg Daniel4065d452018-11-16 15:43:41 -050081 const GrBackendFormat format =
82 ctx->contextPriv().caps()->getBackendFormatFromColorType(kRGB_565_SkColorType);
Chris Dalton4c458b12018-06-16 17:22:59 -060083 fProxy = GrProxyProvider::MakeFullyLazyProxy(
84 [this, nullTexture](GrResourceProvider* rp) {
85 if (!rp) {
86 return sk_sp<GrTexture>();
87 }
88 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture);
89 fTest->fHasOpTexture = true;
90 if (nullTexture) {
91 return sk_sp<GrTexture>();
92 } else {
93 GrSurfaceDesc desc;
94 desc.fWidth = 1234;
95 desc.fHeight = 567;
96 desc.fConfig = kRGB_565_GrPixelConfig;
97 sk_sp<GrTexture> texture = rp->createTexture(desc, SkBudgeted::kYes);
98 REPORTER_ASSERT(fTest->fReporter, texture);
99 return texture;
100 }
101 },
Greg Daniel4065d452018-11-16 15:43:41 -0500102 format, GrProxyProvider::Renderable::kNo, kTopLeft_GrSurfaceOrigin,
Chris Dalton4c458b12018-06-16 17:22:59 -0600103 kRGB_565_GrPixelConfig, *proxyProvider->caps());
104
105 this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo,
106 GrOp::IsZeroArea::kNo);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700107 }
108
Chris Dalton706a6ff2017-11-29 22:01:06 -0700109 const char* name() const override { return "LazyProxyTest::Op"; }
110 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman532b3f92018-07-11 10:02:07 -0400111 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
Chris Dalton706a6ff2017-11-29 22:01:06 -0700112 return RequiresDstTexture::kNo;
113 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700114 void onPrepare(GrOpFlushState*) override {}
115
116 LazyProxyTest* const fTest;
117 sk_sp<GrTextureProxy> fProxy;
118 };
119
120 class ClipFP : public GrFragmentProcessor {
121 public:
Greg Daniel4065d452018-11-16 15:43:41 -0500122 ClipFP(GrContext* ctx, GrProxyProvider* proxyProvider, LazyProxyTest* test,
123 GrTextureProxy* atlas)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700124 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
Greg Daniel4065d452018-11-16 15:43:41 -0500125 , fContext(ctx)
Robert Phillips777707b2018-01-17 11:40:14 -0500126 , fProxyProvider(proxyProvider)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700127 , fTest(test)
128 , fAtlas(atlas) {
Greg Daniel4065d452018-11-16 15:43:41 -0500129 const GrBackendFormat format =
130 ctx->contextPriv().caps()->getBackendFormatFromGrColorType(GrColorType::kAlpha_F16,
131 GrSRGBEncoded::kNo);
Chris Dalton4c458b12018-06-16 17:22:59 -0600132 fLazyProxy = GrProxyProvider::MakeFullyLazyProxy(
Robert Phillipsce5209a2018-02-13 11:13:51 -0500133 [this](GrResourceProvider* rp) {
134 if (!rp) {
135 return sk_sp<GrTexture>();
136 }
137 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
138 fTest->fHasClipTexture = true;
139 fAtlas->instantiate(rp);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400140 return sk_ref_sp(fAtlas->peekTexture());
Robert Phillipsce5209a2018-02-13 11:13:51 -0500141 },
Greg Daniel4065d452018-11-16 15:43:41 -0500142 format,
Robert Phillipsce5209a2018-02-13 11:13:51 -0500143 GrProxyProvider::Renderable::kYes,
144 kBottomLeft_GrSurfaceOrigin,
Chris Dalton4c458b12018-06-16 17:22:59 -0600145 kAlpha_half_GrPixelConfig, *proxyProvider->caps());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700146 fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
Brian Salomone782f842018-07-31 13:53:11 -0400147 GrSamplerState::WrapMode::kClamp);
Brian Salomonf7dcd762018-07-30 14:48:15 -0400148 this->setTextureSamplerCnt(1);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700149 }
150
151 private:
152 const char* name() const override { return "LazyProxyTest::ClipFP"; }
153 std::unique_ptr<GrFragmentProcessor> clone() const override {
Greg Daniel4065d452018-11-16 15:43:41 -0500154 return skstd::make_unique<ClipFP>(fContext, fProxyProvider, fTest, fAtlas);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700155 }
156 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
157 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
158 bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400159 const TextureSampler& onTextureSampler(int) const override { return fAccess; }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700160
Greg Daniel4065d452018-11-16 15:43:41 -0500161 GrContext* const fContext;
Robert Phillips777707b2018-01-17 11:40:14 -0500162 GrProxyProvider* const fProxyProvider;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700163 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:
172 Clip(LazyProxyTest* test, GrTextureProxy* atlas)
173 : fTest(test)
174 , fAtlas(atlas) {}
175
176 private:
Robert Phillips777707b2018-01-17 11:40:14 -0500177 bool apply(GrContext* context, GrRenderTargetContext*, bool, bool, GrAppliedClip* out,
Chris Dalton706a6ff2017-11-29 22:01:06 -0700178 SkRect* bounds) const override {
Robert Phillips777707b2018-01-17 11:40:14 -0500179 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
Greg Daniel4065d452018-11-16 15:43:41 -0500180 out->addCoverageFP(skstd::make_unique<ClipFP>(context, proxyProvider, fTest, fAtlas));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700181 return true;
182 }
183 bool quickContains(const SkRect&) const final { return false; }
184 bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
185 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
196private:
197 skiatest::Reporter* fReporter;
198 bool fHasOpTexture;
199 bool fHasClipTexture;
200};
201
202DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
203 GrMockOptions mockOptions;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500204 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderability =
205 GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700206 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true;
207 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips777707b2018-01-17 11:40:14 -0500208 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700209 for (bool nullTexture : {false, true}) {
210 LazyProxyTest test(reporter);
211 ctx->contextPriv().addOnFlushCallbackObject(&test);
Greg Daniel4065d452018-11-16 15:43:41 -0500212 GrBackendFormat format =
213 ctx->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500214 sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500215 format, SkBackingFit::kExact, 100, 100,
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500216 kRGBA_8888_GrPixelConfig, nullptr);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700217 REPORTER_ASSERT(reporter, rtc);
Greg Daniel4065d452018-11-16 15:43:41 -0500218 format =
219 ctx->contextPriv().caps()->getBackendFormatFromGrColorType(GrColorType::kAlpha_F16,
220 GrSRGBEncoded::kNo);
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500221 sk_sp<GrRenderTargetContext> mockAtlas = ctx->contextPriv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500222 format, SkBackingFit::kExact, 10, 10,
Chris Dalton706a6ff2017-11-29 22:01:06 -0700223 kAlpha_half_GrPixelConfig, nullptr);
224 REPORTER_ASSERT(reporter, mockAtlas);
225 rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
Robert Phillips88a32ef2018-06-07 11:05:56 -0400226 LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700227 ctx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
228 }
229}
230
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500231static const int kSize = 16;
232
Greg Daniel94a6ce82018-01-16 16:14:41 -0500233DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
234 GrMockOptions mockOptions;
235 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips777707b2018-01-17 11:40:14 -0500236 auto proxyProvider = ctx->contextPriv().proxyProvider();
Greg Daniel94a6ce82018-01-16 16:14:41 -0500237
238 GrSurfaceDesc desc;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500239 desc.fWidth = kSize;
240 desc.fHeight = kSize;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500241 desc.fConfig = kRGBA_8888_GrPixelConfig;
242
Greg Daniel4065d452018-11-16 15:43:41 -0500243 GrBackendFormat format =
244 ctx->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
245
Greg Daniel457469c2018-02-08 15:05:44 -0500246 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500247 for (bool doInstantiate : {true, false}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500248 for (auto lazyType : {LazyInstantiationType::kSingleUse,
Greg Daniela8d92112018-03-09 12:05:04 -0500249 LazyInstantiationType::kMultipleUse,
Brian Salomon967df202018-12-07 11:15:53 -0500250 LazyInstantiationType::kDeinstantiate}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500251 int testCount = 0;
252 int* testCountPtr = &testCount;
253 sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
Robert Phillipsce5209a2018-02-13 11:13:51 -0500254 [testCountPtr](GrResourceProvider* resourceProvider) {
Greg Daniel457469c2018-02-08 15:05:44 -0500255 if (!resourceProvider) {
256 *testCountPtr = -1;
257 return sk_sp<GrTexture>();
258 }
259 *testCountPtr = 1;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500260 return sk_sp<GrTexture>();
Brian Salomon2a4f9832018-03-03 22:43:43 -0500261 },
Greg Daniel4065d452018-11-16 15:43:41 -0500262 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
Brian Salomon7226c232018-07-30 13:13:17 -0400263 GrInternalSurfaceFlags::kNone, SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel94a6ce82018-01-16 16:14:41 -0500264
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400265 REPORTER_ASSERT(reporter, proxy.get());
Greg Daniel457469c2018-02-08 15:05:44 -0500266 REPORTER_ASSERT(reporter, 0 == testCount);
267
268 if (doInstantiate) {
269 proxy->priv().doLazyInstantiation(ctx->contextPriv().resourceProvider());
270 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
271 // In SingleUse we will call the cleanup and delete the callback in the
272 // doLazyInstantiationCall.
273 REPORTER_ASSERT(reporter, -1 == testCount);
274 } else {
275 REPORTER_ASSERT(reporter, 1 == testCount);
276 }
277 proxy.reset();
278 REPORTER_ASSERT(reporter, -1 == testCount);
279 } else {
280 proxy.reset();
281 REPORTER_ASSERT(reporter, -1 == testCount);
282 }
Greg Daniel94a6ce82018-01-16 16:14:41 -0500283 }
284 }
285}
286
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500287class LazyFailedInstantiationTestOp : public GrDrawOp {
288public:
289 DEFINE_OP_CLASS_ID
290
Robert Phillips88a32ef2018-06-07 11:05:56 -0400291 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
292 GrProxyProvider* proxyProvider,
293 int* testExecuteValue,
294 bool shouldFailInstantiation) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400295 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
296
Greg Daniel4065d452018-11-16 15:43:41 -0500297 return pool->allocate<LazyFailedInstantiationTestOp>(context, proxyProvider,
Robert Phillipsc994a932018-06-19 13:09:54 -0400298 testExecuteValue,
299 shouldFailInstantiation);
Robert Phillips88a32ef2018-06-07 11:05:56 -0400300 }
301
Brian Salomon7d94bb52018-10-12 14:37:19 -0400302 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillips88a32ef2018-06-07 11:05:56 -0400303 func(fLazyProxy.get());
304 }
305
306private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400307 friend class GrOpMemoryPool; // for ctor
308
Greg Daniel4065d452018-11-16 15:43:41 -0500309 LazyFailedInstantiationTestOp(GrContext* ctx, GrProxyProvider* proxyProvider,
310 int* testExecuteValue, bool shouldFailInstantiation)
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500311 : INHERITED(ClassID())
312 , fTestExecuteValue(testExecuteValue) {
313 GrSurfaceDesc desc;
314 desc.fWidth = kSize;
315 desc.fHeight = kSize;
316 desc.fConfig = kRGBA_8888_GrPixelConfig;
Greg Daniel4065d452018-11-16 15:43:41 -0500317 GrBackendFormat format =
318 ctx->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500319
320 fLazyProxy = proxyProvider->createLazyProxy(
Brian Salomon2a4f9832018-03-03 22:43:43 -0500321 [testExecuteValue, shouldFailInstantiation, desc](GrResourceProvider* rp) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500322 if (!rp) {
323 return sk_sp<GrTexture>();
324 }
325 if (shouldFailInstantiation) {
326 *testExecuteValue = 1;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500327 return sk_sp<GrTexture>();
328 }
329 return rp->createTexture(desc, SkBudgeted::kNo);
Brian Salomon2a4f9832018-03-03 22:43:43 -0500330 },
Greg Daniel4065d452018-11-16 15:43:41 -0500331 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
Brian Salomon7226c232018-07-30 13:13:17 -0400332 SkBackingFit::kExact, SkBudgeted::kNo);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500333
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400334 SkASSERT(fLazyProxy.get());
335
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500336 this->setBounds(SkRect::MakeIWH(kSize, kSize),
337 HasAABloat::kNo, IsZeroArea::kNo);
338 }
339
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500340 const char* name() const override { return "LazyFailedInstantiationTestOp"; }
341 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman532b3f92018-07-11 10:02:07 -0400342 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500343 return RequiresDstTexture::kNo;
344 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500345 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500346 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500347 *fTestExecuteValue = 2;
348 }
349
350 int* fTestExecuteValue;
351 sk_sp<GrSurfaceProxy> fLazyProxy;
352
353 typedef GrDrawOp INHERITED;
354};
355
356// Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was
357// associated with.
358DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) {
359 GrMockOptions mockOptions;
360 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips4150eea2018-02-07 17:08:21 -0500361 GrResourceProvider* resourceProvider = ctx->contextPriv().resourceProvider();
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500362 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
Greg Daniel4065d452018-11-16 15:43:41 -0500363 GrBackendFormat format =
364 ctx->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500365 for (bool failInstantiation : {false, true}) {
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500366 sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500367 format, SkBackingFit::kExact, 100, 100,
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500368 kRGBA_8888_GrPixelConfig, nullptr);
369 REPORTER_ASSERT(reporter, rtc);
370
Brian Osman9a9baae2018-11-05 15:06:26 -0500371 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
372 GrRenderTargetContext::CanClearFullscreen::kYes);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500373
374 int executeTestValue = 0;
Robert Phillips88a32ef2018-06-07 11:05:56 -0400375 rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make(
376 ctx.get(), proxyProvider, &executeTestValue, failInstantiation));
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500377 ctx->flush();
378
379 if (failInstantiation) {
Robert Phillips4150eea2018-02-07 17:08:21 -0500380 if (resourceProvider->explicitlyAllocateGPUResources()) {
381 REPORTER_ASSERT(reporter, 1 == executeTestValue);
382 } else {
383 // When we disable explicit gpu resource allocation we don't throw away ops that
384 // have uninstantiated proxies.
385 REPORTER_ASSERT(reporter, 2 == executeTestValue);
386 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500387 } else {
388 REPORTER_ASSERT(reporter, 2 == executeTestValue);
389 }
390 }
Greg Daniel4684f822018-03-08 15:27:36 -0500391}
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500392
Brian Salomon967df202018-12-07 11:15:53 -0500393class LazyDeinstantiateTestOp : public GrDrawOp {
Greg Daniel4684f822018-03-08 15:27:36 -0500394public:
395 DEFINE_OP_CLASS_ID
396
Robert Phillips88a32ef2018-06-07 11:05:56 -0400397 static std::unique_ptr<GrDrawOp> Make(GrContext* context, sk_sp<GrTextureProxy> proxy) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400398 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
399
Brian Salomon967df202018-12-07 11:15:53 -0500400 return pool->allocate<LazyDeinstantiateTestOp>(std::move(proxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500401 }
402
Brian Salomon7d94bb52018-10-12 14:37:19 -0400403 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Greg Daniel4684f822018-03-08 15:27:36 -0500404 func(fLazyProxy.get());
405 }
406
407private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400408 friend class GrOpMemoryPool; // for ctor
409
Brian Salomon967df202018-12-07 11:15:53 -0500410 LazyDeinstantiateTestOp(sk_sp<GrTextureProxy> proxy)
411 : INHERITED(ClassID()), fLazyProxy(std::move(proxy)) {
Robert Phillips88a32ef2018-06-07 11:05:56 -0400412 this->setBounds(SkRect::MakeIWH(kSize, kSize), HasAABloat::kNo, IsZeroArea::kNo);
413 }
414
Brian Salomon967df202018-12-07 11:15:53 -0500415 const char* name() const override { return "LazyDeinstantiateTestOp"; }
Greg Daniel4684f822018-03-08 15:27:36 -0500416 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman532b3f92018-07-11 10:02:07 -0400417 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
Greg Daniel4684f822018-03-08 15:27:36 -0500418 return RequiresDstTexture::kNo;
419 }
Greg Daniel4684f822018-03-08 15:27:36 -0500420 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500421 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {}
Greg Daniel4684f822018-03-08 15:27:36 -0500422
423 sk_sp<GrSurfaceProxy> fLazyProxy;
424
425 typedef GrDrawOp INHERITED;
426};
427
Brian Salomon967df202018-12-07 11:15:53 -0500428static void DeinstantiateReleaseProc(void* releaseValue) { (*static_cast<int*>(releaseValue))++; }
Greg Daniel4684f822018-03-08 15:27:36 -0500429
Brian Salomon967df202018-12-07 11:15:53 -0500430// Test that lazy proxies with the Deinstantiate LazyCallbackType are deinstantiated and released as
Greg Daniel4684f822018-03-08 15:27:36 -0500431// expected.
Brian Salomon967df202018-12-07 11:15:53 -0500432DEF_GPUTEST(LazyProxyDeinstantiateTest, reporter, /* options */) {
Greg Daniel4684f822018-03-08 15:27:36 -0500433 GrMockOptions mockOptions;
434 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
435 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
436 GrGpu* gpu = ctx->contextPriv().getGpu();
437
Greg Daniel4065d452018-11-16 15:43:41 -0500438 GrBackendFormat format =
439 ctx->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
440
Greg Daniel4684f822018-03-08 15:27:36 -0500441 using LazyType = GrSurfaceProxy::LazyInstantiationType;
Brian Salomon967df202018-12-07 11:15:53 -0500442 for (auto lazyType : {LazyType::kSingleUse, LazyType::kMultipleUse, LazyType::kDeinstantiate}) {
Greg Daniel4684f822018-03-08 15:27:36 -0500443 sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500444 format, SkBackingFit::kExact, 100, 100,
Greg Daniel4684f822018-03-08 15:27:36 -0500445 kRGBA_8888_GrPixelConfig, nullptr);
446 REPORTER_ASSERT(reporter, rtc);
447
Brian Osman9a9baae2018-11-05 15:06:26 -0500448 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
449 GrRenderTargetContext::CanClearFullscreen::kYes);
Greg Daniel4684f822018-03-08 15:27:36 -0500450
451 int instantiateTestValue = 0;
452 int releaseTestValue = 0;
453 int* instantiatePtr = &instantiateTestValue;
454 int* releasePtr = &releaseTestValue;
455 GrSurfaceDesc desc;
456 desc.fWidth = kSize;
457 desc.fHeight = kSize;
458 desc.fConfig = kRGBA_8888_GrPixelConfig;
459
460 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
Robert Phillips646f6372018-09-25 09:31:10 -0400461 nullptr, kSize, kSize, GrColorType::kRGBA_8888, false, GrMipMapped::kNo);
Greg Daniel4684f822018-03-08 15:27:36 -0500462
463 sk_sp<GrTextureProxy> lazyProxy = proxyProvider->createLazyProxy(
464 [instantiatePtr, releasePtr, backendTex](GrResourceProvider* rp) {
465 if (!rp) {
466 return sk_sp<GrTexture>();
467 }
468
Brian Salomonc67c31c2018-12-06 10:00:03 -0500469 sk_sp<GrTexture> texture = rp->wrapBackendTexture(
470 backendTex, kBorrow_GrWrapOwnership, kRead_GrIOType);
Greg Daniel4684f822018-03-08 15:27:36 -0500471 if (!texture) {
472 return sk_sp<GrTexture>();
473 }
474 (*instantiatePtr)++;
Brian Salomon967df202018-12-07 11:15:53 -0500475 texture->setRelease(DeinstantiateReleaseProc, releasePtr);
Greg Daniel4684f822018-03-08 15:27:36 -0500476 return texture;
477 },
Greg Daniel4065d452018-11-16 15:43:41 -0500478 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
Brian Salomonc67c31c2018-12-06 10:00:03 -0500479 GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel4684f822018-03-08 15:27:36 -0500480
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400481 REPORTER_ASSERT(reporter, lazyProxy.get());
482
Brian Salomon967df202018-12-07 11:15:53 -0500483 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500484
485 ctx->flush();
486
487 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
Brian Salomon967df202018-12-07 11:15:53 -0500488 if (LazyType::kDeinstantiate == lazyType) {
Greg Daniel4684f822018-03-08 15:27:36 -0500489 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
490 } else {
491 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
492 }
493
494 // This should cause the uninstantiate proxies to be instantiated again but have no effect
495 // on the others
Brian Salomon967df202018-12-07 11:15:53 -0500496 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500497 // Add a second op to make sure we only instantiate once.
Brian Salomon967df202018-12-07 11:15:53 -0500498 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500499 ctx->flush();
500
Brian Salomon967df202018-12-07 11:15:53 -0500501 if (LazyType::kDeinstantiate == lazyType) {
Greg Daniel4684f822018-03-08 15:27:36 -0500502 REPORTER_ASSERT(reporter, 2 == instantiateTestValue);
503 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
504 } else {
505 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
506 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
507 }
508
509 lazyProxy.reset();
Brian Salomon967df202018-12-07 11:15:53 -0500510 if (LazyType::kDeinstantiate == lazyType) {
Greg Daniel4684f822018-03-08 15:27:36 -0500511 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
512 } else {
513 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
514 }
515
Brian Salomon26102cb2018-03-09 09:33:19 -0500516 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel4684f822018-03-08 15:27:36 -0500517 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500518}