29struct PromiseImageChecker {
30 PromiseImageChecker() =
default;
36 int fImageReleaseCount = 0;
38 static void ImageRelease(
void*
self) {
39 auto checker =
reinterpret_cast<PromiseImageChecker*
>(
self);
41 checker->fImageReleaseCount++;
49 fBackendTextures[0] = backendTex;
54 : fHasTwoBackendTextures(
true) {
55 fBackendTextures[0] = backendTex0;
56 fBackendTextures[1] = backendTex1;
59 int totalReleaseCount()
const {
return fTextureReleaseCounts[0] + fTextureReleaseCounts[1]; }
61 bool fHasTwoBackendTextures =
false;
64 int fTextureReleaseCounts[2] = { 0, 0 };
66 static std::tuple<BackendTexture, void*>
Fulfill(
void*
self) {
71 if (checker->fHasTwoBackendTextures) {
72 int whichToUse = checker->fFulfillCount % 2;
73 return { checker->fBackendTextures[whichToUse],
74 &checker->fTextureReleaseCounts[whichToUse] };
76 return { checker->fBackendTextures[0], &checker->fTextureReleaseCounts[0] };
80 static void TextureRelease(
void* context) {
81 int* releaseCount =
reinterpret_cast<int*
>(context);
95 const PromiseImageChecker& promiseImageChecker,
97 int expectedFulfillCnt,
100 int maxFulfillCnt = 0;
101 for (
int i = 0;
i < 4; ++
i) {
102 maxFulfillCnt =
std::max(promiseTextureCheckers[
i].fFulfillCount, maxFulfillCnt);
103 if (!expectedFulfillCnt) {
110 if (promiseTextureCheckers[
i].fFulfillCount) {
112 promiseTextureCheckers[
i].totalReleaseCount();
113 switch (releaseBalanceExpectation) {
118 case ReleaseBalanceExpectation::kOffByOne:
122 case ReleaseBalanceExpectation::kOffByTwo:
126 case ReleaseBalanceExpectation::kFulfillsOnly:
132 SkASSERT(maxFulfillCnt == expectedFulfillCnt);
145 const PromiseImageChecker& promiseImageChecker,
147 int expectedFulfillCnt) {
149 expectedFulfillCnt, ReleaseBalanceExpectation::kOffByOne);
153 const PromiseImageChecker& promiseImageChecker,
155 int expectedFulfillCnt) {
157 expectedFulfillCnt, ReleaseBalanceExpectation::kOffByTwo);
161 const PromiseImageChecker& promiseImageChecker,
163 int expectedFulfillCnt) {
169 const PromiseImageChecker& promiseImageChecker,
171 int expectedFulfillCnt) {
173 expectedFulfillCnt, ReleaseBalanceExpectation::kFulfillsOnly);
180 for (
int i = 0;
i < 8; ++
i) {
181 if (fBackendTextures[
i].isValid()) {
188 std::unique_ptr<Recorder> fRecorder;
190 PromiseImageChecker fPromiseImageChecker;
194 &fPromiseTextureCheckers[0],
195 &fPromiseTextureCheckers[1],
196 &fPromiseTextureCheckers[2],
197 &fPromiseTextureCheckers[3],
203void setup_test_context(
Context* context,
208 bool invalidBackendTex) {
209 testCtx->fContext = context;
217 testCtx->fPromiseImageChecker = PromiseImageChecker();
220 for (
int i = 0;
i < 4; ++
i) {
226 if (invalidBackendTex) {
231 testCtx->fBackendTextures[
i] =
232 testCtx->fRecorder->createBackendTexture(dimensions, textureInfo[
i]);
235 if (isVolatile == Volatile::kYes) {
236 testCtx->fBackendTextures[
i+4] =
237 testCtx->fRecorder->createBackendTexture(dimensions, textureInfo[
i]);
242 if (isVolatile == Volatile::kYes) {
243 testCtx->fPromiseTextureCheckers[
i] =
245 testCtx->fBackendTextures[
i+4]);
247 testCtx->fPromiseTextureCheckers[
i] =
265 PromiseTextureChecker::Fulfill,
266 PromiseImageChecker::ImageRelease,
267 PromiseTextureChecker::TextureRelease,
268 testCtx->fImageContext,
269 testCtx->fTextureContexts);
286 constexpr SkISize kDimensions { 16, 16 };
289 setup_test_context(context,
reporter, &testContext,
290 kDimensions, Volatile::kNo,
false);
293 SkCanvas* canvas = testContext.fSurface->getCanvas();
295 canvas->
drawImage(testContext.fImg, 0, 0);
296 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
299 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
300 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
304 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
305 testContext.fPromiseTextureCheckers,
309 context->
submit(SyncToCpu::kNo);
311 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
312 testContext.fPromiseTextureCheckers,
315 testGpuContext->syncedSubmit(context);
317 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
318 testContext.fPromiseTextureCheckers,
323 SkCanvas* canvas = testContext.fSurface->getCanvas();
325 canvas->
drawImage(testContext.fImg, 0, 0);
326 canvas->
drawImage(testContext.fImg, 0, 0);
328 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
329 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
330 testContext.fPromiseTextureCheckers,
335 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
336 testContext.fPromiseTextureCheckers,
340 testGpuContext->syncedSubmit(context);
342 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
343 testContext.fPromiseTextureCheckers, 1);
347 SkCanvas* canvas = testContext.fSurface->getCanvas();
349 canvas->
drawImage(testContext.fImg, 0, 0);
350 testContext.fImg.reset();
352 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
353 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
354 testContext.fPromiseTextureCheckers,
358 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
359 testContext.fPromiseTextureCheckers,
365 testContext.fPromiseImageChecker.checkImageReleased(
reporter, 1);
368 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
369 testContext.fPromiseTextureCheckers, 1);
371 testGpuContext->syncedSubmit(context);
379 NonVolatileGraphiteYUVAPromiseImageFulfillFailureTest,
385 constexpr SkISize kDimensions { 16, 16 };
388 setup_test_context(context,
reporter, &testContext,
389 kDimensions, Volatile::kNo,
true);
393 SkCanvas* canvas = testContext.fSurface->getCanvas();
395 canvas->
drawImage(testContext.fImg, 0, 0);
396 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
399 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
400 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
404 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
405 testContext.fPromiseTextureCheckers,
410 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
411 testContext.fPromiseTextureCheckers, 2);
415 SkCanvas* canvas = testContext.fSurface->getCanvas();
421 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
422 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
423 testContext.fPromiseTextureCheckers, 2);
426 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
427 testContext.fPromiseTextureCheckers, 3);
431 SkCanvas* canvas = testContext.fSurface->getCanvas();
437 paint.setShader(std::move(shader));
440 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
441 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
442 testContext.fPromiseTextureCheckers, 3);
445 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
446 testContext.fPromiseTextureCheckers, 4);
449 testContext.fSurface.reset();
450 testContext.fImg.reset();
453 testContext.fPromiseImageChecker.checkImageReleased(
reporter, 1);
455 testGpuContext->syncedSubmit(context);
457 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
458 testContext.fPromiseTextureCheckers, 4);
466 constexpr SkISize kDimensions { 0, 0 };
469 setup_test_context(context,
reporter, &testContext,
470 kDimensions, Volatile::kNo,
true);
476 for (
int i = 0;
i < 4; ++
i) {
488 constexpr SkISize kDimensions { 16, 16 };
491 setup_test_context(context,
reporter, &testContext,
492 kDimensions, Volatile::kYes,
false);
495 SkCanvas* canvas = testContext.fSurface->getCanvas();
497 canvas->
drawImage(testContext.fImg, 0, 0);
498 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
501 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
503 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
507 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
508 testContext.fPromiseTextureCheckers,
513 check_fulfilled_ahead_by_two(
reporter, testContext.fPromiseImageChecker,
514 testContext.fPromiseTextureCheckers,
518 testGpuContext->syncedSubmit(context);
522 for (
int i = 0;
i < 4; ++
i) {
524 testContext.fPromiseTextureCheckers[
i].fTextureReleaseCounts[0] == 1);
526 testContext.fPromiseTextureCheckers[
i].fTextureReleaseCounts[1] == 1);
530 SkCanvas* canvas = testContext.fSurface->getCanvas();
532 canvas->
drawImage(testContext.fImg, 0, 0);
533 canvas->
drawImage(testContext.fImg, 0, 0);
535 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
538 testContext.fPromiseTextureCheckers, 2);
541 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
542 testContext.fPromiseTextureCheckers,
546 check_fulfilled_ahead_by_two(
reporter, testContext.fPromiseImageChecker,
547 testContext.fPromiseTextureCheckers,
551 testGpuContext->syncedSubmit(context);
555 for (
int i = 0;
i < 4; ++
i) {
557 testContext.fPromiseTextureCheckers[
i].fTextureReleaseCounts[0] == 2);
559 testContext.fPromiseTextureCheckers[
i].fTextureReleaseCounts[1] == 2);
563 SkCanvas* canvas = testContext.fSurface->getCanvas();
565 canvas->
drawImage(testContext.fImg, 0, 0);
566 testContext.fImg.reset();
568 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
571 testContext.fPromiseTextureCheckers, 4);
574 check_fulfilled_ahead_by_one(
reporter, testContext.fPromiseImageChecker,
575 testContext.fPromiseTextureCheckers,
579 check_fulfilled_ahead_by_two(
reporter, testContext.fPromiseImageChecker,
580 testContext.fPromiseTextureCheckers,
585 check_fulfilled_ahead_by_two(
reporter, testContext.fPromiseImageChecker,
586 testContext.fPromiseTextureCheckers,
589 testGpuContext->syncedSubmit(context);
595 for (
int i = 0;
i < 4; ++
i) {
597 testContext.fPromiseTextureCheckers[
i].fTextureReleaseCounts[0] == 3);
599 testContext.fPromiseTextureCheckers[
i].fTextureReleaseCounts[1] == 3);
604 VolatileGraphiteYUVAPromiseImageFulfillFailureTest,
610 constexpr SkISize kDimensions { 16, 16 };
613 setup_test_context(context,
reporter, &testContext,
614 kDimensions, Volatile::kYes,
true);
618 SkCanvas* canvas = testContext.fSurface->getCanvas();
620 canvas->
drawImage(testContext.fImg, 0, 0);
621 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
624 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
625 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
629 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
630 testContext.fPromiseTextureCheckers, 1);
633 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
634 testContext.fPromiseTextureCheckers, 2);
638 SkCanvas* canvas = testContext.fSurface->getCanvas();
644 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
645 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
646 testContext.fPromiseTextureCheckers, 2);
649 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
650 testContext.fPromiseTextureCheckers, 3);
653 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
654 testContext.fPromiseTextureCheckers, 4);
658 SkCanvas* canvas = testContext.fSurface->getCanvas();
664 paint.setShader(std::move(shader));
667 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
668 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
669 testContext.fPromiseTextureCheckers, 4);
672 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
673 testContext.fPromiseTextureCheckers, 5);
676 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
677 testContext.fPromiseTextureCheckers, 6);
680 testContext.fSurface.reset();
681 testContext.fImg.reset();
683 testGpuContext->syncedSubmit(context);
684 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
685 testContext.fPromiseTextureCheckers, 6);
695 constexpr SkISize kDimensions{ 16, 16 };
697 for (
Volatile isVolatile : { Volatile::kNo, Volatile::kYes }) {
699 setup_test_context(context,
reporter, &testContext,
700 kDimensions, isVolatile,
false);
702 SkCanvas* canvas = testContext.fSurface->getCanvas();
704 canvas->
drawImage(testContext.fImg, 0, 0);
705 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
708 std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
709 check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
712 testContext.fRecorder.reset();
715 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
716 testContext.fPromiseTextureCheckers, 1);
718 testGpuContext->syncedSubmit(context);
720 testContext.fSurface.reset();
721 testContext.fImg.reset();
725 testContext.fPromiseTextureCheckers, 1);
737 constexpr SkISize kDimensions{ 16, 16 };
739 static constexpr int kNumRecordings = 3;
741 for (
Volatile isVolatile : { Volatile::kNo, Volatile::kYes }) {
742 int expectedVolatile = (isVolatile == Volatile::kYes) ? 4 : 0;
743 int expectedNonVolatile = 4 - expectedVolatile;
746 setup_test_context(context,
reporter, &testContext,
747 kDimensions, isVolatile,
false);
749 std::unique_ptr<Recording> recordings[kNumRecordings];
751 SkCanvas* canvas = testContext.fSurface->getCanvas();
753 for (
int i = 0;
i < kNumRecordings; ++
i) {
754 canvas->
drawImage(testContext.fImg, 0, 0);
756 recordings[
i] = testContext.fRecorder->snap();
758 if (isVolatile == Volatile::kYes) {
759 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
760 testContext.fPromiseTextureCheckers,
763 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
764 testContext.fPromiseTextureCheckers,
769 recordings[
i]->
priv().numVolatilePromiseImages() == expectedVolatile);
771 recordings[
i]->
priv().numNonVolatilePromiseImages() ==
772 expectedNonVolatile);
776 if (isVolatile == Volatile::kYes) {
777 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
778 testContext.fPromiseTextureCheckers,
781 check_fulfills_only(
reporter, testContext.fPromiseImageChecker,
782 testContext.fPromiseTextureCheckers,
790 testGpuContext->syncedSubmit(context);
792 testContext.fSurface.reset();
793 testContext.fImg.reset();
794 for (
int i = 0;
i < kNumRecordings; ++
i) {
795 recordings[
i].reset();
798 if (isVolatile == Volatile::kYes) {
800 testContext.fPromiseTextureCheckers,
804 testContext.fPromiseTextureCheckers, 1);
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(NonVolatileGraphiteYUVAPromiseImageCreationFailureTest, reporter, context, CtsEnforcement::kNextRelease)
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(NonVolatileGraphiteYUVAPromiseImageTest, 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
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kJPEG_Full_SkYUVColorSpace
describes full range
#define REPORTER_ASSERT(r, cond,...)
void drawRect(const SkRect &rect, const SkPaint &paint)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
static sk_sp< SkColorFilter > LinearToSRGBGamma()
static sk_sp< SkColorSpace > MakeSRGBLinear()
@ kY_U_V_A
Plane 0: Y, Plane 1: U, Plane 2: V, Plane 3: A.
@ k444
No subsampling. UV values for each Y.
bool protectedSupport() const
virtual TextureInfo getDefaultSampledTextureInfo(SkColorType, Mipmapped mipmapped, Protected, Renderable) const =0
const Caps * caps() const
std::unique_ptr< Recorder > makeRecorder(const RecorderOptions &={})
bool submit(SyncToCpu=SyncToCpu::kNo)
void deleteBackendTexture(const BackendTexture &)
bool insertRecording(const InsertRecordingInfo &)
FlPixelBufferTexturePrivate * priv
static float max(float r, float g, float b)
void * GraphitePromiseTextureFulfillContext
void * GraphitePromiseImageContext
SK_API sk_sp< SkImage > PromiseTextureFromYUVA(skgpu::graphite::Recorder *, const skgpu::graphite::YUVABackendTextureInfo &, sk_sp< SkColorSpace > imageColorSpace, skgpu::graphite::Volatile, GraphitePromiseTextureFulfillProc, GraphitePromiseImageReleaseProc, GraphitePromiseTextureReleaseProc, GraphitePromiseImageContext imageContext, GraphitePromiseTextureFulfillContext planeContexts[], 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)
SkSamplingOptions(SkFilterMode::kLinear))
static sk_sp< GrPromiseImageTexture > Fulfill(void *self)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkRect MakeWH(float w, float h)