blob: e3fa1b83739f8152046655a128608cae55e14cb4 [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"
Robert Phillips7c525e62018-06-12 10:11:12 -040011#include "GrMemoryPool.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070012#include "GrOnFlushResourceProvider.h"
Robert Phillips7c525e62018-06-12 10:11:12 -040013#include "GrProxyProvider.h"
Robert Phillips6f0e02f2019-02-13 11:02:28 -050014#include "GrRecordingContextPriv.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"
Brian Salomon67f01952019-02-14 13:05:25 -050022#include "SkExchange.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070023#include "SkMakeUnique.h"
Mike Reed274218e2018-01-08 15:05:02 -050024#include "SkRectPriv.h"
Greg Daniel4684f822018-03-08 15:27:36 -050025#include "mock/GrMockGpu.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070026#include "mock/GrMockTypes.h"
27
28// This test verifies that lazy proxy callbacks get invoked during flush, after onFlush callbacks,
29// but before Ops are executed. It also ensures that lazy proxy callbacks are invoked both for
30// regular Ops and for clips.
31class LazyProxyTest final : public GrOnFlushCallbackObject {
32public:
33 LazyProxyTest(skiatest::Reporter* reporter)
34 : fReporter(reporter)
35 , fHasOpTexture(false)
36 , fHasClipTexture(false) {
37 }
38
39 ~LazyProxyTest() override {
40 REPORTER_ASSERT(fReporter, fHasOpTexture);
41 REPORTER_ASSERT(fReporter, fHasClipTexture);
42 }
43
44 void preFlush(GrOnFlushResourceProvider*, const uint32_t*, int,
45 SkTArray<sk_sp<GrRenderTargetContext>>*) override {
46 REPORTER_ASSERT(fReporter, !fHasOpTexture);
47 REPORTER_ASSERT(fReporter, !fHasClipTexture);
48 }
49
50 void postFlush(GrDeferredUploadToken, const uint32_t* opListIDs, int numOpListIDs) override {
51 REPORTER_ASSERT(fReporter, fHasOpTexture);
52 REPORTER_ASSERT(fReporter, fHasClipTexture);
53 }
54
55 class Op final : public GrDrawOp {
56 public:
57 DEFINE_OP_CLASS_ID
58
Robert Phillips6f0e02f2019-02-13 11:02:28 -050059 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips88a32ef2018-06-07 11:05:56 -040060 GrProxyProvider* proxyProvider,
61 LazyProxyTest* test,
62 bool nullTexture) {
Robert Phillips9da87e02019-02-04 13:26:26 -050063 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -040064
Greg Daniel4065d452018-11-16 15:43:41 -050065 return pool->allocate<Op>(context, proxyProvider, test, nullTexture);
Robert Phillips88a32ef2018-06-07 11:05:56 -040066 }
67
Brian Salomon7d94bb52018-10-12 14:37:19 -040068 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillips88a32ef2018-06-07 11:05:56 -040069 func(fProxy.get());
70 }
71
Brian Salomon588cec72018-11-14 13:56:37 -050072 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override {
Robert Phillips88a32ef2018-06-07 11:05:56 -040073 REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
74 REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
75 }
76
77 private:
Robert Phillips7c525e62018-06-12 10:11:12 -040078 friend class GrOpMemoryPool; // for ctor
79
Robert Phillips6f0e02f2019-02-13 11:02:28 -050080 Op(GrRecordingContext* ctx, GrProxyProvider* proxyProvider,
81 LazyProxyTest* test, bool nullTexture)
Robert Phillips777707b2018-01-17 11:40:14 -050082 : GrDrawOp(ClassID()), fTest(test) {
Greg Daniel4065d452018-11-16 15:43:41 -050083 const GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -050084 ctx->priv().caps()->getBackendFormatFromColorType(kRGB_565_SkColorType);
Chris Dalton4c458b12018-06-16 17:22:59 -060085 fProxy = GrProxyProvider::MakeFullyLazyProxy(
86 [this, nullTexture](GrResourceProvider* rp) {
87 if (!rp) {
88 return sk_sp<GrTexture>();
89 }
90 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture);
91 fTest->fHasOpTexture = true;
92 if (nullTexture) {
93 return sk_sp<GrTexture>();
94 } else {
95 GrSurfaceDesc desc;
96 desc.fWidth = 1234;
97 desc.fHeight = 567;
98 desc.fConfig = kRGB_565_GrPixelConfig;
99 sk_sp<GrTexture> texture = rp->createTexture(desc, SkBudgeted::kYes);
100 REPORTER_ASSERT(fTest->fReporter, texture);
101 return texture;
102 }
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 Dalton4b62aed2019-01-15 11:53:00 -0700113 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*) override {
114 return GrProcessorSet::EmptySetAnalysis();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700115 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700116 void onPrepare(GrOpFlushState*) override {}
117
118 LazyProxyTest* const fTest;
119 sk_sp<GrTextureProxy> fProxy;
120 };
121
122 class ClipFP : public GrFragmentProcessor {
123 public:
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500124 ClipFP(GrRecordingContext* ctx, GrProxyProvider* proxyProvider, LazyProxyTest* test,
Greg Daniel4065d452018-11-16 15:43:41 -0500125 GrTextureProxy* atlas)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700126 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
Greg Daniel4065d452018-11-16 15:43:41 -0500127 , fContext(ctx)
Robert Phillips777707b2018-01-17 11:40:14 -0500128 , fProxyProvider(proxyProvider)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700129 , fTest(test)
130 , fAtlas(atlas) {
Greg Daniel4065d452018-11-16 15:43:41 -0500131 const GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500132 ctx->priv().caps()->getBackendFormatFromGrColorType(GrColorType::kAlpha_F16,
133 GrSRGBEncoded::kNo);
Chris Dalton4c458b12018-06-16 17:22:59 -0600134 fLazyProxy = GrProxyProvider::MakeFullyLazyProxy(
Robert Phillipsce5209a2018-02-13 11:13:51 -0500135 [this](GrResourceProvider* rp) {
136 if (!rp) {
137 return sk_sp<GrTexture>();
138 }
139 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
140 fTest->fHasClipTexture = true;
141 fAtlas->instantiate(rp);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400142 return sk_ref_sp(fAtlas->peekTexture());
Robert Phillipsce5209a2018-02-13 11:13:51 -0500143 },
Greg Daniel4065d452018-11-16 15:43:41 -0500144 format,
Robert Phillipsce5209a2018-02-13 11:13:51 -0500145 GrProxyProvider::Renderable::kYes,
146 kBottomLeft_GrSurfaceOrigin,
Chris Dalton4c458b12018-06-16 17:22:59 -0600147 kAlpha_half_GrPixelConfig, *proxyProvider->caps());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700148 fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
Brian Salomone782f842018-07-31 13:53:11 -0400149 GrSamplerState::WrapMode::kClamp);
Brian Salomonf7dcd762018-07-30 14:48:15 -0400150 this->setTextureSamplerCnt(1);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700151 }
152
153 private:
154 const char* name() const override { return "LazyProxyTest::ClipFP"; }
155 std::unique_ptr<GrFragmentProcessor> clone() const override {
Greg Daniel4065d452018-11-16 15:43:41 -0500156 return skstd::make_unique<ClipFP>(fContext, fProxyProvider, fTest, fAtlas);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700157 }
158 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
159 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
160 bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400161 const TextureSampler& onTextureSampler(int) const override { return fAccess; }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700162
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500163 GrRecordingContext* const fContext;
Robert Phillips777707b2018-01-17 11:40:14 -0500164 GrProxyProvider* const fProxyProvider;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700165 LazyProxyTest* const fTest;
166 GrTextureProxy* const fAtlas;
167 sk_sp<GrTextureProxy> fLazyProxy;
168 TextureSampler fAccess;
169 };
170
171
172 class Clip : public GrClip {
173 public:
174 Clip(LazyProxyTest* test, GrTextureProxy* atlas)
175 : fTest(test)
176 , fAtlas(atlas) {}
177
178 private:
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500179 bool apply(GrRecordingContext* context, GrRenderTargetContext*, bool useHWAA,
180 bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override {
Robert Phillips9da87e02019-02-04 13:26:26 -0500181 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Greg Daniel4065d452018-11-16 15:43:41 -0500182 out->addCoverageFP(skstd::make_unique<ClipFP>(context, proxyProvider, fTest, fAtlas));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700183 return true;
184 }
185 bool quickContains(const SkRect&) const final { return false; }
186 bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
187 void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
188 rect->set(0, 0, width, height);
189 if (iior) {
190 *iior = false;
191 }
192 }
193
194 LazyProxyTest* const fTest;
195 GrTextureProxy* fAtlas;
196 };
197
198private:
199 skiatest::Reporter* fReporter;
200 bool fHasOpTexture;
201 bool fHasClipTexture;
202};
203
204DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
205 GrMockOptions mockOptions;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500206 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderability =
207 GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700208 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true;
209 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500210 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700211 for (bool nullTexture : {false, true}) {
212 LazyProxyTest test(reporter);
Robert Phillips9da87e02019-02-04 13:26:26 -0500213 ctx->priv().addOnFlushCallbackObject(&test);
Greg Daniel4065d452018-11-16 15:43:41 -0500214 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500215 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
216 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500217 format, SkBackingFit::kExact, 100, 100,
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500218 kRGBA_8888_GrPixelConfig, nullptr);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700219 REPORTER_ASSERT(reporter, rtc);
Greg Daniel4065d452018-11-16 15:43:41 -0500220 format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500221 ctx->priv().caps()->getBackendFormatFromGrColorType(GrColorType::kAlpha_F16,
Greg Daniel4065d452018-11-16 15:43:41 -0500222 GrSRGBEncoded::kNo);
Robert Phillips9da87e02019-02-04 13:26:26 -0500223 sk_sp<GrRenderTargetContext> mockAtlas = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500224 format, SkBackingFit::kExact, 10, 10,
Chris Dalton706a6ff2017-11-29 22:01:06 -0700225 kAlpha_half_GrPixelConfig, nullptr);
226 REPORTER_ASSERT(reporter, mockAtlas);
227 rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
Robert Phillips88a32ef2018-06-07 11:05:56 -0400228 LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
Robert Phillips9da87e02019-02-04 13:26:26 -0500229 ctx->priv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700230 }
231}
232
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500233static const int kSize = 16;
234
Greg Daniel94a6ce82018-01-16 16:14:41 -0500235DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
236 GrMockOptions mockOptions;
237 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500238 auto proxyProvider = ctx->priv().proxyProvider();
Greg Daniel94a6ce82018-01-16 16:14:41 -0500239
240 GrSurfaceDesc desc;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500241 desc.fWidth = kSize;
242 desc.fHeight = kSize;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500243 desc.fConfig = kRGBA_8888_GrPixelConfig;
244
Greg Daniel4065d452018-11-16 15:43:41 -0500245 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500246 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Daniel4065d452018-11-16 15:43:41 -0500247
Greg Daniel457469c2018-02-08 15:05:44 -0500248 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500249 for (bool doInstantiate : {true, false}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500250 for (auto lazyType : {LazyInstantiationType::kSingleUse,
Greg Daniela8d92112018-03-09 12:05:04 -0500251 LazyInstantiationType::kMultipleUse,
Brian Salomon967df202018-12-07 11:15:53 -0500252 LazyInstantiationType::kDeinstantiate}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500253 int testCount = 0;
Brian Salomon67f01952019-02-14 13:05:25 -0500254 // Sets an integer to 1 when the callback is called and -1 when it is deleted.
255 class TestCallback {
256 public:
257 TestCallback(int* value) : fValue(value) {}
258 TestCallback(const TestCallback& that) { SkASSERT(0); }
259 TestCallback(TestCallback&& that) : fValue(that.fValue) { that.fValue = nullptr; }
260
261 ~TestCallback() { fValue ? (void)(*fValue = -1) : void(); }
262
263 TestCallback& operator=(TestCallback&& that) {
264 fValue = skstd::exchange(that.fValue, nullptr);
265 return *this;
266 }
267 TestCallback& operator=(const TestCallback& that) = delete;
268
269 sk_sp<GrSurface> operator()(GrResourceProvider* resourceProvider) const {
270 *fValue = 1;
271 return {};
272 }
273
274 private:
275 int* fValue = nullptr;
276 };
Greg Daniel457469c2018-02-08 15:05:44 -0500277 sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
Brian Salomon67f01952019-02-14 13:05:25 -0500278 TestCallback(&testCount), format, desc, kTopLeft_GrSurfaceOrigin,
279 GrMipMapped::kNo, GrInternalSurfaceFlags::kNone, SkBackingFit::kExact,
280 SkBudgeted::kNo, lazyType);
Greg Daniel94a6ce82018-01-16 16:14:41 -0500281
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400282 REPORTER_ASSERT(reporter, proxy.get());
Greg Daniel457469c2018-02-08 15:05:44 -0500283 REPORTER_ASSERT(reporter, 0 == testCount);
284
285 if (doInstantiate) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500286 proxy->priv().doLazyInstantiation(ctx->priv().resourceProvider());
Greg Daniel457469c2018-02-08 15:05:44 -0500287 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
288 // In SingleUse we will call the cleanup and delete the callback in the
289 // doLazyInstantiationCall.
290 REPORTER_ASSERT(reporter, -1 == testCount);
291 } else {
292 REPORTER_ASSERT(reporter, 1 == testCount);
293 }
294 proxy.reset();
295 REPORTER_ASSERT(reporter, -1 == testCount);
296 } else {
297 proxy.reset();
298 REPORTER_ASSERT(reporter, -1 == testCount);
299 }
Greg Daniel94a6ce82018-01-16 16:14:41 -0500300 }
301 }
302}
303
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500304class LazyFailedInstantiationTestOp : public GrDrawOp {
305public:
306 DEFINE_OP_CLASS_ID
307
Robert Phillips88a32ef2018-06-07 11:05:56 -0400308 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
309 GrProxyProvider* proxyProvider,
310 int* testExecuteValue,
311 bool shouldFailInstantiation) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500312 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400313
Greg Daniel4065d452018-11-16 15:43:41 -0500314 return pool->allocate<LazyFailedInstantiationTestOp>(context, proxyProvider,
Robert Phillipsc994a932018-06-19 13:09:54 -0400315 testExecuteValue,
316 shouldFailInstantiation);
Robert Phillips88a32ef2018-06-07 11:05:56 -0400317 }
318
Brian Salomon7d94bb52018-10-12 14:37:19 -0400319 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillips88a32ef2018-06-07 11:05:56 -0400320 func(fLazyProxy.get());
321 }
322
323private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400324 friend class GrOpMemoryPool; // for ctor
325
Greg Daniel4065d452018-11-16 15:43:41 -0500326 LazyFailedInstantiationTestOp(GrContext* ctx, GrProxyProvider* proxyProvider,
327 int* testExecuteValue, bool shouldFailInstantiation)
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500328 : INHERITED(ClassID())
329 , fTestExecuteValue(testExecuteValue) {
330 GrSurfaceDesc desc;
331 desc.fWidth = kSize;
332 desc.fHeight = kSize;
333 desc.fConfig = kRGBA_8888_GrPixelConfig;
Greg Daniel4065d452018-11-16 15:43:41 -0500334 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500335 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500336
337 fLazyProxy = proxyProvider->createLazyProxy(
Brian Salomon2a4f9832018-03-03 22:43:43 -0500338 [testExecuteValue, shouldFailInstantiation, desc](GrResourceProvider* rp) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500339 if (shouldFailInstantiation) {
340 *testExecuteValue = 1;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500341 return sk_sp<GrTexture>();
342 }
343 return rp->createTexture(desc, SkBudgeted::kNo);
Brian Salomon2a4f9832018-03-03 22:43:43 -0500344 },
Greg Daniel4065d452018-11-16 15:43:41 -0500345 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
Brian Salomon7226c232018-07-30 13:13:17 -0400346 SkBackingFit::kExact, SkBudgeted::kNo);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500347
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400348 SkASSERT(fLazyProxy.get());
349
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500350 this->setBounds(SkRect::MakeIWH(kSize, kSize),
351 HasAABloat::kNo, IsZeroArea::kNo);
352 }
353
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500354 const char* name() const override { return "LazyFailedInstantiationTestOp"; }
355 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Chris Dalton4b62aed2019-01-15 11:53:00 -0700356 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*) override {
357 return GrProcessorSet::EmptySetAnalysis();
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500358 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500359 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500360 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500361 *fTestExecuteValue = 2;
362 }
363
364 int* fTestExecuteValue;
365 sk_sp<GrSurfaceProxy> fLazyProxy;
366
367 typedef GrDrawOp INHERITED;
368};
369
370// Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was
371// associated with.
372DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) {
373 GrMockOptions mockOptions;
374 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500375 GrResourceProvider* resourceProvider = ctx->priv().resourceProvider();
376 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Greg Daniel4065d452018-11-16 15:43:41 -0500377 GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500378 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500379 for (bool failInstantiation : {false, true}) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500380 sk_sp<GrRenderTargetContext> rtc = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500381 format, SkBackingFit::kExact, 100, 100,
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500382 kRGBA_8888_GrPixelConfig, nullptr);
383 REPORTER_ASSERT(reporter, rtc);
384
Brian Osman9a9baae2018-11-05 15:06:26 -0500385 rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
386 GrRenderTargetContext::CanClearFullscreen::kYes);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500387
388 int executeTestValue = 0;
Robert Phillips88a32ef2018-06-07 11:05:56 -0400389 rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make(
390 ctx.get(), proxyProvider, &executeTestValue, failInstantiation));
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500391 ctx->flush();
392
393 if (failInstantiation) {
Robert Phillips4150eea2018-02-07 17:08:21 -0500394 if (resourceProvider->explicitlyAllocateGPUResources()) {
395 REPORTER_ASSERT(reporter, 1 == executeTestValue);
396 } else {
397 // When we disable explicit gpu resource allocation we don't throw away ops that
398 // have uninstantiated proxies.
399 REPORTER_ASSERT(reporter, 2 == executeTestValue);
400 }
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; }
Chris Dalton4b62aed2019-01-15 11:53:00 -0700431 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*) override {
432 return GrProcessorSet::EmptySetAnalysis();
Greg Daniel4684f822018-03-08 15:27:36 -0500433 }
Greg Daniel4684f822018-03-08 15:27:36 -0500434 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500435 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {}
Greg Daniel4684f822018-03-08 15:27:36 -0500436
437 sk_sp<GrSurfaceProxy> fLazyProxy;
438
439 typedef GrDrawOp INHERITED;
440};
441
Brian Salomon967df202018-12-07 11:15:53 -0500442static void DeinstantiateReleaseProc(void* releaseValue) { (*static_cast<int*>(releaseValue))++; }
Greg Daniel4684f822018-03-08 15:27:36 -0500443
Brian Salomon967df202018-12-07 11:15:53 -0500444// Test that lazy proxies with the Deinstantiate LazyCallbackType are deinstantiated and released as
Greg Daniel4684f822018-03-08 15:27:36 -0500445// expected.
Brian Salomon967df202018-12-07 11:15:53 -0500446DEF_GPUTEST(LazyProxyDeinstantiateTest, reporter, /* options */) {
Greg Daniel4684f822018-03-08 15:27:36 -0500447 GrMockOptions mockOptions;
448 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips9da87e02019-02-04 13:26:26 -0500449 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
450 GrGpu* gpu = ctx->priv().getGpu();
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 Salomon967df202018-12-07 11:15:53 -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
474 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
Robert Phillips646f6372018-09-25 09:31:10 -0400475 nullptr, kSize, kSize, GrColorType::kRGBA_8888, false, GrMipMapped::kNo);
Greg Daniel4684f822018-03-08 15:27:36 -0500476
477 sk_sp<GrTextureProxy> lazyProxy = proxyProvider->createLazyProxy(
478 [instantiatePtr, releasePtr, backendTex](GrResourceProvider* rp) {
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500479 sk_sp<GrTexture> texture =
480 rp->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership,
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500481 GrWrapCacheable::kNo, kRead_GrIOType);
Greg Daniel4684f822018-03-08 15:27:36 -0500482 if (!texture) {
483 return sk_sp<GrTexture>();
484 }
485 (*instantiatePtr)++;
Brian Salomon967df202018-12-07 11:15:53 -0500486 texture->setRelease(DeinstantiateReleaseProc, releasePtr);
Greg Daniel4684f822018-03-08 15:27:36 -0500487 return texture;
488 },
Greg Daniel4065d452018-11-16 15:43:41 -0500489 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
Brian Salomonc67c31c2018-12-06 10:00:03 -0500490 GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo, lazyType);
Greg Daniel4684f822018-03-08 15:27:36 -0500491
Greg Daniel92cbf3f2018-04-12 16:50:17 -0400492 REPORTER_ASSERT(reporter, lazyProxy.get());
493
Brian Salomon967df202018-12-07 11:15:53 -0500494 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500495
496 ctx->flush();
497
498 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
Brian Salomon967df202018-12-07 11:15:53 -0500499 if (LazyType::kDeinstantiate == lazyType) {
Greg Daniel4684f822018-03-08 15:27:36 -0500500 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
501 } else {
502 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
503 }
504
505 // This should cause the uninstantiate proxies to be instantiated again but have no effect
506 // on the others
Brian Salomon967df202018-12-07 11:15:53 -0500507 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500508 // Add a second op to make sure we only instantiate once.
Brian Salomon967df202018-12-07 11:15:53 -0500509 rtc->priv().testingOnly_addDrawOp(LazyDeinstantiateTestOp::Make(ctx.get(), lazyProxy));
Greg Daniel4684f822018-03-08 15:27:36 -0500510 ctx->flush();
511
Brian Salomon967df202018-12-07 11:15:53 -0500512 if (LazyType::kDeinstantiate == lazyType) {
Greg Daniel4684f822018-03-08 15:27:36 -0500513 REPORTER_ASSERT(reporter, 2 == instantiateTestValue);
514 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
515 } else {
516 REPORTER_ASSERT(reporter, 1 == instantiateTestValue);
517 REPORTER_ASSERT(reporter, 0 == releaseTestValue);
518 }
519
520 lazyProxy.reset();
Brian Salomon967df202018-12-07 11:15:53 -0500521 if (LazyType::kDeinstantiate == lazyType) {
Greg Daniel4684f822018-03-08 15:27:36 -0500522 REPORTER_ASSERT(reporter, 2 == releaseTestValue);
523 } else {
524 REPORTER_ASSERT(reporter, 1 == releaseTestValue);
525 }
526
Brian Salomon26102cb2018-03-09 09:33:19 -0500527 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel4684f822018-03-08 15:27:36 -0500528 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500529}