blob: 1c5f5ea9a7ecd17358bf47a1e366c030f27ba4ca [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
Brian Salomonf55e8d52019-01-30 17:28:20 -05008#include "SkExchange.h"
Greg Daniela8d92112018-03-09 12:05:04 -05009#include "Test.h"
10
Greg Daniela8d92112018-03-09 12:05:04 -050011#include "GrBackendSurface.h"
12#include "GrContextPriv.h"
13#include "GrGpu.h"
Brian Salomon1bf0ed82019-01-16 13:51:35 -050014#include "GrTexture.h"
Greg Daniela8d92112018-03-09 12:05:04 -050015#include "SkImage_Gpu.h"
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050016#include "SkPromiseImageTexture.h"
Greg Daniela8d92112018-03-09 12:05:04 -050017
18using namespace sk_gpu_test;
19
20struct PromiseTextureChecker {
Brian Salomon9bc76d92019-01-24 12:18:33 -050021 // shared indicates whether the backend texture is used to fulfill more than one promise
22 // image.
23 explicit PromiseTextureChecker(const GrBackendTexture& tex, skiatest::Reporter* reporter,
24 bool shared)
Brian Salomon3f4cd772019-01-11 16:03:19 -050025 : fTexture(SkPromiseImageTexture::Make(tex))
Brian Salomon9bc76d92019-01-24 12:18:33 -050026 , fReporter(reporter)
27 , fShared(shared)
Greg Daniela8d92112018-03-09 12:05:04 -050028 , fFulfillCount(0)
Greg Daniel7278d682018-03-16 14:57:21 -040029 , fReleaseCount(0)
30 , fDoneCount(0) {}
Brian Salomon3f4cd772019-01-11 16:03:19 -050031 sk_sp<SkPromiseImageTexture> fTexture;
Brian Salomon9bc76d92019-01-24 12:18:33 -050032 skiatest::Reporter* fReporter;
33 bool fShared;
Greg Daniela8d92112018-03-09 12:05:04 -050034 int fFulfillCount;
35 int fReleaseCount;
Greg Daniel7278d682018-03-16 14:57:21 -040036 int fDoneCount;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050037 GrBackendTexture fLastFulfilledTexture;
38
39 /**
40 * Replaces the backend texture that this checker will return from fulfill. Also, transfers
41 * ownership of the previous PromiseImageTexture to the caller, if they want to control when
42 * it is deleted. The default argument will remove the existing texture without installing a
43 * valid replacement.
44 */
Brian Salomon3f4cd772019-01-11 16:03:19 -050045 sk_sp<const SkPromiseImageTexture> replaceTexture(
46 const GrBackendTexture& tex = GrBackendTexture()) {
Brian Salomonf55e8d52019-01-30 17:28:20 -050047 return skstd::exchange(fTexture, SkPromiseImageTexture::Make(tex));
Greg Daniela8d92112018-03-09 12:05:04 -050048 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050049
50 SkTArray<GrUniqueKey> uniqueKeys() const {
Brian Salomon3f4cd772019-01-11 16:03:19 -050051 return fTexture->testingOnly_uniqueKeysToInvalidate();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050052 }
53
Brian Salomon3f4cd772019-01-11 16:03:19 -050054 static sk_sp<SkPromiseImageTexture> Fulfill(void* self) {
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050055 auto checker = static_cast<PromiseTextureChecker*>(self);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050056 checker->fFulfillCount++;
Brian Salomon3f4cd772019-01-11 16:03:19 -050057 checker->fLastFulfilledTexture = checker->fTexture->backendTexture();
58 return checker->fTexture;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050059 }
Brian Salomon9bc76d92019-01-24 12:18:33 -050060 static void Release(void* self) {
61 auto checker = static_cast<PromiseTextureChecker*>(self);
62 checker->fReleaseCount++;
63 if (!checker->fShared) {
64 // This is only used in a single threaded fashion with a single promise image. So
65 // every fulfill should be balanced by a release before the next fulfill.
66 REPORTER_ASSERT(checker->fReporter, checker->fReleaseCount == checker->fFulfillCount);
67 }
68 }
Greg Daniel7278d682018-03-16 14:57:21 -040069 static void Done(void* self) {
70 static_cast<PromiseTextureChecker*>(self)->fDoneCount++;
71 }
Greg Daniela8d92112018-03-09 12:05:04 -050072};
73
Brian Salomonf55e8d52019-01-30 17:28:20 -050074enum class ReleaseBalanceExpecation {
75 kBalanced,
76 kBalancedOrPlusOne,
77 kAny
78};
79
Greg Daniela8d92112018-03-09 12:05:04 -050080static bool check_fulfill_and_release_cnts(const PromiseTextureChecker& promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -050081 ReleaseBalanceExpecation balanceExpecation,
Greg Daniela8d92112018-03-09 12:05:04 -050082 int expectedFulfillCnt,
83 int expectedReleaseCnt,
84 bool expectedRequired,
Greg Daniel7278d682018-03-16 14:57:21 -040085 int expectedDoneCnt,
Greg Daniela8d92112018-03-09 12:05:04 -050086 skiatest::Reporter* reporter) {
87 bool result = true;
88 int countDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
89 // FulfillCount should always equal ReleaseCount or be at most one higher
90 if (countDiff != 0) {
Brian Salomonf55e8d52019-01-30 17:28:20 -050091 if (balanceExpecation == ReleaseBalanceExpecation::kBalanced) {
Greg Daniela8d92112018-03-09 12:05:04 -050092 result = false;
93 REPORTER_ASSERT(reporter, 0 == countDiff);
Brian Salomonf55e8d52019-01-30 17:28:20 -050094 } else if (countDiff != 1 &&
95 balanceExpecation == ReleaseBalanceExpecation::kBalancedOrPlusOne) {
Greg Daniela8d92112018-03-09 12:05:04 -050096 result = false;
97 REPORTER_ASSERT(reporter, 0 == countDiff || 1 == countDiff);
Brian Salomonf55e8d52019-01-30 17:28:20 -050098 } else if (countDiff < 0) {
99 result = false;
100 REPORTER_ASSERT(reporter, countDiff >= 0);
Greg Daniela8d92112018-03-09 12:05:04 -0500101 }
102 }
103
104 int fulfillDiff = expectedFulfillCnt - promiseChecker.fFulfillCount;
105 REPORTER_ASSERT(reporter, fulfillDiff >= 0);
106 if (fulfillDiff != 0) {
107 if (expectedRequired) {
108 result = false;
109 REPORTER_ASSERT(reporter, expectedFulfillCnt == promiseChecker.fFulfillCount);
110 } else if (fulfillDiff > 1) {
111 result = false;
112 REPORTER_ASSERT(reporter, fulfillDiff <= 1);
113 }
114 }
115
116 int releaseDiff = expectedReleaseCnt - promiseChecker.fReleaseCount;
117 REPORTER_ASSERT(reporter, releaseDiff >= 0);
118 if (releaseDiff != 0) {
119 if (expectedRequired) {
120 result = false;
121 REPORTER_ASSERT(reporter, expectedReleaseCnt == promiseChecker.fReleaseCount);
122 } else if (releaseDiff > 1) {
123 result = false;
124 REPORTER_ASSERT(reporter, releaseDiff <= 1);
125 }
126 }
127
Greg Daniel7278d682018-03-16 14:57:21 -0400128 if (expectedDoneCnt != promiseChecker.fDoneCount) {
129 result = false;
130 REPORTER_ASSERT(reporter, expectedDoneCnt == promiseChecker.fDoneCount);
131 }
132
Greg Daniela8d92112018-03-09 12:05:04 -0500133 return result;
134}
135
Brian Salomonf55e8d52019-01-30 17:28:20 -0500136DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTestNoDelayedRelease, reporter, ctxInfo) {
Greg Daniela8d92112018-03-09 12:05:04 -0500137 const int kWidth = 10;
138 const int kHeight = 10;
Greg Daniela8d92112018-03-09 12:05:04 -0500139
140 GrContext* ctx = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500141 GrGpu* gpu = ctx->priv().getGpu();
Greg Daniela8d92112018-03-09 12:05:04 -0500142
Greg Daniel7278d682018-03-16 14:57:21 -0400143 for (bool releaseImageEarly : {true, false}) {
144 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
Robert Phillips646f6372018-09-25 09:31:10 -0400145 nullptr, kWidth, kHeight, GrColorType::kRGBA_8888, true, GrMipMapped::kNo);
Greg Daniel7278d682018-03-16 14:57:21 -0400146 REPORTER_ASSERT(reporter, backendTex.isValid());
Greg Daniela8d92112018-03-09 12:05:04 -0500147
Brian Salomonf391d0f2018-12-14 09:18:50 -0500148 GrBackendFormat backendFormat = backendTex.getBackendFormat();
Greg Daniel7278d682018-03-16 14:57:21 -0400149 REPORTER_ASSERT(reporter, backendFormat.isValid());
Greg Daniela8d92112018-03-09 12:05:04 -0500150
Brian Salomon9bc76d92019-01-24 12:18:33 -0500151 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
Greg Daniel7278d682018-03-16 14:57:21 -0400152 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
153 sk_sp<SkImage> refImg(
Brian Salomonf55e8d52019-01-30 17:28:20 -0500154 SkImage_Gpu::MakePromiseTexture(
155 ctx, backendFormat, kWidth, kHeight,
156 GrMipMapped::kNo, texOrigin,
157 kRGBA_8888_SkColorType, kPremul_SkAlphaType,
158 nullptr,
159 PromiseTextureChecker::Fulfill,
160 PromiseTextureChecker::Release,
161 PromiseTextureChecker::Done,
162 &promiseChecker,
163 SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo));
Greg Daniela8d92112018-03-09 12:05:04 -0500164
Greg Daniel7278d682018-03-16 14:57:21 -0400165 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
166 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
167 SkCanvas* canvas = surface->getCanvas();
Greg Daniela8d92112018-03-09 12:05:04 -0500168
Greg Daniel7278d682018-03-16 14:57:21 -0400169 int expectedFulfillCnt = 0;
170 int expectedReleaseCnt = 0;
171 int expectedDoneCnt = 0;
Brian Salomonf55e8d52019-01-30 17:28:20 -0500172 ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kBalanced;
Greg Daniela8d92112018-03-09 12:05:04 -0500173
Greg Daniel7278d682018-03-16 14:57:21 -0400174 canvas->drawImage(refImg, 0, 0);
175 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500176 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400177 expectedFulfillCnt,
178 expectedReleaseCnt,
179 true,
180 expectedDoneCnt,
181 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500182
Robert Phillips4217ea72019-01-30 13:08:28 -0500183 bool isVulkan = GrBackendApi::kVulkan == ctx->backend();
Greg Daniel7278d682018-03-16 14:57:21 -0400184 canvas->flush();
185 expectedFulfillCnt++;
186 expectedReleaseCnt++;
Brian Salomonf55e8d52019-01-30 17:28:20 -0500187 if (isVulkan) {
188 balanceExpecation = ReleaseBalanceExpecation::kBalancedOrPlusOne;
189 }
Greg Daniel7278d682018-03-16 14:57:21 -0400190 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500191 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400192 expectedFulfillCnt,
193 expectedReleaseCnt,
194 !isVulkan,
195 expectedDoneCnt,
196 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500197
Greg Daniel7278d682018-03-16 14:57:21 -0400198 gpu->testingOnly_flushGpuAndSync();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500199 balanceExpecation = ReleaseBalanceExpecation::kBalanced;
Greg Daniel7278d682018-03-16 14:57:21 -0400200 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500201 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400202 expectedFulfillCnt,
203 expectedReleaseCnt,
204 true,
205 expectedDoneCnt,
206 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500207
Greg Daniel7278d682018-03-16 14:57:21 -0400208 canvas->drawImage(refImg, 0, 0);
209 canvas->drawImage(refImg, 0, 0);
Greg Daniela8d92112018-03-09 12:05:04 -0500210
Greg Daniel7278d682018-03-16 14:57:21 -0400211 canvas->flush();
212 expectedFulfillCnt++;
213 expectedReleaseCnt++;
Greg Daniela8d92112018-03-09 12:05:04 -0500214
Greg Daniel7278d682018-03-16 14:57:21 -0400215 gpu->testingOnly_flushGpuAndSync();
216 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500217 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400218 expectedFulfillCnt,
219 expectedReleaseCnt,
220 true,
221 expectedDoneCnt,
222 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500223
Greg Daniel7278d682018-03-16 14:57:21 -0400224 // Now test code path on Vulkan where we released the texture, but the GPU isn't done with
225 // resource yet and we do another draw. We should only call fulfill on the first draw and
226 // use the cached GrBackendTexture on the second. Release should only be called after the
227 // second draw is finished.
228 canvas->drawImage(refImg, 0, 0);
229 canvas->flush();
230 expectedFulfillCnt++;
231 expectedReleaseCnt++;
Brian Salomonf55e8d52019-01-30 17:28:20 -0500232 if (isVulkan) {
233 balanceExpecation = ReleaseBalanceExpecation::kBalancedOrPlusOne;
234 }
Greg Daniel7278d682018-03-16 14:57:21 -0400235 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500236 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400237 expectedFulfillCnt,
238 expectedReleaseCnt,
239 !isVulkan,
240 expectedDoneCnt,
241 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500242
Greg Daniel7278d682018-03-16 14:57:21 -0400243 canvas->drawImage(refImg, 0, 0);
Greg Daniela8d92112018-03-09 12:05:04 -0500244
Greg Daniel7278d682018-03-16 14:57:21 -0400245 if (releaseImageEarly) {
246 refImg.reset();
247 }
Greg Daniela8d92112018-03-09 12:05:04 -0500248
Greg Daniel7278d682018-03-16 14:57:21 -0400249 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500250 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400251 expectedFulfillCnt,
252 expectedReleaseCnt,
253 !isVulkan,
254 expectedDoneCnt,
255 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500256
Greg Daniel7278d682018-03-16 14:57:21 -0400257 canvas->flush();
258 expectedFulfillCnt++;
Greg Daniela8d92112018-03-09 12:05:04 -0500259
Greg Daniel7278d682018-03-16 14:57:21 -0400260 gpu->testingOnly_flushGpuAndSync();
261 expectedReleaseCnt++;
262 if (releaseImageEarly) {
263 expectedDoneCnt++;
264 }
Brian Salomonf55e8d52019-01-30 17:28:20 -0500265 balanceExpecation = ReleaseBalanceExpecation::kBalanced;
Greg Daniel7278d682018-03-16 14:57:21 -0400266 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500267 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400268 expectedFulfillCnt,
269 expectedReleaseCnt,
270 !isVulkan,
271 expectedDoneCnt,
272 reporter));
273 expectedFulfillCnt = promiseChecker.fFulfillCount;
274 expectedReleaseCnt = promiseChecker.fReleaseCount;
275
276 if (!releaseImageEarly) {
277 refImg.reset();
278 expectedDoneCnt++;
279 }
280
281 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500282 balanceExpecation,
Greg Daniel7278d682018-03-16 14:57:21 -0400283 expectedFulfillCnt,
284 expectedReleaseCnt,
285 true,
286 expectedDoneCnt,
287 reporter));
288
289 gpu->deleteTestingOnlyBackendTexture(backendTex);
290 }
Greg Daniela8d92112018-03-09 12:05:04 -0500291}
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500292
Brian Salomonf55e8d52019-01-30 17:28:20 -0500293DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTestDelayedRelease, reporter, ctxInfo) {
294 const int kWidth = 10;
295 const int kHeight = 10;
296
297 GrContext* ctx = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500298 GrGpu* gpu = ctx->priv().getGpu();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500299
300 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
301 nullptr, kWidth, kHeight, GrColorType::kRGBA_8888, true, GrMipMapped::kNo);
302 REPORTER_ASSERT(reporter, backendTex.isValid());
303
304 GrBackendFormat backendFormat = backendTex.getBackendFormat();
305 REPORTER_ASSERT(reporter, backendFormat.isValid());
306
307 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
308 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
309 sk_sp<SkImage> refImg(
310 SkImage_Gpu::MakePromiseTexture(
311 ctx, backendFormat, kWidth, kHeight,
312 GrMipMapped::kNo, texOrigin,
313 kRGBA_8888_SkColorType, kPremul_SkAlphaType,
314 nullptr,
315 PromiseTextureChecker::Fulfill,
316 PromiseTextureChecker::Release,
317 PromiseTextureChecker::Done,
318 &promiseChecker,
319 SkDeferredDisplayListRecorder::DelayReleaseCallback::kYes));
320
321 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
322 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
323 SkCanvas* canvas = surface->getCanvas();
324
325 int expectedFulfillCnt = 0;
326 int expectedReleaseCnt = 0;
327 int expectedDoneCnt = 0;
328 ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kBalanced;
329
330 canvas->drawImage(refImg, 0, 0);
331 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
332 balanceExpecation,
333 expectedFulfillCnt,
334 expectedReleaseCnt,
335 true,
336 expectedDoneCnt,
337 reporter));
338
339 bool isVulkan = GrBackendApi::kVulkan == ctx->backend();
340 canvas->flush();
341 expectedFulfillCnt++;
342 // Because we've delayed release, we expect a +1 balance.
343 balanceExpecation = ReleaseBalanceExpecation::kBalancedOrPlusOne;
344 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
345 balanceExpecation,
346 expectedFulfillCnt,
347 expectedReleaseCnt,
348 !isVulkan,
349 expectedDoneCnt,
350 reporter));
351
352 gpu->testingOnly_flushGpuAndSync();
353 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
354 balanceExpecation,
355 expectedFulfillCnt,
356 expectedReleaseCnt,
357 true,
358 expectedDoneCnt,
359 reporter));
360
361 canvas->drawImage(refImg, 0, 0);
362 canvas->drawImage(refImg, 0, 0);
363
364 canvas->flush();
365
366 gpu->testingOnly_flushGpuAndSync();
367 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
368 balanceExpecation,
369 expectedFulfillCnt,
370 expectedReleaseCnt,
371 true,
372 expectedDoneCnt,
373 reporter));
374
375 canvas->drawImage(refImg, 0, 0);
376 canvas->flush();
377 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
378 balanceExpecation,
379 expectedFulfillCnt,
380 expectedReleaseCnt,
381 !isVulkan,
382 expectedDoneCnt,
383 reporter));
384
385 canvas->drawImage(refImg, 0, 0);
386
387 refImg.reset();
388
389 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
390 balanceExpecation,
391 expectedFulfillCnt,
392 expectedReleaseCnt,
393 !isVulkan,
394 expectedDoneCnt,
395 reporter));
396
397 canvas->flush();
398 gpu->testingOnly_flushGpuAndSync();
399 // We released the image already and we flushed and synced.
400 balanceExpecation = ReleaseBalanceExpecation::kBalanced;
401 expectedReleaseCnt++;
402 expectedDoneCnt++;
403 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
404 balanceExpecation,
405 expectedFulfillCnt,
406 expectedReleaseCnt,
407 !isVulkan,
408 expectedDoneCnt,
409 reporter));
410
411 gpu->deleteTestingOnlyBackendTexture(backendTex);
412}
413
414// Tests replacing the backing texture for a promise image after a release and then refulfilling in
415// the SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo case.
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500416DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureReuse, reporter, ctxInfo) {
417 const int kWidth = 10;
418 const int kHeight = 10;
419
420 GrContext* ctx = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500421 GrGpu* gpu = ctx->priv().getGpu();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500422
423 GrBackendTexture backendTex1 = gpu->createTestingOnlyBackendTexture(
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500424 nullptr, kWidth, kHeight, GrColorType::kRGBA_8888, false, GrMipMapped::kNo);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500425 GrBackendTexture backendTex2 = gpu->createTestingOnlyBackendTexture(
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500426 nullptr, kWidth, kHeight, GrColorType::kRGBA_8888, false, GrMipMapped::kNo);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500427 GrBackendTexture backendTex3 = gpu->createTestingOnlyBackendTexture(
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500428 nullptr, kWidth, kHeight, GrColorType::kRGBA_8888, false, GrMipMapped::kNo);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500429 REPORTER_ASSERT(reporter, backendTex1.isValid());
430 REPORTER_ASSERT(reporter, backendTex2.isValid());
431 REPORTER_ASSERT(reporter, backendTex3.isValid());
432
433 GrBackendFormat backendFormat = backendTex1.getBackendFormat();
434 REPORTER_ASSERT(reporter, backendFormat.isValid());
435 REPORTER_ASSERT(reporter, backendFormat == backendTex2.getBackendFormat());
436 REPORTER_ASSERT(reporter, backendFormat == backendTex3.getBackendFormat());
437
Brian Salomon9bc76d92019-01-24 12:18:33 -0500438 PromiseTextureChecker promiseChecker(backendTex1, reporter, true);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500439 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
440 sk_sp<SkImage> refImg(
Brian Salomonf55e8d52019-01-30 17:28:20 -0500441 SkImage_Gpu::MakePromiseTexture(
442 ctx, backendFormat, kWidth, kHeight,
443 GrMipMapped::kNo, texOrigin,
444 kRGBA_8888_SkColorType, kPremul_SkAlphaType,
445 nullptr,
446 PromiseTextureChecker::Fulfill,
447 PromiseTextureChecker::Release,
448 PromiseTextureChecker::Done,
449 &promiseChecker,
450 SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500451
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500452 SkImageInfo info =
453 SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500454 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
455 SkCanvas* canvas = surface->getCanvas();
456
457 int expectedFulfillCnt = 0;
458 int expectedReleaseCnt = 0;
459 int expectedDoneCnt = 0;
460
461 canvas->drawImage(refImg, 0, 0);
462 canvas->drawImage(refImg, 5, 5);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500463 ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kBalanced;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500464 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500465 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500466 expectedFulfillCnt,
467 expectedReleaseCnt,
468 true,
469 expectedDoneCnt,
470 reporter));
471
Robert Phillips4217ea72019-01-30 13:08:28 -0500472 bool isVulkan = GrBackendApi::kVulkan == ctx->backend();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500473 canvas->flush();
474 expectedFulfillCnt++;
475 expectedReleaseCnt++;
Brian Salomonf55e8d52019-01-30 17:28:20 -0500476 if (isVulkan) {
477 balanceExpecation = ReleaseBalanceExpecation::kBalancedOrPlusOne;
478 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500479 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500480 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500481 expectedFulfillCnt,
482 expectedReleaseCnt,
483 !isVulkan,
484 expectedDoneCnt,
485 reporter));
486 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(
487 promiseChecker.fLastFulfilledTexture, backendTex1));
488 // We should have put a GrTexture for this fulfillment into the cache.
489 auto keys = promiseChecker.uniqueKeys();
490 REPORTER_ASSERT(reporter, keys.count() == 1);
491 GrUniqueKey texKey1;
492 if (keys.count()) {
493 texKey1 = keys[0];
494 }
495 REPORTER_ASSERT(reporter, texKey1.isValid());
Robert Phillips9da87e02019-02-04 13:26:26 -0500496 REPORTER_ASSERT(reporter, ctx->priv().resourceProvider()->findByUniqueKey<>(texKey1));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500497
498 gpu->testingOnly_flushGpuAndSync();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500499 balanceExpecation = ReleaseBalanceExpecation::kBalanced;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500500 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500501 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500502 expectedFulfillCnt,
503 expectedReleaseCnt,
504 true,
505 expectedDoneCnt,
506 reporter));
507 REPORTER_ASSERT(reporter,
508 GrBackendTexture::TestingOnly_Equals(
Brian Salomon3f4cd772019-01-11 16:03:19 -0500509 promiseChecker.replaceTexture()->backendTexture(), backendTex1));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500510 gpu->deleteTestingOnlyBackendTexture(backendTex1);
511
Robert Phillips9da87e02019-02-04 13:26:26 -0500512 ctx->priv().getResourceCache()->purgeAsNeeded();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500513 // We should have invalidated the key on the previously cached texture (after ensuring
514 // invalidation messages have been processed by calling purgeAsNeeded.)
Robert Phillips9da87e02019-02-04 13:26:26 -0500515 REPORTER_ASSERT(reporter, !ctx->priv().resourceProvider()->findByUniqueKey<>(texKey1));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500516
517 promiseChecker.replaceTexture(backendTex2);
518
519 canvas->drawImage(refImg, 0, 0);
520 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500521 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500522 expectedFulfillCnt,
523 expectedReleaseCnt,
524 true,
525 expectedDoneCnt,
526 reporter));
527
528 canvas->flush();
529 expectedFulfillCnt++;
530 expectedReleaseCnt++;
Brian Salomonf55e8d52019-01-30 17:28:20 -0500531 if (isVulkan) {
532 balanceExpecation = ReleaseBalanceExpecation::kBalancedOrPlusOne;
533 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500534 // Second texture should be in the cache.
535 keys = promiseChecker.uniqueKeys();
536 REPORTER_ASSERT(reporter, keys.count() == 1);
537 GrUniqueKey texKey2;
538 if (keys.count()) {
539 texKey2 = keys[0];
540 }
541 REPORTER_ASSERT(reporter, texKey2.isValid() && texKey2 != texKey1);
Robert Phillips9da87e02019-02-04 13:26:26 -0500542 REPORTER_ASSERT(reporter, ctx->priv().resourceProvider()->findByUniqueKey<>(texKey2));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500543
544 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500545 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500546 expectedFulfillCnt,
547 expectedReleaseCnt,
548 !isVulkan,
549 expectedDoneCnt,
550 reporter));
551 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(
552 promiseChecker.fLastFulfilledTexture, backendTex2));
553
554 gpu->testingOnly_flushGpuAndSync();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500555 balanceExpecation = ReleaseBalanceExpecation::kBalanced;
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500556 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500557 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500558 expectedFulfillCnt,
559 expectedReleaseCnt,
560 true,
561 expectedDoneCnt,
562 reporter));
563
564 // Because we have kept the SkPromiseImageTexture alive, we should be able to use it again and
565 // hit the cache.
Robert Phillips9da87e02019-02-04 13:26:26 -0500566 ctx->priv().getResourceCache()->purgeAsNeeded();
567 REPORTER_ASSERT(reporter, ctx->priv().resourceProvider()->findByUniqueKey<>(texKey2));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500568
569 canvas->drawImage(refImg, 0, 0);
570
571 canvas->flush();
572 gpu->testingOnly_flushGpuAndSync();
573 expectedFulfillCnt++;
574 expectedReleaseCnt++;
575 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500576 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500577 expectedFulfillCnt,
578 expectedReleaseCnt,
579 true,
580 expectedDoneCnt,
581 reporter));
582
583 // Make sure we didn't add another key and that the second texture is still alive in the cache.
584 keys = promiseChecker.uniqueKeys();
585 REPORTER_ASSERT(reporter, keys.count() == 1);
586 if (keys.count()) {
587 REPORTER_ASSERT(reporter, texKey2 == keys[0]);
588 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500589 ctx->priv().getResourceCache()->purgeAsNeeded();
590 REPORTER_ASSERT(reporter, ctx->priv().resourceProvider()->findByUniqueKey<>(texKey2));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500591
592 // Now we test keeping tex2 alive but fulfilling with a new texture.
Brian Salomon3f4cd772019-01-11 16:03:19 -0500593 sk_sp<const SkPromiseImageTexture> promiseImageTexture2 =
594 promiseChecker.replaceTexture(backendTex3);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500595 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(
Brian Salomon3f4cd772019-01-11 16:03:19 -0500596 promiseImageTexture2->backendTexture(), backendTex2));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500597
598 canvas->drawImage(refImg, 0, 0);
599
600 canvas->flush();
601 gpu->testingOnly_flushGpuAndSync();
602 expectedFulfillCnt++;
603 expectedReleaseCnt++;
604 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500605 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500606 expectedFulfillCnt,
607 expectedReleaseCnt,
608 true,
609 expectedDoneCnt,
610 reporter));
611
612 keys = promiseChecker.uniqueKeys();
613 REPORTER_ASSERT(reporter, keys.count() == 1);
614 GrUniqueKey texKey3;
615 if (keys.count()) {
616 texKey3 = keys[0];
617 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500618 ctx->priv().getResourceCache()->purgeAsNeeded();
619 REPORTER_ASSERT(reporter, !ctx->priv().resourceProvider()->findByUniqueKey<>(texKey2));
620 REPORTER_ASSERT(reporter, ctx->priv().resourceProvider()->findByUniqueKey<>(texKey3));
Brian Salomon3f4cd772019-01-11 16:03:19 -0500621 gpu->deleteTestingOnlyBackendTexture(promiseImageTexture2->backendTexture());
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500622
623 // Make a new promise image also backed by texture 3.
624 sk_sp<SkImage> refImg2(
Brian Salomonf55e8d52019-01-30 17:28:20 -0500625 SkImage_Gpu::MakePromiseTexture(
626 ctx, backendFormat, kWidth, kHeight,
627 GrMipMapped::kNo, texOrigin,
628 kRGBA_8888_SkColorType, kPremul_SkAlphaType,
629 nullptr,
630 PromiseTextureChecker::Fulfill,
631 PromiseTextureChecker::Release,
632 PromiseTextureChecker::Done,
633 &promiseChecker,
634 SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500635 canvas->drawImage(refImg, 0, 0);
636 canvas->drawImage(refImg2, 1, 1);
637
638 canvas->flush();
639 gpu->testingOnly_flushGpuAndSync();
640 expectedFulfillCnt += 2;
641 expectedReleaseCnt += 2;
642 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500643 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500644 expectedFulfillCnt,
645 expectedReleaseCnt,
646 true,
647 expectedDoneCnt,
648 reporter));
649
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500650 // The two images should share a single GrTexture by using the same key. The key is only
651 // dependent on the pixel config and the PromiseImageTexture key.
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500652 keys = promiseChecker.uniqueKeys();
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500653 REPORTER_ASSERT(reporter, keys.count() == 1);
654 if (keys.count() > 0) {
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500655 REPORTER_ASSERT(reporter, texKey3 == keys[0]);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500656 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500657 ctx->priv().getResourceCache()->purgeAsNeeded();
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500658
659 // If we delete the SkPromiseImageTexture we should trigger both key removals.
660 REPORTER_ASSERT(reporter,
661 GrBackendTexture::TestingOnly_Equals(
Brian Salomon3f4cd772019-01-11 16:03:19 -0500662 promiseChecker.replaceTexture()->backendTexture(), backendTex3));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500663
Robert Phillips9da87e02019-02-04 13:26:26 -0500664 ctx->priv().getResourceCache()->purgeAsNeeded();
665 REPORTER_ASSERT(reporter, !ctx->priv().resourceProvider()->findByUniqueKey<>(texKey3));
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500666 gpu->deleteTestingOnlyBackendTexture(backendTex3);
667
668 // After deleting each image we should get a done call.
669 refImg.reset();
670 ++expectedDoneCnt;
671 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500672 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500673 expectedFulfillCnt,
674 expectedReleaseCnt,
675 true,
676 expectedDoneCnt,
677 reporter));
678 refImg2.reset();
679 ++expectedDoneCnt;
680 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500681 balanceExpecation,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500682 expectedFulfillCnt,
683 expectedReleaseCnt,
684 true,
685 expectedDoneCnt,
686 reporter));
687}
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500688
689DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureReuseDifferentConfig, reporter, ctxInfo) {
690 // Try making two promise SkImages backed by the same texture but with different configs.
691 // This will only be testable on backends where a single texture format (8bit red unorm) can
692 // be used for alpha and gray image color types.
693
694 const int kWidth = 10;
695 const int kHeight = 10;
696
697 GrContext* ctx = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500698 GrGpu* gpu = ctx->priv().getGpu();
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500699
700 GrBackendTexture backendTex1 = gpu->createTestingOnlyBackendTexture(
701 nullptr, kWidth, kHeight, GrColorType::kGray_8, false, GrMipMapped::kNo);
702 REPORTER_ASSERT(reporter, backendTex1.isValid());
703
704 GrBackendTexture backendTex2 = gpu->createTestingOnlyBackendTexture(
705 nullptr, kWidth, kHeight, GrColorType::kAlpha_8, false, GrMipMapped::kNo);
706 REPORTER_ASSERT(reporter, backendTex2.isValid());
Brian Salomonf55e8d52019-01-30 17:28:20 -0500707 if (backendTex1.getBackendFormat() != backendTex2.getBackendFormat()) {
708 gpu->deleteTestingOnlyBackendTexture(backendTex1);
709 return;
710 }
711 // We only needed this texture to check that alpha and gray color types use the same format.
712 gpu->deleteTestingOnlyBackendTexture(backendTex2);
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500713
714 SkImageInfo info =
715 SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
716 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
717 SkCanvas* canvas = surface->getCanvas();
718
Brian Salomonf55e8d52019-01-30 17:28:20 -0500719 for (auto delayRelease : {SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo,
720 SkDeferredDisplayListRecorder::DelayReleaseCallback::kYes}) {
721 PromiseTextureChecker promiseChecker(backendTex1, reporter, true);
722 sk_sp<SkImage> alphaImg(SkImage_Gpu::MakePromiseTexture(
723 ctx, backendTex1.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
724 kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
725 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
726 PromiseTextureChecker::Done, &promiseChecker, delayRelease));
727 REPORTER_ASSERT(reporter, alphaImg);
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500728
Brian Salomonf55e8d52019-01-30 17:28:20 -0500729 sk_sp<SkImage> grayImg(SkImage_Gpu::MakePromiseTexture(
730 ctx, backendTex1.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
731 kBottomLeft_GrSurfaceOrigin, kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr,
732 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
733 PromiseTextureChecker::Done, &promiseChecker, delayRelease));
734 REPORTER_ASSERT(reporter, grayImg);
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500735
Brian Salomonf55e8d52019-01-30 17:28:20 -0500736 canvas->drawImage(alphaImg, 0, 0);
737 canvas->drawImage(grayImg, 1, 1);
738 canvas->flush();
739 gpu->testingOnly_flushGpuAndSync();
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500740
Brian Salomonf55e8d52019-01-30 17:28:20 -0500741 int expectedFulfillCnt = 2;
742 int expectedReleaseCnt = 0;
743 int expectedDoneCnt = 0;
744 ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kAny;
745 if (delayRelease == SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo) {
746 expectedReleaseCnt = 2;
747 balanceExpecation = ReleaseBalanceExpecation::kBalanced;
748 }
749 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
750 balanceExpecation,
751 expectedFulfillCnt,
752 expectedReleaseCnt,
753 true,
754 expectedDoneCnt,
755 reporter));
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500756
Brian Salomonf55e8d52019-01-30 17:28:20 -0500757 // Because they use different configs, each image should have created a different GrTexture
758 // and they both should still be cached.
Robert Phillips9da87e02019-02-04 13:26:26 -0500759 ctx->priv().getResourceCache()->purgeAsNeeded();
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500760
Brian Salomonf55e8d52019-01-30 17:28:20 -0500761 auto keys = promiseChecker.uniqueKeys();
762 REPORTER_ASSERT(reporter, keys.count() == 2);
763 for (const auto& key : keys) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500764 auto surf = ctx->priv().resourceProvider()->findByUniqueKey<GrSurface>(key);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500765 REPORTER_ASSERT(reporter, surf && surf->asTexture());
766 if (surf && surf->asTexture()) {
767 REPORTER_ASSERT(reporter,
768 !GrBackendTexture::TestingOnly_Equals(
769 backendTex1, surf->asTexture()->getBackendTexture()));
770 }
771 }
772
773 // Change the backing texture, this should invalidate the keys.
774 promiseChecker.replaceTexture();
Robert Phillips9da87e02019-02-04 13:26:26 -0500775 ctx->priv().getResourceCache()->purgeAsNeeded();
Brian Salomonf55e8d52019-01-30 17:28:20 -0500776
777 for (const auto& key : keys) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500778 auto surf = ctx->priv().resourceProvider()->findByUniqueKey<GrSurface>(key);
Brian Salomonf55e8d52019-01-30 17:28:20 -0500779 REPORTER_ASSERT(reporter, !surf);
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500780 }
781 }
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500782 gpu->deleteTestingOnlyBackendTexture(backendTex1);
Brian Salomon1bf0ed82019-01-16 13:51:35 -0500783}
Brian Salomon9bc76d92019-01-24 12:18:33 -0500784
785DEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) {
786 const int kWidth = 10;
787 const int kHeight = 10;
788
789 // Different ways of killing contexts.
790 using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrContext*)>;
791 DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrContext* context) {
792 factory->destroyContexts();
793 };
794 DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrContext* context) {
795 context->abandonContext();
796 };
797 DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory,
798 GrContext* context) {
799 context->releaseResourcesAndAbandonContext();
800 };
801
802 for (int type = 0; type < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++type) {
803 auto contextType = static_cast<sk_gpu_test::GrContextFactory::ContextType>(type);
804 // These tests are difficult to get working with Vulkan. See http://skbug.com/8705
805 // and http://skbug.com/8275
806 GrBackendApi api = sk_gpu_test::GrContextFactory::ContextTypeBackend(contextType);
807 if (api == GrBackendApi::kVulkan) {
808 continue;
809 }
810 DeathFn contextKillers[] = {destroy, abandon, releaseResourcesAndAbandon};
811 for (auto contextDeath : contextKillers) {
812 sk_gpu_test::GrContextFactory factory;
813 auto ctx = factory.get(contextType);
814 if (!ctx) {
815 continue;
816 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500817 GrGpu* gpu = ctx->priv().getGpu();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500818
819 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
820 nullptr, kWidth, kHeight, GrColorType::kAlpha_8, false, GrMipMapped::kNo);
821 REPORTER_ASSERT(reporter, backendTex.isValid());
822
823 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
824 kPremul_SkAlphaType);
825 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
826 SkCanvas* canvas = surface->getCanvas();
827
828 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
829 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
830 ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500831 kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
832 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
833 PromiseTextureChecker::Done, &promiseChecker,
834 SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500835 REPORTER_ASSERT(reporter, image);
836
837 canvas->drawImage(image, 0, 0);
838 image.reset();
839 // If the surface still holds a ref to the context then the factory will not be able
840 // to destroy the context (and instead will release-all-and-abandon).
841 surface.reset();
842
843 ctx->flush();
844 contextDeath(&factory, ctx);
845
846 int expectedFulfillCnt = 1;
847 int expectedReleaseCnt = 1;
848 int expectedDoneCnt = 1;
Brian Salomonf55e8d52019-01-30 17:28:20 -0500849 ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kBalanced;
Brian Salomon9bc76d92019-01-24 12:18:33 -0500850 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500851 balanceExpecation,
Brian Salomon9bc76d92019-01-24 12:18:33 -0500852 expectedFulfillCnt,
853 expectedReleaseCnt,
854 true,
855 expectedDoneCnt,
856 reporter));
857 }
858 }
859}
860
861DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxInfo) {
862 const int kWidth = 10;
863 const int kHeight = 10;
864
865 GrContext* ctx = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500866 GrGpu* gpu = ctx->priv().getGpu();
Brian Salomon9bc76d92019-01-24 12:18:33 -0500867
868 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
869 nullptr, kWidth, kHeight, GrColorType::kAlpha_8, false, GrMipMapped::kNo);
870 REPORTER_ASSERT(reporter, backendTex.isValid());
871
872 SkImageInfo info =
873 SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
874 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
875 SkCanvas* canvas = surface->getCanvas();
876
877 PromiseTextureChecker promiseChecker(backendTex, reporter, false);
878 sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
879 ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
880 kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
881 PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500882 PromiseTextureChecker::Done, &promiseChecker,
883 SkDeferredDisplayListRecorder::DelayReleaseCallback::kNo));
Brian Salomon9bc76d92019-01-24 12:18:33 -0500884 REPORTER_ASSERT(reporter, image);
885
886 // Make the cache full. This tests that we don't preemptively purge cached textures for
887 // fulfillment due to cache pressure.
888 static constexpr int kMaxResources = 10;
889 static constexpr int kMaxBytes = 100;
890 ctx->setResourceCacheLimits(kMaxResources, kMaxBytes);
891 sk_sp<GrTexture> textures[2 * kMaxResources];
892 for (int i = 0; i < 2 * kMaxResources; ++i) {
893 GrSurfaceDesc desc;
894 desc.fConfig = kRGBA_8888_GrPixelConfig;
895 desc.fWidth = desc.fHeight = 100;
Robert Phillips9da87e02019-02-04 13:26:26 -0500896 textures[i] = ctx->priv().resourceProvider()->createTexture(desc, SkBudgeted::kYes);
Brian Salomon9bc76d92019-01-24 12:18:33 -0500897 REPORTER_ASSERT(reporter, textures[i]);
898 }
899
900 // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are
901 // properly ordered.
902 canvas->drawImage(image, 0, 0);
903 canvas->flush();
904 canvas->drawImage(image, 1, 0);
905 canvas->flush();
906 canvas->drawImage(image, 2, 0);
907 canvas->flush();
908 canvas->drawImage(image, 3, 0);
909 canvas->flush();
910 canvas->drawImage(image, 4, 0);
911 canvas->flush();
912 canvas->drawImage(image, 5, 0);
913 canvas->flush();
914 // Must call this to ensure that all callbacks are performed before the checker is destroyed.
915 gpu->testingOnly_flushGpuAndSync();
916 gpu->deleteTestingOnlyBackendTexture(backendTex);
917}