| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 1 | /* | 
 | 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 Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 10 | #include "GrClip.h" | 
 | 11 | #include "GrContextPriv.h" | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 12 | #include "GrMemoryPool.h" | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 13 | #include "GrOnFlushResourceProvider.h" | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 14 | #include "GrProxyProvider.h" | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 15 | #include "GrRenderTargetContext.h" | 
 | 16 | #include "GrRenderTargetContextPriv.h" | 
 | 17 | #include "GrSurfaceProxy.h" | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 18 | #include "GrSurfaceProxyPriv.h" | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 19 | #include "GrTexture.h" | 
 | 20 | #include "GrTextureProxy.h" | 
 | 21 | #include "GrTextureProxyPriv.h" | 
 | 22 | #include "SkMakeUnique.h" | 
| Mike Reed | 274218e | 2018-01-08 15:05:02 -0500 | [diff] [blame] | 23 | #include "SkRectPriv.h" | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 24 | #include "mock/GrMockGpu.h" | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 25 | #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. | 
 | 30 | class LazyProxyTest final : public GrOnFlushCallbackObject { | 
 | 31 | public: | 
 | 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 Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 58 |         static std::unique_ptr<GrDrawOp> Make(GrContext* context, | 
 | 59 |                                               GrProxyProvider* proxyProvider, | 
 | 60 |                                               LazyProxyTest* test, | 
 | 61 |                                               bool nullTexture) { | 
| Robert Phillips | c994a93 | 2018-06-19 13:09:54 -0400 | [diff] [blame] | 62 |             GrOpMemoryPool* pool = context->contextPriv().opMemoryPool(); | 
 | 63 |  | 
 | 64 |             return pool->allocate<Op>(proxyProvider, test, nullTexture); | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 65 |         } | 
 | 66 |  | 
 | 67 |         void visitProxies(const VisitProxyFunc& func) const override { | 
 | 68 |             func(fProxy.get()); | 
 | 69 |         } | 
 | 70 |  | 
 | 71 |         void onExecute(GrOpFlushState*) override { | 
 | 72 |             REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture); | 
 | 73 |             REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture); | 
 | 74 |         } | 
 | 75 |  | 
 | 76 |     private: | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 77 |         friend class GrOpMemoryPool; // for ctor | 
 | 78 |  | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 79 |         Op(GrProxyProvider* proxyProvider, LazyProxyTest* test, bool nullTexture) | 
 | 80 |                     : GrDrawOp(ClassID()), fTest(test) { | 
| Chris Dalton | 4c458b1 | 2018-06-16 17:22:59 -0600 | [diff] [blame] | 81 |             fProxy = GrProxyProvider::MakeFullyLazyProxy( | 
 | 82 |                     [this, nullTexture](GrResourceProvider* rp) { | 
 | 83 |                         if (!rp) { | 
 | 84 |                             return sk_sp<GrTexture>(); | 
 | 85 |                         } | 
 | 86 |                         REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture); | 
 | 87 |                         fTest->fHasOpTexture = true; | 
 | 88 |                         if (nullTexture) { | 
 | 89 |                             return sk_sp<GrTexture>(); | 
 | 90 |                         } else { | 
 | 91 |                             GrSurfaceDesc desc; | 
 | 92 |                             desc.fWidth = 1234; | 
 | 93 |                             desc.fHeight = 567; | 
 | 94 |                             desc.fConfig = kRGB_565_GrPixelConfig; | 
 | 95 |                             sk_sp<GrTexture> texture = rp->createTexture(desc, SkBudgeted::kYes); | 
 | 96 |                             REPORTER_ASSERT(fTest->fReporter, texture); | 
 | 97 |                             return texture; | 
 | 98 |                         } | 
 | 99 |                     }, | 
 | 100 |                     GrProxyProvider::Renderable::kNo, kTopLeft_GrSurfaceOrigin, | 
 | 101 |                     kRGB_565_GrPixelConfig, *proxyProvider->caps()); | 
 | 102 |  | 
 | 103 |             this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo, | 
 | 104 |                             GrOp::IsZeroArea::kNo); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 105 |         } | 
 | 106 |  | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 107 |         const char* name() const override { return "LazyProxyTest::Op"; } | 
 | 108 |         FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } | 
| Brian Osman | 532b3f9 | 2018-07-11 10:02:07 -0400 | [diff] [blame] | 109 |         RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override { | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 110 |             return RequiresDstTexture::kNo; | 
 | 111 |         } | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 112 |         void onPrepare(GrOpFlushState*) override {} | 
 | 113 |  | 
 | 114 |         LazyProxyTest* const fTest; | 
 | 115 |         sk_sp<GrTextureProxy> fProxy; | 
 | 116 |     }; | 
 | 117 |  | 
 | 118 |     class ClipFP : public GrFragmentProcessor { | 
 | 119 |     public: | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 120 |         ClipFP(GrProxyProvider* proxyProvider, LazyProxyTest* test, GrTextureProxy* atlas) | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 121 |                 : GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags) | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 122 |                 , fProxyProvider(proxyProvider) | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 123 |                 , fTest(test) | 
 | 124 |                 , fAtlas(atlas) { | 
| Chris Dalton | 4c458b1 | 2018-06-16 17:22:59 -0600 | [diff] [blame] | 125 |             fLazyProxy = GrProxyProvider::MakeFullyLazyProxy( | 
| Robert Phillips | ce5209a | 2018-02-13 11:13:51 -0500 | [diff] [blame] | 126 |                                 [this](GrResourceProvider* rp) { | 
 | 127 |                                     if (!rp) { | 
 | 128 |                                         return sk_sp<GrTexture>(); | 
 | 129 |                                     } | 
 | 130 |                                     REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture); | 
 | 131 |                                     fTest->fHasClipTexture = true; | 
 | 132 |                                     fAtlas->instantiate(rp); | 
| Brian Salomon | fd98c2c | 2018-07-31 17:25:29 -0400 | [diff] [blame] | 133 |                                     return sk_ref_sp(fAtlas->peekTexture()); | 
| Robert Phillips | ce5209a | 2018-02-13 11:13:51 -0500 | [diff] [blame] | 134 |                                 }, | 
 | 135 |                                 GrProxyProvider::Renderable::kYes, | 
 | 136 |                                 kBottomLeft_GrSurfaceOrigin, | 
| Chris Dalton | 4c458b1 | 2018-06-16 17:22:59 -0600 | [diff] [blame] | 137 |                                 kAlpha_half_GrPixelConfig, *proxyProvider->caps()); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 138 |             fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest, | 
| Brian Salomon | e782f84 | 2018-07-31 13:53:11 -0400 | [diff] [blame] | 139 |                           GrSamplerState::WrapMode::kClamp); | 
| Brian Salomon | f7dcd76 | 2018-07-30 14:48:15 -0400 | [diff] [blame] | 140 |             this->setTextureSamplerCnt(1); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 141 |         } | 
 | 142 |  | 
 | 143 |     private: | 
 | 144 |         const char* name() const override { return "LazyProxyTest::ClipFP"; } | 
 | 145 |         std::unique_ptr<GrFragmentProcessor> clone() const override { | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 146 |             return skstd::make_unique<ClipFP>(fProxyProvider, fTest, fAtlas); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 147 |         } | 
 | 148 |         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; } | 
 | 149 |         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} | 
 | 150 |         bool onIsEqual(const GrFragmentProcessor&) const override { return false; } | 
| Brian Salomon | f7dcd76 | 2018-07-30 14:48:15 -0400 | [diff] [blame] | 151 |         const TextureSampler& onTextureSampler(int) const override { return fAccess; } | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 152 |  | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 153 |         GrProxyProvider* const fProxyProvider; | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 154 |         LazyProxyTest* const fTest; | 
 | 155 |         GrTextureProxy* const fAtlas; | 
 | 156 |         sk_sp<GrTextureProxy> fLazyProxy; | 
 | 157 |         TextureSampler fAccess; | 
 | 158 |     }; | 
 | 159 |  | 
 | 160 |  | 
 | 161 |     class Clip : public GrClip { | 
 | 162 |     public: | 
 | 163 |         Clip(LazyProxyTest* test, GrTextureProxy* atlas) | 
 | 164 |                 : fTest(test) | 
 | 165 |                 , fAtlas(atlas) {} | 
 | 166 |  | 
 | 167 |     private: | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 168 |         bool apply(GrContext* context, GrRenderTargetContext*, bool, bool, GrAppliedClip* out, | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 169 |                    SkRect* bounds) const override { | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 170 |             GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); | 
 | 171 |             out->addCoverageFP(skstd::make_unique<ClipFP>(proxyProvider, fTest, fAtlas)); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 172 |             return true; | 
 | 173 |         } | 
 | 174 |         bool quickContains(const SkRect&) const final { return false; } | 
 | 175 |         bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; } | 
 | 176 |         void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final { | 
 | 177 |             rect->set(0, 0, width, height); | 
 | 178 |             if (iior) { | 
 | 179 |                 *iior = false; | 
 | 180 |             } | 
 | 181 |         } | 
 | 182 |  | 
 | 183 |         LazyProxyTest* const fTest; | 
 | 184 |         GrTextureProxy* fAtlas; | 
 | 185 |     }; | 
 | 186 |  | 
 | 187 | private: | 
 | 188 |     skiatest::Reporter* fReporter; | 
 | 189 |     bool fHasOpTexture; | 
 | 190 |     bool fHasClipTexture; | 
 | 191 | }; | 
 | 192 |  | 
 | 193 | DEF_GPUTEST(LazyProxyTest, reporter, /* options */) { | 
 | 194 |     GrMockOptions mockOptions; | 
| Brian Salomon | bdecacf | 2018-02-02 20:32:49 -0500 | [diff] [blame] | 195 |     mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderability = | 
 | 196 |             GrMockOptions::ConfigOptions::Renderability::kNonMSAA; | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 197 |     mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true; | 
 | 198 |     sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions()); | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 199 |     GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider(); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 200 |     for (bool nullTexture : {false, true}) { | 
 | 201 |         LazyProxyTest test(reporter); | 
 | 202 |         ctx->contextPriv().addOnFlushCallbackObject(&test); | 
| Robert Phillips | 0c4b7b1 | 2018-03-06 08:20:37 -0500 | [diff] [blame] | 203 |         sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext( | 
 | 204 |                                                              SkBackingFit::kExact, 100, 100, | 
 | 205 |                                                              kRGBA_8888_GrPixelConfig, nullptr); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 206 |         REPORTER_ASSERT(reporter, rtc); | 
| Robert Phillips | 0c4b7b1 | 2018-03-06 08:20:37 -0500 | [diff] [blame] | 207 |         sk_sp<GrRenderTargetContext> mockAtlas = ctx->contextPriv().makeDeferredRenderTargetContext( | 
 | 208 |                                                      SkBackingFit::kExact, 10, 10, | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 209 |                                                      kAlpha_half_GrPixelConfig, nullptr); | 
 | 210 |         REPORTER_ASSERT(reporter, mockAtlas); | 
 | 211 |         rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()), | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 212 |                         LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture)); | 
