36const SkISize kSurfaceSize = { 16, 16 };
38constexpr int kNumMutations = 2;
40constexpr SkColor4f kMutationColors[kNumMutations] = {
72 , fWithMips(withMips) {
74 virtual ~Mutator() =
default;
76 virtual std::unique_ptr<Recording>
init(
const Caps*) = 0;
77 virtual std::unique_ptr<Recording> mutate(
int mutationIndex) = 0;
78 virtual int getCase()
const = 0;
81 return fMutatingImg.get();
99 , fRecorder(recorder) {
103 fReadbackPM.alloc(ii);
113 fImgDrawRecording = MakeRedrawRecording(fRecorder, fImgDrawSurface.get(), imageToDraw);
117 return fImgDrawRecording.get();
121 void checkResult(
Context* context,
123 bool useTwoRecorders,
129 if (!fImgDrawSurface->readPixels(fReadbackPM, 0, 0)) {
130 ERRORF(fReporter,
"readPixels failed");
133 auto error = std::function<ComparePixmapsErrorReporter>(
134 [&](
int x,
int y,
const float diffs[4]) {
137 "expected (%.1f %.1f %.1f %.1f) "
138 "- diffs (%.1f, %.1f, %.1f, %.1f)",
139 testcaseID, useTwoRecorders ?
'b' :
'a',
140 withMips ?
"mipmapped" :
"not-mipmapped",
141 expectedColor.fR, expectedColor.fG, expectedColor.fB, expectedColor.fA,
142 diffs[0], diffs[1], diffs[2], diffs[3]);
145 static constexpr float kTol[] = {0, 0, 0, 0};
150 static std::unique_ptr<Recording> MakeRedrawRecording(
Recorder* recorder,
163 return recorder->
snap();
170 std::unique_ptr<Recording> fImgDrawRecording;
182 std::unique_ptr<char[]> memForPixmaps;
188 SkASSERT(numMipLevels == 1 || numMipLevels == kNumMipLevels);
197class UpdateBackendTextureMutator :
public Mutator {
202 return std::make_unique<UpdateBackendTextureMutator>(
reporter, recorder, withMips);
206 : Mutator(
reporter, recorder, withMips) {
208 ~UpdateBackendTextureMutator()
override {
209 fRecorder->deleteBackendTexture(fBETexture);
212 std::unique_ptr<Recording>
init(
const Caps* caps)
override {
227 fWithMips, kInitialColor);
236 return fRecorder->snap();
239 std::unique_ptr<Recording> mutate(
int mutationIndex)
override {
241 fWithMips, kMutationColors[mutationIndex]);
242 return fRecorder->snap();
245 int getCase()
const override {
return 1; }
255class VolatilePromiseImageMutator :
public Mutator {
260 return std::make_unique<VolatilePromiseImageMutator>(
reporter, recorder, withMips);
264 : Mutator(
reporter, recorder, withMips) {
267 ~VolatilePromiseImageMutator()
override {
270 fMutatingImg.reset();
272 fCallbackTracker.finishedTest();
274 for (
int i = 0;
i < kNumMutations+1; ++
i) {
275 fRecorder->deleteBackendTexture(fBETextures[
i]);
279 static std::tuple<BackendTexture, void*> fulfill(
void* ctx) {
280 VolatilePromiseImageMutator* mutator =
reinterpret_cast<VolatilePromiseImageMutator*
>(ctx);
282 int index = mutator->fCallbackTracker.onFulfillCB();
284 return { mutator->fBETextures[index], &mutator->fCallbackTracker };
287 static void imageRelease(
void* ctx) {
288 VolatilePromiseImageMutator* mutator =
reinterpret_cast<VolatilePromiseImageMutator*
>(ctx);
290 mutator->fCallbackTracker.onImageReleaseCB();
293 static void textureRelease(
void* ctx) {
294 CallbackTracker* callbackTracker =
reinterpret_cast<CallbackTracker*
>(ctx);
296 callbackTracker->onTextureReleaseCB();
299 std::unique_ptr<Recording>
init(
const Caps* caps)
override {
310 fBETextures[0] = fRecorder->createBackendTexture(
kImageSize,
info);
314 fWithMips, kInitialColor);
316 for (
int i = 0;
i < kNumMutations; ++
i) {
321 fWithMips, kMutationColors[
i]);
337 return fRecorder->snap();
340 std::unique_ptr<Recording> mutate(
int mutationIndex)
override {
341 fCallbackTracker.onMutation();
345 int getCase()
const override {
return 2; }
348 class CallbackTracker {
351 for (
int i = 0;
i < kNumMutations+1; ++
i) {
352 fFulfilled[
i] =
false;
353 fReleased[
i] =
false;
363 SkASSERT(fMutationCount < kNumMutations+1);
364 SkASSERT(fFulfilledCount == fMutationCount);
366 SkASSERT(!fFulfilled[fFulfilledCount]);
367 SkASSERT(!fReleased[fFulfilledCount]);
369 fFulfilled[fFulfilledCount] =
true;
370 return fFulfilledCount++;
373 void onImageReleaseCB() {
375 fImageReleased =
true;
378 void onTextureReleaseCB() {
379 SkASSERT(fReleasedCount >= 0 && fReleasedCount < kNumMutations+1);
381 SkASSERT(fFulfilled[fReleasedCount]);
382 SkASSERT(!fReleased[fReleasedCount]);
383 fReleased[fReleasedCount] =
true;
387 void finishedTest()
const {
388 SkASSERT(fMutationCount == kNumMutations);
391 for (
int i = 0;
i < kNumMutations+1; ++
i) {
398 int fMutationCount = 0;
399 int fFulfilledCount = 0;
400 bool fImageReleased =
false;
401 int fReleasedCount = 0;
402 bool fFulfilled[kNumMutations+1];
403 bool fReleased[kNumMutations+1];
406 CallbackTracker fCallbackTracker;
414class SurfaceMutator :
public Mutator {
419 return std::make_unique<SurfaceMutator>(
reporter, recorder, withMips);
423 : Mutator(
reporter, recorder, withMips) {
426 std::unique_ptr<Recording>
init(
const Caps* )
override {
433 fMutatingSurface->getCanvas()->clear(kInitialColor);
438 return fRecorder->snap();
441 std::unique_ptr<Recording> mutate(
int mutationIndex)
override {
442 fMutatingSurface->getCanvas()->clear(kMutationColors[mutationIndex]);
443 return fRecorder->snap();
446 int getCase()
const override {
return 3; }
456 bool useTwoRecorders,
458 MutatorFactoryT createMutator) {
461 std::unique_ptr<Recorder> recorders[2];
464 Recorder* mutatorRecorder = recorders[0].get();
465 Recorder* redrawerRecorder = recorders[0].get();
467 if (useTwoRecorders) {
469 redrawerRecorder = recorders[1].get();
472 std::unique_ptr<Mutator> mutator = createMutator(
reporter, mutatorRecorder, withMips);
475 std::unique_ptr<Recording> imgCreationRecording = mutator->init(caps);
480 Redrawer redrawer(
reporter, redrawerRecorder);
482 redrawer.init(mutator->getMutatingImage());
485 redrawer.checkResult(context, mutator->getCase(),
486 useTwoRecorders, withMips, kInitialColor);
488 for (
int i = 0;
i < kNumMutations; ++
i) {
490 std::unique_ptr<Recording> imgMutationRecording = mutator->mutate(
i);
491 if (imgMutationRecording) {
498 redrawer.checkResult(context, mutator->getCase(),
499 useTwoRecorders, withMips, kMutationColors[
i]);
509 for (
bool useTwoRecorders : {
false,
true }) {
510 for (
bool withMips : {
false,
true }) {
static void run_test(GrDirectContext *dContext, skiatest::Reporter *reporter, BulkRectTest test)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(MutableImagesTest, reporter, context, CtsEnforcement::kNextRelease)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
bool CheckSolidPixels(const SkColor4f &col, const SkPixmap &pixmap, const float tolRGBA[4], std::function< ComparePixmapsErrorReporter > &error)
#define REPORTER_ASSERT(r, cond,...)
void clear(SkColor color)
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
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 insertRecording(const InsertRecordingInfo &)
std::unique_ptr< Recording > snap()
bool updateBackendTexture(const BackendTexture &, const SkPixmap srcData[], int numLevels)
const uint8_t uint32_t uint32_t GError ** error
static const int kImageSize
constexpr SkColor4f kGreen
constexpr SkColor4f kTransparent
constexpr SkColor4f kBlue
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< SkImage > WrapTexture(skgpu::graphite::Recorder *, const skgpu::graphite::BackendTexture &, SkColorType colorType, SkAlphaType alphaType, sk_sp< SkColorSpace > colorSpace, skgpu::Origin origin, GenerateMipmapsFromBase generateMipmapsFromBase, TextureReleaseProc=nullptr, ReleaseContext=nullptr, std::string_view label={})
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
PODArray< SkColor > colors
SkSamplingOptions sampling
SK_API sk_sp< SkImage > AsImage(sk_sp< const SkSurface >)
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 SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkRect MakeWH(float w, float h)