blob: ef4dcb4f442332821cd9306e26529a4c7a892d89 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tests/Test.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -07009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrTexture.h"
11#include "include/gpu/mock/GrMockTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#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"
Greg Danielf91aeb22019-06-18 09:58:02 -040023#include "src/gpu/GrSurfaceProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/gpu/GrSurfaceProxyPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040025#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/GrTextureProxyPriv.h"
27#include "src/gpu/mock/GrMockGpu.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070028
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.
32class LazyProxyTest final : public GrOnFlushCallbackObject {
33public:
34 LazyProxyTest(skiatest::Reporter* reporter)
35 : fReporter(reporter)
36 , fHasOpTexture(false)
37 , fHasClipTexture(false) {
38 }
39
40 ~LazyProxyTest() override {
41 REPORTER_ASSERT(fReporter, fHasOpTexture);
42 REPORTER_ASSERT(fReporter, fHasClipTexture);
43 }
44
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
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
Robert Phillips6f0e02f2019-02-13 11:02:28 -050060 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips88a32ef2018-06-07 11:05:56 -040061 GrProxyProvider* proxyProvider,
62 LazyProxyTest* test,
63 bool nullTexture) {
Robert Phillips9da87e02019-02-04 13:26:26 -050064 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -040065
Greg Daniel4065d452018-11-16 15:43:41 -050066 return pool->allocate<Op>(context, proxyProvider, test, nullTexture);
Robert Phillips88a32ef2018-06-07 11:05:56 -040067 }
68
Chris Dalton1706cbf2019-05-21 19:35:29 -060069 void visitProxies(const VisitProxyFunc& func) const override {
Chris Dalton7eb5c0f2019-05-23 15:15:47 -060070 func(fProxy.get(), GrMipMapped::kNo);
Robert Phillips88a32ef2018-06-07 11:05:56 -040071 }
72
Brian Salomon588cec72018-11-14 13:56:37 -050073 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override {
Robert Phillips88a32ef2018-06-07 11:05:56 -040074 REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
75 REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
76 }
77
78 private:
Robert Phillips7c525e62018-06-12 10:11:12 -040079 friend class GrOpMemoryPool; // for ctor
80
Robert Phillips6f0e02f2019-02-13 11:02:28 -050081 Op(GrRecordingContext* ctx, GrProxyProvider* proxyProvider,
82 LazyProxyTest* test, bool nullTexture)
Robert Phillips777707b2018-01-17 11:40:14 -050083 : GrDrawOp(ClassID()), fTest(test) {
Greg Daniel4065d452018-11-16 15:43:41 -050084 const GrBackendFormat format =
Greg Daniel627d0532019-07-08 16:48:14 -040085 ctx->priv().caps()->getBackendFormatFromColorType(GrColorType::kBGR_565);
Chris Dalton4c458b12018-06-16 17:22:59 -060086 fProxy = GrProxyProvider::MakeFullyLazyProxy(
Brian Salomonb6a3a3b2019-04-01 12:29:34 -040087 [this, nullTexture](
88 GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
Chris Dalton4c458b12018-06-16 17:22:59 -060089 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture);
90 fTest->fHasOpTexture = true;
91 if (nullTexture) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -040092 return {};
Chris Dalton4c458b12018-06-16 17:22:59 -060093 } else {
94 GrSurfaceDesc desc;
95 desc.fWidth = 1234;
96 desc.fHeight = 567;
97 desc.fConfig = kRGB_565_GrPixelConfig;
Brian Salomonf2c2ba92019-07-17 09:59:59 -040098 sk_sp<GrTexture> texture =
99 rp->createTexture(desc, GrRenderable::kNo, SkBudgeted::kYes,
100 GrResourceProvider::Flags::kNoPendingIO);
Chris Dalton4c458b12018-06-16 17:22:59 -0600101 REPORTER_ASSERT(fTest->fReporter, texture);
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400102 return std::move(texture);
Chris Dalton4c458b12018-06-16 17:22:59 -0600103 }
104 },
Greg Daniel4065d452018-11-16 15:43:41 -0500105 format, GrProxyProvider::Renderable::kNo, kTopLeft_GrSurfaceOrigin,
Chris Dalton4c458b12018-06-16 17:22:59 -0600106 kRGB_565_GrPixelConfig, *proxyProvider->caps());
107
108 this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo,
109 GrOp::IsZeroArea::kNo);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700110 }
111
Chris Dalton706a6ff2017-11-29 22:01:06 -0700112 const char* name() const override { return "LazyProxyTest::Op"; }
113 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600114 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip* clip,
115 bool hasMixedSampledCoverage, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700116 return GrProcessorSet::EmptySetAnalysis();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700117 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700118 void onPrepare(GrOpFlushState*) override {}
119
120 LazyProxyTest* const fTest;
121 sk_sp<GrTextureProxy> fProxy;
122 };
123
124 class ClipFP : public GrFragmentProcessor {
125 public:
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500126 ClipFP(GrRecordingContext* ctx, GrProxyProvider* proxyProvider, LazyProxyTest* test,
Greg Daniel4065d452018-11-16 15:43:41 -0500127 GrTextureProxy* atlas)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700128 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
Greg Daniel4065d452018-11-16 15:43:41 -0500129 , fContext(ctx)
Robert Phillips777707b2018-01-17 11:40:14 -0500130 , fProxyProvider(proxyProvider)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700131 , fTest(test)
132 , fAtlas(atlas) {
Greg Daniel4065d452018-11-16 15:43:41 -0500133 const GrBackendFormat format =
Greg Daniele877dce2019-07-11 10:52:43 -0400134 ctx->priv().caps()->getBackendFormatFromColorType(GrColorType::kAlpha_F16);
Chris Dalton4c458b12018-06-16 17:22:59 -0600135 fLazyProxy = GrProxyProvider::MakeFullyLazyProxy(
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400136 [this](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
137 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
138 fTest->fHasClipTexture = true;
139 fAtlas->instantiate(rp);
140 return sk_ref_sp(fAtlas->peekTexture());
141 },
142 format, GrProxyProvider::Renderable::kYes, kBottomLeft_GrSurfaceOrigin,
143 kAlpha_half_GrPixelConfig, *proxyProvider->caps());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700144 fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
Brian Salomone782f842018-07-31 13:53:11 -0400145 GrSamplerState::WrapMode::kClamp);
Brian Salomonf7dcd762018-07-30 14:48:15 -0400146 this->setTextureSamplerCnt(1);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700147 }
148
149 private:
150 const char* name() const override { return "LazyProxyTest::ClipFP"; }
151 std::unique_ptr<GrFragmentProcessor> clone() const override {
Greg Daniel4065d452018-11-16 15:43:41 -0500152 return skstd::make_unique<ClipFP>(fContext, fProxyProvider, fTest, fAtlas);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700153 }
154 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
155 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
156 bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400157 const TextureSampler& onTextureSampler(int) const override { return fAccess; }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700158
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500159 GrRecordingContext* const fContext;
Robert Phillips777707b2018-01-17 11:40:14 -0500160 GrProxyProvider* const fProxyProvider;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700161 LazyProxyTest* const fTest;
162 GrTextureProxy* const fAtlas;
163 sk_sp<GrTextureProxy> fLazyProxy;
164 TextureSampler fAccess;
165 };
166
167
168 class Clip : public GrClip {
169 public:
170 Clip(LazyProxyTest* test, GrTextureProxy* atlas)
171 : fTest(test)
172 , fAtlas(atlas) {}
173
174 private:
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500175 bool apply(GrRecordingContext* context, GrRenderTargetContext*, bool useHWAA,
176 bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override {
Robert Phillips9da87e02019-02-04 13:26:26 -0500177 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Greg Daniel4065d452018-11-16 15:43:41 -0500178 out->addCoverageFP(skstd::make_unique<ClipFP>(context, proxyProvider, fTest, fAtlas));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700179 return true;
180 }
181 bool quickContains(const SkRect&) const final { return false; }
182 bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
183 void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
184 rect->set(0, 0, width, height);
185 if (iior) {
186 *iior = false;
187 }
188 }
189
190 LazyProxyTest* const fTest;
191 GrTextureProxy* fAtlas;
192 };
193
194private:
195 skiatest::Reporter* fReporter;
196 bool fHasOpTexture;
197 bool fHasClipTexture;
198};
199
200DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
201 GrMockOptions mockOptions;
Robert Phillipsa5e78be2019-07-09 12:34:38 -0400202 mockOptions.fConfigOptions[(int)GrColorType::kAlpha_F16].fRenderability =
Brian Salomonbdecacf2018-02-02 20:32:49 -0500203 GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
Robert Phillipsa5e78be2019-07-09 12:34:38 -0400204 mockOptions.fConfigOptions[(int)GrColorType::kAlpha_F16].fTexturable = true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700205 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500206 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700207 for (bool nullTexture : {false, true}) {
208 LazyProxyTest test(reporter);
Robert Phillips9da87e02019-02-04 13:26:26 -0500209 ctx->priv().addOnFlushCallbackObject(&test);
Robert Phillips9da87e02019-02-04 13:26:26 -0500210 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400211 SkBackingFit::kExact, 100, 100, GrColorType::kRGBA_8888, nullptr);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700212 REPORTER_ASSERT(reporter, rtc);
Robert Phillips9da87e02019-02-04 13:26:26 -0500213 sk_sp<GrRenderTargetContext> mockAtlas = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400214 SkBackingFit::kExact, 10, 10, GrColorType::kAlpha_F16, nullptr);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700215 REPORTER_ASSERT(reporter, mockAtlas);
216 rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
Robert Phillips88a32ef2018-06-07 11:05:56 -0400217 LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
Robert Phillips9da87e02019-02-04 13:26:26 -0500218 ctx->priv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700219 }
220}
221
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500222static const int kSize = 16;
223
Greg Daniel94a6ce82018-01-16 16:14:41 -0500224DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
225 GrMockOptions mockOptions;
226 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500227 auto proxyProvider = ctx->priv().proxyProvider();
Greg Daniel94a6ce82018-01-16 16:14:41 -0500228
229 GrSurfaceDesc desc;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500230 desc.fWidth = kSize;
231 desc.fHeight = kSize;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500232 desc.fConfig = kRGBA_8888_GrPixelConfig;
233
Greg Daniel4065d452018-11-16 15:43:41 -0500234 GrBackendFormat format =
Greg Daniel627d0532019-07-08 16:48:14 -0400235 ctx->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
Greg Daniel4065d452018-11-16 15:43:41 -0500236
Greg Daniel457469c2018-02-08 15:05:44 -0500237 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400238 using LazyInstantiationResult = GrSurfaceProxy::LazyInstantiationResult;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500239 for (bool doInstantiate : {true, false}) {
Brian Salomon876a0172019-03-08 11:12:14 -0500240 for (auto lazyType : {LazyInstantiationType::kSingleUse,
241 LazyInstantiationType::kMultipleUse,
242 LazyInstantiationType::kDeinstantiate}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500243 int testCount = 0;
Brian Salomon67f01952019-02-14 13:05:25 -0500244 // Sets an integer to 1 when the callback is called and -1 when it is deleted.
245 class TestCallback {
246 public:
247 TestCallback(int* value) : fValue(value) {}
248 TestCallback(const TestCallback& that) { SkASSERT(0); }
249 TestCallback(TestCallback&& that) : fValue(that.fValue) { that.fValue = nullptr; }
250
251 ~TestCallback() { fValue ? (void)(*fValue = -1) : void(); }
252
253 TestCallback& operator=(TestCallback&& that) {
254 fValue = skstd::exchange(that.fValue, nullptr);
255 return *this;
256 }
257 TestCallback& operator=(const TestCallback& that) = delete;
258
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400259 LazyInstantiationResult operator()(GrResourceProvider* resourceProvider) const {
Brian Salomon67f01952019-02-14 13:05:25 -0500260 *fValue = 1;
261 return {};
262 }
263
264 private:
265 int* fValue = nullptr;
266 };
Greg Daniel457469c2018-02-08 15:05:44 -0500267 sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400268 TestCallback(&testCount), format, desc, GrRenderable::kNo,
269 kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrInternalSurfaceFlags::kNone,
270 SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel94a6ce82018-01-16 16:14:41 -0500271
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400272 REPORTER_ASSERT(reporter, proxy.get());
Greg Daniel457469c2018-02-08 15:05:44 -0500273 REPORTER_ASSERT(reporter, 0 == testCount);
274
275 if (doInstantiate) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500276 proxy->priv().doLazyInstantiation(ctx->priv().resourceProvider());
Greg Daniel457469c2018-02-08 15:05:44 -0500277 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
278 // In SingleUse we will call the cleanup and delete the callback in the
279 // doLazyInstantiationCall.
280 REPORTER_ASSERT(reporter, -1 == testCount);
281 } else {
282 REPORTER_ASSERT(reporter, 1 == testCount);
283 }
284 proxy.reset();
285 REPORTER_ASSERT(reporter, -1 == testCount);
286 } else {
287 proxy.reset();
288 REPORTER_ASSERT(reporter, -1 == testCount);
289 }
Greg Daniel94a6ce82018-01-16 16:14:41 -0500290 }
291 }
292}
293
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500294class LazyFailedInstantiationTestOp : public GrDrawOp {
295public:
296 DEFINE_OP_CLASS_ID
297
Robert Phillips88a32ef2018-06-07 11:05:56 -0400298 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
299 GrProxyProvider* proxyProvider,
300 int* testExecuteValue,
301 bool shouldFailInstantiation) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500302 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400303
Greg Daniel4065d452018-11-16 15:43:41 -0500304 return pool->allocate<LazyFailedInstantiationTestOp>(context, proxyProvider,
Robert Phillipsc994a932018-06-19 13:09:54 -0400305 testExecuteValue,
306 shouldFailInstantiation);
Robert Phillips88a32ef2018-06-07 11:05:56 -0400307 }
308
Chris Dalton1706cbf2019-05-21 19:35:29 -0600309 void visitProxies(const VisitProxyFunc& func) const override {
Chris Dalton7eb5c0f2019-05-23 15:15:47 -0600310 func(fLazyProxy.get(), GrMipMapped::kNo);
Robert Phillips88a32ef2018-06-07 11:05:56 -0400311 }
312
313private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400314 friend class GrOpMemoryPool; // for ctor
315
Greg Daniel4065d452018-11-16 15:43:41 -0500316 LazyFailedInstantiationTestOp(GrContext* ctx, GrProxyProvider* proxyProvider,
317 int* testExecuteValue, bool shouldFailInstantiation)
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500318 : INHERITED(ClassID())
319 , fTestExecuteValue(testExecuteValue) {
320 GrSurfaceDesc desc;
321 desc.fWidth = kSize;
322 desc.fHeight = kSize;
323 desc.fConfig = kRGBA_8888_GrPixelConfig;
Greg Daniel4065d452018-11-16 15:43:41 -0500324 GrBackendFormat format =
Greg Daniel627d0532019-07-08 16:48:14 -0400325 ctx->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500326
327 fLazyProxy = proxyProvider->createLazyProxy(
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400328 [testExecuteValue, shouldFailInstantiation,
329 desc](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
Greg Daniel0a375db2018-02-01 12:21:39 -0500330 if (shouldFailInstantiation) {
331 *testExecuteValue = 1;
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400332 return {};
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500333 }
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400334 return {rp->createTexture(desc, GrRenderable::kNo, SkBudgeted::kNo,
Robert Phillips9313aa72019-04-09 18:41:27 -0400335 GrResourceProvider::Flags::kNoPendingIO),
Brian Salomon01ceae92019-04-02 11:49:54 -0400336 GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced};
Brian Salomon2a4f9832018-03-03 22:43:43 -0500337 },
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400338 format, desc, GrRenderable::kNo, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
339 SkBackingFit::kExact, SkBudgeted::kNo);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500340
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400341 SkASSERT(fLazyProxy.get());
342
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500343 this->setBounds(SkRect::MakeIWH(kSize, kSize),
344 HasAABloat::kNo, IsZeroArea::kNo);
345 }
346
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500347 const char* name() const override { return "LazyFailedInstantiationTestOp"; }
348 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600349 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
350 bool hasMixedSampledCoverage, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700351 return GrProcessorSet::EmptySetAnalysis();
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500352 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500353 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500354 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500355 *fTestExecuteValue = 2;
356 }
357
358 int* fTestExecuteValue;
359 sk_sp<GrSurfaceProxy> fLazyProxy;
360
361 typedef GrDrawOp INHERITED;
362};
363
364// Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was
365// associated with.
366DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) {
367 GrMockOptions mockOptions;
368 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500369 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500370 for (bool failInstantiation : {false, true}) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500371 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400372 SkBackingFit::kExact, 100, 100, GrColorType::kRGBA_8888, nullptr);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500373 REPORTER_ASSERT(reporter, rtc);
374
Brian Osman9a9baae2018-11-05 15:06:26 -0500375 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
376 GrRenderTargetContext::CanClearFullscreen::kYes);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500377
378 int executeTestValue = 0;
Robert Phillips88a32ef2018-06-07 11:05:56 -0400379 rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make(
380 ctx.get(), proxyProvider, &executeTestValue, failInstantiation));
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500381 ctx->flush();
382
383 if (failInstantiation) {
Robert Phillips12c46292019-04-23 07:36:17 -0400384 REPORTER_ASSERT(reporter, 1 == executeTestValue);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500385 } else {
386 REPORTER_ASSERT(reporter, 2 == executeTestValue);
387 }
388 }
Greg Daniel4684f822018-03-08 15:27:36 -0500389}
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500390
Brian Salomon967df202018-12-07 11:15:53 -0500391class LazyDeinstantiateTestOp : public GrDrawOp {
Greg Daniel4684f822018-03-08 15:27:36 -0500392public:
393 DEFINE_OP_CLASS_ID
394
Robert Phillips88a32ef2018-06-07 11:05:56 -0400395 static std::unique_ptr<GrDrawOp> Make(GrContext* context, sk_sp<GrTextureProxy> proxy) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500396 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400397
Brian Salomon967df202018-12-07 11:15:53 -0500398 return pool->allocate<LazyDeinstantiateTestOp>(std::move(proxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500399 }
400
Chris Dalton1706cbf2019-05-21 19:35:29 -0600401 void visitProxies(const VisitProxyFunc& func) const override {
Chris Dalton7eb5c0f2019-05-23 15:15:47 -0600402 func(fLazyProxy.get(), GrMipMapped::kNo);
Greg Daniel4684f822018-03-08 15:27:36 -0500403 }
404
405private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400406 friend class GrOpMemoryPool; // for ctor
407
Brian Salomon967df202018-12-07 11:15:53 -0500408 LazyDeinstantiateTestOp(sk_sp<GrTextureProxy> proxy)
409 : INHERITED(ClassID()), fLazyProxy(std::move(proxy)) {
Robert Phillips88a32ef2018-06-07 11:05:56 -0400410 this->setBounds(SkRect::MakeIWH(kSize, kSize), HasAABloat::kNo, IsZeroArea::kNo);
411 }
412
Brian Salomon967df202018-12-07 11:15:53 -0500413 const char* name() const override { return "LazyDeinstantiateTestOp"; }
Greg Daniel4684f822018-03-08 15:27:36 -0500414 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600415 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
416 bool hasMixedSampledCoverage, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700417 return GrProcessorSet::EmptySetAnalysis();
Greg Daniel4684f822018-03-08 15:27:36 -0500418 }
Greg Daniel4684f822018-03-08 15:27:36 -0500419 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500420 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {}
Greg Daniel4684f822018-03-08 15:27:36 -0500421
422 sk_sp<GrSurfaceProxy> fLazyProxy;
423
424 typedef GrDrawOp INHERITED;
425};
426
Brian Salomon967df202018-12-07 11:15:53 -0500427static void DeinstantiateReleaseProc(void* releaseValue) { (*static_cast<int*>(releaseValue))++; }
Greg Daniel4684f822018-03-08 15:27:36 -0500428
Brian Salomon967df202018-12-07 11:15:53 -0500429// Test that lazy proxies with the Deinstantiate LazyCallbackType are deinstantiated and released as
Greg Daniel4684f822018-03-08 15:27:36 -0500430// expected.
Brian Salomon967df202018-12-07 11:15:53 -0500431DEF_GPUTEST(LazyProxyDeinstantiateTest, reporter, /* options */) {
Greg Daniel4684f822018-03-08 15:27:36 -0500432 GrMockOptions mockOptions;
433 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500434 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Greg Daniel4684f822018-03-08 15:27:36 -0500435
Greg Daniel4065d452018-11-16 15:43:41 -0500436 GrBackendFormat format =
Greg Daniel627d0532019-07-08 16:48:14 -0400437 ctx->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
Greg Daniel4065d452018-11-16 15:43:41 -0500438
Greg Daniel4684f822018-03-08 15:27:36 -0500439 using LazyType = GrSurfaceProxy::LazyInstantiationType;
Brian Salomon876a0172019-03-08 11:12:14 -0500440 for (auto lazyType : {LazyType::kSingleUse, LazyType::kMultipleUse, LazyType::kDeinstantiate}) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500441 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400442 SkBackingFit::kExact, 100, 100, GrColorType::kRGBA_8888, nullptr);
Greg Daniel4684f822018-03-08 15:27:36 -0500443 REPORTER_ASSERT(reporter, rtc);
444
Brian Osman9a9baae2018-11-05 15:06:26 -0500445 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
446 GrRenderTargetContext::CanClearFullscreen::kYes);
Greg Daniel4684f822018-03-08 15:27:36 -0500447
448 int instantiateTestValue = 0;
449 int releaseTestValue = 0;
450 int* instantiatePtr = &instantiateTestValue;
451 int* releasePtr = &releaseTestValue;
452 GrSurfaceDesc desc;
453 desc.fWidth = kSize;
454 desc.fHeight = kSize;
455 desc.fConfig = kRGBA_8888_GrPixelConfig;
456
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400457 GrBackendTexture backendTex = ctx->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400458 kSize, kSize, kRGBA_8888_SkColorType, SkColors::kTransparent,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400459 GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Greg Daniel4684f822018-03-08 15:27:36 -0500460
461 sk_sp<GrTextureProxy> lazyProxy = proxyProvider->createLazyProxy(
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400462 [instantiatePtr, releasePtr,
463 backendTex](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500464 sk_sp<GrTexture> texture =
Robert Phillips97256382019-07-17 15:26:36 -0400465 rp->wrapBackendTexture(backendTex, GrColorType::kRGBA_8888,
466 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
467 kRead_GrIOType);
Greg Daniel4684f822018-03-08 15:27:36 -0500468 if (!texture) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400469 return {};
Greg Daniel4684f822018-03-08 15:27:36 -0500470 }
471 (*instantiatePtr)++;
Brian Salomon967df202018-12-07 11:15:53 -0500472 texture->setRelease(DeinstantiateReleaseProc, releasePtr);
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400473 return std::move(texture);
Greg Daniel4684f822018-03-08 15:27:36 -0500474 },
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400475 format, desc, GrRenderable::kNo, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
Brian Salomonc67c31c2018-12-06 10:00:03 -0500476 GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel4684f822018-03-08 15:27:36 -0500477
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400478 REPORTER_ASSERT(reporter, lazyProxy.get());
479
Brian Salomon967df202018-12-07 11:15:53 -0500480 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500481
482 ctx->flush();
483
484 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
Brian Salomon876a0172019-03-08 11:12:14 -0500485 if (LazyType::kDeinstantiate == lazyType) {
486 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
487 } else {
488 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
489 }
Greg Daniel4684f822018-03-08 15:27:36 -0500490
491 // This should cause the uninstantiate proxies to be instantiated again but have no effect
492 // on the others
Brian Salomon967df202018-12-07 11:15:53 -0500493 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500494 // Add a second op to make sure we only instantiate once.
Brian Salomon967df202018-12-07 11:15:53 -0500495 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500496 ctx->flush();
497
Brian Salomon876a0172019-03-08 11:12:14 -0500498 if (LazyType::kDeinstantiate == lazyType) {
499 REPORTER_ASSERT(reporter, 2 == instantiateTestValue);
500 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
501 } else {
502 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
503 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
504 }
Greg Daniel4684f822018-03-08 15:27:36 -0500505
506 lazyProxy.reset();
Brian Salomon876a0172019-03-08 11:12:14 -0500507 if (LazyType::kDeinstantiate == lazyType) {
508 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
509 } else {
510 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
511 }
Greg Daniel4684f822018-03-08 15:27:36 -0500512
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400513 ctx->deleteBackendTexture(backendTex);
Greg Daniel4684f822018-03-08 15:27:36 -0500514 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500515}