| Chris Dalton | 706a6ff | 2017-11-29 22:01:06 -0700 | [diff] [blame] | 213 |         ctx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test); | 
 | 214 |     } | 
 | 215 | } | 
 | 216 |  | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 217 | static const int kSize = 16; | 
 | 218 |  | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 219 | DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) { | 
 | 220 |     GrMockOptions mockOptions; | 
 | 221 |     sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions()); | 
| Robert Phillips | 777707b | 2018-01-17 11:40:14 -0500 | [diff] [blame] | 222 |     auto proxyProvider = ctx->contextPriv().proxyProvider(); | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 223 |  | 
 | 224 |     GrSurfaceDesc desc; | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 225 |     desc.fWidth = kSize; | 
 | 226 |     desc.fHeight = kSize; | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 227 |     desc.fConfig = kRGBA_8888_GrPixelConfig; | 
 | 228 |  | 
| Greg Daniel | 457469c | 2018-02-08 15:05:44 -0500 | [diff] [blame] | 229 |     using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType; | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 230 |     for (bool doInstantiate : {true, false}) { | 
| Greg Daniel | 457469c | 2018-02-08 15:05:44 -0500 | [diff] [blame] | 231 |         for (auto lazyType : {LazyInstantiationType::kSingleUse, | 
| Greg Daniel | a8d9211 | 2018-03-09 12:05:04 -0500 | [diff] [blame] | 232 |                               LazyInstantiationType::kMultipleUse, | 
 | 233 |                               LazyInstantiationType::kUninstantiate}) { | 
| Greg Daniel | 457469c | 2018-02-08 15:05:44 -0500 | [diff] [blame] | 234 |             int testCount = 0; | 
 | 235 |             int* testCountPtr = &testCount; | 
 | 236 |             sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy( | 
| Robert Phillips | ce5209a | 2018-02-13 11:13:51 -0500 | [diff] [blame] | 237 |                     [testCountPtr](GrResourceProvider* resourceProvider) { | 
| Greg Daniel | 457469c | 2018-02-08 15:05:44 -0500 | [diff] [blame] | 238 |                         if (!resourceProvider) { | 
 | 239 |                             *testCountPtr = -1; | 
 | 240 |                             return sk_sp<GrTexture>(); | 
 | 241 |                         } | 
 | 242 |                         *testCountPtr = 1; | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 243 |                         return sk_sp<GrTexture>(); | 
| Brian Salomon | 2a4f983 | 2018-03-03 22:43:43 -0500 | [diff] [blame] | 244 |                     }, | 
| Brian Salomon | 7226c23 | 2018-07-30 13:13:17 -0400 | [diff] [blame] | 245 |                     desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrTextureType::k2D, | 
 | 246 |                     GrInternalSurfaceFlags::kNone, SkBackingFit::kExact, SkBudgeted::kNo, lazyType); | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 247 |  | 
| Greg Daniel | 92cbf3f | 2018-04-12 16:50:17 -0400 | [diff] [blame] | 248 |             REPORTER_ASSERT(reporter, proxy.get()); | 
| Greg Daniel | 457469c | 2018-02-08 15:05:44 -0500 | [diff] [blame] | 249 |             REPORTER_ASSERT(reporter, 0 == testCount); | 
 | 250 |  | 
 | 251 |             if (doInstantiate) { | 
 | 252 |                 proxy->priv().doLazyInstantiation(ctx->contextPriv().resourceProvider()); | 
 | 253 |                 if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) { | 
 | 254 |                     // In SingleUse we will call the cleanup and delete the callback in the | 
 | 255 |                     // doLazyInstantiationCall. | 
 | 256 |                     REPORTER_ASSERT(reporter, -1 == testCount); | 
 | 257 |                 } else { | 
 | 258 |                     REPORTER_ASSERT(reporter, 1 == testCount); | 
 | 259 |                 } | 
 | 260 |                 proxy.reset(); | 
 | 261 |                 REPORTER_ASSERT(reporter, -1 == testCount); | 
 | 262 |             } else { | 
 | 263 |                 proxy.reset(); | 
 | 264 |                 REPORTER_ASSERT(reporter, -1 == testCount); | 
 | 265 |             } | 
| Greg Daniel | 94a6ce8 | 2018-01-16 16:14:41 -0500 | [diff] [blame] | 266 |         } | 
 | 267 |     } | 
 | 268 | } | 
 | 269 |  | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 270 | class LazyFailedInstantiationTestOp : public GrDrawOp { | 
 | 271 | public: | 
 | 272 |     DEFINE_OP_CLASS_ID | 
 | 273 |  | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 274 |     static std::unique_ptr<GrDrawOp> Make(GrContext* context, | 
 | 275 |                                           GrProxyProvider* proxyProvider, | 
 | 276 |                                           int* testExecuteValue, | 
 | 277 |                                           bool shouldFailInstantiation) { | 
| Robert Phillips | c994a93 | 2018-06-19 13:09:54 -0400 | [diff] [blame] | 278 |         GrOpMemoryPool* pool = context->contextPriv().opMemoryPool(); | 
 | 279 |  | 
 | 280 |         return pool->allocate<LazyFailedInstantiationTestOp>(proxyProvider, | 
 | 281 |                                                              testExecuteValue, | 
 | 282 |                                                              shouldFailInstantiation); | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 283 |     } | 
 | 284 |  | 
 | 285 |     void visitProxies(const VisitProxyFunc& func) const override { | 
 | 286 |         func(fLazyProxy.get()); | 
 | 287 |     } | 
 | 288 |  | 
 | 289 | private: | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 290 |     friend class GrOpMemoryPool; // for ctor | 
 | 291 |  | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 292 |     LazyFailedInstantiationTestOp(GrProxyProvider* proxyProvider, int* testExecuteValue, | 
 | 293 |                                   bool shouldFailInstantiation) | 
 | 294 |             : INHERITED(ClassID()) | 
 | 295 |             , fTestExecuteValue(testExecuteValue) { | 
 | 296 |         GrSurfaceDesc desc; | 
 | 297 |         desc.fWidth = kSize; | 
 | 298 |         desc.fHeight = kSize; | 
 | 299 |         desc.fConfig = kRGBA_8888_GrPixelConfig; | 
 | 300 |  | 
 | 301 |         fLazyProxy = proxyProvider->createLazyProxy( | 
| Brian Salomon | 2a4f983 | 2018-03-03 22:43:43 -0500 | [diff] [blame] | 302 |                 [testExecuteValue, shouldFailInstantiation, desc](GrResourceProvider* rp) { | 
| Greg Daniel | 0a375db | 2018-02-01 12:21:39 -0500 | [diff] [blame] | 303 |                     if (!rp) { | 
 | 304 |                         return sk_sp<GrTexture>(); | 
 | 305 |                     } | 
 | 306 |                     if (shouldFailInstantiation) { | 
 | 307 |                         *testExecuteValue = 1; | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 308 |                         return sk_sp<GrTexture>(); | 
 | 309 |                     } | 
 | 310 |                     return rp->createTexture(desc, SkBudgeted::kNo); | 
| Brian Salomon | 2a4f983 | 2018-03-03 22:43:43 -0500 | [diff] [blame] | 311 |                 }, | 
| Brian Salomon | 7226c23 | 2018-07-30 13:13:17 -0400 | [diff] [blame] | 312 |                 desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrTextureType::k2D, | 
 | 313 |                 SkBackingFit::kExact, SkBudgeted::kNo); | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 314 |  | 
| Greg Daniel | 92cbf3f | 2018-04-12 16:50:17 -0400 | [diff] [blame] | 315 |         SkASSERT(fLazyProxy.get()); | 
 | 316 |  | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 317 |         this->setBounds(SkRect::MakeIWH(kSize, kSize), | 
 | 318 |                         HasAABloat::kNo, IsZeroArea::kNo); | 
 | 319 |     } | 
 | 320 |  | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 321 |     const char* name() const override { return "LazyFailedInstantiationTestOp"; } | 
 | 322 |     FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } | 
