Flutter Engine
The Flutter Engine
GraphitePromiseImageTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
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
9
21#include "tests/Test.h"
23
24using namespace skgpu::graphite;
25
26namespace {
27
29 PromiseTextureChecker() = default;
30
31 explicit PromiseTextureChecker(const BackendTexture& backendTex,
34 fBackendTextures[0] = backendTex;
35 }
36
37 explicit PromiseTextureChecker(const BackendTexture& backendTex0,
38 const BackendTexture& backendTex1,
41 , fHasTwoBackendTextures(true) {
42 fBackendTextures[0] = backendTex0;
43 fBackendTextures[1] = backendTex1;
44 }
45
46 void checkImageReleased(skiatest::Reporter* reporter, int expectedReleaseCnt) {
47 REPORTER_ASSERT(reporter, expectedReleaseCnt == fImageReleaseCount);
48 }
49
50 int totalReleaseCount() const { return fTextureReleaseCounts[0] + fTextureReleaseCounts[1]; }
51
53 bool fHasTwoBackendTextures = false;
54 BackendTexture fBackendTextures[2];
55 int fFulfillCount = 0;
56 int fImageReleaseCount = 0;
57 int fTextureReleaseCounts[2] = { 0, 0 };
58
59 static std::tuple<BackendTexture, void*> Fulfill(void* self) {
60 auto checker = reinterpret_cast<PromiseTextureChecker*>(self);
61
62 checker->fFulfillCount++;
63
64 if (checker->fHasTwoBackendTextures) {
65 int whichToUse = checker->fFulfillCount % 2;
66 return { checker->fBackendTextures[whichToUse],
67 &checker->fTextureReleaseCounts[whichToUse] };
68 } else {
69 return { checker->fBackendTextures[0], &checker->fTextureReleaseCounts[0] };
70 }
71 }
72
73 static void ImageRelease(void* self) {
74 auto checker = reinterpret_cast<PromiseTextureChecker*>(self);
75
76 checker->fImageReleaseCount++;
77 }
78
79 static void TextureRelease(void* context) {
80 int* releaseCount = reinterpret_cast<int*>(context);
81
82 (*releaseCount)++;
83 }
84};
85
87 kBalanced,
88 kOffByOne, // fulfill calls ahead of release calls by 1
89 kOffByTwo, // fulfill calls ahead of release calls by 2
90 kFulfillsOnly, // 'n' fulfill calls, 0 release calls
91};
92
94 const PromiseTextureChecker& promiseChecker,
95 int expectedFulfillCnt,
96 ReleaseBalanceExpectation releaseBalanceExpectation) {
97 SkASSERT(promiseChecker.fFulfillCount == expectedFulfillCnt);
98 REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt);
99 if (!expectedFulfillCnt) {
100 // Release should only ever be called after Fulfill.
101 REPORTER_ASSERT(reporter, !promiseChecker.fImageReleaseCount);
102 REPORTER_ASSERT(reporter, !promiseChecker.totalReleaseCount());
103 return;
104 }
105
106 int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.totalReleaseCount();
107 switch (releaseBalanceExpectation) {
109 SkASSERT(!releaseDiff);
110 REPORTER_ASSERT(reporter, !releaseDiff);
111 break;
112 case ReleaseBalanceExpectation::kOffByOne:
113 SkASSERT(releaseDiff == 1);
114 REPORTER_ASSERT(reporter, releaseDiff == 1);
115 break;
116 case ReleaseBalanceExpectation::kOffByTwo:
117 SkASSERT(releaseDiff == 2);
118 REPORTER_ASSERT(reporter, releaseDiff == 2);
119 break;
120 case ReleaseBalanceExpectation::kFulfillsOnly:
121 REPORTER_ASSERT(reporter, promiseChecker.totalReleaseCount() == 0);
122 break;
123 }
124}
125
126void check_unfulfilled(const PromiseTextureChecker& promiseChecker,
128 check_fulfill_and_release_cnts(reporter, promiseChecker, /* expectedFulfillCnt= */ 0,
130}
131
132void check_fulfilled_ahead_by_one(skiatest::Reporter* reporter,
133 const PromiseTextureChecker& promiseChecker,
134 int expectedFulfillCnt) {
135 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
136 ReleaseBalanceExpectation::kOffByOne);
137}
138
139void check_fulfilled_ahead_by_two(skiatest::Reporter* reporter,
140 const PromiseTextureChecker& promiseChecker,
141 int expectedFulfillCnt) {
142 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
143 ReleaseBalanceExpectation::kOffByTwo);
144}
145
147 const PromiseTextureChecker& promiseChecker,
148 int expectedFulfillCnt) {
149 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
151}
152
153void check_fulfills_only(skiatest::Reporter* reporter,
154 const PromiseTextureChecker& promiseChecker,
155 int expectedFulfillCnt) {
156 check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
157 ReleaseBalanceExpectation::kFulfillsOnly);
158}
159
160struct TestCtx {
161 TestCtx() {}
162
163 ~TestCtx() {
164 for (int i = 0; i < 2; ++i) {
165 if (fBackendTextures[i].isValid()) {
166 fContext->deleteBackendTexture(fBackendTextures[i]);
167 }
168 }
169 }
170
172 std::unique_ptr<Recorder> fRecorder;
173 BackendTexture fBackendTextures[2];
174 PromiseTextureChecker fPromiseChecker;
175 sk_sp<SkImage> fImg;
176 sk_sp<SkSurface> fSurface;
177};
178
179void setup_test_context(Context* context,
181 TestCtx* testCtx,
182 SkISize dimensions,
183 Volatile isVolatile,
184 bool invalidBackendTex) {
185 testCtx->fContext = context;
186
187 const Caps* caps = context->priv().caps();
188 testCtx->fRecorder = context->makeRecorder();
189
191
194 isProtected,
196
197 if (invalidBackendTex) {
198 // Having invalid backend textures will invalidate all the fulfill calls
199 REPORTER_ASSERT(reporter, !testCtx->fBackendTextures[0].isValid());
200 REPORTER_ASSERT(reporter, !testCtx->fBackendTextures[1].isValid());
201 } else {
202 testCtx->fBackendTextures[0] = testCtx->fRecorder->createBackendTexture(dimensions,
203 textureInfo);
204 REPORTER_ASSERT(reporter, testCtx->fBackendTextures[0].isValid());
205
206 if (isVolatile == Volatile::kYes) {
207 testCtx->fBackendTextures[1] = testCtx->fRecorder->createBackendTexture(dimensions,
208 textureInfo);
209 REPORTER_ASSERT(reporter, testCtx->fBackendTextures[1].isValid());
210 }
211 }
212
213 if (isVolatile == Volatile::kYes) {
214 testCtx->fPromiseChecker = PromiseTextureChecker(testCtx->fBackendTextures[0],
215 testCtx->fBackendTextures[1],
216 reporter);
217 } else {
218 testCtx->fPromiseChecker = PromiseTextureChecker(testCtx->fBackendTextures[0],
219 reporter);
220 }
221
222 SkImageInfo ii = SkImageInfo::Make(dimensions.fWidth,
223 dimensions.fHeight,
226
227 testCtx->fImg = SkImages::PromiseTextureFrom(testCtx->fRecorder.get(),
228 dimensions,
229 textureInfo,
230 ii.colorInfo(),
231 isVolatile,
232 PromiseTextureChecker::Fulfill,
233 PromiseTextureChecker::ImageRelease,
234 PromiseTextureChecker::TextureRelease,
235 &testCtx->fPromiseChecker);
236
237 testCtx->fSurface = SkSurfaces::RenderTarget(testCtx->fRecorder.get(), ii);
238}
239
240} // anonymous namespace
241
243 reporter,
244 context,
245 testGpuContext,
246 true,
248 constexpr SkISize kDimensions { 16, 16 };
249
250 TestCtx testContext;
251 setup_test_context(context, reporter, &testContext,
252 kDimensions, Volatile::kNo, /* invalidBackendTex= */ false);
253
254 {
255 SkCanvas* canvas = testContext.fSurface->getCanvas();
256
257 canvas->drawImage(testContext.fImg, 0, 0);
258 check_unfulfilled(testContext.fPromiseChecker, reporter);
259
260 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
261 check_unfulfilled(testContext.fPromiseChecker, reporter); // NVPIs not fulfilled at snap
262
263 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
264 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
265 /* expectedFulfillCnt= */ 1); // NVPIs fulfilled at insert
266 }
267
268 context->submit(SyncToCpu::kNo);
269 // testContext.fImg still has a ref so we should not have called TextureRelease.
270 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
271 /* expectedFulfillCnt= */ 1);
272
273 testGpuContext->syncedSubmit(context);
274 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
275 /* expectedFulfillCnt= */ 1);
276
277 // Test that more draws and insertions don't refulfill the NVPI
278 {
279 SkCanvas* canvas = testContext.fSurface->getCanvas();
280
281 canvas->drawImage(testContext.fImg, 0, 0);
282 canvas->drawImage(testContext.fImg, 0, 0);
283
284 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
285 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
286 /* expectedFulfillCnt= */ 1); // No new fulfill
287
288 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
289 // testContext.fImg should still be fulfilled from the first time we inserted a Recording.
290 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
291 /* expectedFulfillCnt= */ 1);
292 }
293
294 testGpuContext->syncedSubmit(context);
295 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
296 /* expectedFulfillCnt= */ 1);
297
298 // Test that dropping the SkImage's ref doesn't change anything
299 {
300 SkCanvas* canvas = testContext.fSurface->getCanvas();
301
302 canvas->drawImage(testContext.fImg, 0, 0);
303 testContext.fImg.reset();
304
305 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
306 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
307 /* expectedFulfillCnt= */ 1);
308
309 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
310 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
311 /* expectedFulfillCnt= */ 1);
312 }
313
314 // fImg's proxy is reffed by the recording so, despite fImg being reset earlier,
315 // the imageRelease callback doesn't occur until the recording is deleted.
316 testContext.fPromiseChecker.checkImageReleased(reporter, /* expectedReleaseCnt= */ 1);
317
318 // testContext.fImg no longer holds a ref but the last recording is still not submitted.
319 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
320 /* expectedFulfillCnt= */ 1);
321
322 testGpuContext->syncedSubmit(context);
323
324 // Now TextureRelease should definitely have been called.
325 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 1);
326}
327
329 NonVolatileGraphitePromiseImageFulfillFailureTest,
330 reporter,
331 context,
332 testGpuContext,
333 true,
335 constexpr SkISize kDimensions { 16, 16 };
336
337 TestCtx testContext;
338 setup_test_context(context, reporter, &testContext,
339 kDimensions, Volatile::kNo, /* invalidBackendTex= */ true);
340
341 // Draw the image a few different ways.
342 {
343 SkCanvas* canvas = testContext.fSurface->getCanvas();
344
345 canvas->drawImage(testContext.fImg, 0, 0);
346 check_unfulfilled(testContext.fPromiseChecker, reporter);
347
348 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
349 check_unfulfilled(testContext.fPromiseChecker, reporter);
350
351 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
352 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
353 /* expectedFulfillCnt= */ 1);
354
355 // Test that reinserting gives uninstantiated PromiseImages a second chance
356 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
357 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 2);
358 }
359
360 {
361 SkCanvas* canvas = testContext.fSurface->getCanvas();
362
365 canvas->drawImage(testContext.fImg, 0, 0, SkSamplingOptions(), &paint);
366
367 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
368 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 2);
369
370 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
371 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 3);
372 }
373
374 {
375 SkCanvas* canvas = testContext.fSurface->getCanvas();
376
377 sk_sp<SkShader> shader = testContext.fImg->makeShader(SkSamplingOptions());
378 REPORTER_ASSERT(reporter, shader);
379
381 paint.setShader(std::move(shader));
382 canvas->drawRect(SkRect::MakeWH(1, 1), paint);
383
384 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
385 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 3);
386
387 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
388 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 4);
389 }
390
391 testContext.fSurface.reset();
392 testContext.fImg.reset();
393
394 // Despite fulfill failing 4x, the imageRelease callback still fires
395 testContext.fPromiseChecker.checkImageReleased(reporter, /* expectedReleaseCnt= */ 1);
396
397 testGpuContext->syncedSubmit(context);
398 // fulfill should've been called 4x while release should never have been called
399 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 4);
400}
401
403 NonVolatileGraphitePromiseImageCreationFailureTest,
404 reporter,
405 context,
406 testGpuContext,
407 true,
409 // Note: these dimensions are invalid and will cause MakeGraphitePromiseTexture to fail
410 constexpr SkISize kDimensions { 0, 0 };
411
412 TestCtx testContext;
413 setup_test_context(context, reporter, &testContext,
414 kDimensions, Volatile::kNo, /* invalidBackendTex= */ true);
415
416 SkASSERT(!testContext.fImg);
417
418 // Despite MakeGraphitePromiseTexture failing, ImageRelease is called
419 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fFulfillCount == 0);
420 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fImageReleaseCount == 1);
421 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.totalReleaseCount() == 0);
422}
423
425 reporter,
426 context,
427 testGpuContext,
428 true,
430 constexpr SkISize kDimensions { 16, 16 };
431
432 TestCtx testContext;
433 setup_test_context(context, reporter, &testContext,
434 kDimensions, Volatile::kYes, /* invalidBackendTex= */ false);
435
436 {
437 SkCanvas* canvas = testContext.fSurface->getCanvas();
438
439 canvas->drawImage(testContext.fImg, 0, 0);
440 check_unfulfilled(testContext.fPromiseChecker, reporter);
441
442 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
443 // Nothing happens at snap time for VPIs
444 check_unfulfilled(testContext.fPromiseChecker, reporter);
445
446 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
447 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
448 /* expectedFulfillCnt= */ 1); // VPIs fulfilled on insert
449
450 // Test that multiple insertions will clobber prior fulfills
451 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
452 check_fulfilled_ahead_by_two(reporter, testContext.fPromiseChecker,
453 /* expectedFulfillCnt= */ 2);
454 }
455
456 testGpuContext->syncedSubmit(context);
457 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 2);
458
459 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fTextureReleaseCounts[0] == 1);
460 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fTextureReleaseCounts[1] == 1);
461
462 {
463 SkCanvas* canvas = testContext.fSurface->getCanvas();
464
465 canvas->drawImage(testContext.fImg, 0, 0);
466 canvas->drawImage(testContext.fImg, 0, 0);
467
468 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
469 // Nothing happens at snap time for volatile images
470 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 2);
471
472 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
473 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
474 /* expectedFulfillCnt= */ 3);
475
476 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
477 check_fulfilled_ahead_by_two(reporter, testContext.fPromiseChecker,
478 /* expectedFulfillCnt= */ 4);
479 }
480
481 testGpuContext->syncedSubmit(context);
482 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 4);
483
484 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fTextureReleaseCounts[0] == 2);
485 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fTextureReleaseCounts[1] == 2);
486
487 {
488 SkCanvas* canvas = testContext.fSurface->getCanvas();
489
490 canvas->drawImage(testContext.fImg, 0, 0);
491 testContext.fImg.reset();
492
493 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
494 // Nothing happens at snap time for volatile images
495 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 4);
496
497 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
498 check_fulfilled_ahead_by_one(reporter, testContext.fPromiseChecker,
499 /* expectedFulfillCnt= */ 5);
500
501 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
502 check_fulfilled_ahead_by_two(reporter, testContext.fPromiseChecker,
503 /* expectedFulfillCnt= */ 6);
504 }
505
506 // testContext.fImg no longer holds a ref but the last recordings are still not submitted.
507 check_fulfilled_ahead_by_two(reporter, testContext.fPromiseChecker,
508 /* expectedFulfillCnt= */ 6);
509
510 testGpuContext->syncedSubmit(context);
511
512 // Now all Releases should definitely have been called.
513 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 6);
514
515 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fTextureReleaseCounts[0] == 3);
516 REPORTER_ASSERT(reporter, testContext.fPromiseChecker.fTextureReleaseCounts[1] == 3);
517}
518
519DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(VolatileGraphitePromiseImageFulfillFailureTest,
520 reporter,
521 context,
522 testGpuContext,
523 true,
525 constexpr SkISize kDimensions { 16, 16 };
526
527 TestCtx testContext;
528 setup_test_context(context, reporter, &testContext,
529 kDimensions, Volatile::kYes, /* invalidBackendTex= */ true);
530
531 // Draw the image a few different ways.
532 {
533 SkCanvas* canvas = testContext.fSurface->getCanvas();
534
535 canvas->drawImage(testContext.fImg, 0, 0);
536 check_unfulfilled(testContext.fPromiseChecker, reporter);
537
538 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
539 check_unfulfilled(testContext.fPromiseChecker, reporter);
540
541 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
542 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 1);
543
544 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
545 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 2);
546 }
547
548 {
549 SkCanvas* canvas = testContext.fSurface->getCanvas();
550
553 canvas->drawImage(testContext.fImg, 0, 0, SkSamplingOptions(), &paint);
554
555 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
556 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 2);
557
558 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
559 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 3);
560
561 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
562 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 4);
563 }
564
565 {
566 SkCanvas* canvas = testContext.fSurface->getCanvas();
567
568 sk_sp<SkShader> shader = testContext.fImg->makeShader(SkSamplingOptions());
569 REPORTER_ASSERT(reporter, shader);
570
572 paint.setShader(std::move(shader));
573 canvas->drawRect(SkRect::MakeWH(1, 1), paint);
574
575 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
576 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 4);
577
578 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
579 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 5);
580
581 REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
582 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 6);
583 }
584
585 testContext.fSurface.reset();
586 testContext.fImg.reset();
587
588 testGpuContext->syncedSubmit(context);
589 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 6);
590}
591
592// Test out dropping the Recorder prior to inserting the Recording
594 reporter,
595 context,
596 testGpuContext,
597 true,
599 constexpr SkISize kDimensions{ 16, 16 };
600
601 for (Volatile isVolatile : { Volatile::kNo, Volatile::kYes }) {
602 TestCtx testContext;
603 setup_test_context(context, reporter, &testContext,
604 kDimensions, isVolatile, /* invalidBackendTex= */ false);
605
606 SkCanvas* canvas = testContext.fSurface->getCanvas();
607
608 canvas->drawImage(testContext.fImg, 0, 0);
609 check_unfulfilled(testContext.fPromiseChecker, reporter);
610
611 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
612 check_unfulfilled(testContext.fPromiseChecker, reporter);
613
614 testContext.fRecorder.reset(); // Recorder drop
615
616 REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
617 check_fulfills_only(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 1);
618
619 testGpuContext->syncedSubmit(context);
620
621 testContext.fSurface.reset();
622 testContext.fImg.reset();
623 recording.reset();
624
625 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 1);
626 }
627}
628
629// Test out PromiseImages appearing in multiple Recordings. In particular, test that
630// previous instantiations don't impact the Recording's collection of PromiseImages.
632 reporter,
633 context,
634 testGpuContext,
635 true,
637 constexpr SkISize kDimensions{ 16, 16 };
638
639 static constexpr int kNumRecordings = 3;
640
641 for (Volatile isVolatile : { Volatile::kNo, Volatile::kYes }) {
642 int expectedVolatile = (isVolatile == Volatile::kYes) ? 1 : 0;
643 int expectedNonVolatile = 1 - expectedVolatile;
644
645 TestCtx testContext;
646 setup_test_context(context, reporter, &testContext,
647 kDimensions, isVolatile, /* invalidBackendTex= */ false);
648
649 std::unique_ptr<Recording> recordings[kNumRecordings];
650
651 SkCanvas* canvas = testContext.fSurface->getCanvas();
652
653 for (int i = 0; i < kNumRecordings; ++i) {
654 canvas->drawImage(testContext.fImg, 0, 0);
655
656 recordings[i] = testContext.fRecorder->snap();
657
658 if (isVolatile == Volatile::kYes) {
659 check_fulfills_only(reporter, testContext.fPromiseChecker,
660 /* expectedFulfillCnt= */ i);
661 } else {
662 check_fulfills_only(reporter, testContext.fPromiseChecker,
663 /* expectedFulfillCnt= */ i > 0 ? 1 : 0);
664 }
665
667 recordings[i]->priv().numVolatilePromiseImages() == expectedVolatile);
669 recordings[i]->priv().numNonVolatilePromiseImages() ==
670 expectedNonVolatile);
671
672 REPORTER_ASSERT(reporter, context->insertRecording({ recordings[i].get() }));
673
674 if (isVolatile == Volatile::kYes) {
675 check_fulfills_only(reporter, testContext.fPromiseChecker,
676 /* expectedFulfillCnt= */ i+1);
677 } else {
678 check_fulfills_only(reporter, testContext.fPromiseChecker,
679 /* expectedFulfillCnt= */ 1);
680 }
681
682 // Non-volatiles are cleared out after a successful insertion
683 REPORTER_ASSERT(reporter, recordings[i]->priv().numNonVolatilePromiseImages() == 0);
684 }
685
686 testGpuContext->syncedSubmit(context);
687
688 testContext.fSurface.reset();
689 testContext.fImg.reset();
690 for (int i = 0; i < kNumRecordings; ++i) {
691 recordings[i].reset();
692 }
693
694 if (isVolatile == Volatile::kYes) {
695 check_all_done(reporter, testContext.fPromiseChecker,
696 /* expectedFulfillCnt= */ kNumRecordings);
697 } else {
698 check_all_done(reporter, testContext.fPromiseChecker, /* expectedFulfillCnt= */ 1);
699 }
700 }
701}
reporter
Definition: FontMgrTest.cpp:39
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(NonVolatileGraphitePromiseImageTest, reporter, context, testGpuContext, true, CtsEnforcement::kNextRelease)
ReleaseBalanceExpectation
static void check_fulfill_and_release_cnts(skiatest::Reporter *reporter, const PromiseTextureChecker &promiseChecker, int expectedFulfillCnt, ReleaseBalanceExpectation releaseBalanceExpecation)
static void check_unfulfilled(const PromiseTextureChecker &promiseChecker, skiatest::Reporter *reporter)
static void check_all_done(skiatest::Reporter *reporter, const PromiseTextureChecker &promiseChecker, int expectedFulfillCnt=1)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
const Context & fContext
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
static sk_sp< SkColorFilter > LinearToSRGBGamma()
bool protectedSupport() const
Definition: Caps.h:226
virtual TextureInfo getDefaultSampledTextureInfo(SkColorType, Mipmapped mipmapped, Protected, Renderable) const =0
const Caps * caps() const
Definition: ContextPriv.h:32
std::unique_ptr< Recorder > makeRecorder(const RecorderOptions &={})
Definition: Context.cpp:132
bool submit(SyncToCpu=SyncToCpu::kNo)
Definition: Context.cpp:162
void deleteBackendTexture(const BackendTexture &)
Definition: Context.cpp:750
bool insertRecording(const InsertRecordingInfo &)
Definition: Context.cpp:156
const Paint & paint
Definition: color_source.cc:38
FlPixelBufferTexturePrivate * priv
SK_API sk_sp< SkImage > PromiseTextureFrom(skgpu::graphite::Recorder *, SkISize dimensions, const skgpu::graphite::TextureInfo &, const SkColorInfo &, skgpu::Origin origin, skgpu::graphite::Volatile, GraphitePromiseTextureFulfillProc, GraphitePromiseImageReleaseProc, GraphitePromiseTextureReleaseProc, GraphitePromiseImageContext, std::string_view label={})
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
Protected
Definition: GpuTypes.h:61
SkSamplingOptions(SkFilterMode::kLinear))
static sk_sp< GrPromiseImageTexture > Fulfill(void *self)
skiatest::Reporter * fReporter
Definition: SkSize.h:16
int32_t fHeight
Definition: SkSize.h:18
int32_t fWidth
Definition: SkSize.h:17
const SkColorInfo & colorInfo() const
Definition: SkImageInfo.h:404
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609