blob: 4e7b2317312ca608b3f87302eb12faa378454b18 [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"
12#include "include/private/GrSurfaceProxy.h"
13#include "include/private/GrTextureProxy.h"
14#include "src/core/SkExchange.h"
15#include "src/core/SkMakeUnique.h"
16#include "src/core/SkRectPriv.h"
17#include "src/gpu/GrClip.h"
18#include "src/gpu/GrContextPriv.h"
19#include "src/gpu/GrMemoryPool.h"
20#include "src/gpu/GrOnFlushResourceProvider.h"
21#include "src/gpu/GrProxyProvider.h"
22#include "src/gpu/GrRecordingContextPriv.h"
23#include "src/gpu/GrRenderTargetContext.h"
24#include "src/gpu/GrRenderTargetContextPriv.h"
25#include "src/gpu/GrSurfaceProxyPriv.h"
26#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
Brian Salomon7d94bb52018-10-12 14:37:19 -040069 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillips88a32ef2018-06-07 11:05:56 -040070 func(fProxy.get());
71 }
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 =
Robert Phillips9da87e02019-02-04 13:26:26 -050085 ctx->priv().caps()->getBackendFormatFromColorType(kRGB_565_SkColorType);
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;
Robert Phillips9313aa72019-04-09 18:41:27 -040098 sk_sp<GrTexture> texture = rp->createTexture(
99 desc, SkBudgeted::kYes, GrResourceProvider::Flags::kNoPendingIO);
Chris Dalton4c458b12018-06-16 17:22:59 -0600100 REPORTER_ASSERT(fTest->fReporter, texture);
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400101 return std::move(texture);
Chris Dalton4c458b12018-06-16 17:22:59 -0600102 }
103 },
Greg Daniel4065d452018-11-16 15:43:41 -0500104 format, GrProxyProvider::Renderable::kNo, kTopLeft_GrSurfaceOrigin,
Chris Dalton4c458b12018-06-16 17:22:59 -0600105 kRGB_565_GrPixelConfig, *proxyProvider->caps());
106
107 this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo,
108 GrOp::IsZeroArea::kNo);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700109 }
110
Chris Dalton706a6ff2017-11-29 22:01:06 -0700111 const char* name() const override { return "LazyProxyTest::Op"; }
112 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Chris Daltonb8fff0d2019-03-05 10:11:58 -0700113 GrProcessorSet::Analysis finalize(
Robert Phillips39667382019-04-17 16:03:30 -0400114 const GrCaps&, const GrAppliedClip* clip, GrFSAAType, GrClampType) override {
115 if (clip) {
116 for (int i = 0; i < clip->numClipCoverageFragmentProcessors(); ++i) {
117 const GrFragmentProcessor* clipFP = clip->clipCoverageFragmentProcessor(i);
118 clipFP->markPendingExecution();
119 }
120 }
Chris Dalton4b62aed2019-01-15 11:53:00 -0700121 return GrProcessorSet::EmptySetAnalysis();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700122 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700123 void onPrepare(GrOpFlushState*) override {}
124
125 LazyProxyTest* const fTest;
126 sk_sp<GrTextureProxy> fProxy;
127 };
128
129 class ClipFP : public GrFragmentProcessor {
130 public:
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500131 ClipFP(GrRecordingContext* ctx, GrProxyProvider* proxyProvider, LazyProxyTest* test,
Greg Daniel4065d452018-11-16 15:43:41 -0500132 GrTextureProxy* atlas)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700133 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
Greg Daniel4065d452018-11-16 15:43:41 -0500134 , fContext(ctx)
Robert Phillips777707b2018-01-17 11:40:14 -0500135 , fProxyProvider(proxyProvider)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700136 , fTest(test)
137 , fAtlas(atlas) {
Greg Daniel4065d452018-11-16 15:43:41 -0500138 const GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500139 ctx->priv().caps()->getBackendFormatFromGrColorType(GrColorType::kAlpha_F16,
140 GrSRGBEncoded::kNo);
Chris Dalton4c458b12018-06-16 17:22:59 -0600141 fLazyProxy = GrProxyProvider::MakeFullyLazyProxy(
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400142 [this](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
143 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
144 fTest->fHasClipTexture = true;
145 fAtlas->instantiate(rp);
146 return sk_ref_sp(fAtlas->peekTexture());
147 },
148 format, GrProxyProvider::Renderable::kYes, kBottomLeft_GrSurfaceOrigin,
149 kAlpha_half_GrPixelConfig, *proxyProvider->caps());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700150 fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
Brian Salomone782f842018-07-31 13:53:11 -0400151 GrSamplerState::WrapMode::kClamp);
Brian Salomonf7dcd762018-07-30 14:48:15 -0400152 this->setTextureSamplerCnt(1);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700153 }
154
155 private:
156 const char* name() const override { return "LazyProxyTest::ClipFP"; }
157 std::unique_ptr<GrFragmentProcessor> clone() const override {
Greg Daniel4065d452018-11-16 15:43:41 -0500158 return skstd::make_unique<ClipFP>(fContext, fProxyProvider, fTest, fAtlas);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700159 }
160 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
161 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
162 bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400163 const TextureSampler& onTextureSampler(int) const override { return fAccess; }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700164
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500165 GrRecordingContext* const fContext;
Robert Phillips777707b2018-01-17 11:40:14 -0500166 GrProxyProvider* const fProxyProvider;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700167 LazyProxyTest* const fTest;
168 GrTextureProxy* const fAtlas;
169 sk_sp<GrTextureProxy> fLazyProxy;
170 TextureSampler fAccess;
171 };
172
173
174 class Clip : public GrClip {
175 public:
176 Clip(LazyProxyTest* test, GrTextureProxy* atlas)
177 : fTest(test)
178 , fAtlas(atlas) {}
179
180 private:
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500181 bool apply(GrRecordingContext* context, GrRenderTargetContext*, bool useHWAA,
182 bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override {
Robert Phillips9da87e02019-02-04 13:26:26 -0500183 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Greg Daniel4065d452018-11-16 15:43:41 -0500184 out->addCoverageFP(skstd::make_unique<ClipFP>(context, proxyProvider, fTest, fAtlas));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700185 return true;
186 }
187 bool quickContains(const SkRect&) const final { return false; }
188 bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
189 void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
190 rect->set(0, 0, width, height);
191 if (iior) {
192 *iior = false;
193 }
194 }
195
196 LazyProxyTest* const fTest;
197 GrTextureProxy* fAtlas;
198 };
199
200private:
201 skiatest::Reporter* fReporter;
202 bool fHasOpTexture;
203 bool fHasClipTexture;
204};
205
206DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
207 GrMockOptions mockOptions;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500208 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderability =
209 GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700210 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true;
211 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500212 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700213 for (bool nullTexture : {false, true}) {
214 LazyProxyTest test(reporter);
Robert Phillips9da87e02019-02-04 13:26:26 -0500215 ctx->priv().addOnFlushCallbackObject(&test);
Greg Daniel4065d452018-11-16 15:43:41 -0500216 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500217 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
218 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500219 format, SkBackingFit::kExact, 100, 100,
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500220 kRGBA_8888_GrPixelConfig, nullptr);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700221 REPORTER_ASSERT(reporter, rtc);
Greg Daniel4065d452018-11-16 15:43:41 -0500222 format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500223 ctx->priv().caps()->getBackendFormatFromGrColorType(GrColorType::kAlpha_F16,
Greg Daniel4065d452018-11-16 15:43:41 -0500224 GrSRGBEncoded::kNo);
Robert Phillips9da87e02019-02-04 13:26:26 -0500225 sk_sp<GrRenderTargetContext> mockAtlas = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500226 format, SkBackingFit::kExact, 10, 10,
Chris Dalton706a6ff2017-11-29 22:01:06 -0700227 kAlpha_half_GrPixelConfig, nullptr);
228 REPORTER_ASSERT(reporter, mockAtlas);
229 rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
Robert Phillips88a32ef2018-06-07 11:05:56 -0400230 LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
Robert Phillips9da87e02019-02-04 13:26:26 -0500231 ctx->priv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700232 }
233}
234
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500235static const int kSize = 16;
236
Greg Daniel94a6ce82018-01-16 16:14:41 -0500237DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
238 GrMockOptions mockOptions;
239 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500240 auto proxyProvider = ctx->priv().proxyProvider();
Greg Daniel94a6ce82018-01-16 16:14:41 -0500241
242 GrSurfaceDesc desc;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500243 desc.fWidth = kSize;
244 desc.fHeight = kSize;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500245 desc.fConfig = kRGBA_8888_GrPixelConfig;
246
Greg Daniel4065d452018-11-16 15:43:41 -0500247 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500248 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Daniel4065d452018-11-16 15:43:41 -0500249
Greg Daniel457469c2018-02-08 15:05:44 -0500250 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400251 using LazyInstantiationResult = GrSurfaceProxy::LazyInstantiationResult;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500252 for (bool doInstantiate : {true, false}) {
Brian Salomon876a0172019-03-08 11:12:14 -0500253 for (auto lazyType : {LazyInstantiationType::kSingleUse,
254 LazyInstantiationType::kMultipleUse,
255 LazyInstantiationType::kDeinstantiate}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500256 int testCount = 0;
Brian Salomon67f01952019-02-14 13:05:25 -0500257 // Sets an integer to 1 when the callback is called and -1 when it is deleted.
258 class TestCallback {
259 public:
260 TestCallback(int* value) : fValue(value) {}
261 TestCallback(const TestCallback& that) { SkASSERT(0); }
262 TestCallback(TestCallback&& that) : fValue(that.fValue) { that.fValue = nullptr; }
263
264 ~TestCallback() { fValue ? (void)(*fValue = -1) : void(); }
265
266 TestCallback& operator=(TestCallback&& that) {
267 fValue = skstd::exchange(that.fValue, nullptr);
268 return *this;
269 }
270 TestCallback& operator=(const TestCallback& that) = delete;
271
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400272 LazyInstantiationResult operator()(GrResourceProvider* resourceProvider) const {
Brian Salomon67f01952019-02-14 13:05:25 -0500273 *fValue = 1;
274 return {};
275 }
276
277 private:
278 int* fValue = nullptr;
279 };
Greg Daniel457469c2018-02-08 15:05:44 -0500280 sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
Brian Salomon67f01952019-02-14 13:05:25 -0500281 TestCallback(&testCount), format, desc, kTopLeft_GrSurfaceOrigin,
282 GrMipMapped::kNo, GrInternalSurfaceFlags::kNone, SkBackingFit::kExact,
283 SkBudgeted::kNo, lazyType);
Greg Daniel94a6ce82018-01-16 16:14:41 -0500284
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400285 REPORTER_ASSERT(reporter, proxy.get());
Greg Daniel457469c2018-02-08 15:05:44 -0500286 REPORTER_ASSERT(reporter, 0 == testCount);
287
288 if (doInstantiate) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500289 proxy->priv().doLazyInstantiation(ctx->priv().resourceProvider());
Greg Daniel457469c2018-02-08 15:05:44 -0500290 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
291 // In SingleUse we will call the cleanup and delete the callback in the
292 // doLazyInstantiationCall.
293 REPORTER_ASSERT(reporter, -1 == testCount);
294 } else {
295 REPORTER_ASSERT(reporter, 1 == testCount);
296 }
297 proxy.reset();
298 REPORTER_ASSERT(reporter, -1 == testCount);
299 } else {
300 proxy.reset();
301 REPORTER_ASSERT(reporter, -1 == testCount);
302 }
Greg Daniel94a6ce82018-01-16 16:14:41 -0500303 }
304 }
305}
306
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500307class LazyFailedInstantiationTestOp : public GrDrawOp {
308public:
309 DEFINE_OP_CLASS_ID
310
Robert Phillips88a32ef2018-06-07 11:05:56 -0400311 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
312 GrProxyProvider* proxyProvider,
313 int* testExecuteValue,
314 bool shouldFailInstantiation) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500315 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400316
Greg Daniel4065d452018-11-16 15:43:41 -0500317 return pool->allocate<LazyFailedInstantiationTestOp>(context, proxyProvider,
Robert Phillipsc994a932018-06-19 13:09:54 -0400318 testExecuteValue,
319 shouldFailInstantiation);
Robert Phillips88a32ef2018-06-07 11:05:56 -0400320 }
321
Brian Salomon7d94bb52018-10-12 14:37:19 -0400322 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillips88a32ef2018-06-07 11:05:56 -0400323 func(fLazyProxy.get());
324 }
325
326private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400327 friend class GrOpMemoryPool; // for ctor
328
Greg Daniel4065d452018-11-16 15:43:41 -0500329 LazyFailedInstantiationTestOp(GrContext* ctx, GrProxyProvider* proxyProvider,
330 int* testExecuteValue, bool shouldFailInstantiation)
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500331 : INHERITED(ClassID())
332 , fTestExecuteValue(testExecuteValue) {
333 GrSurfaceDesc desc;
334 desc.fWidth = kSize;
335 desc.fHeight = kSize;
336 desc.fConfig = kRGBA_8888_GrPixelConfig;
Greg Daniel4065d452018-11-16 15:43:41 -0500337 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500338 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500339
340 fLazyProxy = proxyProvider->createLazyProxy(
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400341 [testExecuteValue, shouldFailInstantiation,
342 desc](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
Greg Daniel0a375db2018-02-01 12:21:39 -0500343 if (shouldFailInstantiation) {
344 *testExecuteValue = 1;
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400345 return {};
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500346 }
Robert Phillips9313aa72019-04-09 18:41:27 -0400347 return {rp->createTexture(desc, SkBudgeted::kNo,
348 GrResourceProvider::Flags::kNoPendingIO),
Brian Salomon01ceae92019-04-02 11:49:54 -0400349 GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced};
Brian Salomon2a4f9832018-03-03 22:43:43 -0500350 },
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400351 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kExact,
352 SkBudgeted::kNo);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500353
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400354 SkASSERT(fLazyProxy.get());
355
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500356 this->setBounds(SkRect::MakeIWH(kSize, kSize),
357 HasAABloat::kNo, IsZeroArea::kNo);
358 }
359
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500360 const char* name() const override { return "LazyFailedInstantiationTestOp"; }
361 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman5ced0bf2019-03-15 10:15:29 -0400362 GrProcessorSet::Analysis finalize(
363 const GrCaps&, const GrAppliedClip*, GrFSAAType, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700364 return GrProcessorSet::EmptySetAnalysis();
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500365 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500366 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500367 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500368 *fTestExecuteValue = 2;
369 }
370
371 int* fTestExecuteValue;
372 sk_sp<GrSurfaceProxy> fLazyProxy;
373
374 typedef GrDrawOp INHERITED;
375};
376
377// Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was
378// associated with.
379DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) {
380 GrMockOptions mockOptions;
381 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500382 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Greg Daniel4065d452018-11-16 15:43:41 -0500383 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500384 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500385 for (bool failInstantiation : {false, true}) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500386 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500387 format, SkBackingFit::kExact, 100, 100,
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500388 kRGBA_8888_GrPixelConfig, nullptr);
389 REPORTER_ASSERT(reporter, rtc);
390
Brian Osman9a9baae2018-11-05 15:06:26 -0500391 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
392 GrRenderTargetContext::CanClearFullscreen::kYes);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500393
394 int executeTestValue = 0;
Robert Phillips88a32ef2018-06-07 11:05:56 -0400395 rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make(
396 ctx.get(), proxyProvider, &executeTestValue, failInstantiation));
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500397 ctx->flush();
398
399 if (failInstantiation) {
Robert Phillips12c46292019-04-23 07:36:17 -0400400 REPORTER_ASSERT(reporter, 1 == executeTestValue);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500401 } else {
402 REPORTER_ASSERT(reporter, 2 == executeTestValue);
403 }
404 }
Greg Daniel4684f822018-03-08 15:27:36 -0500405}
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500406
Brian Salomon967df202018-12-07 11:15:53 -0500407class LazyDeinstantiateTestOp : public GrDrawOp {
Greg Daniel4684f822018-03-08 15:27:36 -0500408public:
409 DEFINE_OP_CLASS_ID
410
Robert Phillips88a32ef2018-06-07 11:05:56 -0400411 static std::unique_ptr<GrDrawOp> Make(GrContext* context, sk_sp<GrTextureProxy> proxy) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500412 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400413
Brian Salomon967df202018-12-07 11:15:53 -0500414 return pool->allocate<LazyDeinstantiateTestOp>(std::move(proxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500415 }
416
Brian Salomon7d94bb52018-10-12 14:37:19 -0400417 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Greg Daniel4684f822018-03-08 15:27:36 -0500418 func(fLazyProxy.get());
419 }
420
421private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400422 friend class GrOpMemoryPool; // for ctor
423
Brian Salomon967df202018-12-07 11:15:53 -0500424 LazyDeinstantiateTestOp(sk_sp<GrTextureProxy> proxy)
425 : INHERITED(ClassID()), fLazyProxy(std::move(proxy)) {
Robert Phillips88a32ef2018-06-07 11:05:56 -0400426 this->setBounds(SkRect::MakeIWH(kSize, kSize), HasAABloat::kNo, IsZeroArea::kNo);
427 }
428
Brian Salomon967df202018-12-07 11:15:53 -0500429 const char* name() const override { return "LazyDeinstantiateTestOp"; }
Greg Daniel4684f822018-03-08 15:27:36 -0500430 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman5ced0bf2019-03-15 10:15:29 -0400431 GrProcessorSet::Analysis finalize(
432 const GrCaps&, const GrAppliedClip*, GrFSAAType, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700433 return GrProcessorSet::EmptySetAnalysis();
Greg Daniel4684f822018-03-08 15:27:36 -0500434 }
Greg Daniel4684f822018-03-08 15:27:36 -0500435 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500436 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {}
Greg Daniel4684f822018-03-08 15:27:36 -0500437
438 sk_sp<GrSurfaceProxy> fLazyProxy;
439
440 typedef GrDrawOp INHERITED;
441};
442
Brian Salomon967df202018-12-07 11:15:53 -0500443static void DeinstantiateReleaseProc(void* releaseValue) { (*static_cast<int*>(releaseValue))++; }
Greg Daniel4684f822018-03-08 15:27:36 -0500444
Brian Salomon967df202018-12-07 11:15:53 -0500445// Test that lazy proxies with the Deinstantiate LazyCallbackType are deinstantiated and released as
Greg Daniel4684f822018-03-08 15:27:36 -0500446// expected.
Brian Salomon967df202018-12-07 11:15:53 -0500447DEF_GPUTEST(LazyProxyDeinstantiateTest, reporter, /* options */) {
Greg Daniel4684f822018-03-08 15:27:36 -0500448 GrMockOptions mockOptions;
449 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500450 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Greg Daniel4684f822018-03-08 15:27:36 -0500451
Greg Daniel4065d452018-11-16 15:43:41 -0500452 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500453 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Daniel4065d452018-11-16 15:43:41 -0500454
Greg Daniel4684f822018-03-08 15:27:36 -0500455 using LazyType = GrSurfaceProxy::LazyInstantiationType;
Brian Salomon876a0172019-03-08 11:12:14 -0500456 for (auto lazyType : {LazyType::kSingleUse, LazyType::kMultipleUse, LazyType::kDeinstantiate}) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500457 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500458 format, SkBackingFit::kExact, 100, 100,
Greg Daniel4684f822018-03-08 15:27:36 -0500459 kRGBA_8888_GrPixelConfig, nullptr);
460 REPORTER_ASSERT(reporter, rtc);
461
Brian Osman9a9baae2018-11-05 15:06:26 -0500462 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
463 GrRenderTargetContext::CanClearFullscreen::kYes);
Greg Daniel4684f822018-03-08 15:27:36 -0500464
465 int instantiateTestValue = 0;
466 int releaseTestValue = 0;
467 int* instantiatePtr = &instantiateTestValue;
468 int* releasePtr = &releaseTestValue;
469 GrSurfaceDesc desc;
470 desc.fWidth = kSize;
471 desc.fHeight = kSize;
472 desc.fConfig = kRGBA_8888_GrPixelConfig;
473
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400474 GrBackendTexture backendTex = ctx->createBackendTexture(
Robert Phillips9dbcdcc2019-05-13 10:40:06 -0400475 kSize, kSize, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo);
Greg Daniel4684f822018-03-08 15:27:36 -0500476
477 sk_sp<GrTextureProxy> lazyProxy = proxyProvider->createLazyProxy(
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400478 [instantiatePtr, releasePtr,
479 backendTex](GrResourceProvider* rp) -> GrSurfaceProxy::LazyInstantiationResult {
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500480 sk_sp<GrTexture> texture =
481 rp->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500482 GrWrapCacheable::kNo, kRead_GrIOType);
Greg Daniel4684f822018-03-08 15:27:36 -0500483 if (!texture) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400484 return {};
Greg Daniel4684f822018-03-08 15:27:36 -0500485 }
486 (*instantiatePtr)++;
Brian Salomon967df202018-12-07 11:15:53 -0500487 texture->setRelease(DeinstantiateReleaseProc, releasePtr);
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400488 return std::move(texture);
Greg Daniel4684f822018-03-08 15:27:36 -0500489 },
Greg Daniel4065d452018-11-16 15:43:41 -0500490 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
Brian Salomonc67c31c2018-12-06 10:00:03 -0500491 GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel4684f822018-03-08 15:27:36 -0500492
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400493 REPORTER_ASSERT(reporter, lazyProxy.get());
494
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
497 ctx->flush();
498
499 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
Brian Salomon876a0172019-03-08 11:12:14 -0500500 if (LazyType::kDeinstantiate == lazyType) {
501 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
502 } else {
503 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
504 }
Greg Daniel4684f822018-03-08 15:27:36 -0500505
506 // This should cause the uninstantiate proxies to be instantiated again but have no effect
507 // on the others
Brian Salomon967df202018-12-07 11:15:53 -0500508 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500509 // Add a second op to make sure we only instantiate once.
Brian Salomon967df202018-12-07 11:15:53 -0500510 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500511 ctx->flush();
512
Brian Salomon876a0172019-03-08 11:12:14 -0500513 if (LazyType::kDeinstantiate == lazyType) {
514 REPORTER_ASSERT(reporter, 2 == instantiateTestValue);
515 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
516 } else {
517 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
518 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
519 }
Greg Daniel4684f822018-03-08 15:27:36 -0500520
521 lazyProxy.reset();
Brian Salomon876a0172019-03-08 11:12:14 -0500522 if (LazyType::kDeinstantiate == lazyType) {
523 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
524 } else {
525 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
526 }
Greg Daniel4684f822018-03-08 15:27:36 -0500527
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400528 ctx->deleteBackendTexture(backendTex);
Greg Daniel4684f822018-03-08 15:27:36 -0500529 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500530}