| Brian Osman | 532b3f9 | 2018-07-11 10:02:07 -0400 | [diff] [blame] | 323 |     RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override { | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 324 |         return RequiresDstTexture::kNo; | 
 | 325 |     } | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 326 |     void onPrepare(GrOpFlushState*) override {} | 
 | 327 |     void onExecute(GrOpFlushState* state) override { | 
 | 328 |         *fTestExecuteValue = 2; | 
 | 329 |     } | 
 | 330 |  | 
 | 331 |     int* fTestExecuteValue; | 
 | 332 |     sk_sp<GrSurfaceProxy> fLazyProxy; | 
 | 333 |  | 
 | 334 |     typedef GrDrawOp INHERITED; | 
 | 335 | }; | 
 | 336 |  | 
 | 337 | // Test that when a lazy proxy fails to instantiate during flush that we drop the Op that it was | 
 | 338 | // associated with. | 
 | 339 | DEF_GPUTEST(LazyProxyFailedInstantiationTest, reporter, /* options */) { | 
 | 340 |     GrMockOptions mockOptions; | 
 | 341 |     sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions()); | 
| Robert Phillips | 4150eea | 2018-02-07 17:08:21 -0500 | [diff] [blame] | 342 |     GrResourceProvider* resourceProvider = ctx->contextPriv().resourceProvider(); | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 343 |     GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider(); | 
 | 344 |     for (bool failInstantiation : {false, true}) { | 
| Robert Phillips | 0c4b7b1 | 2018-03-06 08:20:37 -0500 | [diff] [blame] | 345 |         sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext( | 
 | 346 |                                                      SkBackingFit::kExact, 100, 100, | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 347 |                                                      kRGBA_8888_GrPixelConfig, nullptr); | 
 | 348 |         REPORTER_ASSERT(reporter, rtc); | 
 | 349 |  | 
 | 350 |         rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes); | 
 | 351 |  | 
 | 352 |         int executeTestValue = 0; | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 353 |         rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make( | 
 | 354 |                 ctx.get(), proxyProvider, &executeTestValue, failInstantiation)); | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 355 |         ctx->flush(); | 
 | 356 |  | 
 | 357 |         if (failInstantiation) { | 
| Robert Phillips | 4150eea | 2018-02-07 17:08:21 -0500 | [diff] [blame] | 358 |             if (resourceProvider->explicitlyAllocateGPUResources()) { | 
 | 359 |                 REPORTER_ASSERT(reporter, 1 == executeTestValue); | 
 | 360 |             } else { | 
 | 361 |                 // When we disable explicit gpu resource allocation we don't throw away ops that | 
 | 362 |                 // have uninstantiated proxies. | 
 | 363 |                 REPORTER_ASSERT(reporter, 2 == executeTestValue); | 
 | 364 |             } | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 365 |         } else { | 
 | 366 |             REPORTER_ASSERT(reporter, 2 == executeTestValue); | 
 | 367 |         } | 
 | 368 |     } | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 369 | } | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 370 |  | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 371 | class LazyUninstantiateTestOp : public GrDrawOp { | 
 | 372 | public: | 
 | 373 |     DEFINE_OP_CLASS_ID | 
 | 374 |  | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 375 |     static std::unique_ptr<GrDrawOp> Make(GrContext* context, sk_sp<GrTextureProxy> proxy) { | 
| Robert Phillips | c994a93 | 2018-06-19 13:09:54 -0400 | [diff] [blame] | 376 |         GrOpMemoryPool* pool = context->contextPriv().opMemoryPool(); | 
 | 377 |  | 
 | 378 |         return pool->allocate<LazyUninstantiateTestOp>(std::move(proxy)); | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 379 |     } | 
 | 380 |  | 
 | 381 |     void visitProxies(const VisitProxyFunc& func) const override { | 
 | 382 |         func(fLazyProxy.get()); | 
 | 383 |     } | 
 | 384 |  | 
 | 385 | private: | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 386 |     friend class GrOpMemoryPool; // for ctor | 
 | 387 |  | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 388 |     LazyUninstantiateTestOp(sk_sp<GrTextureProxy> proxy) | 
 | 389 |             : INHERITED(ClassID()) | 
 | 390 |             , fLazyProxy(std::move(proxy)) { | 
 | 391 |         this->setBounds(SkRect::MakeIWH(kSize, kSize), HasAABloat::kNo, IsZeroArea::kNo); | 
 | 392 |     } | 
 | 393 |  | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 394 |     const char* name() const override { return "LazyUninstantiateTestOp"; } | 
 | 395 |     FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } | 
