blob: 5a0211d71713234a6ebc3c02570989ccb131e30a [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
10#if SK_SUPPORT_GPU
11
12#include "GrClip.h"
13#include "GrContextPriv.h"
Robert Phillips777707b2018-01-17 11:40:14 -050014#include "GrProxyProvider.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070015#include "GrOnFlushResourceProvider.h"
16#include "GrRenderTargetContext.h"
17#include "GrRenderTargetContextPriv.h"
18#include "GrSurfaceProxy.h"
Greg Daniel94a6ce82018-01-16 16:14:41 -050019#include "GrSurfaceProxyPriv.h"
Chris Dalton706a6ff2017-11-29 22:01:06 -070020#include "GrTexture.h"
21#include "GrTextureProxy.h"
22#include "GrTextureProxyPriv.h"
23#include "SkMakeUnique.h"
Mike Reed274218e2018-01-08 15:05:02 -050024#include "SkRectPriv.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 Phillips777707b2018-01-17 11:40:14 -050058 Op(GrProxyProvider* proxyProvider, LazyProxyTest* test, bool nullTexture)
59 : GrDrawOp(ClassID()), fTest(test) {
60 fProxy = proxyProvider->createFullyLazyProxy([this, nullTexture](
61 GrResourceProvider* rp, GrSurfaceOrigin* origin) {
Greg Daniel0a375db2018-02-01 12:21:39 -050062 if (!rp) {
63 return sk_sp<GrTexture>();
64 }
Chris Dalton706a6ff2017-11-29 22:01:06 -070065 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture);
66 fTest->fHasOpTexture = true;
67 *origin = kTopLeft_GrSurfaceOrigin;
68 if (nullTexture) {
69 return sk_sp<GrTexture>();
70 } else {
71 GrSurfaceDesc desc;
72 desc.fWidth = 1234;
73 desc.fHeight = 567;
74 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
75 desc.fConfig = kRGB_565_GrPixelConfig;
76 sk_sp<GrTexture> texture = rp->createTexture(desc, SkBudgeted::kYes);
77 REPORTER_ASSERT(fTest->fReporter, texture);
78 return texture;
79 }
Robert Phillips777707b2018-01-17 11:40:14 -050080 }, GrProxyProvider::Renderable::kNo, kRGB_565_GrPixelConfig);
Mike Reed274218e2018-01-08 15:05:02 -050081 this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
Chris Dalton706a6ff2017-11-29 22:01:06 -070082 }
83
84 void visitProxies(const VisitProxyFunc& func) const override {
85 func(fProxy.get());
86 }
87
88 void onExecute(GrOpFlushState*) override {
89 REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
90 REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
91 }
92
93 private:
94 const char* name() const override { return "LazyProxyTest::Op"; }
95 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
96 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
97 GrPixelConfigIsClamped) override {
98 return RequiresDstTexture::kNo;
99 }
100 void wasRecorded(GrRenderTargetOpList*) override {}
101 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; }
102 void onPrepare(GrOpFlushState*) override {}
103
104 LazyProxyTest* const fTest;
105 sk_sp<GrTextureProxy> fProxy;
106 };
107
108 class ClipFP : public GrFragmentProcessor {
109 public:
Robert Phillips777707b2018-01-17 11:40:14 -0500110 ClipFP(GrProxyProvider* proxyProvider, LazyProxyTest* test, GrTextureProxy* atlas)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700111 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
Robert Phillips777707b2018-01-17 11:40:14 -0500112 , fProxyProvider(proxyProvider)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700113 , fTest(test)
114 , fAtlas(atlas) {
Robert Phillips777707b2018-01-17 11:40:14 -0500115 fLazyProxy = proxyProvider->createFullyLazyProxy([this](GrResourceProvider* rp,
116 GrSurfaceOrigin* origin) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500117 if (!rp) {
118 return sk_sp<GrTexture>();
119 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700120 REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
121 fTest->fHasClipTexture = true;
122 *origin = kBottomLeft_GrSurfaceOrigin;
123 fAtlas->instantiate(rp);
124 return sk_ref_sp(fAtlas->priv().peekTexture());
Robert Phillips777707b2018-01-17 11:40:14 -0500125 }, GrProxyProvider::Renderable::kYes, kAlpha_half_GrPixelConfig);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700126 fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
127 GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag);
128 this->addTextureSampler(&fAccess);
129 }
130
131 private:
132 const char* name() const override { return "LazyProxyTest::ClipFP"; }
133 std::unique_ptr<GrFragmentProcessor> clone() const override {
Robert Phillips777707b2018-01-17 11:40:14 -0500134 return skstd::make_unique<ClipFP>(fProxyProvider, fTest, fAtlas);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700135 }
136 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
137 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
138 bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
139
Robert Phillips777707b2018-01-17 11:40:14 -0500140 GrProxyProvider* const fProxyProvider;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700141 LazyProxyTest* const fTest;
142 GrTextureProxy* const fAtlas;
143 sk_sp<GrTextureProxy> fLazyProxy;
144 TextureSampler fAccess;
145 };
146
147
148 class Clip : public GrClip {
149 public:
150 Clip(LazyProxyTest* test, GrTextureProxy* atlas)
151 : fTest(test)
152 , fAtlas(atlas) {}
153
154 private:
Robert Phillips777707b2018-01-17 11:40:14 -0500155 bool apply(GrContext* context, GrRenderTargetContext*, bool, bool, GrAppliedClip* out,
Chris Dalton706a6ff2017-11-29 22:01:06 -0700156 SkRect* bounds) const override {
Robert Phillips777707b2018-01-17 11:40:14 -0500157 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
158 out->addCoverageFP(skstd::make_unique<ClipFP>(proxyProvider, fTest, fAtlas));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700159 return true;
160 }
161 bool quickContains(const SkRect&) const final { return false; }
162 bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
163 void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
164 rect->set(0, 0, width, height);
165 if (iior) {
166 *iior = false;
167 }
168 }
169
170 LazyProxyTest* const fTest;
171 GrTextureProxy* fAtlas;
172 };
173
174private:
175 skiatest::Reporter* fReporter;
176 bool fHasOpTexture;
177 bool fHasClipTexture;
178};
179
180DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
181 GrMockOptions mockOptions;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500182 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderability =
183 GrMockOptions::ConfigOptions::Renderability::kNonMSAA;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700184 mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true;
185 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips777707b2018-01-17 11:40:14 -0500186 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
Chris Dalton706a6ff2017-11-29 22:01:06 -0700187 for (bool nullTexture : {false, true}) {
188 LazyProxyTest test(reporter);
189 ctx->contextPriv().addOnFlushCallbackObject(&test);
190 sk_sp<GrRenderTargetContext> rtc =
191 ctx->makeDeferredRenderTargetContext(SkBackingFit::kExact, 100, 100,
192 kRGBA_8888_GrPixelConfig, nullptr);
193 REPORTER_ASSERT(reporter, rtc);
194 sk_sp<GrRenderTargetContext> mockAtlas =
195 ctx->makeDeferredRenderTargetContext(SkBackingFit::kExact, 10, 10,
196 kAlpha_half_GrPixelConfig, nullptr);
197 REPORTER_ASSERT(reporter, mockAtlas);
198 rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
Robert Phillips777707b2018-01-17 11:40:14 -0500199 skstd::make_unique<LazyProxyTest::Op>(proxyProvider, &test, nullTexture));
Chris Dalton706a6ff2017-11-29 22:01:06 -0700200 ctx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
201 }
202}
203
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500204static const int kSize = 16;
205
Greg Daniel94a6ce82018-01-16 16:14:41 -0500206DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
207 GrMockOptions mockOptions;
208 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips777707b2018-01-17 11:40:14 -0500209 auto proxyProvider = ctx->contextPriv().proxyProvider();
Greg Daniel94a6ce82018-01-16 16:14:41 -0500210
211 GrSurfaceDesc desc;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500212 desc.fWidth = kSize;
213 desc.fHeight = kSize;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500214 desc.fConfig = kRGBA_8888_GrPixelConfig;
215
Greg Daniel457469c2018-02-08 15:05:44 -0500216 using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500217 for (bool doInstantiate : {true, false}) {
Greg Daniel457469c2018-02-08 15:05:44 -0500218 for (auto lazyType : {LazyInstantiationType::kSingleUse,
219 LazyInstantiationType::kMultipleUse}) {
220 int testCount = 0;
221 int* testCountPtr = &testCount;
222 sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
223 [testCountPtr](GrResourceProvider* resourceProvider,
224 GrSurfaceOrigin* /*outOrigin*/) {
225 if (!resourceProvider) {
226 *testCountPtr = -1;
227 return sk_sp<GrTexture>();
228 }
229 *testCountPtr = 1;
Greg Daniel94a6ce82018-01-16 16:14:41 -0500230 return sk_sp<GrTexture>();
Greg Daniel457469c2018-02-08 15:05:44 -0500231 }, desc, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kNo);
Greg Daniel94a6ce82018-01-16 16:14:41 -0500232
Greg Daniel457469c2018-02-08 15:05:44 -0500233 proxy->priv().testingOnly_setLazyInstantiationType(lazyType);
Greg Daniel94a6ce82018-01-16 16:14:41 -0500234
Greg Daniel457469c2018-02-08 15:05:44 -0500235 REPORTER_ASSERT(reporter, 0 == testCount);
236
237 if (doInstantiate) {
238 proxy->priv().doLazyInstantiation(ctx->contextPriv().resourceProvider());
239 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
240 // In SingleUse we will call the cleanup and delete the callback in the
241 // doLazyInstantiationCall.
242 REPORTER_ASSERT(reporter, -1 == testCount);
243 } else {
244 REPORTER_ASSERT(reporter, 1 == testCount);
245 }
246 proxy.reset();
247 REPORTER_ASSERT(reporter, -1 == testCount);
248 } else {
249 proxy.reset();
250 REPORTER_ASSERT(reporter, -1 == testCount);
251 }
Greg Daniel94a6ce82018-01-16 16:14:41 -0500252 }
253 }
254}
255
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500256class LazyFailedInstantiationTestOp : public GrDrawOp {
257public:
258 DEFINE_OP_CLASS_ID
259
260 LazyFailedInstantiationTestOp(GrProxyProvider* proxyProvider, int* testExecuteValue,
261 bool shouldFailInstantiation)
262 : INHERITED(ClassID())
263 , fTestExecuteValue(testExecuteValue) {
264 GrSurfaceDesc desc;
265 desc.fWidth = kSize;
266 desc.fHeight = kSize;
267 desc.fConfig = kRGBA_8888_GrPixelConfig;
268
269 fLazyProxy = proxyProvider->createLazyProxy(
270 [testExecuteValue, shouldFailInstantiation, desc] (
271 GrResourceProvider* rp, GrSurfaceOrigin* /*origin*/) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500272 if (!rp) {
273 return sk_sp<GrTexture>();
274 }
275 if (shouldFailInstantiation) {
276 *testExecuteValue = 1;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500277 return sk_sp<GrTexture>();
278 }
279 return rp->createTexture(desc, SkBudgeted::kNo);
280 }, desc, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kNo);
281
282 this->setBounds(SkRect::MakeIWH(kSize, kSize),
283 HasAABloat::kNo, IsZeroArea::kNo);
284 }
285
286 void visitProxies(const VisitProxyFunc& func) const override {
287 func(fLazyProxy.get());
288 }
289
290private:
291 const char* name() const override { return "LazyFailedInstantiationTestOp"; }
292 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
293 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
294 GrPixelConfigIsClamped) override {
295 return RequiresDstTexture::kNo;
296 }
297 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; }
298 void onPrepare(GrOpFlushState*) override {}
299 void onExecute(GrOpFlushState* state) override {
300 *fTestExecuteValue = 2;
301 }
302
303 int* fTestExecuteValue;
304 sk_sp<GrSurfaceProxy> fLazyProxy;
305
306 typedef GrDrawOp INHERITED;
307};
308
309// Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was
310// associated with.
311DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) {
312 GrMockOptions mockOptions;
313 sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
Robert Phillips4150eea2018-02-07 17:08:21 -0500314 GrResourceProvider* resourceProvider = ctx->contextPriv().resourceProvider();
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500315 GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
316 for (bool failInstantiation : {false, true}) {
317 sk_sp<GrRenderTargetContext> rtc =
318 ctx->makeDeferredRenderTargetContext(SkBackingFit::kExact, 100, 100,
319 kRGBA_8888_GrPixelConfig, nullptr);
320 REPORTER_ASSERT(reporter, rtc);
321
322 rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes);
323
324 int executeTestValue = 0;
325 rtc->priv().testingOnly_addDrawOp(
326 skstd::make_unique<LazyFailedInstantiationTestOp>(proxyProvider, &executeTestValue,
327 failInstantiation));
328 ctx->flush();
329
330 if (failInstantiation) {
Robert Phillips4150eea2018-02-07 17:08:21 -0500331 if (resourceProvider->explicitlyAllocateGPUResources()) {
332 REPORTER_ASSERT(reporter, 1 == executeTestValue);
333 } else {
334 // When we disable explicit gpu resource allocation we don't throw away ops that
335 // have uninstantiated proxies.
336 REPORTER_ASSERT(reporter, 2 == executeTestValue);
337 }
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500338 } else {
339 REPORTER_ASSERT(reporter, 2 == executeTestValue);
340 }
341 }
342
343}
344
Chris Dalton706a6ff2017-11-29 22:01:06 -0700345#endif