blob: 5f8c7c6b0f8c3b51f9831d618bc9580187265d12 [file] [log] [blame]
Greg Daniela8d92112018-03-09 12:05:04 -05001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tests/Test.h"
Greg Daniela8d92112018-03-09 12:05:04 -05009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkColorFilter.h"
11#include "include/core/SkPromiseImageTexture.h"
12#include "include/gpu/GrBackendSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040013#include "include/gpu/GrDirectContext.h"
Adlai Hollera0693042020-10-14 11:23:11 -040014#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrGpu.h"
Robert Phillips1a82a4e2021-07-01 10:27:44 -040016#include "src/gpu/GrResourceProvider.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000017#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/image/SkImage_Gpu.h"
Brian Salomon72050802020-10-12 20:45:06 -040019#include "tools/gpu/ManagedBackendTexture.h"
Greg Daniela8d92112018-03-09 12:05:04 -050020
21using namespace sk_gpu_test;
22
23struct PromiseTextureChecker {
Brian Salomon9bc76d92019-01-24 12:18:33 -050024 // shared indicates whether the backend texture is used to fulfill more than one promise
25 // image.
Brian Salomonf1432742020-11-09 15:40:27 -050026 explicit PromiseTextureChecker(const GrBackendTexture& tex,
27 skiatest::Reporter* reporter,
Brian Salomon9bc76d92019-01-24 12:18:33 -050028 bool shared)
Brian Salomonf1432742020-11-09 15:40:27 -050029 : fTexture(SkPromiseImageTexture::Make(tex)), fReporter(reporter), fShared(shared) {}
Brian Salomon3f4cd772019-01-11 16:03:19 -050030 sk_sp<SkPromiseImageTexture> fTexture;
Brian Salomon9bc76d92019-01-24 12:18:33 -050031 skiatest::Reporter* fReporter;
32 bool fShared;
Brian Salomonf1432742020-11-09 15:40:27 -050033 int fFulfillCount = 0;
34 int fReleaseCount = 0;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050035
36 /**
Brian Salomon7d88f312019-02-28 10:03:03 -050037 * Releases the SkPromiseImageTexture. Used to test that cached GrTexture representations
38 * in the cache are freed.
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050039 */
Brian Salomon7d88f312019-02-28 10:03:03 -050040 void releaseTexture() { fTexture.reset(); }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050041
42 SkTArray<GrUniqueKey> uniqueKeys() const {
Brian Salomon3f4cd772019-01-11 16:03:19 -050043 return fTexture->testingOnly_uniqueKeysToInvalidate();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050044 }
45
Brian Salomon3f4cd772019-01-11 16:03:19 -050046 static sk_sp<SkPromiseImageTexture> Fulfill(void* self) {
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050047 auto checker = static_cast<PromiseTextureChecker*>(self);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050048 checker->fFulfillCount++;
Brian Salomon3f4cd772019-01-11 16:03:19 -050049 return checker->fTexture;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050050 }
Brian Salomonf1432742020-11-09 15:40:27 -050051 static void Release(void* self) { static_cast<PromiseTextureChecker*>(self)->fReleaseCount++; }
Greg Daniela8d92112018-03-09 12:05:04 -050052};
53
Brian Salomon0cc57542019-03-08 13:28:46 -050054enum class ReleaseBalanceExpectation {
Brian Salomonf55e8d52019-01-30 17:28:20 -050055 kBalanced,
Brian Salomon0cc57542019-03-08 13:28:46 -050056 kAllUnbalanced,
Brian Salomon0cc57542019-03-08 13:28:46 -050057 kUnknown,
58 kUnbalancedByOne,
59 kBalancedOrOffByOne,
60};
61
62static void check_fulfill_and_release_cnts(skiatest::Reporter* reporter,
63 const PromiseTextureChecker& promiseChecker,
Greg Daniela8d92112018-03-09 12:05:04 -050064 int expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -050065 ReleaseBalanceExpectation releaseBalanceExpecation) {
Brian Salomon0cc57542019-03-08 13:28:46 -050066 REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt);
67 if (!expectedFulfillCnt) {
68 // Release and Done should only ever be called after Fulfill.
69 REPORTER_ASSERT(reporter, !promiseChecker.fReleaseCount);
Brian Salomon0cc57542019-03-08 13:28:46 -050070 return;
Greg Daniela8d92112018-03-09 12:05:04 -050071 }
Brian Salomon0cc57542019-03-08 13:28:46 -050072 int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
73 switch (releaseBalanceExpecation) {
74 case ReleaseBalanceExpectation::kBalanced:
75 REPORTER_ASSERT(reporter, !releaseDiff);
76 break;
77 case ReleaseBalanceExpectation::kAllUnbalanced:
78 REPORTER_ASSERT(reporter, releaseDiff == promiseChecker.fFulfillCount);
79 break;
Brian Salomonf1432742020-11-09 15:40:27 -050080 case ReleaseBalanceExpectation::kUnknown:
81 REPORTER_ASSERT(reporter,
82 releaseDiff >= 0 && releaseDiff <= promiseChecker.fFulfillCount);
83 break;
Brian Salomon0cc57542019-03-08 13:28:46 -050084 case ReleaseBalanceExpectation::kUnbalancedByOne:
85 REPORTER_ASSERT(reporter, releaseDiff == 1);
86 break;
Brian Salomonf1432742020-11-09 15:40:27 -050087 case ReleaseBalanceExpectation::kBalancedOrOffByOne:
88 REPORTER_ASSERT(reporter, releaseDiff == 0 || releaseDiff == 1);
Brian Salomon0cc57542019-03-08 13:28:46 -050089 break;
Greg Daniela8d92112018-03-09 12:05:04 -050090 }
Brian Salomon0cc57542019-03-08 13:28:46 -050091}
Greg Daniela8d92112018-03-09 12:05:04 -050092
Brian Salomon0cc57542019-03-08 13:28:46 -050093static void check_unfulfilled(const PromiseTextureChecker& promiseChecker,
94 skiatest::Reporter* reporter) {
95 check_fulfill_and_release_cnts(reporter, promiseChecker, 0,
Brian Salomonf1432742020-11-09 15:40:27 -050096 ReleaseBalanceExpectation::kBalanced);
Brian Salomon0cc57542019-03-08 13:28:46 -050097}
98
99static void check_only_fulfilled(skiatest::Reporter* reporter,
100 const PromiseTextureChecker& promiseChecker,
101 int expectedFulfillCnt = 1) {
102 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -0500103 ReleaseBalanceExpectation::kAllUnbalanced);
Brian Salomon0cc57542019-03-08 13:28:46 -0500104}
105
106static void check_all_flushed_but_not_synced(skiatest::Reporter* reporter,
107 const PromiseTextureChecker& promiseChecker,
108 GrBackendApi api,
109 int expectedFulfillCnt = 1) {
Brian Salomonf1432742020-11-09 15:40:27 -0500110 ReleaseBalanceExpectation releaseBalanceExpectation = ReleaseBalanceExpectation::kBalanced;
Greg Daniela026e912020-06-24 13:38:08 -0400111 // On Vulkan and D3D Done isn't guaranteed to be called until a sync has occurred.
112 if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDirect3D) {
Brian Salomonf1432742020-11-09 15:40:27 -0500113 releaseBalanceExpectation = expectedFulfillCnt == 1
114 ? ReleaseBalanceExpectation::kBalancedOrOffByOne
115 : ReleaseBalanceExpectation::kUnknown;
Greg Daniel7278d682018-03-16 14:57:21 -0400116 }
Brian Salomon0cc57542019-03-08 13:28:46 -0500117 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -0500118 releaseBalanceExpectation);
Brian Salomon0cc57542019-03-08 13:28:46 -0500119}
Greg Daniel7278d682018-03-16 14:57:21 -0400120
Brian Salomon0cc57542019-03-08 13:28:46 -0500121static void check_all_done(skiatest::Reporter* reporter,
122 const PromiseTextureChecker& promiseChecker,
123 int expectedFulfillCnt = 1) {
124 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -0500125 ReleaseBalanceExpectation::kBalanced);
Greg Daniela8d92112018-03-09 12:05:04 -0500126}
127
Brian Salomon7d88f312019-02-28 10:03:03 -0500128DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
Brian Salomonf55e8d52019-01-30 17:28:20 -0500129 const int kWidth = 10;
130 const int kHeight = 10;
131
Robert Phillips6d344c32020-07-06 10:56:46 -0400132 auto ctx = ctxInfo.directContext();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500133
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400134 GrBackendTexture backendTex = ctx->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400135 kWidth, kHeight, kRGBA_8888_SkColorType,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400136 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes, GrProtected::kNo);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500137 REPORTER_ASSERT(reporter, backendTex.isValid());
138
139 GrBackendFormat backendFormat = backendTex.getBackendFormat();
140 REPORTER_ASSERT(reporter, backendFormat.isValid());
141
142 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
143 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
Adlai Hollerdced31f2021-02-19 12:33:46 -0500144 sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(ctx->threadSafeProxy(),
Brian Salomonf1432742020-11-09 15:40:27 -0500145 backendFormat,
146 {kWidth, kHeight},
147 GrMipmapped::kNo,
148 texOrigin,
149 kRGBA_8888_SkColorType,
150 kPremul_SkAlphaType,
151 nullptr,
152 PromiseTextureChecker::Fulfill,
153 PromiseTextureChecker::Release,
154 &promiseChecker));
Brian Salomonf55e8d52019-01-30 17:28:20 -0500155
156 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
157 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
158 SkCanvas* canvas = surface->getCanvas();
159
Brian Salomond716d442019-03-07 15:23:30 +0000160 canvas->drawImage(refImg, 0, 0);
Brian Salomon0cc57542019-03-08 13:28:46 -0500161 check_unfulfilled(promiseChecker, reporter);
Brian Salomond716d442019-03-07 15:23:30 +0000162
Greg Daniel0a2464f2020-05-14 15:45:44 -0400163 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500164 // We still own the image so we should not have called Release or Done.
165 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500166
Brian Salomon725f1582021-02-12 12:10:43 -0500167 ctx->submit(true);
Brian Salomon0cc57542019-03-08 13:28:46 -0500168 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500169
170 canvas->drawImage(refImg, 0, 0);
171 canvas->drawImage(refImg, 0, 0);
172
Brian Salomon725f1582021-02-12 12:10:43 -0500173 surface->flushAndSubmit(true);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500174
Brian Salomon0cc57542019-03-08 13:28:46 -0500175 // Image should still be fulfilled from the first time we drew/flushed it.
176 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500177
178 canvas->drawImage(refImg, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400179 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500180 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500181
182 canvas->drawImage(refImg, 0, 0);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500183 refImg.reset();
Brian Salomon0cc57542019-03-08 13:28:46 -0500184 // We no longer own the image but the last draw is still unflushed.
185 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500186
Greg Daniel0a2464f2020-05-14 15:45:44 -0400187 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500188 // Flushing should have called Release. Depending on the backend and timing it may have called
189 // done.
190 check_all_flushed_but_not_synced(reporter, promiseChecker, ctx->backend());
Brian Salomon725f1582021-02-12 12:10:43 -0500191 ctx->submit(true);
Brian Salomon0cc57542019-03-08 13:28:46 -0500192 // Now Done should definitely have been called.
193 check_all_done(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500194
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400195 ctx->deleteBackendTexture(backendTex);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500196}
197
Brian Salomon9bc76d92019-01-24 12:18:33 -0500198DEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) {
199 const int kWidth = 10;
200 const int kHeight = 10;
201
202 // Different ways of killing contexts.
Robert Phillips58adb342020-07-23 09:41:57 -0400203 using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrDirectContext*)>;
204 DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext*) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500205 factory->destroyContexts();
206 };
Robert Phillips58adb342020-07-23 09:41:57 -0400207 DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext* dContext) {
208 dContext->abandonContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500209 };
210 DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory,
Robert Phillips58adb342020-07-23 09:41:57 -0400211 GrDirectContext* dContext) {
212 dContext->releaseResourcesAndAbandonContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500213 };
214
215 for (int type = 0; type < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++type) {
216 auto contextType = static_cast<sk_gpu_test::GrContextFactory::ContextType>(type);
217 // These tests are difficult to get working with Vulkan. See http://skbug.com/8705
218 // and http://skbug.com/8275
Stephen Whiteb007bb22020-06-04 09:02:04 -0400219 // Also problematic on Dawn; see http://skbug.com/10326
Jim Van Verthaed25a92020-06-23 15:00:04 -0400220 // And Direct3D, for similar reasons.
Brian Salomon9bc76d92019-01-24 12:18:33 -0500221 GrBackendApi api = sk_gpu_test::GrContextFactory::ContextTypeBackend(contextType);
Jim Van Verthaed25a92020-06-23 15:00:04 -0400222 if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDawn ||
223 api == GrBackendApi::kDirect3D) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500224 continue;
225 }
226 DeathFn contextKillers[] = {destroy, abandon, releaseResourcesAndAbandon};
John Stilesbd3ffa42020-07-30 20:24:57 -0400227 for (const DeathFn& contextDeath : contextKillers) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500228 sk_gpu_test::GrContextFactory factory;
229 auto ctx = factory.get(contextType);
230 if (!ctx) {
231 continue;
232 }
Brian Salomon9bc76d92019-01-24 12:18:33 -0500233
Brian Salomon72050802020-10-12 20:45:06 -0400234 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(ctx,
235 kWidth,
236 kHeight,
237 kAlpha_8_SkColorType,
238 GrMipmapped::kNo,
239 GrRenderable::kNo);
240 if (!mbet) {
241 ERRORF(reporter, "Could not create texture alpha texture.");
242 continue;
243 }
Brian Salomon9bc76d92019-01-24 12:18:33 -0500244
245 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
246 kPremul_SkAlphaType);
247 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
248 SkCanvas* canvas = surface->getCanvas();
249
Brian Salomon72050802020-10-12 20:45:06 -0400250 PromiseTextureChecker promiseChecker(mbet->texture(), reporter, false);
Adlai Hollerdced31f2021-02-19 12:33:46 -0500251 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(ctx->threadSafeProxy(),
Brian Salomonf1432742020-11-09 15:40:27 -0500252 mbet->texture().getBackendFormat(),
253 {kWidth, kHeight},
254 GrMipmapped::kNo,
255 kTopLeft_GrSurfaceOrigin,
256 kAlpha_8_SkColorType,
257 kPremul_SkAlphaType,
258 /*color space*/ nullptr,
259 PromiseTextureChecker::Fulfill,
260 PromiseTextureChecker::Release,
261 &promiseChecker));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500262 REPORTER_ASSERT(reporter, image);
263
264 canvas->drawImage(image, 0, 0);
265 image.reset();
266 // If the surface still holds a ref to the context then the factory will not be able
267 // to destroy the context (and instead will release-all-and-abandon).
268 surface.reset();
269
Greg Daniel0a2464f2020-05-14 15:45:44 -0400270 ctx->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500271 contextDeath(&factory, ctx);
272
Brian Salomon0cc57542019-03-08 13:28:46 -0500273 check_all_done(reporter, promiseChecker);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500274 }
275 }
276}
277
278DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxInfo) {
279 const int kWidth = 10;
280 const int kHeight = 10;
281
Robert Phillips58adb342020-07-23 09:41:57 -0400282 auto dContext = ctxInfo.directContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500283
Robert Phillips58adb342020-07-23 09:41:57 -0400284 GrBackendTexture backendTex = dContext->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400285 kWidth, kHeight, kAlpha_8_SkColorType,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400286 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500287 REPORTER_ASSERT(reporter, backendTex.isValid());
288
289 SkImageInfo info =
290 SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
Robert Phillips58adb342020-07-23 09:41:57 -0400291 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500292 SkCanvas* canvas = surface->getCanvas();
293
294 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
Adlai Hollerdced31f2021-02-19 12:33:46 -0500295 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(dContext->threadSafeProxy(),
Brian Salomonf1432742020-11-09 15:40:27 -0500296 backendTex.getBackendFormat(),
297 {kWidth, kHeight},
298 GrMipmapped::kNo,
299 kTopLeft_GrSurfaceOrigin,
300 kAlpha_8_SkColorType,
301 kPremul_SkAlphaType,
302 nullptr,
303 PromiseTextureChecker::Fulfill,
304 PromiseTextureChecker::Release,
305 &promiseChecker));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500306 REPORTER_ASSERT(reporter, image);
307
308 // Make the cache full. This tests that we don't preemptively purge cached textures for
309 // fulfillment due to cache pressure.
Robert Phillipscf39f372019-09-03 10:29:20 -0400310 static constexpr int kMaxBytes = 1;
Robert Phillips58adb342020-07-23 09:41:57 -0400311 dContext->setResourceCacheLimit(kMaxBytes);
Robert Phillipscf39f372019-09-03 10:29:20 -0400312 SkTArray<sk_sp<GrTexture>> textures;
313 for (int i = 0; i < 5; ++i) {
Robert Phillips58adb342020-07-23 09:41:57 -0400314 auto format = dContext->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
315 GrRenderable::kNo);
316 textures.emplace_back(dContext->priv().resourceProvider()->createTexture(
Greg Daniel0e9d34d2021-08-13 16:20:18 -0400317 {100, 100}, format, GrTextureType::k2D, GrRenderable::kNo, 1, GrMipmapped::kNo,
318 SkBudgeted::kYes, GrProtected::kNo));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500319 REPORTER_ASSERT(reporter, textures[i]);
320 }
321
Robert Phillipscf39f372019-09-03 10:29:20 -0400322 size_t bytesUsed;
323
Robert Phillips58adb342020-07-23 09:41:57 -0400324 dContext->getResourceCacheUsage(nullptr, &bytesUsed);
Robert Phillipscf39f372019-09-03 10:29:20 -0400325 REPORTER_ASSERT(reporter, bytesUsed > kMaxBytes);
326
Brian Salomon9bc76d92019-01-24 12:18:33 -0500327 // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are
328 // properly ordered.
329 canvas->drawImage(image, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400330 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500331 canvas->drawImage(image, 1, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400332 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500333 canvas->drawImage(image, 2, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400334 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500335 canvas->drawImage(image, 3, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400336 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500337 canvas->drawImage(image, 4, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400338 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500339 canvas->drawImage(image, 5, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400340 surface->flushAndSubmit();
Brian Salomon876a0172019-03-08 11:12:14 -0500341 // Must call these to ensure that all callbacks are performed before the checker is destroyed.
342 image.reset();
Brian Salomon725f1582021-02-12 12:10:43 -0500343 dContext->flushAndSubmit(true);
Brian Salomon876a0172019-03-08 11:12:14 -0500344
Robert Phillips58adb342020-07-23 09:41:57 -0400345 dContext->deleteBackendTexture(backendTex);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500346}
Brian Salomond538d3d2019-04-04 12:18:17 -0400347
348// Test case where promise image fulfill returns nullptr.
349DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill, reporter, ctxInfo) {
350 const int kWidth = 10;
351 const int kHeight = 10;
352
Robert Phillips58adb342020-07-23 09:41:57 -0400353 auto dContext = ctxInfo.directContext();
Brian Salomond538d3d2019-04-04 12:18:17 -0400354
Brian Salomon72050802020-10-12 20:45:06 -0400355 GrBackendFormat backendFormat =
356 dContext->defaultBackendFormat(kRGBA_8888_SkColorType, GrRenderable::kYes);
357 if (!backendFormat.isValid()) {
358 ERRORF(reporter, "No valid default kRGBA_8888 texture format.");
359 return;
360 }
Brian Salomond538d3d2019-04-04 12:18:17 -0400361
362 struct Counts {
363 int fFulfillCount = 0;
364 int fReleaseCount = 0;
Brian Salomond538d3d2019-04-04 12:18:17 -0400365 } counts;
366 auto fulfill = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
367 ++static_cast<Counts*>(ctx)->fFulfillCount;
368 return sk_sp<SkPromiseImageTexture>();
369 };
370 auto release = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
371 ++static_cast<Counts*>(ctx)->fReleaseCount;
372 };
Brian Salomond538d3d2019-04-04 12:18:17 -0400373 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
Adlai Hollerdced31f2021-02-19 12:33:46 -0500374 sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(dContext->threadSafeProxy(),
Brian Salomonf1432742020-11-09 15:40:27 -0500375 backendFormat,
376 {kWidth, kHeight},
377 GrMipmapped::kNo,
378 texOrigin,
379 kRGBA_8888_SkColorType,
380 kPremul_SkAlphaType,
381 nullptr,
382 fulfill,
383 release,
384 &counts));
Brian Salomond538d3d2019-04-04 12:18:17 -0400385
386 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
Robert Phillips58adb342020-07-23 09:41:57 -0400387 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Brian Salomond538d3d2019-04-04 12:18:17 -0400388 SkCanvas* canvas = surface->getCanvas();
389 // Draw the image a few different ways.
390 canvas->drawImage(refImg, 0, 0);
391 SkPaint paint;
Mike Reedb286bc22019-04-08 16:23:20 -0400392 paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
Mike Reed039f1362021-01-27 21:21:08 -0500393 canvas->drawImage(refImg, 0, 0, SkSamplingOptions(), &paint);
Mike Reedb612b6c2020-12-08 21:58:35 -0500394 auto shader = refImg->makeShader(SkSamplingOptions());
Brian Salomond538d3d2019-04-04 12:18:17 -0400395 REPORTER_ASSERT(reporter, shader);
396 paint.setShader(std::move(shader));
397 canvas->drawRect(SkRect::MakeWH(1,1), paint);
398 paint.setShader(nullptr);
399 refImg.reset();
Greg Daniel0a2464f2020-05-14 15:45:44 -0400400 surface->flushAndSubmit();
Brian Salomond538d3d2019-04-04 12:18:17 -0400401 // We should only call each callback once and we should have made all the calls by this point.
402 REPORTER_ASSERT(reporter, counts.fFulfillCount == 1);
403 REPORTER_ASSERT(reporter, counts.fReleaseCount == 1);
Brian Salomond538d3d2019-04-04 12:18:17 -0400404}