| Brian Osman | 532b3f9 | 2018-07-11 10:02:07 -0400 | [diff] [blame] | 396 |     RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override { | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 397 |         return RequiresDstTexture::kNo; | 
 | 398 |     } | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 399 |     void onPrepare(GrOpFlushState*) override {} | 
 | 400 |     void onExecute(GrOpFlushState* state) override {} | 
 | 401 |  | 
 | 402 |     sk_sp<GrSurfaceProxy> fLazyProxy; | 
 | 403 |  | 
 | 404 |     typedef GrDrawOp INHERITED; | 
 | 405 | }; | 
 | 406 |  | 
 | 407 | static void UninstantiateReleaseProc(void* releaseValue) { | 
 | 408 |     (*static_cast<int*>(releaseValue))++; | 
 | 409 | } | 
 | 410 |  | 
 | 411 | // Test that lazy proxies with the Uninstantiate LazyCallbackType are uninstantiated and released as | 
 | 412 | // expected. | 
 | 413 | DEF_GPUTEST(LazyProxyUninstantiateTest, reporter, /* options */) { | 
 | 414 |     GrMockOptions mockOptions; | 
 | 415 |     sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions()); | 
 | 416 |     GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider(); | 
 | 417 |     GrGpu* gpu = ctx->contextPriv().getGpu(); | 
 | 418 |  | 
 | 419 |     using LazyType = GrSurfaceProxy::LazyInstantiationType; | 
 | 420 |     for (auto lazyType : {LazyType::kSingleUse, LazyType::kMultipleUse, LazyType::kUninstantiate}) { | 
 | 421 |         sk_sp<GrRenderTargetContext> rtc = ctx->contextPriv().makeDeferredRenderTargetContext( | 
 | 422 |                 SkBackingFit::kExact, 100, 100, | 
 | 423 |                 kRGBA_8888_GrPixelConfig, nullptr); | 
 | 424 |         REPORTER_ASSERT(reporter, rtc); | 
 | 425 |  | 
 | 426 |         rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes); | 
 | 427 |  | 
 | 428 |         int instantiateTestValue = 0; | 
 | 429 |         int releaseTestValue = 0; | 
 | 430 |         int* instantiatePtr = &instantiateTestValue; | 
 | 431 |         int* releasePtr = &releaseTestValue; | 
 | 432 |         GrSurfaceDesc desc; | 
 | 433 |         desc.fWidth = kSize; | 
 | 434 |         desc.fHeight = kSize; | 
 | 435 |         desc.fConfig = kRGBA_8888_GrPixelConfig; | 
 | 436 |  | 
 | 437 |         GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture( | 
 | 438 |                 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, false, GrMipMapped::kNo); | 
 | 439 |  | 
 | 440 |         sk_sp<GrTextureProxy> lazyProxy = proxyProvider->createLazyProxy( | 
 | 441 |                 [instantiatePtr, releasePtr, backendTex](GrResourceProvider* rp) { | 
 | 442 |                     if (!rp) { | 
 | 443 |                         return sk_sp<GrTexture>(); | 
 | 444 |                     } | 
 | 445 |  | 
 | 446 |                     sk_sp<GrTexture> texture = rp->wrapBackendTexture(backendTex); | 
 | 447 |                     if (!texture) { | 
 | 448 |                         return sk_sp<GrTexture>(); | 
 | 449 |                     } | 
 | 450 |                     (*instantiatePtr)++; | 
 | 451 |                     texture->setRelease(UninstantiateReleaseProc, releasePtr); | 
 | 452 |                     return texture; | 
 | 453 |                 }, | 
| Brian Salomon | 7226c23 | 2018-07-30 13:13:17 -0400 | [diff] [blame] | 454 |                 desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, GrTextureType::k2D, | 
 | 455 |                 GrInternalSurfaceFlags::kNone, SkBackingFit::kExact, SkBudgeted::kNo, lazyType); | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 456 |  | 
