1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/GrDeferredDisplayListRecorder.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/GrPromiseImageTexture.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/SkImageChromium.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ContextType.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/FenceSync.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ManagedBackendTexture.h"
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
44*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
45*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker using namespace sk_gpu_test;
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker struct PromiseTextureChecker {
54*c8dee2aaSAndroid Build Coastguard Worker // shared indicates whether the backend texture is used to fulfill more than one promise
55*c8dee2aaSAndroid Build Coastguard Worker // image.
PromiseTextureCheckerPromiseTextureChecker56*c8dee2aaSAndroid Build Coastguard Worker explicit PromiseTextureChecker(const GrBackendTexture& tex,
57*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter* reporter,
58*c8dee2aaSAndroid Build Coastguard Worker bool shared)
59*c8dee2aaSAndroid Build Coastguard Worker : fTexture(GrPromiseImageTexture::Make(tex)), fReporter(reporter), fShared(shared) {}
60*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrPromiseImageTexture> fTexture;
61*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter* fReporter;
62*c8dee2aaSAndroid Build Coastguard Worker bool fShared;
63*c8dee2aaSAndroid Build Coastguard Worker int fFulfillCount = 0;
64*c8dee2aaSAndroid Build Coastguard Worker int fReleaseCount = 0;
65*c8dee2aaSAndroid Build Coastguard Worker
FulfillPromiseTextureChecker66*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrPromiseImageTexture> Fulfill(void* self) {
67*c8dee2aaSAndroid Build Coastguard Worker auto checker = static_cast<PromiseTextureChecker*>(self);
68*c8dee2aaSAndroid Build Coastguard Worker checker->fFulfillCount++;
69*c8dee2aaSAndroid Build Coastguard Worker return checker->fTexture;
70*c8dee2aaSAndroid Build Coastguard Worker }
ReleasePromiseTextureChecker71*c8dee2aaSAndroid Build Coastguard Worker static void Release(void* self) { static_cast<PromiseTextureChecker*>(self)->fReleaseCount++; }
72*c8dee2aaSAndroid Build Coastguard Worker };
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker enum class ReleaseBalanceExpectation {
75*c8dee2aaSAndroid Build Coastguard Worker kBalanced,
76*c8dee2aaSAndroid Build Coastguard Worker kAllUnbalanced,
77*c8dee2aaSAndroid Build Coastguard Worker kUnknown,
78*c8dee2aaSAndroid Build Coastguard Worker kUnbalancedByOne,
79*c8dee2aaSAndroid Build Coastguard Worker kBalancedOrOffByOne,
80*c8dee2aaSAndroid Build Coastguard Worker };
81*c8dee2aaSAndroid Build Coastguard Worker
check_fulfill_and_release_cnts(skiatest::Reporter * reporter,const PromiseTextureChecker & promiseChecker,int expectedFulfillCnt,ReleaseBalanceExpectation releaseBalanceExpecation)82*c8dee2aaSAndroid Build Coastguard Worker static void check_fulfill_and_release_cnts(skiatest::Reporter* reporter,
83*c8dee2aaSAndroid Build Coastguard Worker const PromiseTextureChecker& promiseChecker,
84*c8dee2aaSAndroid Build Coastguard Worker int expectedFulfillCnt,
85*c8dee2aaSAndroid Build Coastguard Worker ReleaseBalanceExpectation releaseBalanceExpecation) {
86*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt);
87*c8dee2aaSAndroid Build Coastguard Worker if (!expectedFulfillCnt) {
88*c8dee2aaSAndroid Build Coastguard Worker // Release and Done should only ever be called after Fulfill.
89*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !promiseChecker.fReleaseCount);
90*c8dee2aaSAndroid Build Coastguard Worker return;
91*c8dee2aaSAndroid Build Coastguard Worker }
92*c8dee2aaSAndroid Build Coastguard Worker int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
93*c8dee2aaSAndroid Build Coastguard Worker switch (releaseBalanceExpecation) {
94*c8dee2aaSAndroid Build Coastguard Worker case ReleaseBalanceExpectation::kBalanced:
95*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !releaseDiff);
96*c8dee2aaSAndroid Build Coastguard Worker break;
97*c8dee2aaSAndroid Build Coastguard Worker case ReleaseBalanceExpectation::kAllUnbalanced:
98*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, releaseDiff == promiseChecker.fFulfillCount);
99*c8dee2aaSAndroid Build Coastguard Worker break;
100*c8dee2aaSAndroid Build Coastguard Worker case ReleaseBalanceExpectation::kUnknown:
101*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
102*c8dee2aaSAndroid Build Coastguard Worker releaseDiff >= 0 && releaseDiff <= promiseChecker.fFulfillCount);
103*c8dee2aaSAndroid Build Coastguard Worker break;
104*c8dee2aaSAndroid Build Coastguard Worker case ReleaseBalanceExpectation::kUnbalancedByOne:
105*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, releaseDiff == 1);
106*c8dee2aaSAndroid Build Coastguard Worker break;
107*c8dee2aaSAndroid Build Coastguard Worker case ReleaseBalanceExpectation::kBalancedOrOffByOne:
108*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, releaseDiff == 0 || releaseDiff == 1);
109*c8dee2aaSAndroid Build Coastguard Worker break;
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker
check_unfulfilled(const PromiseTextureChecker & promiseChecker,skiatest::Reporter * reporter)113*c8dee2aaSAndroid Build Coastguard Worker static void check_unfulfilled(const PromiseTextureChecker& promiseChecker,
114*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter* reporter) {
115*c8dee2aaSAndroid Build Coastguard Worker check_fulfill_and_release_cnts(reporter, promiseChecker, 0,
116*c8dee2aaSAndroid Build Coastguard Worker ReleaseBalanceExpectation::kBalanced);
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker
check_only_fulfilled(skiatest::Reporter * reporter,const PromiseTextureChecker & promiseChecker,int expectedFulfillCnt=1)119*c8dee2aaSAndroid Build Coastguard Worker static void check_only_fulfilled(skiatest::Reporter* reporter,
120*c8dee2aaSAndroid Build Coastguard Worker const PromiseTextureChecker& promiseChecker,
121*c8dee2aaSAndroid Build Coastguard Worker int expectedFulfillCnt = 1) {
122*c8dee2aaSAndroid Build Coastguard Worker check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
123*c8dee2aaSAndroid Build Coastguard Worker ReleaseBalanceExpectation::kAllUnbalanced);
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker
check_all_flushed_but_not_synced(skiatest::Reporter * reporter,const PromiseTextureChecker & promiseChecker,GrBackendApi api,int expectedFulfillCnt=1)126*c8dee2aaSAndroid Build Coastguard Worker static void check_all_flushed_but_not_synced(skiatest::Reporter* reporter,
127*c8dee2aaSAndroid Build Coastguard Worker const PromiseTextureChecker& promiseChecker,
128*c8dee2aaSAndroid Build Coastguard Worker GrBackendApi api,
129*c8dee2aaSAndroid Build Coastguard Worker int expectedFulfillCnt = 1) {
130*c8dee2aaSAndroid Build Coastguard Worker ReleaseBalanceExpectation releaseBalanceExpectation = ReleaseBalanceExpectation::kBalanced;
131*c8dee2aaSAndroid Build Coastguard Worker // On Vulkan and D3D Done isn't guaranteed to be called until a sync has occurred.
132*c8dee2aaSAndroid Build Coastguard Worker if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDirect3D) {
133*c8dee2aaSAndroid Build Coastguard Worker releaseBalanceExpectation = expectedFulfillCnt == 1
134*c8dee2aaSAndroid Build Coastguard Worker ? ReleaseBalanceExpectation::kBalancedOrOffByOne
135*c8dee2aaSAndroid Build Coastguard Worker : ReleaseBalanceExpectation::kUnknown;
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
138*c8dee2aaSAndroid Build Coastguard Worker releaseBalanceExpectation);
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker
check_all_done(skiatest::Reporter * reporter,const PromiseTextureChecker & promiseChecker,int expectedFulfillCnt=1)141*c8dee2aaSAndroid Build Coastguard Worker static void check_all_done(skiatest::Reporter* reporter,
142*c8dee2aaSAndroid Build Coastguard Worker const PromiseTextureChecker& promiseChecker,
143*c8dee2aaSAndroid Build Coastguard Worker int expectedFulfillCnt = 1) {
144*c8dee2aaSAndroid Build Coastguard Worker check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
145*c8dee2aaSAndroid Build Coastguard Worker ReleaseBalanceExpectation::kBalanced);
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PromiseImageTest,reporter,ctxInfo,CtsEnforcement::kNever)148*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PromiseImageTest,
149*c8dee2aaSAndroid Build Coastguard Worker reporter,
150*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
151*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kNever) {
152*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu;
153*c8dee2aaSAndroid Build Coastguard Worker const int kWidth = 10;
154*c8dee2aaSAndroid Build Coastguard Worker const int kHeight = 10;
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker auto ctx = ctxInfo.directContext();
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker Protected isProtected = Protected(ctx->priv().caps()->supportsProtectedContent());
159*c8dee2aaSAndroid Build Coastguard Worker
160*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture backendTex = ctx->createBackendTexture(kWidth,
161*c8dee2aaSAndroid Build Coastguard Worker kHeight,
162*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
163*c8dee2aaSAndroid Build Coastguard Worker SkColors::kTransparent,
164*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
165*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kYes,
166*c8dee2aaSAndroid Build Coastguard Worker isProtected);
167*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, backendTex.isValid());
168*c8dee2aaSAndroid Build Coastguard Worker
169*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat backendFormat = backendTex.getBackendFormat();
170*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, backendFormat.isValid());
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker promiseChecker(backendTex, reporter, false);
173*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
174*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg(SkImages::PromiseTextureFrom(ctx->threadSafeProxy(),
175*c8dee2aaSAndroid Build Coastguard Worker backendFormat,
176*c8dee2aaSAndroid Build Coastguard Worker {kWidth, kHeight},
177*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
178*c8dee2aaSAndroid Build Coastguard Worker texOrigin,
179*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
180*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
181*c8dee2aaSAndroid Build Coastguard Worker nullptr,
182*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker::Fulfill,
183*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker::Release,
184*c8dee2aaSAndroid Build Coastguard Worker &promiseChecker));
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
187*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(ctx, skgpu::Budgeted::kNo, info);
188*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
191*c8dee2aaSAndroid Build Coastguard Worker check_unfulfilled(promiseChecker, reporter);
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker ctx->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
194*c8dee2aaSAndroid Build Coastguard Worker // We still own the image so we should not have called Release or Done.
195*c8dee2aaSAndroid Build Coastguard Worker check_only_fulfilled(reporter, promiseChecker);
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker ctx->submit(GrSyncCpu::kYes);
198*c8dee2aaSAndroid Build Coastguard Worker check_only_fulfilled(reporter, promiseChecker);
199*c8dee2aaSAndroid Build Coastguard Worker
200*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
201*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
202*c8dee2aaSAndroid Build Coastguard Worker
203*c8dee2aaSAndroid Build Coastguard Worker ctx->flushAndSubmit(surface.get(), GrSyncCpu::kYes);
204*c8dee2aaSAndroid Build Coastguard Worker
205*c8dee2aaSAndroid Build Coastguard Worker // Image should still be fulfilled from the first time we drew/flushed it.
206*c8dee2aaSAndroid Build Coastguard Worker check_only_fulfilled(reporter, promiseChecker);
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
209*c8dee2aaSAndroid Build Coastguard Worker ctx->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
210*c8dee2aaSAndroid Build Coastguard Worker check_only_fulfilled(reporter, promiseChecker);
211*c8dee2aaSAndroid Build Coastguard Worker
212*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
213*c8dee2aaSAndroid Build Coastguard Worker refImg.reset();
214*c8dee2aaSAndroid Build Coastguard Worker // We no longer own the image but the last draw is still unflushed.
215*c8dee2aaSAndroid Build Coastguard Worker check_only_fulfilled(reporter, promiseChecker);
216*c8dee2aaSAndroid Build Coastguard Worker
217*c8dee2aaSAndroid Build Coastguard Worker ctx->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
218*c8dee2aaSAndroid Build Coastguard Worker // Flushing should have called Release. Depending on the backend and timing it may have called
219*c8dee2aaSAndroid Build Coastguard Worker // done.
220*c8dee2aaSAndroid Build Coastguard Worker check_all_flushed_but_not_synced(reporter, promiseChecker, ctx->backend());
221*c8dee2aaSAndroid Build Coastguard Worker ctx->submit(GrSyncCpu::kYes);
222*c8dee2aaSAndroid Build Coastguard Worker // Now Done should definitely have been called.
223*c8dee2aaSAndroid Build Coastguard Worker check_all_done(reporter, promiseChecker);
224*c8dee2aaSAndroid Build Coastguard Worker
225*c8dee2aaSAndroid Build Coastguard Worker ctx->deleteBackendTexture(backendTex);
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST(PromiseImageTextureShutdown,reporter,ctxInfo,CtsEnforcement::kNever)228*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST(PromiseImageTextureShutdown, reporter, ctxInfo, CtsEnforcement::kNever) {
229*c8dee2aaSAndroid Build Coastguard Worker const int kWidth = 10;
230*c8dee2aaSAndroid Build Coastguard Worker const int kHeight = 10;
231*c8dee2aaSAndroid Build Coastguard Worker
232*c8dee2aaSAndroid Build Coastguard Worker // Different ways of killing contexts.
233*c8dee2aaSAndroid Build Coastguard Worker using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrDirectContext*)>;
234*c8dee2aaSAndroid Build Coastguard Worker DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext*) {
235*c8dee2aaSAndroid Build Coastguard Worker factory->destroyContexts();
236*c8dee2aaSAndroid Build Coastguard Worker };
237*c8dee2aaSAndroid Build Coastguard Worker DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext* dContext) {
238*c8dee2aaSAndroid Build Coastguard Worker dContext->abandonContext();
239*c8dee2aaSAndroid Build Coastguard Worker };
240*c8dee2aaSAndroid Build Coastguard Worker DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory,
241*c8dee2aaSAndroid Build Coastguard Worker GrDirectContext* dContext) {
242*c8dee2aaSAndroid Build Coastguard Worker dContext->releaseResourcesAndAbandonContext();
243*c8dee2aaSAndroid Build Coastguard Worker };
244*c8dee2aaSAndroid Build Coastguard Worker
245*c8dee2aaSAndroid Build Coastguard Worker for (int type = 0; type < skgpu::kContextTypeCount; ++type) {
246*c8dee2aaSAndroid Build Coastguard Worker auto contextType = static_cast<skgpu::ContextType>(type);
247*c8dee2aaSAndroid Build Coastguard Worker // These tests are difficult to get working with Vulkan. See http://skbug.com/8705
248*c8dee2aaSAndroid Build Coastguard Worker // and http://skbug.com/8275
249*c8dee2aaSAndroid Build Coastguard Worker // And Direct3D, for similar reasons.
250*c8dee2aaSAndroid Build Coastguard Worker GrBackendApi api = skgpu::ganesh::ContextTypeBackend(contextType);
251*c8dee2aaSAndroid Build Coastguard Worker if (api == GrBackendApi::kUnsupported || api == GrBackendApi::kVulkan ||
252*c8dee2aaSAndroid Build Coastguard Worker api == GrBackendApi::kDirect3D) {
253*c8dee2aaSAndroid Build Coastguard Worker continue;
254*c8dee2aaSAndroid Build Coastguard Worker }
255*c8dee2aaSAndroid Build Coastguard Worker DeathFn contextKillers[] = {destroy, abandon, releaseResourcesAndAbandon};
256*c8dee2aaSAndroid Build Coastguard Worker for (const DeathFn& contextDeath : contextKillers) {
257*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::GrContextFactory factory;
258*c8dee2aaSAndroid Build Coastguard Worker auto ctx = factory.get(contextType);
259*c8dee2aaSAndroid Build Coastguard Worker if (!ctx) {
260*c8dee2aaSAndroid Build Coastguard Worker continue;
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker
263*c8dee2aaSAndroid Build Coastguard Worker auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(ctx,
264*c8dee2aaSAndroid Build Coastguard Worker kWidth,
265*c8dee2aaSAndroid Build Coastguard Worker kHeight,
266*c8dee2aaSAndroid Build Coastguard Worker kAlpha_8_SkColorType,
267*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
268*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kNo);
269*c8dee2aaSAndroid Build Coastguard Worker if (!mbet) {
270*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not create texture alpha texture.");
271*c8dee2aaSAndroid Build Coastguard Worker continue;
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
275*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType);
276*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(ctx, skgpu::Budgeted::kNo, info);
277*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
278*c8dee2aaSAndroid Build Coastguard Worker
279*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker promiseChecker(mbet->texture(), reporter, false);
280*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(SkImages::PromiseTextureFrom(ctx->threadSafeProxy(),
281*c8dee2aaSAndroid Build Coastguard Worker mbet->texture().getBackendFormat(),
282*c8dee2aaSAndroid Build Coastguard Worker {kWidth, kHeight},
283*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
284*c8dee2aaSAndroid Build Coastguard Worker kTopLeft_GrSurfaceOrigin,
285*c8dee2aaSAndroid Build Coastguard Worker kAlpha_8_SkColorType,
286*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
287*c8dee2aaSAndroid Build Coastguard Worker /*color space*/ nullptr,
288*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker::Fulfill,
289*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker::Release,
290*c8dee2aaSAndroid Build Coastguard Worker &promiseChecker));
291*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image);
292*c8dee2aaSAndroid Build Coastguard Worker
293*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 0, 0);
294*c8dee2aaSAndroid Build Coastguard Worker image.reset();
295*c8dee2aaSAndroid Build Coastguard Worker // If the surface still holds a ref to the context then the factory will not be able
296*c8dee2aaSAndroid Build Coastguard Worker // to destroy the context (and instead will release-all-and-abandon).
297*c8dee2aaSAndroid Build Coastguard Worker surface.reset();
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker ctx->flushAndSubmit();
300*c8dee2aaSAndroid Build Coastguard Worker contextDeath(&factory, ctx);
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker check_all_done(reporter, promiseChecker);
303*c8dee2aaSAndroid Build Coastguard Worker }
304*c8dee2aaSAndroid Build Coastguard Worker }
305*c8dee2aaSAndroid Build Coastguard Worker }
306*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache,reporter,ctxInfo,CtsEnforcement::kNever)307*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache,
308*c8dee2aaSAndroid Build Coastguard Worker reporter,
309*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
310*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kNever) {
311*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu;
312*c8dee2aaSAndroid Build Coastguard Worker
313*c8dee2aaSAndroid Build Coastguard Worker const int kWidth = 10;
314*c8dee2aaSAndroid Build Coastguard Worker const int kHeight = 10;
315*c8dee2aaSAndroid Build Coastguard Worker
316*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
317*c8dee2aaSAndroid Build Coastguard Worker
318*c8dee2aaSAndroid Build Coastguard Worker Protected isProtected = Protected(dContext->priv().caps()->supportsProtectedContent());
319*c8dee2aaSAndroid Build Coastguard Worker
320*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture backendTex = dContext->createBackendTexture(kWidth,
321*c8dee2aaSAndroid Build Coastguard Worker kHeight,
322*c8dee2aaSAndroid Build Coastguard Worker kAlpha_8_SkColorType,
323*c8dee2aaSAndroid Build Coastguard Worker SkColors::kTransparent,
324*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
325*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kNo,
326*c8dee2aaSAndroid Build Coastguard Worker isProtected);
327*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, backendTex.isValid());
328*c8dee2aaSAndroid Build Coastguard Worker
329*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info =
330*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
331*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, info);
332*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
333*c8dee2aaSAndroid Build Coastguard Worker
334*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker promiseChecker(backendTex, reporter, false);
335*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(SkImages::PromiseTextureFrom(dContext->threadSafeProxy(),
336*c8dee2aaSAndroid Build Coastguard Worker backendTex.getBackendFormat(),
337*c8dee2aaSAndroid Build Coastguard Worker {kWidth, kHeight},
338*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
339*c8dee2aaSAndroid Build Coastguard Worker kTopLeft_GrSurfaceOrigin,
340*c8dee2aaSAndroid Build Coastguard Worker kAlpha_8_SkColorType,
341*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
342*c8dee2aaSAndroid Build Coastguard Worker nullptr,
343*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker::Fulfill,
344*c8dee2aaSAndroid Build Coastguard Worker PromiseTextureChecker::Release,
345*c8dee2aaSAndroid Build Coastguard Worker &promiseChecker));
346*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image);
347*c8dee2aaSAndroid Build Coastguard Worker
348*c8dee2aaSAndroid Build Coastguard Worker // Make the cache full. This tests that we don't preemptively purge cached textures for
349*c8dee2aaSAndroid Build Coastguard Worker // fulfillment due to cache pressure.
350*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kMaxBytes = 1;
351*c8dee2aaSAndroid Build Coastguard Worker dContext->setResourceCacheLimit(kMaxBytes);
352*c8dee2aaSAndroid Build Coastguard Worker TArray<sk_sp<GrTexture>> textures;
353*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 5; ++i) {
354*c8dee2aaSAndroid Build Coastguard Worker auto format = dContext->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
355*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kNo);
356*c8dee2aaSAndroid Build Coastguard Worker textures.emplace_back(dContext->priv().resourceProvider()->createTexture(
357*c8dee2aaSAndroid Build Coastguard Worker {100, 100},
358*c8dee2aaSAndroid Build Coastguard Worker format,
359*c8dee2aaSAndroid Build Coastguard Worker GrTextureType::k2D,
360*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kNo,
361*c8dee2aaSAndroid Build Coastguard Worker 1,
362*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
363*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kYes,
364*c8dee2aaSAndroid Build Coastguard Worker isProtected,
365*c8dee2aaSAndroid Build Coastguard Worker /*label=*/"PromiseImageTextureFullCacheTest"));
366*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, textures[i]);
367*c8dee2aaSAndroid Build Coastguard Worker }
368*c8dee2aaSAndroid Build Coastguard Worker
369*c8dee2aaSAndroid Build Coastguard Worker size_t bytesUsed;
370*c8dee2aaSAndroid Build Coastguard Worker
371*c8dee2aaSAndroid Build Coastguard Worker dContext->getResourceCacheUsage(nullptr, &bytesUsed);
372*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, bytesUsed > kMaxBytes);
373*c8dee2aaSAndroid Build Coastguard Worker
374*c8dee2aaSAndroid Build Coastguard Worker // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are
375*c8dee2aaSAndroid Build Coastguard Worker // properly ordered.
376*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 0, 0);
377*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
378*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 1, 0);
379*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
380*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 2, 0);
381*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
382*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 3, 0);
383*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
384*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 4, 0);
385*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
386*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 5, 0);
387*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
388*c8dee2aaSAndroid Build Coastguard Worker // Must call these to ensure that all callbacks are performed before the checker is destroyed.
389*c8dee2aaSAndroid Build Coastguard Worker image.reset();
390*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(GrSyncCpu::kYes);
391*c8dee2aaSAndroid Build Coastguard Worker
392*c8dee2aaSAndroid Build Coastguard Worker dContext->deleteBackendTexture(backendTex);
393*c8dee2aaSAndroid Build Coastguard Worker }
394*c8dee2aaSAndroid Build Coastguard Worker
395*c8dee2aaSAndroid Build Coastguard Worker // Test case where promise image fulfill returns nullptr.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill,reporter,ctxInfo,CtsEnforcement::kNever)396*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill,
397*c8dee2aaSAndroid Build Coastguard Worker reporter,
398*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
399*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kNever) {
400*c8dee2aaSAndroid Build Coastguard Worker const int kWidth = 10;
401*c8dee2aaSAndroid Build Coastguard Worker const int kHeight = 10;
402*c8dee2aaSAndroid Build Coastguard Worker
403*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
404*c8dee2aaSAndroid Build Coastguard Worker
405*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat backendFormat =
406*c8dee2aaSAndroid Build Coastguard Worker dContext->defaultBackendFormat(kRGBA_8888_SkColorType, GrRenderable::kYes);
407*c8dee2aaSAndroid Build Coastguard Worker if (!backendFormat.isValid()) {
408*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "No valid default kRGBA_8888 texture format.");
409*c8dee2aaSAndroid Build Coastguard Worker return;
410*c8dee2aaSAndroid Build Coastguard Worker }
411*c8dee2aaSAndroid Build Coastguard Worker
412*c8dee2aaSAndroid Build Coastguard Worker struct Counts {
413*c8dee2aaSAndroid Build Coastguard Worker int fFulfillCount = 0;
414*c8dee2aaSAndroid Build Coastguard Worker int fReleaseCount = 0;
415*c8dee2aaSAndroid Build Coastguard Worker } counts;
416*c8dee2aaSAndroid Build Coastguard Worker auto fulfill = [](SkImages::PromiseImageTextureContext ctx) {
417*c8dee2aaSAndroid Build Coastguard Worker ++static_cast<Counts*>(ctx)->fFulfillCount;
418*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<GrPromiseImageTexture>();
419*c8dee2aaSAndroid Build Coastguard Worker };
420*c8dee2aaSAndroid Build Coastguard Worker auto release = [](SkImages::PromiseImageTextureContext ctx) {
421*c8dee2aaSAndroid Build Coastguard Worker ++static_cast<Counts*>(ctx)->fReleaseCount;
422*c8dee2aaSAndroid Build Coastguard Worker };
423*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
424*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg(SkImages::PromiseTextureFrom(dContext->threadSafeProxy(),
425*c8dee2aaSAndroid Build Coastguard Worker backendFormat,
426*c8dee2aaSAndroid Build Coastguard Worker {kWidth, kHeight},
427*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
428*c8dee2aaSAndroid Build Coastguard Worker texOrigin,
429*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
430*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
431*c8dee2aaSAndroid Build Coastguard Worker nullptr,
432*c8dee2aaSAndroid Build Coastguard Worker fulfill,
433*c8dee2aaSAndroid Build Coastguard Worker release,
434*c8dee2aaSAndroid Build Coastguard Worker &counts));
435*c8dee2aaSAndroid Build Coastguard Worker
436*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
437*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, info);
438*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
439*c8dee2aaSAndroid Build Coastguard Worker // Draw the image a few different ways.
440*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
441*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
442*c8dee2aaSAndroid Build Coastguard Worker paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
443*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0, SkSamplingOptions(), &paint);
444*c8dee2aaSAndroid Build Coastguard Worker auto shader = refImg->makeShader(SkSamplingOptions());
445*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, shader);
446*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(std::move(shader));
447*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeWH(1,1), paint);
448*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(nullptr);
449*c8dee2aaSAndroid Build Coastguard Worker refImg.reset();
450*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
451*c8dee2aaSAndroid Build Coastguard Worker // We should only call each callback once and we should have made all the calls by this point.
452*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, counts.fFulfillCount == 1);
453*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, counts.fReleaseCount == 1);
454*c8dee2aaSAndroid Build Coastguard Worker }
455