* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/graphite/BackendTexture.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkSurface.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Image.h"
#include "include/gpu/graphite/Recording.h"
#include "include/gpu/graphite/Surface.h"
#include "include/gpu/graphite/YUVABackendTextures.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/RecordingPriv.h"
#include "tests/Test.h"
#include "tools/graphite/GraphiteTestContext.h"
using namespace skgpu::graphite;
namespace {
struct PromiseImageChecker {
PromiseImageChecker() = default;
void checkImageReleased(skiatest::Reporter* reporter, int expectedReleaseCnt) {
REPORTER_ASSERT(reporter, expectedReleaseCnt == fImageReleaseCount);
}
int fImageReleaseCount = 0;
static void ImageRelease(void* self) {
auto checker = reinterpret_cast<PromiseImageChecker*>(self);
checker->fImageReleaseCount++;
}
};
struct PromiseTextureChecker {
PromiseTextureChecker() = default;
explicit PromiseTextureChecker(const BackendTexture& backendTex) {
fBackendTextures[0] = backendTex;
}
explicit PromiseTextureChecker(const BackendTexture& backendTex0,
const BackendTexture& backendTex1)
: fHasTwoBackendTextures(true) {
fBackendTextures[0] = backendTex0;
fBackendTextures[1] = backendTex1;
}
int totalReleaseCount() const { return fTextureReleaseCounts[0] + fTextureReleaseCounts[1]; }
bool fHasTwoBackendTextures = false;
BackendTexture fBackendTextures[2];
int fFulfillCount = 0;
int fTextureReleaseCounts[2] = { 0, 0 };
static std::tuple<BackendTexture, void*> Fulfill(void* self) {
auto checker = reinterpret_cast<PromiseTextureChecker*>(self);
checker->fFulfillCount++;
if (checker->fHasTwoBackendTextures) {
int whichToUse = checker->fFulfillCount % 2;
return { checker->fBackendTextures[whichToUse],
&checker->fTextureReleaseCounts[whichToUse] };
} else {
return { checker->fBackendTextures[0], &checker->fTextureReleaseCounts[0] };
}
}
static void TextureRelease(void* context) {
int* releaseCount = reinterpret_cast<int*>(context);
(*releaseCount)++;
}
};
enum class ReleaseBalanceExpectation {
kBalanced,
kOffByOne,
kOffByTwo,
kFulfillsOnly,
};
void check_fulfill_and_release_cnts(skiatest::Reporter* reporter,
const PromiseImageChecker& promiseImageChecker,
const PromiseTextureChecker* promiseTextureCheckers,
int expectedFulfillCnt,
ReleaseBalanceExpectation releaseBalanceExpectation) {
int maxFulfillCnt = 0;
for (int i = 0; i < 4; ++i) {
maxFulfillCnt = std::max(promiseTextureCheckers[i].fFulfillCount, maxFulfillCnt);
if (!expectedFulfillCnt) {
REPORTER_ASSERT(reporter, promiseImageChecker.fImageReleaseCount == 0);
REPORTER_ASSERT(reporter, promiseTextureCheckers[i].totalReleaseCount() == 0);
return;
}
if (promiseTextureCheckers[i].fFulfillCount) {
int releaseDiff = promiseTextureCheckers[i].fFulfillCount -
promiseTextureCheckers[i].totalReleaseCount();
switch (releaseBalanceExpectation) {
case ReleaseBalanceExpectation::kBalanced:
SkASSERT(!releaseDiff);
REPORTER_ASSERT(reporter, !releaseDiff);
break;
case ReleaseBalanceExpectation::kOffByOne:
SkASSERT(releaseDiff == 1);
REPORTER_ASSERT(reporter, releaseDiff == 1);
break;
case ReleaseBalanceExpectation::kOffByTwo:
SkASSERT(releaseDiff == 2);
REPORTER_ASSERT(reporter, releaseDiff == 2);
break;
case ReleaseBalanceExpectation::kFulfillsOnly:
REPORTER_ASSERT(reporter, promiseTextureCheckers[i].totalReleaseCount() == 0);
break;
}
}
}
SkASSERT(maxFulfillCnt == expectedFulfillCnt);
REPORTER_ASSERT(reporter, maxFulfillCnt == expectedFulfillCnt);
}
void check_unfulfilled(const PromiseImageChecker& promiseImageChecker,
const PromiseTextureChecker* promiseTextureCheckers,
skiatest::Reporter* reporter) {
check_fulfill_and_release_cnts(reporter, promiseImageChecker, promiseTextureCheckers,
0,
ReleaseBalanceExpectation::kBalanced);
}
void check_fulfilled_ahead_by_one(skiatest::Reporter* reporter,
const PromiseImageChecker& promiseImageChecker,
const PromiseTextureChecker* promiseTextureCheckers,
int expectedFulfillCnt) {
check_fulfill_and_release_cnts(reporter, promiseImageChecker, promiseTextureCheckers,
expectedFulfillCnt, ReleaseBalanceExpectation::kOffByOne);
}
void check_fulfilled_ahead_by_two(skiatest::Reporter* reporter,
const PromiseImageChecker& promiseImageChecker,
const PromiseTextureChecker* promiseTextureCheckers,
int expectedFulfillCnt) {
check_fulfill_and_release_cnts(reporter, promiseImageChecker, promiseTextureCheckers,
expectedFulfillCnt, ReleaseBalanceExpectation::kOffByTwo);
}
void check_all_done(skiatest::Reporter* reporter,
const PromiseImageChecker& promiseImageChecker,
const PromiseTextureChecker* promiseTextureCheckers,
int expectedFulfillCnt) {
check_fulfill_and_release_cnts(reporter, promiseImageChecker, promiseTextureCheckers,
expectedFulfillCnt, ReleaseBalanceExpectation::kBalanced);
}
void check_fulfills_only(skiatest::Reporter* reporter,
const PromiseImageChecker& promiseImageChecker,
const PromiseTextureChecker* promiseTextureCheckers,
int expectedFulfillCnt) {
check_fulfill_and_release_cnts(reporter, promiseImageChecker, promiseTextureCheckers,
expectedFulfillCnt, ReleaseBalanceExpectation::kFulfillsOnly);
}
struct TestCtx {
TestCtx() {}
~TestCtx() {
for (int i = 0; i < 8; ++i) {
if (fBackendTextures[i].isValid()) {
fContext->deleteBackendTexture(fBackendTextures[i]);
}
}
}
Context* fContext;
std::unique_ptr<Recorder> fRecorder;
BackendTexture fBackendTextures[8];
PromiseImageChecker fPromiseImageChecker;
SkImages::GraphitePromiseImageContext fImageContext = &fPromiseImageChecker;
PromiseTextureChecker fPromiseTextureCheckers[4];
SkImages::GraphitePromiseTextureFulfillContext fTextureContexts[4] = {
&fPromiseTextureCheckers[0],
&fPromiseTextureCheckers[1],
&fPromiseTextureCheckers[2],
&fPromiseTextureCheckers[3],
};
sk_sp<SkImage> fImg;
sk_sp<SkSurface> fSurface;
};
void setup_test_context(Context* context,
skiatest::Reporter* reporter,
TestCtx* testCtx,
SkISize dimensions,
Volatile isVolatile,
bool invalidBackendTex) {
testCtx->fContext = context;
const Caps* caps = context->priv().caps();
skgpu::Protected isProtected = skgpu::Protected(caps->protectedSupport());
testCtx->fRecorder = context->makeRecorder();
testCtx->fPromiseImageChecker = PromiseImageChecker();
TextureInfo textureInfo[4];
for (int i = 0; i < 4; ++i) {
textureInfo[i] = caps->getDefaultSampledTextureInfo(kAlpha_8_SkColorType,
skgpu::Mipmapped::kNo,
isProtected,
skgpu::Renderable::kYes);
if (invalidBackendTex) {
REPORTER_ASSERT(reporter, !testCtx->fBackendTextures[i].isValid());
REPORTER_ASSERT(reporter, !testCtx->fBackendTextures[i+4].isValid());
} else {
testCtx->fBackendTextures[i] =
testCtx->fRecorder->createBackendTexture(dimensions, textureInfo[i]);
REPORTER_ASSERT(reporter, testCtx->fBackendTextures[i].isValid());
if (isVolatile == Volatile::kYes) {
testCtx->fBackendTextures[i+4] =
testCtx->fRecorder->createBackendTexture(dimensions, textureInfo[i]);
REPORTER_ASSERT(reporter, testCtx->fBackendTextures[i+4].isValid());
}
}
if (isVolatile == Volatile::kYes) {
testCtx->fPromiseTextureCheckers[i] =
PromiseTextureChecker(testCtx->fBackendTextures[i],
testCtx->fBackendTextures[i+4]);
} else {
testCtx->fPromiseTextureCheckers[i] =
PromiseTextureChecker(testCtx->fBackendTextures[i]);
}
}
SkYUVAInfo yuvaInfo(dimensions,
SkYUVAInfo::PlaneConfig::kY_U_V_A,
SkYUVAInfo::Subsampling::k444,
kJPEG_Full_SkYUVColorSpace);
YUVABackendTextureInfo yuvaBackendInfo(testCtx->fRecorder.get(),
yuvaInfo,
textureInfo,
skgpu::Mipmapped::kNo);
testCtx->fImg = SkImages::PromiseTextureFromYUVA(testCtx->fRecorder.get(),
yuvaBackendInfo,
SkColorSpace::MakeSRGBLinear(),
isVolatile,
PromiseTextureChecker::Fulfill,
PromiseImageChecker::ImageRelease,
PromiseTextureChecker::TextureRelease,
testCtx->fImageContext,
testCtx->fTextureContexts);
SkImageInfo ii = SkImageInfo::Make(dimensions.fWidth,
dimensions.fHeight,
kRGBA_8888_SkColorType,
kPremul_SkAlphaType);
testCtx->fSurface = SkSurfaces::RenderTarget(testCtx->fRecorder.get(), ii);
}
}
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(NonVolatileGraphiteYUVAPromiseImageTest,
reporter,
context,
testGpuContext,
true,
CtsEnforcement::kApiLevel_V) {
constexpr SkISize kDimensions { 16, 16 };
TestCtx testContext;
setup_test_context(context, reporter, &testContext,
kDimensions, Volatile::kNo, false);
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
}
context->submit(SyncToCpu::kNo);
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
testGpuContext->syncedSubmit(context);
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
canvas->drawImage(testContext.fImg, 0, 0);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
}
testGpuContext->syncedSubmit(context);
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 1);
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
testContext.fImg.reset();
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
}
testContext.fPromiseImageChecker.checkImageReleased(reporter, 1);
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 1);
testGpuContext->syncedSubmit(context);
check_all_done(reporter, testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
1);
}
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(
NonVolatileGraphiteYUVAPromiseImageFulfillFailureTest,
reporter,
context,
testGpuContext,
true,
CtsEnforcement::kApiLevel_V) {
constexpr SkISize kDimensions { 16, 16 };
TestCtx testContext;
setup_test_context(context, reporter, &testContext,
kDimensions, Volatile::kNo, true);
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 2);
}
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
SkPaint paint;
paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
canvas->drawImage(testContext.fImg, 0, 0, SkSamplingOptions(), &paint);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 2);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 3);
}
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
sk_sp<SkShader> shader = testContext.fImg->makeShader(SkSamplingOptions());
REPORTER_ASSERT(reporter, shader);
SkPaint paint;
paint.setShader(std::move(shader));
canvas->drawRect(SkRect::MakeWH(1, 1), paint);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 3);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 4);
}
testContext.fSurface.reset();
testContext.fImg.reset();
testContext.fPromiseImageChecker.checkImageReleased(reporter, 1);
testGpuContext->syncedSubmit(context);
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 4);
}
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(NonVolatileGraphiteYUVAPromiseImageCreationFailureTest,
reporter,
context,
CtsEnforcement::kApiLevel_V) {
constexpr SkISize kDimensions { 0, 0 };
TestCtx testContext;
setup_test_context(context, reporter, &testContext,
kDimensions, Volatile::kNo, true);
SkASSERT(!testContext.fImg);
REPORTER_ASSERT(reporter, testContext.fPromiseImageChecker.fImageReleaseCount == 1);
for (int i = 0; i < 4; ++i) {
REPORTER_ASSERT(reporter, testContext.fPromiseTextureCheckers[i].fFulfillCount == 0);
REPORTER_ASSERT(reporter, testContext.fPromiseTextureCheckers[i].totalReleaseCount() == 0);
}
}
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(VolatileGraphiteYUVAPromiseImageTest,
reporter,
context,
testGpuContext,
true,
CtsEnforcement::kApiLevel_V) {
constexpr SkISize kDimensions { 16, 16 };
TestCtx testContext;
setup_test_context(context, reporter, &testContext,
kDimensions, Volatile::kYes, false);
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_two(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
2);
}
testGpuContext->syncedSubmit(context);
check_all_done(reporter, testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
2);
for (int i = 0; i < 4; ++i) {
REPORTER_ASSERT(reporter,
testContext.fPromiseTextureCheckers[i].fTextureReleaseCounts[0] == 1);
REPORTER_ASSERT(reporter,
testContext.fPromiseTextureCheckers[i].fTextureReleaseCounts[1] == 1);
}
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
canvas->drawImage(testContext.fImg, 0, 0);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_all_done(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 2);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
3);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_two(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
4);
}
testGpuContext->syncedSubmit(context);
check_all_done(reporter, testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
4);
for (int i = 0; i < 4; ++i) {
REPORTER_ASSERT(reporter,
testContext.fPromiseTextureCheckers[i].fTextureReleaseCounts[0] == 2);
REPORTER_ASSERT(reporter,
testContext.fPromiseTextureCheckers[i].fTextureReleaseCounts[1] == 2);
}
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
testContext.fImg.reset();
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_all_done(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 4);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_one(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
5);
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfilled_ahead_by_two(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
6);
}
check_fulfilled_ahead_by_two(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
6);
testGpuContext->syncedSubmit(context);
check_all_done(reporter, testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
6);
for (int i = 0; i < 4; ++i) {
REPORTER_ASSERT(reporter,
testContext.fPromiseTextureCheckers[i].fTextureReleaseCounts[0] == 3);
REPORTER_ASSERT(reporter,
testContext.fPromiseTextureCheckers[i].fTextureReleaseCounts[1] == 3);
}
}
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(
VolatileGraphiteYUVAPromiseImageFulfillFailureTest,
reporter,
context,
testGpuContext,
true,
CtsEnforcement::kApiLevel_V) {
constexpr SkISize kDimensions { 16, 16 };
TestCtx testContext;
setup_test_context(context, reporter, &testContext,
kDimensions, Volatile::kYes, true);
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 1);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 2);
}
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
SkPaint paint;
paint.setColorFilter(SkColorFilters::LinearToSRGBGamma());
canvas->drawImage(testContext.fImg, 0, 0, SkSamplingOptions(), &paint);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 2);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 3);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 4);
}
{
SkCanvas* canvas = testContext.fSurface->getCanvas();
sk_sp<SkShader> shader = testContext.fImg->makeShader(SkSamplingOptions());
REPORTER_ASSERT(reporter, shader);
SkPaint paint;
paint.setShader(std::move(shader));
canvas->drawRect(SkRect::MakeWH(1, 1), paint);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 4);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 5);
REPORTER_ASSERT(reporter, !context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 6);
}
testContext.fSurface.reset();
testContext.fImg.reset();
testGpuContext->syncedSubmit(context);
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 6);
}
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(GraphiteYUVAPromiseImageRecorderLoss,
reporter,
context,
testGpuContext,
true,
CtsEnforcement::kApiLevel_V) {
constexpr SkISize kDimensions{ 16, 16 };
for (Volatile isVolatile : { Volatile::kNo, Volatile::kYes }) {
TestCtx testContext;
setup_test_context(context, reporter, &testContext,
kDimensions, isVolatile, false);
SkCanvas* canvas = testContext.fSurface->getCanvas();
canvas->drawImage(testContext.fImg, 0, 0);
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
std::unique_ptr<Recording> recording = testContext.fRecorder->snap();
check_unfulfilled(testContext.fPromiseImageChecker, testContext.fPromiseTextureCheckers,
reporter);
testContext.fRecorder.reset();
REPORTER_ASSERT(reporter, context->insertRecording({ recording.get() }));
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 1);
testGpuContext->syncedSubmit(context);
testContext.fSurface.reset();
testContext.fImg.reset();
recording.reset();
check_all_done(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 1);
}
}
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(GraphiteYUVAPromiseImageMultipleImgUses,
reporter,
context,
testGpuContext,
true,
CtsEnforcement::kApiLevel_V) {
constexpr SkISize kDimensions{ 16, 16 };
static constexpr int kNumRecordings = 3;
for (Volatile isVolatile : { Volatile::kNo, Volatile::kYes }) {
int expectedVolatile = (isVolatile == Volatile::kYes) ? 4 : 0;
int expectedNonVolatile = 4 - expectedVolatile;
TestCtx testContext;
setup_test_context(context, reporter, &testContext,
kDimensions, isVolatile, false);
std::unique_ptr<Recording> recordings[kNumRecordings];
SkCanvas* canvas = testContext.fSurface->getCanvas();
for (int i = 0; i < kNumRecordings; ++i) {
canvas->drawImage(testContext.fImg, 0, 0);
recordings[i] = testContext.fRecorder->snap();
if (isVolatile == Volatile::kYes) {
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
i);
} else {
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
i > 0 ? 1 : 0);
}
REPORTER_ASSERT(reporter,
recordings[i]->priv().numVolatilePromiseImages() == expectedVolatile);
REPORTER_ASSERT(reporter,
recordings[i]->priv().numNonVolatilePromiseImages() ==
expectedNonVolatile);
REPORTER_ASSERT(reporter, context->insertRecording({ recordings[i].get() }));
if (isVolatile == Volatile::kYes) {
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
i+1);
} else {
check_fulfills_only(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
1);
}
REPORTER_ASSERT(reporter, recordings[i]->priv().numNonVolatilePromiseImages() == 0);
}
testGpuContext->syncedSubmit(context);
testContext.fSurface.reset();
testContext.fImg.reset();
for (int i = 0; i < kNumRecordings; ++i) {
recordings[i].reset();
}
if (isVolatile == Volatile::kYes) {
check_all_done(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers,
kNumRecordings);
} else {
check_all_done(reporter, testContext.fPromiseImageChecker,
testContext.fPromiseTextureCheckers, 1);
}
}
}