| Greg Daniel | 92cbf3f | 2018-04-12 16:50:17 -0400 | [diff] [blame] | 457 |         REPORTER_ASSERT(reporter, lazyProxy.get()); | 
 | 458 |  | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 459 |         rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy)); | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 460 |  | 
 | 461 |         ctx->flush(); | 
 | 462 |  | 
 | 463 |         REPORTER_ASSERT(reporter, 1 == instantiateTestValue); | 
 | 464 |         if (LazyType::kUninstantiate == lazyType) { | 
 | 465 |             REPORTER_ASSERT(reporter, 1 == releaseTestValue); | 
 | 466 |         } else { | 
 | 467 |             REPORTER_ASSERT(reporter, 0 == releaseTestValue); | 
 | 468 |         } | 
 | 469 |  | 
 | 470 |         // This should cause the uninstantiate proxies to be instantiated again but have no effect | 
 | 471 |         // on the others | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 472 |         rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy)); | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 473 |         // Add a second op to make sure we only instantiate once. | 
| Robert Phillips | 88a32ef | 2018-06-07 11:05:56 -0400 | [diff] [blame] | 474 |         rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy)); | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 475 |         ctx->flush(); | 
 | 476 |  | 
 | 477 |         if (LazyType::kUninstantiate == lazyType) { | 
 | 478 |             REPORTER_ASSERT(reporter, 2 == instantiateTestValue); | 
 | 479 |             REPORTER_ASSERT(reporter, 2 == releaseTestValue); | 
 | 480 |         } else { | 
 | 481 |             REPORTER_ASSERT(reporter, 1 == instantiateTestValue); | 
 | 482 |             REPORTER_ASSERT(reporter, 0 == releaseTestValue); | 
 | 483 |         } | 
 | 484 |  | 
 | 485 |         lazyProxy.reset(); | 
 | 486 |         if (LazyType::kUninstantiate == lazyType) { | 
 | 487 |             REPORTER_ASSERT(reporter, 2 == releaseTestValue); | 
 | 488 |         } else { | 
 | 489 |             REPORTER_ASSERT(reporter, 1 == releaseTestValue); | 
 | 490 |         } | 
 | 491 |  | 
| Brian Salomon | 26102cb | 2018-03-09 09:33:19 -0500 | [diff] [blame] | 492 |         gpu->deleteTestingOnlyBackendTexture(backendTex); | 
| Greg Daniel | 4684f82 | 2018-03-08 15:27:36 -0500 | [diff] [blame] | 493 |     } | 
| Greg Daniel | aa3dfbe | 2018-01-29 10:34:25 -0500 | [diff] [blame] | 494 | } |