PromiseImageTest.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  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. #include "tests/Test.h"
  8. #include "include/core/SkColorFilter.h"
  9. #include "include/core/SkPromiseImageTexture.h"
  10. #include "include/gpu/GrBackendSurface.h"
  11. #include "include/gpu/GrTexture.h"
  12. #include "src/gpu/GrContextPriv.h"
  13. #include "src/gpu/GrGpu.h"
  14. #include "src/image/SkImage_Gpu.h"
  15. using namespace sk_gpu_test;
  16. struct PromiseTextureChecker {
  17. // shared indicates whether the backend texture is used to fulfill more than one promise
  18. // image.
  19. explicit PromiseTextureChecker(const GrBackendTexture& tex, skiatest::Reporter* reporter,
  20. bool shared)
  21. : fTexture(SkPromiseImageTexture::Make(tex))
  22. , fReporter(reporter)
  23. , fShared(shared)
  24. , fFulfillCount(0)
  25. , fReleaseCount(0)
  26. , fDoneCount(0) {}
  27. sk_sp<SkPromiseImageTexture> fTexture;
  28. skiatest::Reporter* fReporter;
  29. bool fShared;
  30. int fFulfillCount;
  31. int fReleaseCount;
  32. int fDoneCount;
  33. /**
  34. * Releases the SkPromiseImageTexture. Used to test that cached GrTexture representations
  35. * in the cache are freed.
  36. */
  37. void releaseTexture() { fTexture.reset(); }
  38. SkTArray<GrUniqueKey> uniqueKeys() const {
  39. return fTexture->testingOnly_uniqueKeysToInvalidate();
  40. }
  41. static sk_sp<SkPromiseImageTexture> Fulfill(void* self) {
  42. auto checker = static_cast<PromiseTextureChecker*>(self);
  43. checker->fFulfillCount++;
  44. return checker->fTexture;
  45. }
  46. static void Release(void* self) {
  47. auto checker = static_cast<PromiseTextureChecker*>(self);
  48. checker->fReleaseCount++;
  49. if (!checker->fShared) {
  50. // This is only used in a single threaded fashion with a single promise image. So
  51. // every fulfill should be balanced by a release before the next fulfill.
  52. REPORTER_ASSERT(checker->fReporter, checker->fReleaseCount == checker->fFulfillCount);
  53. }
  54. }
  55. static void Done(void* self) {
  56. static_cast<PromiseTextureChecker*>(self)->fDoneCount++;
  57. }
  58. };
  59. enum class ReleaseBalanceExpectation {
  60. kBalanced,
  61. kAllUnbalanced,
  62. kUnbalancedByOne,
  63. };
  64. enum class DoneBalanceExpectation {
  65. kBalanced,
  66. kAllUnbalanced,
  67. kUnknown,
  68. kUnbalancedByOne,
  69. kBalancedOrOffByOne,
  70. };
  71. static void check_fulfill_and_release_cnts(skiatest::Reporter* reporter,
  72. const PromiseTextureChecker& promiseChecker,
  73. int expectedFulfillCnt,
  74. ReleaseBalanceExpectation releaseBalanceExpecation,
  75. DoneBalanceExpectation doneBalanceExpecation) {
  76. REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt);
  77. if (!expectedFulfillCnt) {
  78. // Release and Done should only ever be called after Fulfill.
  79. REPORTER_ASSERT(reporter, !promiseChecker.fReleaseCount);
  80. REPORTER_ASSERT(reporter, !promiseChecker.fDoneCount);
  81. return;
  82. }
  83. int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
  84. switch (releaseBalanceExpecation) {
  85. case ReleaseBalanceExpectation::kBalanced:
  86. REPORTER_ASSERT(reporter, !releaseDiff);
  87. break;
  88. case ReleaseBalanceExpectation::kAllUnbalanced:
  89. REPORTER_ASSERT(reporter, releaseDiff == promiseChecker.fFulfillCount);
  90. break;
  91. case ReleaseBalanceExpectation::kUnbalancedByOne:
  92. REPORTER_ASSERT(reporter, releaseDiff == 1);
  93. break;
  94. }
  95. int doneDiff = promiseChecker.fFulfillCount - promiseChecker.fDoneCount;
  96. switch (doneBalanceExpecation) {
  97. case DoneBalanceExpectation::kBalanced:
  98. REPORTER_ASSERT(reporter, !doneDiff);
  99. break;
  100. case DoneBalanceExpectation::kAllUnbalanced:
  101. REPORTER_ASSERT(reporter, doneDiff == promiseChecker.fFulfillCount);
  102. break;
  103. case DoneBalanceExpectation::kUnknown:
  104. REPORTER_ASSERT(reporter, doneDiff >= 0 && doneDiff <= promiseChecker.fFulfillCount);
  105. break;
  106. case DoneBalanceExpectation::kUnbalancedByOne:
  107. REPORTER_ASSERT(reporter, doneDiff == 1);
  108. break;
  109. case DoneBalanceExpectation::kBalancedOrOffByOne:
  110. REPORTER_ASSERT(reporter, doneDiff == 0 || doneDiff == 1);
  111. break;
  112. }
  113. }
  114. static void check_unfulfilled(const PromiseTextureChecker& promiseChecker,
  115. skiatest::Reporter* reporter) {
  116. check_fulfill_and_release_cnts(reporter, promiseChecker, 0,
  117. ReleaseBalanceExpectation::kBalanced,
  118. DoneBalanceExpectation::kBalanced);
  119. }
  120. static void check_only_fulfilled(skiatest::Reporter* reporter,
  121. const PromiseTextureChecker& promiseChecker,
  122. int expectedFulfillCnt = 1) {
  123. check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
  124. ReleaseBalanceExpectation::kAllUnbalanced,
  125. DoneBalanceExpectation::kAllUnbalanced);
  126. }
  127. static void check_all_flushed_but_not_synced(skiatest::Reporter* reporter,
  128. const PromiseTextureChecker& promiseChecker,
  129. GrBackendApi api,
  130. int expectedFulfillCnt = 1) {
  131. DoneBalanceExpectation doneBalanceExpectation = DoneBalanceExpectation::kBalanced;
  132. // On Vulkan Done isn't guaranteed to be called until a sync has occurred.
  133. if (api == GrBackendApi::kVulkan) {
  134. doneBalanceExpectation = expectedFulfillCnt == 1
  135. ? DoneBalanceExpectation::kBalancedOrOffByOne
  136. : DoneBalanceExpectation::kUnknown;
  137. }
  138. check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
  139. ReleaseBalanceExpectation::kBalanced, doneBalanceExpectation);
  140. }
  141. static void check_all_done(skiatest::Reporter* reporter,
  142. const PromiseTextureChecker& promiseChecker,
  143. int expectedFulfillCnt = 1) {
  144. check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
  145. ReleaseBalanceExpectation::kBalanced,
  146. DoneBalanceExpectation::kBalanced);
  147. }
  148. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
  149. const int kWidth = 10;
  150. const int kHeight = 10;
  151. GrContext* ctx = ctxInfo.grContext();
  152. GrGpu* gpu = ctx->priv().getGpu();
  153. GrBackendTexture backendTex = ctx->createBackendTexture(
  154. kWidth, kHeight, kRGBA_8888_SkColorType,
  155. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
  156. REPORTER_ASSERT(reporter, backendTex.isValid());
  157. GrBackendFormat backendFormat = backendTex.getBackendFormat();
  158. REPORTER_ASSERT(reporter, backendFormat.isValid());
  159. PromiseTextureChecker promiseChecker(backendTex, reporter, false);
  160. GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
  161. sk_sp<SkImage> refImg(
  162. SkImage_Gpu::MakePromiseTexture(
  163. ctx, backendFormat, kWidth, kHeight,
  164. GrMipMapped::kNo, texOrigin,
  165. kRGBA_8888_SkColorType, kPremul_SkAlphaType,
  166. nullptr,
  167. PromiseTextureChecker::Fulfill,
  168. PromiseTextureChecker::Release,
  169. PromiseTextureChecker::Done,
  170. &promiseChecker,
  171. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
  172. SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
  173. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
  174. SkCanvas* canvas = surface->getCanvas();
  175. canvas->drawImage(refImg, 0, 0);
  176. check_unfulfilled(promiseChecker, reporter);
  177. surface->flush();
  178. // We still own the image so we should not have called Release or Done.
  179. check_only_fulfilled(reporter, promiseChecker);
  180. gpu->testingOnly_flushGpuAndSync();
  181. check_only_fulfilled(reporter, promiseChecker);
  182. canvas->drawImage(refImg, 0, 0);
  183. canvas->drawImage(refImg, 0, 0);
  184. surface->flush();
  185. gpu->testingOnly_flushGpuAndSync();
  186. // Image should still be fulfilled from the first time we drew/flushed it.
  187. check_only_fulfilled(reporter, promiseChecker);
  188. canvas->drawImage(refImg, 0, 0);
  189. surface->flush();
  190. check_only_fulfilled(reporter, promiseChecker);
  191. canvas->drawImage(refImg, 0, 0);
  192. refImg.reset();
  193. // We no longer own the image but the last draw is still unflushed.
  194. check_only_fulfilled(reporter, promiseChecker);
  195. surface->flush();
  196. // Flushing should have called Release. Depending on the backend and timing it may have called
  197. // done.
  198. check_all_flushed_but_not_synced(reporter, promiseChecker, ctx->backend());
  199. gpu->testingOnly_flushGpuAndSync();
  200. // Now Done should definitely have been called.
  201. check_all_done(reporter, promiseChecker);
  202. ctx->deleteBackendTexture(backendTex);
  203. }
  204. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureReuseDifferentConfig, reporter, ctxInfo) {
  205. // Try making two promise SkImages backed by the same texture but with different configs.
  206. // This will only be testable on backends where a single texture format (8bit red unorm) can
  207. // be used for alpha and gray image color types.
  208. const int kWidth = 10;
  209. const int kHeight = 10;
  210. GrContext* ctx = ctxInfo.grContext();
  211. GrGpu* gpu = ctx->priv().getGpu();
  212. GrBackendTexture backendTex1 = ctx->createBackendTexture(
  213. kWidth, kHeight, kGray_8_SkColorType,
  214. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
  215. REPORTER_ASSERT(reporter, backendTex1.isValid());
  216. GrBackendTexture backendTex2 = ctx->createBackendTexture(
  217. kWidth, kHeight, kAlpha_8_SkColorType,
  218. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
  219. REPORTER_ASSERT(reporter, backendTex2.isValid());
  220. if (backendTex1.getBackendFormat() != backendTex2.getBackendFormat()) {
  221. ctx->deleteBackendTexture(backendTex1);
  222. return;
  223. }
  224. // We only needed this texture to check that alpha and gray color types use the same format.
  225. ctx->deleteBackendTexture(backendTex2);
  226. SkImageInfo info =
  227. SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  228. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
  229. SkCanvas* canvas = surface->getCanvas();
  230. PromiseTextureChecker promiseChecker(backendTex1, reporter, true);
  231. sk_sp<SkImage> alphaImg(SkImage_Gpu::MakePromiseTexture(
  232. ctx, backendTex1.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
  233. kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
  234. PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
  235. PromiseTextureChecker::Done, &promiseChecker,
  236. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
  237. REPORTER_ASSERT(reporter, alphaImg);
  238. sk_sp<SkImage> grayImg(SkImage_Gpu::MakePromiseTexture(
  239. ctx, backendTex1.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
  240. kBottomLeft_GrSurfaceOrigin, kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr,
  241. PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
  242. PromiseTextureChecker::Done, &promiseChecker,
  243. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
  244. REPORTER_ASSERT(reporter, grayImg);
  245. canvas->drawImage(alphaImg, 0, 0);
  246. canvas->drawImage(grayImg, 1, 1);
  247. surface->flush();
  248. gpu->testingOnly_flushGpuAndSync();
  249. check_only_fulfilled(reporter, promiseChecker, 2);
  250. // Because they use different configs, each image should have created a different GrTexture
  251. // and they both should still be cached.
  252. ctx->priv().getResourceCache()->purgeAsNeeded();
  253. auto keys = promiseChecker.uniqueKeys();
  254. REPORTER_ASSERT(reporter, keys.count() == 2);
  255. for (const auto& key : keys) {
  256. auto surf = ctx->priv().resourceProvider()->findByUniqueKey<GrSurface>(key);
  257. REPORTER_ASSERT(reporter, surf && surf->asTexture());
  258. if (surf && surf->asTexture()) {
  259. REPORTER_ASSERT(reporter,
  260. !GrBackendTexture::TestingOnly_Equals(
  261. backendTex1, surf->asTexture()->getBackendTexture()));
  262. }
  263. }
  264. // Invalidate the backing texture, this should invalidate the keys.
  265. promiseChecker.releaseTexture();
  266. ctx->priv().getResourceCache()->purgeAsNeeded();
  267. for (const auto& key : keys) {
  268. auto surf = ctx->priv().resourceProvider()->findByUniqueKey<GrSurface>(key);
  269. REPORTER_ASSERT(reporter, !surf);
  270. }
  271. alphaImg.reset();
  272. ctx->flush(); // We do this to pick up any unref messages that are sent by unref'ing the image.
  273. check_fulfill_and_release_cnts(reporter, promiseChecker, 2,
  274. ReleaseBalanceExpectation::kUnbalancedByOne,
  275. DoneBalanceExpectation::kUnbalancedByOne);
  276. grayImg.reset();
  277. ctx->flush(); // We do this to pick up any unref messages that are sent by unref'ing the image.
  278. check_all_done(reporter, promiseChecker, 2);
  279. ctx->deleteBackendTexture(backendTex1);
  280. }
  281. DEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) {
  282. const int kWidth = 10;
  283. const int kHeight = 10;
  284. // Different ways of killing contexts.
  285. using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrContext*)>;
  286. DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrContext* context) {
  287. factory->destroyContexts();
  288. };
  289. DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrContext* context) {
  290. context->abandonContext();
  291. };
  292. DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory,
  293. GrContext* context) {
  294. context->releaseResourcesAndAbandonContext();
  295. };
  296. for (int type = 0; type < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++type) {
  297. auto contextType = static_cast<sk_gpu_test::GrContextFactory::ContextType>(type);
  298. // These tests are difficult to get working with Vulkan. See http://skbug.com/8705
  299. // and http://skbug.com/8275
  300. GrBackendApi api = sk_gpu_test::GrContextFactory::ContextTypeBackend(contextType);
  301. if (api == GrBackendApi::kVulkan) {
  302. continue;
  303. }
  304. DeathFn contextKillers[] = {destroy, abandon, releaseResourcesAndAbandon};
  305. for (auto contextDeath : contextKillers) {
  306. sk_gpu_test::GrContextFactory factory;
  307. auto ctx = factory.get(contextType);
  308. if (!ctx) {
  309. continue;
  310. }
  311. GrBackendTexture backendTex = ctx->createBackendTexture(
  312. kWidth, kHeight, kAlpha_8_SkColorType,
  313. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
  314. REPORTER_ASSERT(reporter, backendTex.isValid());
  315. SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
  316. kPremul_SkAlphaType);
  317. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
  318. SkCanvas* canvas = surface->getCanvas();
  319. PromiseTextureChecker promiseChecker(backendTex, reporter, false);
  320. sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
  321. ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
  322. kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
  323. PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
  324. PromiseTextureChecker::Done, &promiseChecker,
  325. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
  326. REPORTER_ASSERT(reporter, image);
  327. canvas->drawImage(image, 0, 0);
  328. image.reset();
  329. // If the surface still holds a ref to the context then the factory will not be able
  330. // to destroy the context (and instead will release-all-and-abandon).
  331. surface.reset();
  332. ctx->flush();
  333. contextDeath(&factory, ctx);
  334. check_all_done(reporter, promiseChecker);
  335. }
  336. }
  337. }
  338. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxInfo) {
  339. const int kWidth = 10;
  340. const int kHeight = 10;
  341. GrContext* ctx = ctxInfo.grContext();
  342. GrBackendTexture backendTex = ctx->createBackendTexture(
  343. kWidth, kHeight, kAlpha_8_SkColorType,
  344. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
  345. REPORTER_ASSERT(reporter, backendTex.isValid());
  346. SkImageInfo info =
  347. SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  348. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
  349. SkCanvas* canvas = surface->getCanvas();
  350. PromiseTextureChecker promiseChecker(backendTex, reporter, false);
  351. sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
  352. ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
  353. kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
  354. PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
  355. PromiseTextureChecker::Done, &promiseChecker,
  356. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
  357. REPORTER_ASSERT(reporter, image);
  358. // Make the cache full. This tests that we don't preemptively purge cached textures for
  359. // fulfillment due to cache pressure.
  360. static constexpr int kMaxResources = 10;
  361. static constexpr int kMaxBytes = 100;
  362. ctx->setResourceCacheLimits(kMaxResources, kMaxBytes);
  363. sk_sp<GrTexture> textures[2 * kMaxResources];
  364. for (int i = 0; i < 2 * kMaxResources; ++i) {
  365. GrSurfaceDesc desc;
  366. desc.fConfig = kRGBA_8888_GrPixelConfig;
  367. desc.fWidth = desc.fHeight = 100;
  368. textures[i] = ctx->priv().resourceProvider()->createTexture(
  369. desc, GrRenderable::kNo, 1, SkBudgeted::kYes, GrProtected::kNo,
  370. GrResourceProvider::Flags::kNoPendingIO);
  371. REPORTER_ASSERT(reporter, textures[i]);
  372. }
  373. // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are
  374. // properly ordered.
  375. canvas->drawImage(image, 0, 0);
  376. surface->flush();
  377. canvas->drawImage(image, 1, 0);
  378. surface->flush();
  379. canvas->drawImage(image, 2, 0);
  380. surface->flush();
  381. canvas->drawImage(image, 3, 0);
  382. surface->flush();
  383. canvas->drawImage(image, 4, 0);
  384. surface->flush();
  385. canvas->drawImage(image, 5, 0);
  386. surface->flush();
  387. // Must call these to ensure that all callbacks are performed before the checker is destroyed.
  388. image.reset();
  389. ctx->flush();
  390. ctx->priv().getGpu()->testingOnly_flushGpuAndSync();
  391. ctx->deleteBackendTexture(backendTex);
  392. }
  393. // Test case where promise image fulfill returns nullptr.
  394. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill, reporter, ctxInfo) {
  395. const int kWidth = 10;
  396. const int kHeight = 10;
  397. GrContext* ctx = ctxInfo.grContext();
  398. // Do all this just to get a valid backend format for the image.
  399. GrBackendTexture backendTex = ctx->createBackendTexture(
  400. kWidth, kHeight, kRGBA_8888_SkColorType,
  401. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
  402. REPORTER_ASSERT(reporter, backendTex.isValid());
  403. GrBackendFormat backendFormat = backendTex.getBackendFormat();
  404. REPORTER_ASSERT(reporter, backendFormat.isValid());
  405. ctx->deleteBackendTexture(backendTex);
  406. struct Counts {
  407. int fFulfillCount = 0;
  408. int fReleaseCount = 0;
  409. int fDoneCount = 0;
  410. } counts;
  411. auto fulfill = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
  412. ++static_cast<Counts*>(ctx)->fFulfillCount;
  413. return sk_sp<SkPromiseImageTexture>();
  414. };
  415. auto release = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
  416. ++static_cast<Counts*>(ctx)->fReleaseCount;
  417. };
  418. auto done = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) {
  419. ++static_cast<Counts*>(ctx)->fDoneCount;
  420. };
  421. GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
  422. sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(
  423. ctx, backendFormat, kWidth, kHeight, GrMipMapped::kNo, texOrigin,
  424. kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr, fulfill, release, done, &counts,
  425. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
  426. SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
  427. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
  428. SkCanvas* canvas = surface->getCanvas();
  429. // Draw the image a few different ways.
  430. canvas->drawImage(refImg, 0, 0);
  431. SkPaint paint;
  432. paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
  433. canvas->drawImage(refImg, 0, 0, &paint);
  434. auto shader = refImg->makeShader(SkTileMode::kClamp, SkTileMode::kClamp);
  435. REPORTER_ASSERT(reporter, shader);
  436. paint.setShader(std::move(shader));
  437. canvas->drawRect(SkRect::MakeWH(1,1), paint);
  438. paint.setShader(nullptr);
  439. refImg.reset();
  440. surface->flush();
  441. // We should only call each callback once and we should have made all the calls by this point.
  442. REPORTER_ASSERT(reporter, counts.fFulfillCount == 1);
  443. REPORTER_ASSERT(reporter, counts.fReleaseCount == 1);
  444. REPORTER_ASSERT(reporter, counts.fDoneCount == 1);
  445. }