blob: 126b44b43c3ff2f9bcc9912202fcc79358d9c7a1 [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,
Brian Salomon7e67dca2020-07-21 09:27:25 -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,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400185 GrMipmapped::kNo, texOrigin,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500186 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.
Robert Phillips58adb342020-07-23 09:41:57 -0400242 using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrDirectContext*)>;
243 DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext*) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500244 factory->destroyContexts();
245 };
Robert Phillips58adb342020-07-23 09:41:57 -0400246 DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext* dContext) {
247 dContext->abandonContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500248 };
249 DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory,
Robert Phillips58adb342020-07-23 09:41:57 -0400250 GrDirectContext* dContext) {
251 dContext->releaseResourcesAndAbandonContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500252 };
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};
John Stilesbd3ffa42020-07-30 20:24:57 -0400266 for (const DeathFn& contextDeath : contextKillers) {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500267 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 Phillips58adb342020-07-23 09:41:57 -0400275 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo,
276 GrProtected::kNo);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500277 REPORTER_ASSERT(reporter, backendTex.isValid());
278
279 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
280 kPremul_SkAlphaType);
281 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
282 SkCanvas* canvas = surface->getCanvas();
283
284 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
285 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400286 ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipmapped::kNo,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500287 kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
288 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
Brian Salomon0cc57542019-03-08 13:28:46 -0500289 PromiseTextureChecker::Done, &promiseChecker,
290 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500291 REPORTER_ASSERT(reporter, image);
292
293 canvas->drawImage(image, 0, 0);
294 image.reset();
295 // If the surface still holds a ref to the context then the factory will not be able
296 // to destroy the context (and instead will release-all-and-abandon).
297 surface.reset();
298
Greg Daniel0a2464f2020-05-14 15:45:44 -0400299 ctx->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500300 contextDeath(&factory, ctx);
301
Brian Salomon0cc57542019-03-08 13:28:46 -0500302 check_all_done(reporter, promiseChecker);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500303 }
304 }
305}
306
307DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxInfo) {
308 const int kWidth = 10;
309 const int kHeight = 10;
310
Robert Phillips58adb342020-07-23 09:41:57 -0400311 auto dContext = ctxInfo.directContext();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500312
Robert Phillips58adb342020-07-23 09:41:57 -0400313 GrBackendTexture backendTex = dContext->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400314 kWidth, kHeight, kAlpha_8_SkColorType,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400315 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500316 REPORTER_ASSERT(reporter, backendTex.isValid());
317
318 SkImageInfo info =
319 SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
Robert Phillips58adb342020-07-23 09:41:57 -0400320 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500321 SkCanvas* canvas = surface->getCanvas();
322
323 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
324 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
Robert Phillips58adb342020-07-23 09:41:57 -0400325 dContext, backendTex.getBackendFormat(), kWidth, kHeight, GrMipmapped::kNo,
Brian Salomon9bc76d92019-01-24 12:18:33 -0500326 kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
327 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
Brian Salomon0cc57542019-03-08 13:28:46 -0500328 PromiseTextureChecker::Done, &promiseChecker,
329 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500330 REPORTER_ASSERT(reporter, image);
331
332 // Make the cache full. This tests that we don't preemptively purge cached textures for
333 // fulfillment due to cache pressure.
Robert Phillipscf39f372019-09-03 10:29:20 -0400334 static constexpr int kMaxBytes = 1;
Robert Phillips58adb342020-07-23 09:41:57 -0400335 dContext->setResourceCacheLimit(kMaxBytes);
Robert Phillipscf39f372019-09-03 10:29:20 -0400336 SkTArray<sk_sp<GrTexture>> textures;
337 for (int i = 0; i < 5; ++i) {
Robert Phillips58adb342020-07-23 09:41:57 -0400338 auto format = dContext->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
339 GrRenderable::kNo);
340 textures.emplace_back(dContext->priv().resourceProvider()->createTexture(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400341 {100, 100}, format, GrRenderable::kNo, 1, GrMipmapped::kNo, SkBudgeted::kYes,
Brian Salomona90382f2019-09-17 09:01:56 -0400342 GrProtected::kNo));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500343 REPORTER_ASSERT(reporter, textures[i]);
344 }
345
Robert Phillipscf39f372019-09-03 10:29:20 -0400346 size_t bytesUsed;
347
Robert Phillips58adb342020-07-23 09:41:57 -0400348 dContext->getResourceCacheUsage(nullptr, &bytesUsed);
Robert Phillipscf39f372019-09-03 10:29:20 -0400349 REPORTER_ASSERT(reporter, bytesUsed > kMaxBytes);
350
Brian Salomon9bc76d92019-01-24 12:18:33 -0500351 // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are
352 // properly ordered.
353 canvas->drawImage(image, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400354 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500355 canvas->drawImage(image, 1, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400356 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500357 canvas->drawImage(image, 2, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400358 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500359 canvas->drawImage(image, 3, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400360 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500361 canvas->drawImage(image, 4, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400362 surface->flushAndSubmit();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500363 canvas->drawImage(image, 5, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400364 surface->flushAndSubmit();
Brian Salomon876a0172019-03-08 11:12:14 -0500365 // Must call these to ensure that all callbacks are performed before the checker is destroyed.
366 image.reset();
Robert Phillips58adb342020-07-23 09:41:57 -0400367 dContext->flushAndSubmit();
368 dContext->priv().getGpu()->testingOnly_flushGpuAndSync();
Brian Salomon876a0172019-03-08 11:12:14 -0500369
Robert Phillips58adb342020-07-23 09:41:57 -0400370 dContext->deleteBackendTexture(backendTex);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500371}
Brian Salomond538d3d2019-04-04 12:18:17 -0400372
373// Test case where promise image fulfill returns nullptr.
374DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill, reporter, ctxInfo) {
375 const int kWidth = 10;
376 const int kHeight = 10;
377
Robert Phillips58adb342020-07-23 09:41:57 -0400378 auto dContext = ctxInfo.directContext();
Brian Salomond538d3d2019-04-04 12:18:17 -0400379
380 // Do all this just to get a valid backend format for the image.
Greg Danielc1ad77c2020-05-06 11:40:03 -0400381 GrBackendTexture backendTex;
Robert Phillips58adb342020-07-23 09:41:57 -0400382 CreateBackendTexture(dContext, &backendTex, kWidth, kHeight, kRGBA_8888_SkColorType,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400383 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes,
Greg Danielc1ad77c2020-05-06 11:40:03 -0400384 GrProtected::kNo);
Brian Salomond538d3d2019-04-04 12:18:17 -0400385 REPORTER_ASSERT(reporter, backendTex.isValid());
386 GrBackendFormat backendFormat = backendTex.getBackendFormat();
387 REPORTER_ASSERT(reporter, backendFormat.isValid());
Robert Phillips58adb342020-07-23 09:41:57 -0400388 dContext->deleteBackendTexture(backendTex);
Brian Salomond538d3d2019-04-04 12:18:17 -0400389
390 struct Counts {
391 int fFulfillCount = 0;
392 int fReleaseCount = 0;
393 int fDoneCount = 0;
394 } counts;
395 auto fulfill = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
396 ++static_cast<Counts*>(ctx)->fFulfillCount;
397 return sk_sp<SkPromiseImageTexture>();
398 };
399 auto release = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
400 ++static_cast<Counts*>(ctx)->fReleaseCount;
401 };
402 auto done = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
403 ++static_cast<Counts*>(ctx)->fDoneCount;
404 };
405 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
406 sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(
Robert Phillips58adb342020-07-23 09:41:57 -0400407 dContext, backendFormat, kWidth, kHeight, GrMipmapped::kNo, texOrigin,
Brian Salomond538d3d2019-04-04 12:18:17 -0400408 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr, fulfill, release, done, &counts,
409 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
410
411 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
Robert Phillips58adb342020-07-23 09:41:57 -0400412 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Brian Salomond538d3d2019-04-04 12:18:17 -0400413 SkCanvas* canvas = surface->getCanvas();
414 // Draw the image a few different ways.
415 canvas->drawImage(refImg, 0, 0);
416 SkPaint paint;
Mike Reedb286bc22019-04-08 16:23:20 -0400417 paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
Brian Salomond538d3d2019-04-04 12:18:17 -0400418 canvas->drawImage(refImg, 0, 0, &paint);
419 auto shader = refImg->makeShader(SkTileMode::kClamp, SkTileMode::kClamp);
420 REPORTER_ASSERT(reporter, shader);
421 paint.setShader(std::move(shader));
422 canvas->drawRect(SkRect::MakeWH(1,1), paint);
423 paint.setShader(nullptr);
424 refImg.reset();
Greg Daniel0a2464f2020-05-14 15:45:44 -0400425 surface->flushAndSubmit();
Brian Salomond538d3d2019-04-04 12:18:17 -0400426 // We should only call each callback once and we should have made all the calls by this point.
427 REPORTER_ASSERT(reporter, counts.fFulfillCount == 1);
428 REPORTER_ASSERT(reporter, counts.fReleaseCount == 1);
429 REPORTER_ASSERT(reporter, counts.fDoneCount == 1);
430}