blob: 3aff51957ea794dc242f29992724352f38c43de2 [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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrContextPriv.h"
15#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"
Greg Danielc1ad77c2020-05-06 11:40:03 -040018#include "tests/TestUtils.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.
25 explicit PromiseTextureChecker(const GrBackendTexture& tex, skiatest::Reporter* reporter,
26 bool shared)
Brian Salomon3f4cd772019-01-11 16:03:19 -050027 : fTexture(SkPromiseImageTexture::Make(tex))
Brian Salomon9bc76d92019-01-24 12:18:33 -050028 , fReporter(reporter)
29 , fShared(shared)
Greg Daniela8d92112018-03-09 12:05:04 -050030 , fFulfillCount(0)
Greg Daniel7278d682018-03-16 14:57:21 -040031 , fReleaseCount(0)
32 , fDoneCount(0) {}
Brian Salomon3f4cd772019-01-11 16:03:19 -050033 sk_sp<SkPromiseImageTexture> fTexture;
Brian Salomon9bc76d92019-01-24 12:18:33 -050034 skiatest::Reporter* fReporter;
35 bool fShared;
Greg Daniela8d92112018-03-09 12:05:04 -050036 int fFulfillCount;
37 int fReleaseCount;
Greg Daniel7278d682018-03-16 14:57:21 -040038 int fDoneCount;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050039
40 /**
Brian Salomon7d88f312019-02-28 10:03:03 -050041 * Releases the SkPromiseImageTexture. Used to test that cached GrTexture representations
42 * in the cache are freed.
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050043 */
Brian Salomon7d88f312019-02-28 10:03:03 -050044 void releaseTexture() { fTexture.reset(); }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050045
46 SkTArray<GrUniqueKey> uniqueKeys() const {
Brian Salomon3f4cd772019-01-11 16:03:19 -050047 return fTexture->testingOnly_uniqueKeysToInvalidate();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050048 }
49
Brian Salomon3f4cd772019-01-11 16:03:19 -050050 static sk_sp<SkPromiseImageTexture> Fulfill(void* self) {
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050051 auto checker = static_cast<PromiseTextureChecker*>(self);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050052 checker->fFulfillCount++;
Brian Salomon3f4cd772019-01-11 16:03:19 -050053 return checker->fTexture;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050054 }
Brian Salomon9bc76d92019-01-24 12:18:33 -050055 static void Release(void* self) {
56 auto checker = static_cast<PromiseTextureChecker*>(self);
57 checker->fReleaseCount++;
58 if (!checker->fShared) {
59 // This is only used in a single threaded fashion with a single promise image. So
60 // every fulfill should be balanced by a release before the next fulfill.
61 REPORTER_ASSERT(checker->fReporter, checker->fReleaseCount == checker->fFulfillCount);
62 }
63 }
Greg Daniel7278d682018-03-16 14:57:21 -040064 static void Done(void* self) {
65 static_cast<PromiseTextureChecker*>(self)->fDoneCount++;
66 }
Greg Daniela8d92112018-03-09 12:05:04 -050067};
68
Brian Salomon0cc57542019-03-08 13:28:46 -050069enum class ReleaseBalanceExpectation {
Brian Salomonf55e8d52019-01-30 17:28:20 -050070 kBalanced,
Brian Salomon0cc57542019-03-08 13:28:46 -050071 kAllUnbalanced,
72 kUnbalancedByOne,
Brian Salomonf55e8d52019-01-30 17:28:20 -050073};
74
Brian Salomon0cc57542019-03-08 13:28:46 -050075enum class DoneBalanceExpectation {
76 kBalanced,
77 kAllUnbalanced,
78 kUnknown,
79 kUnbalancedByOne,
80 kBalancedOrOffByOne,
81};
82
83static void check_fulfill_and_release_cnts(skiatest::Reporter* reporter,
84 const PromiseTextureChecker& promiseChecker,
Greg Daniela8d92112018-03-09 12:05:04 -050085 int expectedFulfillCnt,
Brian Salomon0cc57542019-03-08 13:28:46 -050086 ReleaseBalanceExpectation releaseBalanceExpecation,
87 DoneBalanceExpectation doneBalanceExpecation) {
88 REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt);
89 if (!expectedFulfillCnt) {
90 // Release and Done should only ever be called after Fulfill.
91 REPORTER_ASSERT(reporter, !promiseChecker.fReleaseCount);
92 REPORTER_ASSERT(reporter, !promiseChecker.fDoneCount);
93 return;
Greg Daniela8d92112018-03-09 12:05:04 -050094 }
Brian Salomon0cc57542019-03-08 13:28:46 -050095 int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
96 switch (releaseBalanceExpecation) {
97 case ReleaseBalanceExpectation::kBalanced:
98 REPORTER_ASSERT(reporter, !releaseDiff);
99 break;
100 case ReleaseBalanceExpectation::kAllUnbalanced:
101 REPORTER_ASSERT(reporter, releaseDiff == promiseChecker.fFulfillCount);
102 break;
103 case ReleaseBalanceExpectation::kUnbalancedByOne:
104 REPORTER_ASSERT(reporter, releaseDiff == 1);
105 break;
Greg Daniela8d92112018-03-09 12:05:04 -0500106 }
Brian Salomon0cc57542019-03-08 13:28:46 -0500107 int doneDiff = promiseChecker.fFulfillCount - promiseChecker.fDoneCount;
108 switch (doneBalanceExpecation) {
109 case DoneBalanceExpectation::kBalanced:
110 REPORTER_ASSERT(reporter, !doneDiff);
111 break;
112 case DoneBalanceExpectation::kAllUnbalanced:
113 REPORTER_ASSERT(reporter, doneDiff == promiseChecker.fFulfillCount);
114 break;
115 case DoneBalanceExpectation::kUnknown:
116 REPORTER_ASSERT(reporter, doneDiff >= 0 && doneDiff <= promiseChecker.fFulfillCount);
117 break;
118 case DoneBalanceExpectation::kUnbalancedByOne:
119 REPORTER_ASSERT(reporter, doneDiff == 1);
120 break;
121 case DoneBalanceExpectation::kBalancedOrOffByOne:
122 REPORTER_ASSERT(reporter, doneDiff == 0 || doneDiff == 1);
123 break;
Greg Daniela8d92112018-03-09 12:05:04 -0500124 }
Brian Salomon0cc57542019-03-08 13:28:46 -0500125}
Greg Daniela8d92112018-03-09 12:05:04 -0500126
Brian Salomon0cc57542019-03-08 13:28:46 -0500127static void check_unfulfilled(const PromiseTextureChecker& promiseChecker,
128 skiatest::Reporter* reporter) {
129 check_fulfill_and_release_cnts(reporter, promiseChecker, 0,
130 ReleaseBalanceExpectation::kBalanced,
131 DoneBalanceExpectation::kBalanced);
132}
133
134static void check_only_fulfilled(skiatest::Reporter* reporter,
135 const PromiseTextureChecker& promiseChecker,
136 int expectedFulfillCnt = 1) {
137 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
138 ReleaseBalanceExpectation::kAllUnbalanced,
139 DoneBalanceExpectation::kAllUnbalanced);
140}
141
142static void check_all_flushed_but_not_synced(skiatest::Reporter* reporter,
143 const PromiseTextureChecker& promiseChecker,
144 GrBackendApi api,
145 int expectedFulfillCnt = 1) {
146 DoneBalanceExpectation doneBalanceExpectation = DoneBalanceExpectation::kBalanced;
Greg Daniela026e912020-06-24 13:38:08 -0400147 // On Vulkan and D3D Done isn't guaranteed to be called until a sync has occurred.
148 if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDirect3D) {
Brian Salomon0cc57542019-03-08 13:28:46 -0500149 doneBalanceExpectation = expectedFulfillCnt == 1
150 ? DoneBalanceExpectation::kBalancedOrOffByOne
151 : DoneBalanceExpectation::kUnknown;
Greg Daniel7278d682018-03-16 14:57:21 -0400152 }
Brian Salomon0cc57542019-03-08 13:28:46 -0500153 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
154 ReleaseBalanceExpectation::kBalanced, doneBalanceExpectation);
155}
Greg Daniel7278d682018-03-16 14:57:21 -0400156
Brian Salomon0cc57542019-03-08 13:28:46 -0500157static void check_all_done(skiatest::Reporter* reporter,
158 const PromiseTextureChecker& promiseChecker,
159 int expectedFulfillCnt = 1) {
160 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
161 ReleaseBalanceExpectation::kBalanced,
162 DoneBalanceExpectation::kBalanced);
Greg Daniela8d92112018-03-09 12:05:04 -0500163}
164
Brian Salomon7d88f312019-02-28 10:03:03 -0500165DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
Brian Salomonf55e8d52019-01-30 17:28:20 -0500166 const int kWidth = 10;
167 const int kHeight = 10;
168
Robert Phillips6d344c32020-07-06 10:56:46 -0400169 auto ctx = ctxInfo.directContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500170 GrGpu* gpu = ctx->priv().getGpu();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500171
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400172 GrBackendTexture backendTex = ctx->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400173 kWidth, kHeight, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400174 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500175 REPORTER_ASSERT(reporter, backendTex.isValid());
176
177 GrBackendFormat backendFormat = backendTex.getBackendFormat();
178 REPORTER_ASSERT(reporter, backendFormat.isValid());
179
180 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
181 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
182 sk_sp<SkImage> refImg(
183 SkImage_Gpu::MakePromiseTexture(
184 ctx, backendFormat, kWidth, kHeight,
185 GrMipMapped::kNo, texOrigin,
186 kRGBA_8888_SkColorType, kPremul_SkAlphaType,
187 nullptr,
188 PromiseTextureChecker::Fulfill,
189 PromiseTextureChecker::Release,
190 PromiseTextureChecker::Done,
Brian Salomon0cc57542019-03-08 13:28:46 -0500191 &promiseChecker,
192 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
Brian Salomonf55e8d52019-01-30 17:28:20 -0500193
194 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
195 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
196 SkCanvas* canvas = surface->getCanvas();
197
Brian Salomond716d442019-03-07 15:23:30 +0000198 canvas->drawImage(refImg, 0, 0);
Brian Salomon0cc57542019-03-08 13:28:46 -0500199 check_unfulfilled(promiseChecker, reporter);
Brian Salomond716d442019-03-07 15:23:30 +0000200
Greg Daniel0a2464f2020-05-14 15:45:44 -0400201 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500202 // We still own the image so we should not have called Release or Done.
203 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500204
205 gpu->testingOnly_flushGpuAndSync();
Brian Salomon0cc57542019-03-08 13:28:46 -0500206 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500207
208 canvas->drawImage(refImg, 0, 0);
209 canvas->drawImage(refImg, 0, 0);
210
Greg Daniel0a2464f2020-05-14 15:45:44 -0400211 surface->flushAndSubmit();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500212
213 gpu->testingOnly_flushGpuAndSync();
Brian Salomon0cc57542019-03-08 13:28:46 -0500214 // Image should still be fulfilled from the first time we drew/flushed it.
215 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500216
217 canvas->drawImage(refImg, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400218 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500219 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500220
221 canvas->drawImage(refImg, 0, 0);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500222 refImg.reset();
Brian Salomon0cc57542019-03-08 13:28:46 -0500223 // We no longer own the image but the last draw is still unflushed.
224 check_only_fulfilled(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500225
Greg Daniel0a2464f2020-05-14 15:45:44 -0400226 surface->flushAndSubmit();
Brian Salomon0cc57542019-03-08 13:28:46 -0500227 // Flushing should have called Release. Depending on the backend and timing it may have called
228 // done.
229 check_all_flushed_but_not_synced(reporter, promiseChecker, ctx->backend());
Brian Salomonf55e8d52019-01-30 17:28:20 -0500230 gpu->testingOnly_flushGpuAndSync();
Brian Salomon0cc57542019-03-08 13:28:46 -0500231 // Now Done should definitely have been called.
232 check_all_done(reporter, promiseChecker);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500233
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400234 ctx->deleteBackendTexture(backendTex);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500235}
236
Brian Salomon9bc76d92019-01-24 12:18:33 -0500237DEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) {
238 const int kWidth = 10;
239 const int kHeight = 10;
240
241 // Different ways of killing contexts.
242 using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrContext*)>;
243 DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrContext* context) {
244 factory->destroyContexts();
245 };
246 DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrContext* context) {
247 context->abandonContext();
248 };
249 DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory,
250 GrContext* context) {
251 context->releaseResourcesAndAbandonContext();
252 };
253
254 for (int type = 0; type < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++type) {
255 auto contextType = static_cast<sk_gpu_test::GrContextFactory::ContextType>(type);
256 // These tests are difficult to get working with Vulkan. See http://skbug.com/8705
257 // and http://skbug.com/8275
Stephen Whiteb007bb22020-06-04 09:02:04 -0400258 // Also problematic on Dawn; see http://skbug.com/10326
Jim Van Verthaed25a92020-06-23 15:00:04 -0400259 // And Direct3D, for similar reasons.
Brian Salomon9bc76d92019-01-24 12:18:33 -0500260 GrBackendApi api = sk_gpu_test::GrContextFactory::ContextTypeBackend(contextType);
Jim Van Verthaed25a92020-06-23 15:00:04 -0400261 if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDawn ||
262 api == GrBackendApi::kDirect3D) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500263 continue;
264 }
265 DeathFn contextKillers[] = {destroy, abandon, releaseResourcesAndAbandon};
266 for (auto contextDeath : contextKillers) {
267 sk_gpu_test::GrContextFactory factory;
268 auto ctx = factory.get(contextType);
269 if (!ctx) {
270 continue;
271 }
Brian Salomon9bc76d92019-01-24 12:18:33 -0500272
Greg Danielc1ad77c2020-05-06 11:40:03 -0400273 GrBackendTexture backendTex;
274 CreateBackendTexture(ctx, &backendTex, kWidth, kHeight, kAlpha_8_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400275 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500276 REPORTER_ASSERT(reporter, backendTex.isValid());
277
278 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
279 kPremul_SkAlphaType);
280 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
281 SkCanvas* canvas = surface->getCanvas();
282
283 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
284 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
285 ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500286 kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
287 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
Brian Salomon0cc57542019-03-08 13:28:46 -0500288 PromiseTextureChecker::Done, &promiseChecker,
289 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500290 REPORTER_ASSERT(reporter, image);
291
292 canvas->drawImage(image, 0, 0);
293 image.reset();
294 // If the surface still holds a ref to the context then the factory will not be able
295 // to destroy the context (and instead will release-all-and-abandon).
296 surface.reset();
297
Greg Daniel0a2464f2020-05-14 15:45:44 -0400298 ctx->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500299 contextDeath(&factory, ctx);
300
Brian Salomon0cc57542019-03-08 13:28:46 -0500301 check_all_done(reporter, promiseChecker);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500302 }
303 }
304}
305
306DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxInfo) {
307 const int kWidth = 10;
308 const int kHeight = 10;
309
Robert Phillips6d344c32020-07-06 10:56:46 -0400310 auto ctx = ctxInfo.directContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500311
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400312 GrBackendTexture backendTex = ctx->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400313 kWidth, kHeight, kAlpha_8_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400314 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500315 REPORTER_ASSERT(reporter, backendTex.isValid());
316
317 SkImageInfo info =
318 SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
319 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
320 SkCanvas* canvas = surface->getCanvas();
321
322 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
323 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
324 ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
325 kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
326 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
Brian Salomon0cc57542019-03-08 13:28:46 -0500327 PromiseTextureChecker::Done, &promiseChecker,
328 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500329 REPORTER_ASSERT(reporter, image);
330
331 // Make the cache full. This tests that we don't preemptively purge cached textures for
332 // fulfillment due to cache pressure.
Robert Phillipscf39f372019-09-03 10:29:20 -0400333 static constexpr int kMaxBytes = 1;
334 ctx->setResourceCacheLimit(kMaxBytes);
335 SkTArray<sk_sp<GrTexture>> textures;
336 for (int i = 0; i < 5; ++i) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400337 auto format = ctx->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
338 GrRenderable::kNo);
Robert Phillipscf39f372019-09-03 10:29:20 -0400339 textures.emplace_back(ctx->priv().resourceProvider()->createTexture(
Brian Salomona56a7462020-02-07 14:17:25 -0500340 {100, 100}, format, GrRenderable::kNo, 1, GrMipMapped::kNo, SkBudgeted::kYes,
Brian Salomona90382f2019-09-17 09:01:56 -0400341 GrProtected::kNo));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500342 REPORTER_ASSERT(reporter, textures[i]);
343 }
344
Robert Phillipscf39f372019-09-03 10:29:20 -0400345 size_t bytesUsed;
346
347 ctx->getResourceCacheUsage(nullptr, &bytesUsed);
348 REPORTER_ASSERT(reporter, bytesUsed > kMaxBytes);
349
Brian Salomon9bc76d92019-01-24 12:18:33 -0500350 // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are
351 // properly ordered.
352 canvas->drawImage(image, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400353 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500354 canvas->drawImage(image, 1, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400355 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500356 canvas->drawImage(image, 2, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400357 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500358 canvas->drawImage(image, 3, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400359 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500360 canvas->drawImage(image, 4, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400361 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500362 canvas->drawImage(image, 5, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400363 surface->flushAndSubmit();
Brian Salomon876a0172019-03-08 11:12:14 -0500364 // Must call these to ensure that all callbacks are performed before the checker is destroyed.
365 image.reset();
Greg Daniel0a2464f2020-05-14 15:45:44 -0400366 ctx->flushAndSubmit();
Robert Phillips9b16f812019-05-17 10:01:21 -0400367 ctx->priv().getGpu()->testingOnly_flushGpuAndSync();
Brian Salomon876a0172019-03-08 11:12:14 -0500368
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400369 ctx->deleteBackendTexture(backendTex);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500370}
Brian Salomond538d3d2019-04-04 12:18:17 -0400371
372// Test case where promise image fulfill returns nullptr.
373DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill, reporter, ctxInfo) {
374 const int kWidth = 10;
375 const int kHeight = 10;
376
Robert Phillips6d344c32020-07-06 10:56:46 -0400377 auto ctx = ctxInfo.directContext();
Brian Salomond538d3d2019-04-04 12:18:17 -0400378
379 // Do all this just to get a valid backend format for the image.
Greg Danielc1ad77c2020-05-06 11:40:03 -0400380 GrBackendTexture backendTex;
381 CreateBackendTexture(ctx, &backendTex, kWidth, kHeight, kRGBA_8888_SkColorType,
382 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kYes,
383 GrProtected::kNo);
Brian Salomond538d3d2019-04-04 12:18:17 -0400384 REPORTER_ASSERT(reporter, backendTex.isValid());
385 GrBackendFormat backendFormat = backendTex.getBackendFormat();
386 REPORTER_ASSERT(reporter, backendFormat.isValid());
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400387 ctx->deleteBackendTexture(backendTex);
Brian Salomond538d3d2019-04-04 12:18:17 -0400388
389 struct Counts {
390 int fFulfillCount = 0;
391 int fReleaseCount = 0;
392 int fDoneCount = 0;
393 } counts;
394 auto fulfill = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
395 ++static_cast<Counts*>(ctx)->fFulfillCount;
396 return sk_sp<SkPromiseImageTexture>();
397 };
398 auto release = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
399 ++static_cast<Counts*>(ctx)->fReleaseCount;
400 };
401 auto done = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
402 ++static_cast<Counts*>(ctx)->fDoneCount;
403 };
404 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
405 sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(
406 ctx, backendFormat, kWidth, kHeight, GrMipMapped::kNo, texOrigin,
407 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr, fulfill, release, done, &counts,
408 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
409
410 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
411 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
412 SkCanvas* canvas = surface->getCanvas();
413 // Draw the image a few different ways.
414 canvas->drawImage(refImg, 0, 0);
415 SkPaint paint;
Mike Reedb286bc22019-04-08 16:23:20 -0400416 paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
Brian Salomond538d3d2019-04-04 12:18:17 -0400417 canvas->drawImage(refImg, 0, 0, &paint);
418 auto shader = refImg->makeShader(SkTileMode::kClamp, SkTileMode::kClamp);
419 REPORTER_ASSERT(reporter, shader);
420 paint.setShader(std::move(shader));
421 canvas->drawRect(SkRect::MakeWH(1,1), paint);
422 paint.setShader(nullptr);
423 refImg.reset();
Greg Daniel0a2464f2020-05-14 15:45:44 -0400424 surface->flushAndSubmit();
Brian Salomond538d3d2019-04-04 12:18:17 -0400425 // We should only call each callback once and we should have made all the calls by this point.
426 REPORTER_ASSERT(reporter, counts.fFulfillCount == 1);
427 REPORTER_ASSERT(reporter, counts.fReleaseCount == 1);
428 REPORTER_ASSERT(reporter, counts.fDoneCount == 1);
429}