blob: 3d8057fb49befe8398d97adcc89f119940233ebf [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"
Greg Daniel456f9b52020-03-05 19:14:18 +000016#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/image/SkImage_Gpu.h"
Brian Salomon72050802020-10-12 20:45:06 -040018#include "tools/gpu/ManagedBackendTexture.h"
Greg Daniela8d92112018-03-09 12:05:04 -050019
20using namespace sk_gpu_test;
21
22struct PromiseTextureChecker {
Brian Salomon9bc76d92019-01-24 12:18:33 -050023 // shared indicates whether the backend texture is used to fulfill more than one promise
24 // image.
Brian Salomonf1432742020-11-09 15:40:27 -050025 explicit PromiseTextureChecker(const GrBackendTexture& tex,
26 skiatest::Reporter* reporter,
Brian Salomon9bc76d92019-01-24 12:18:33 -050027 bool shared)
Brian Salomonf1432742020-11-09 15:40:27 -050028 : fTexture(SkPromiseImageTexture::Make(tex)), fReporter(reporter), fShared(shared) {}
Brian Salomon3f4cd772019-01-11 16:03:19 -050029 sk_sp<SkPromiseImageTexture> fTexture;
Brian Salomon9bc76d92019-01-24 12:18:33 -050030 skiatest::Reporter* fReporter;
31 bool fShared;
Brian Salomonf1432742020-11-09 15:40:27 -050032 int fFulfillCount = 0;
33 int fReleaseCount = 0;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050034
35 /**
Brian Salomon7d88f312019-02-28 10:03:03 -050036 * Releases the SkPromiseImageTexture. Used to test that cached GrTexture representations
37 * in the cache are freed.
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050038 */
Brian Salomon7d88f312019-02-28 10:03:03 -050039 void releaseTexture() { fTexture.reset(); }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050040
41 SkTArray<GrUniqueKey> uniqueKeys() const {
Brian Salomon3f4cd772019-01-11 16:03:19 -050042 return fTexture->testingOnly_uniqueKeysToInvalidate();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050043 }
44
Brian Salomon3f4cd772019-01-11 16:03:19 -050045 static sk_sp<SkPromiseImageTexture> Fulfill(void* self) {
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050046 auto checker = static_cast<PromiseTextureChecker*>(self);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050047 checker->fFulfillCount++;
Brian Salomon3f4cd772019-01-11 16:03:19 -050048 return checker->fTexture;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050049 }
Brian Salomonf1432742020-11-09 15:40:27 -050050 static void Release(void* self) { static_cast<PromiseTextureChecker*>(self)->fReleaseCount++; }
Greg Daniela8d92112018-03-09 12:05:04 -050051};
52
Brian Salomon0cc57542019-03-08 13:28:46 -050053enum class ReleaseBalanceExpectation {
Brian Salomonf55e8d52019-01-30 17:28:20 -050054 kBalanced,
Brian Salomon0cc57542019-03-08 13:28:46 -050055 kAllUnbalanced,
Brian Salomon0cc57542019-03-08 13:28:46 -050056 kUnknown,
57 kUnbalancedByOne,
58 kBalancedOrOffByOne,
59};
60
61static void check_fulfill_and_release_cnts(skiatest::Reporter* reporter,
62 const PromiseTextureChecker& promiseChecker,
Greg Daniela8d92112018-03-09 12:05:04 -050063 int expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -050064 ReleaseBalanceExpectation releaseBalanceExpecation) {
Brian Salomon0cc57542019-03-08 13:28:46 -050065 REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt);
66 if (!expectedFulfillCnt) {
67 // Release and Done should only ever be called after Fulfill.
68 REPORTER_ASSERT(reporter, !promiseChecker.fReleaseCount);
Brian Salomon0cc57542019-03-08 13:28:46 -050069 return;
Greg Daniela8d92112018-03-09 12:05:04 -050070 }
Brian Salomon0cc57542019-03-08 13:28:46 -050071 int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
72 switch (releaseBalanceExpecation) {
73 case ReleaseBalanceExpectation::kBalanced:
74 REPORTER_ASSERT(reporter, !releaseDiff);
75 break;
76 case ReleaseBalanceExpectation::kAllUnbalanced:
77 REPORTER_ASSERT(reporter, releaseDiff == promiseChecker.fFulfillCount);
78 break;
Brian Salomonf1432742020-11-09 15:40:27 -050079 case ReleaseBalanceExpectation::kUnknown:
80 REPORTER_ASSERT(reporter,
81 releaseDiff >= 0 && releaseDiff <= promiseChecker.fFulfillCount);
82 break;
Brian Salomon0cc57542019-03-08 13:28:46 -050083 case ReleaseBalanceExpectation::kUnbalancedByOne:
84 REPORTER_ASSERT(reporter, releaseDiff == 1);
85 break;
Brian Salomonf1432742020-11-09 15:40:27 -050086 case ReleaseBalanceExpectation::kBalancedOrOffByOne:
87 REPORTER_ASSERT(reporter, releaseDiff == 0 || releaseDiff == 1);
Brian Salomon0cc57542019-03-08 13:28:46 -050088 break;
Greg Daniela8d92112018-03-09 12:05:04 -050089 }
Brian Salomon0cc57542019-03-08 13:28:46 -050090}
Greg Daniela8d92112018-03-09 12:05:04 -050091
Brian Salomon0cc57542019-03-08 13:28:46 -050092static void check_unfulfilled(const PromiseTextureChecker& promiseChecker,
93 skiatest::Reporter* reporter) {
94 check_fulfill_and_release_cnts(reporter, promiseChecker, 0,
Brian Salomonf1432742020-11-09 15:40:27 -050095 ReleaseBalanceExpectation::kBalanced);
Brian Salomon0cc57542019-03-08 13:28:46 -050096}
97
98static void check_only_fulfilled(skiatest::Reporter* reporter,
99 const PromiseTextureChecker& promiseChecker,
100 int expectedFulfillCnt = 1) {
101 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -0500102 ReleaseBalanceExpectation::kAllUnbalanced);
Brian Salomon0cc57542019-03-08 13:28:46 -0500103}
104
105static void check_all_flushed_but_not_synced(skiatest::Reporter* reporter,
106 const PromiseTextureChecker& promiseChecker,
107 GrBackendApi api,
108 int expectedFulfillCnt = 1) {
Brian Salomonf1432742020-11-09 15:40:27 -0500109 ReleaseBalanceExpectation releaseBalanceExpectation = ReleaseBalanceExpectation::kBalanced;
Greg Daniela026e912020-06-24 13:38:08 -0400110 // On Vulkan and D3D Done isn't guaranteed to be called until a sync has occurred.
111 if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDirect3D) {
Brian Salomonf1432742020-11-09 15:40:27 -0500112 releaseBalanceExpectation = expectedFulfillCnt == 1
113 ? ReleaseBalanceExpectation::kBalancedOrOffByOne
114 : ReleaseBalanceExpectation::kUnknown;
Greg Daniel7278d682018-03-16 14:57:21 -0400115 }
Brian Salomon0cc57542019-03-08 13:28:46 -0500116 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -0500117 releaseBalanceExpectation);
Brian Salomon0cc57542019-03-08 13:28:46 -0500118}
Greg Daniel7278d682018-03-16 14:57:21 -0400119
Brian Salomon0cc57542019-03-08 13:28:46 -0500120static void check_all_done(skiatest::Reporter* reporter,
121 const PromiseTextureChecker& promiseChecker,
122 int expectedFulfillCnt = 1) {
123 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
Brian Salomonf1432742020-11-09 15:40:27 -0500124 ReleaseBalanceExpectation::kBalanced);
Greg Daniela8d92112018-03-09 12:05:04 -0500125}
126
Brian Salomon7d88f312019-02-28 10:03:03 -0500127DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
Brian Salomonf55e8d52019-01-30 17:28:20 -0500128 const int kWidth = 10;
129 const int kHeight = 10;
130
Robert Phillips6d344c32020-07-06 10:56:46 -0400131 auto ctx = ctxInfo.directContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500132 GrGpu* gpu = ctx->priv().getGpu();
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;
Brian Salomonf1432742020-11-09 15:40:27 -0500144 sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(ctx,
145 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
167 gpu->testingOnly_flushGpuAndSync();
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
Greg Daniel0a2464f2020-05-14 15:45:44 -0400173 surface->flushAndSubmit();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500174
175 gpu->testingOnly_flushGpuAndSync();
Brian Salomon0cc57542019-03-08 13:28:46 -0500176 // Image should still be fulfilled from the first time we drew/flushed it.
177 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500178
179 canvas->drawImage(refImg, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400180 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500181 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500182
183 canvas->drawImage(refImg, 0, 0);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500184 refImg.reset();
Brian Salomon0cc57542019-03-08 13:28:46 -0500185 // We no longer own the image but the last draw is still unflushed.
186 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500187
Greg Daniel0a2464f2020-05-14 15:45:44 -0400188 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500189 // Flushing should have called Release. Depending on the backend and timing it may have called
190 // done.
191 check_all_flushed_but_not_synced(reporter, promiseChecker, ctx->backend());
Brian Salomonf55e8d52019-01-30 17:28:20 -0500192 gpu->testingOnly_flushGpuAndSync();
Brian Salomon0cc57542019-03-08 13:28:46 -0500193 // Now Done should definitely have been called.
194 check_all_done(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500195
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400196 ctx->deleteBackendTexture(backendTex);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500197}
198
Brian Salomon9bc76d92019-01-24 12:18:33 -0500199DEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) {
200 const int kWidth = 10;
201 const int kHeight = 10;
202
203 // Different ways of killing contexts.
Robert Phillips58adb342020-07-23 09:41:57 -0400204 using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrDirectContext*)>;
205 DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext*) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500206 factory->destroyContexts();
207 };
Robert Phillips58adb342020-07-23 09:41:57 -0400208 DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext* dContext) {
209 dContext->abandonContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500210 };
211 DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory,
Robert Phillips58adb342020-07-23 09:41:57 -0400212 GrDirectContext* dContext) {
213 dContext->releaseResourcesAndAbandonContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500214 };
215
216 for (int type = 0; type < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++type) {
217 auto contextType = static_cast<sk_gpu_test::GrContextFactory::ContextType>(type);
218 // These tests are difficult to get working with Vulkan. See http://skbug.com/8705
219 // and http://skbug.com/8275
Stephen Whiteb007bb22020-06-04 09:02:04 -0400220 // Also problematic on Dawn; see http://skbug.com/10326
Jim Van Verthaed25a92020-06-23 15:00:04 -0400221 // And Direct3D, for similar reasons.
Brian Salomon9bc76d92019-01-24 12:18:33 -0500222 GrBackendApi api = sk_gpu_test::GrContextFactory::ContextTypeBackend(contextType);
Jim Van Verthaed25a92020-06-23 15:00:04 -0400223 if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDawn ||
224 api == GrBackendApi::kDirect3D) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500225 continue;
226 }
227 DeathFn contextKillers[] = {destroy, abandon, releaseResourcesAndAbandon};
John Stilesbd3ffa42020-07-30 20:24:57 -0400228 for (const DeathFn& contextDeath : contextKillers) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500229 sk_gpu_test::GrContextFactory factory;
230 auto ctx = factory.get(contextType);
231 if (!ctx) {
232 continue;
233 }
Brian Salomon9bc76d92019-01-24 12:18:33 -0500234
Brian Salomon72050802020-10-12 20:45:06 -0400235 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(ctx,
236 kWidth,
237 kHeight,
238 kAlpha_8_SkColorType,
239 GrMipmapped::kNo,
240 GrRenderable::kNo);
241 if (!mbet) {
242 ERRORF(reporter, "Could not create texture alpha texture.");
243 continue;
244 }
Brian Salomon9bc76d92019-01-24 12:18:33 -0500245
246 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
247 kPremul_SkAlphaType);
248 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
249 SkCanvas* canvas = surface->getCanvas();
250
Brian Salomon72050802020-10-12 20:45:06 -0400251 PromiseTextureChecker promiseChecker(mbet->texture(), reporter, false);
Brian Salomonf1432742020-11-09 15:40:27 -0500252 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(ctx,
253 mbet->texture().getBackendFormat(),
254 {kWidth, kHeight},
255 GrMipmapped::kNo,
256 kTopLeft_GrSurfaceOrigin,
257 kAlpha_8_SkColorType,
258 kPremul_SkAlphaType,
259 /*color space*/ nullptr,
260 PromiseTextureChecker::Fulfill,
261 PromiseTextureChecker::Release,
262 &promiseChecker));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500263 REPORTER_ASSERT(reporter, image);
264
265 canvas->drawImage(image, 0, 0);
266 image.reset();
267 // If the surface still holds a ref to the context then the factory will not be able
268 // to destroy the context (and instead will release-all-and-abandon).
269 surface.reset();
270
Greg Daniel0a2464f2020-05-14 15:45:44 -0400271 ctx->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500272 contextDeath(&factory, ctx);
273
Brian Salomon0cc57542019-03-08 13:28:46 -0500274 check_all_done(reporter, promiseChecker);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500275 }
276 }
277}
278
279DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxInfo) {
280 const int kWidth = 10;
281 const int kHeight = 10;
282
Robert Phillips58adb342020-07-23 09:41:57 -0400283 auto dContext = ctxInfo.directContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500284
Robert Phillips58adb342020-07-23 09:41:57 -0400285 GrBackendTexture backendTex = dContext->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400286 kWidth, kHeight, kAlpha_8_SkColorType,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400287 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500288 REPORTER_ASSERT(reporter, backendTex.isValid());
289
290 SkImageInfo info =
291 SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
Robert Phillips58adb342020-07-23 09:41:57 -0400292 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500293 SkCanvas* canvas = surface->getCanvas();
294
295 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
Brian Salomonf1432742020-11-09 15:40:27 -0500296 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(dContext,
297 backendTex.getBackendFormat(),
298 {kWidth, kHeight},
299 GrMipmapped::kNo,
300 kTopLeft_GrSurfaceOrigin,
301 kAlpha_8_SkColorType,
302 kPremul_SkAlphaType,
303 nullptr,
304 PromiseTextureChecker::Fulfill,
305 PromiseTextureChecker::Release,
306 &promiseChecker));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500307 REPORTER_ASSERT(reporter, image);
308
309 // Make the cache full. This tests that we don't preemptively purge cached textures for
310 // fulfillment due to cache pressure.
Robert Phillipscf39f372019-09-03 10:29:20 -0400311 static constexpr int kMaxBytes = 1;
Robert Phillips58adb342020-07-23 09:41:57 -0400312 dContext->setResourceCacheLimit(kMaxBytes);
Robert Phillipscf39f372019-09-03 10:29:20 -0400313 SkTArray<sk_sp<GrTexture>> textures;
314 for (int i = 0; i < 5; ++i) {
Robert Phillips58adb342020-07-23 09:41:57 -0400315 auto format = dContext->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
316 GrRenderable::kNo);
317 textures.emplace_back(dContext->priv().resourceProvider()->createTexture(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400318 {100, 100}, format, GrRenderable::kNo, 1, GrMipmapped::kNo, SkBudgeted::kYes,
Brian Salomona90382f2019-09-17 09:01:56 -0400319 GrProtected::kNo));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500320 REPORTER_ASSERT(reporter, textures[i]);
321 }
322
Robert Phillipscf39f372019-09-03 10:29:20 -0400323 size_t bytesUsed;
324
Robert Phillips58adb342020-07-23 09:41:57 -0400325 dContext->getResourceCacheUsage(nullptr, &bytesUsed);
Robert Phillipscf39f372019-09-03 10:29:20 -0400326 REPORTER_ASSERT(reporter, bytesUsed > kMaxBytes);
327
Brian Salomon9bc76d92019-01-24 12:18:33 -0500328 // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are
329 // properly ordered.
330 canvas->drawImage(image, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400331 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500332 canvas->drawImage(image, 1, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400333 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500334 canvas->drawImage(image, 2, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400335 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500336 canvas->drawImage(image, 3, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400337 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500338 canvas->drawImage(image, 4, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400339 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500340 canvas->drawImage(image, 5, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400341 surface->flushAndSubmit();
Brian Salomon876a0172019-03-08 11:12:14 -0500342 // Must call these to ensure that all callbacks are performed before the checker is destroyed.
343 image.reset();
Robert Phillips58adb342020-07-23 09:41:57 -0400344 dContext->flushAndSubmit();
345 dContext->priv().getGpu()->testingOnly_flushGpuAndSync();
Brian Salomon876a0172019-03-08 11:12:14 -0500346
Robert Phillips58adb342020-07-23 09:41:57 -0400347 dContext->deleteBackendTexture(backendTex);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500348}
Brian Salomond538d3d2019-04-04 12:18:17 -0400349
350// Test case where promise image fulfill returns nullptr.
351DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill, reporter, ctxInfo) {
352 const int kWidth = 10;
353 const int kHeight = 10;
354
Robert Phillips58adb342020-07-23 09:41:57 -0400355 auto dContext = ctxInfo.directContext();
Brian Salomond538d3d2019-04-04 12:18:17 -0400356
Brian Salomon72050802020-10-12 20:45:06 -0400357 GrBackendFormat backendFormat =
358 dContext->defaultBackendFormat(kRGBA_8888_SkColorType, GrRenderable::kYes);
359 if (!backendFormat.isValid()) {
360 ERRORF(reporter, "No valid default kRGBA_8888 texture format.");
361 return;
362 }
Brian Salomond538d3d2019-04-04 12:18:17 -0400363
364 struct Counts {
365 int fFulfillCount = 0;
366 int fReleaseCount = 0;
Brian Salomond538d3d2019-04-04 12:18:17 -0400367 } counts;
368 auto fulfill = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
369 ++static_cast<Counts*>(ctx)->fFulfillCount;
370 return sk_sp<SkPromiseImageTexture>();
371 };
372 auto release = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
373 ++static_cast<Counts*>(ctx)->fReleaseCount;
374 };
Brian Salomond538d3d2019-04-04 12:18:17 -0400375 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
Brian Salomonf1432742020-11-09 15:40:27 -0500376 sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(dContext,
377 backendFormat,
378 {kWidth, kHeight},
379 GrMipmapped::kNo,
380 texOrigin,
381 kRGBA_8888_SkColorType,
382 kPremul_SkAlphaType,
383 nullptr,
384 fulfill,
385 release,
386 &counts));
Brian Salomond538d3d2019-04-04 12:18:17 -0400387
388 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
Robert Phillips58adb342020-07-23 09:41:57 -0400389 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Brian Salomond538d3d2019-04-04 12:18:17 -0400390 SkCanvas* canvas = surface->getCanvas();
391 // Draw the image a few different ways.
392 canvas->drawImage(refImg, 0, 0);
393 SkPaint paint;
Mike Reedb286bc22019-04-08 16:23:20 -0400394 paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
Mike Reed039f1362021-01-27 21:21:08 -0500395 canvas->drawImage(refImg, 0, 0, SkSamplingOptions(), &paint);
Mike Reedb612b6c2020-12-08 21:58:35 -0500396 auto shader = refImg->makeShader(SkSamplingOptions());
Brian Salomond538d3d2019-04-04 12:18:17 -0400397 REPORTER_ASSERT(reporter, shader);
398 paint.setShader(std::move(shader));
399 canvas->drawRect(SkRect::MakeWH(1,1), paint);
400 paint.setShader(nullptr);
401 refImg.reset();
Greg Daniel0a2464f2020-05-14 15:45:44 -0400402 surface->flushAndSubmit();
Brian Salomond538d3d2019-04-04 12:18:17 -0400403 // We should only call each callback once and we should have made all the calls by this point.
404 REPORTER_ASSERT(reporter, counts.fFulfillCount == 1);
405 REPORTER_ASSERT(reporter, counts.fReleaseCount == 1);
Brian Salomond538d3d2019-04-04 12:18:17 -0400406}