1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/BackendTexture.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Image.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recording.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkAutoPixmapStorage.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextPriv.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Surface_Graphite.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Texture.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/TextureProxy.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "tests/TestUtils.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu::graphite;
29*c8dee2aaSAndroid Build Coastguard Worker using Mipmapped = skgpu::Mipmapped;
30*c8dee2aaSAndroid Build Coastguard Worker
31*c8dee2aaSAndroid Build Coastguard Worker namespace {
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker // We draw the larger image into the smaller surface to force mipmapping
34*c8dee2aaSAndroid Build Coastguard Worker const SkISize kImageSize = { 32, 32 };
35*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(constexpr int kNumMipLevels = 6;)
36*c8dee2aaSAndroid Build Coastguard Worker const SkISize kSurfaceSize = { 16, 16 };
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker constexpr int kNumMutations = 2;
39*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor4f kInitialColor = SkColors::kRed;
40*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor4f kMutationColors[kNumMutations] = {
41*c8dee2aaSAndroid Build Coastguard Worker SkColors::kGreen,
42*c8dee2aaSAndroid Build Coastguard Worker SkColors::kBlue
43*c8dee2aaSAndroid Build Coastguard Worker };
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker /*
46*c8dee2aaSAndroid Build Coastguard Worker * We have 3 use cases. In each case there is a mutating task which changes the contents of an
47*c8dee2aaSAndroid Build Coastguard Worker * image (somehow) and a shared redraw task which just creates a single Recording which draws the
48*c8dee2aaSAndroid Build Coastguard Worker * image that is being mutated. The mutator's image must start off being 'kInitialColor' and
49*c8dee2aaSAndroid Build Coastguard Worker * then cycle through 'kMutationColors'. The mutation tasks are:
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker * 1) (AHBs) The client has wrapped a backend texture in an image and is changing the backend
52*c8dee2aaSAndroid Build Coastguard Worker * texture's contents.
53*c8dee2aaSAndroid Build Coastguard Worker * 2) (Volatile Promise Images) The client has a pool of backend textures and updates both the
54*c8dee2aaSAndroid Build Coastguard Worker * contents of the backend textures and which one backs the image every frame
55*c8dee2aaSAndroid Build Coastguard Worker * 3) (Surface/Image pair) The client has a surface and has snapped an image w/o a copy but
56*c8dee2aaSAndroid Build Coastguard Worker * keeps drawing to the surface
57*c8dee2aaSAndroid Build Coastguard Worker *
58*c8dee2aaSAndroid Build Coastguard Worker * There are also two scenarios for the mutation and redrawing tasks:
59*c8dee2aaSAndroid Build Coastguard Worker * a) Both use the same recorder
60*c8dee2aaSAndroid Build Coastguard Worker * b) They use separate recorders
61*c8dee2aaSAndroid Build Coastguard Worker * The latter, obviously, requires more synchronization.
62*c8dee2aaSAndroid Build Coastguard Worker */
63*c8dee2aaSAndroid Build Coastguard Worker
64*c8dee2aaSAndroid Build Coastguard Worker // Base class for the 3 mutation methods.
65*c8dee2aaSAndroid Build Coastguard Worker // init - should create the SkImage that is going to be changing
66*c8dee2aaSAndroid Build Coastguard Worker // mutate - should change the contents of the SkImage
67*c8dee2aaSAndroid Build Coastguard Worker class Mutator {
68*c8dee2aaSAndroid Build Coastguard Worker public:
Mutator(skiatest::Reporter * reporter,Recorder * recorder,bool withMips)69*c8dee2aaSAndroid Build Coastguard Worker Mutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
70*c8dee2aaSAndroid Build Coastguard Worker : fReporter(reporter)
71*c8dee2aaSAndroid Build Coastguard Worker , fRecorder(recorder)
72*c8dee2aaSAndroid Build Coastguard Worker , fWithMips(withMips) {
73*c8dee2aaSAndroid Build Coastguard Worker }
74*c8dee2aaSAndroid Build Coastguard Worker virtual ~Mutator() = default;
75*c8dee2aaSAndroid Build Coastguard Worker
76*c8dee2aaSAndroid Build Coastguard Worker virtual std::unique_ptr<Recording> init(const Caps*) = 0;
77*c8dee2aaSAndroid Build Coastguard Worker virtual std::unique_ptr<Recording> mutate(int mutationIndex) = 0;
78*c8dee2aaSAndroid Build Coastguard Worker virtual int getCase() const = 0;
79*c8dee2aaSAndroid Build Coastguard Worker
getMutatingImage()80*c8dee2aaSAndroid Build Coastguard Worker SkImage* getMutatingImage() {
81*c8dee2aaSAndroid Build Coastguard Worker return fMutatingImg.get();
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker protected:
85*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter* fReporter;
86*c8dee2aaSAndroid Build Coastguard Worker Recorder* fRecorder;
87*c8dee2aaSAndroid Build Coastguard Worker bool fWithMips;
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fMutatingImg; // needs to be created in the 'init' method
90*c8dee2aaSAndroid Build Coastguard Worker };
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker // This class puts the 3 mutation use cases through their paces.
93*c8dee2aaSAndroid Build Coastguard Worker // init - creates the single Recording that draws the mutator's image
94*c8dee2aaSAndroid Build Coastguard Worker // checkResult - verifies that replaying the Recording results in the expected/mutated color
95*c8dee2aaSAndroid Build Coastguard Worker class Redrawer {
96*c8dee2aaSAndroid Build Coastguard Worker public:
Redrawer(skiatest::Reporter * reporter,Recorder * recorder)97*c8dee2aaSAndroid Build Coastguard Worker Redrawer(skiatest::Reporter* reporter, Recorder* recorder)
98*c8dee2aaSAndroid Build Coastguard Worker : fReporter(reporter)
99*c8dee2aaSAndroid Build Coastguard Worker , fRecorder(recorder) {
100*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo ii = SkImageInfo::Make(kSurfaceSize,
101*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
102*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType);
103*c8dee2aaSAndroid Build Coastguard Worker fReadbackPM.alloc(ii);
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker
init(SkImage * imageToDraw)106*c8dee2aaSAndroid Build Coastguard Worker void init(SkImage* imageToDraw) {
107*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo ii = SkImageInfo::Make(kSurfaceSize,
108*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
109*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType);
110*c8dee2aaSAndroid Build Coastguard Worker fImgDrawSurface = SkSurfaces::RenderTarget(fRecorder, ii, Mipmapped::kNo);
111*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fImgDrawSurface);
112*c8dee2aaSAndroid Build Coastguard Worker
113*c8dee2aaSAndroid Build Coastguard Worker fImgDrawRecording = MakeRedrawRecording(fRecorder, fImgDrawSurface.get(), imageToDraw);
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
imgDrawRecording()116*c8dee2aaSAndroid Build Coastguard Worker Recording* imgDrawRecording() {
117*c8dee2aaSAndroid Build Coastguard Worker return fImgDrawRecording.get();
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker // This is here bc it uses a lot from the Redrawer (i.e., its recorder, its surface, etc.).
checkResult(Context * context,int testcaseID,bool useTwoRecorders,bool withMips,const SkColor4f & expectedColor)121*c8dee2aaSAndroid Build Coastguard Worker void checkResult(Context* context,
122*c8dee2aaSAndroid Build Coastguard Worker int testcaseID,
123*c8dee2aaSAndroid Build Coastguard Worker bool useTwoRecorders,
124*c8dee2aaSAndroid Build Coastguard Worker bool withMips,
125*c8dee2aaSAndroid Build Coastguard Worker const SkColor4f& expectedColor) {
126*c8dee2aaSAndroid Build Coastguard Worker
127*c8dee2aaSAndroid Build Coastguard Worker fReadbackPM.erase(SkColors::kTransparent);
128*c8dee2aaSAndroid Build Coastguard Worker
129*c8dee2aaSAndroid Build Coastguard Worker if (!fImgDrawSurface->readPixels(fReadbackPM, 0, 0)) {
130*c8dee2aaSAndroid Build Coastguard Worker ERRORF(fReporter, "readPixels failed");
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker auto error = std::function<ComparePixmapsErrorReporter>(
134*c8dee2aaSAndroid Build Coastguard Worker [&](int x, int y, const float diffs[4]) {
135*c8dee2aaSAndroid Build Coastguard Worker ERRORF(fReporter,
136*c8dee2aaSAndroid Build Coastguard Worker "case %d%c - %s: "
137*c8dee2aaSAndroid Build Coastguard Worker "expected (%.1f %.1f %.1f %.1f) "
138*c8dee2aaSAndroid Build Coastguard Worker "- diffs (%.1f, %.1f, %.1f, %.1f)",
139*c8dee2aaSAndroid Build Coastguard Worker testcaseID, useTwoRecorders ? 'b' : 'a',
140*c8dee2aaSAndroid Build Coastguard Worker withMips ? "mipmapped" : "not-mipmapped",
141*c8dee2aaSAndroid Build Coastguard Worker expectedColor.fR, expectedColor.fG, expectedColor.fB, expectedColor.fA,
142*c8dee2aaSAndroid Build Coastguard Worker diffs[0], diffs[1], diffs[2], diffs[3]);
143*c8dee2aaSAndroid Build Coastguard Worker });
144*c8dee2aaSAndroid Build Coastguard Worker
145*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kTol[] = {0, 0, 0, 0};
146*c8dee2aaSAndroid Build Coastguard Worker CheckSolidPixels(expectedColor, fReadbackPM, kTol, error);
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker
149*c8dee2aaSAndroid Build Coastguard Worker private:
MakeRedrawRecording(Recorder * recorder,SkSurface * surfaceToDrawTo,SkImage * imageToDraw)150*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<Recording> MakeRedrawRecording(Recorder* recorder,
151*c8dee2aaSAndroid Build Coastguard Worker SkSurface* surfaceToDrawTo,
152*c8dee2aaSAndroid Build Coastguard Worker SkImage* imageToDraw) {
153*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions sampling = SkSamplingOptions(SkFilterMode::kLinear,
154*c8dee2aaSAndroid Build Coastguard Worker SkMipmapMode::kNearest);
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surfaceToDrawTo->getCanvas();
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SkColors::kTransparent);
159*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(imageToDraw,
160*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeWH(kSurfaceSize.width(), kSurfaceSize.height()),
161*c8dee2aaSAndroid Build Coastguard Worker sampling);
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard Worker return recorder->snap();
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker
166*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter* fReporter;
167*c8dee2aaSAndroid Build Coastguard Worker Recorder* fRecorder;
168*c8dee2aaSAndroid Build Coastguard Worker
169*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> fImgDrawSurface;
170*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> fImgDrawRecording;
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker SkAutoPixmapStorage fReadbackPM;
173*c8dee2aaSAndroid Build Coastguard Worker };
174*c8dee2aaSAndroid Build Coastguard Worker
update_backend_texture(skiatest::Reporter * reporter,Recorder * recorder,const BackendTexture & backendTex,SkColorType ct,bool withMips,SkColor4f color)175*c8dee2aaSAndroid Build Coastguard Worker void update_backend_texture(skiatest::Reporter* reporter,
176*c8dee2aaSAndroid Build Coastguard Worker Recorder* recorder,
177*c8dee2aaSAndroid Build Coastguard Worker const BackendTexture& backendTex,
178*c8dee2aaSAndroid Build Coastguard Worker SkColorType ct,
179*c8dee2aaSAndroid Build Coastguard Worker bool withMips,
180*c8dee2aaSAndroid Build Coastguard Worker SkColor4f color) {
181*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pixmaps[6];
182*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<char[]> memForPixmaps;
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker const SkColor4f colors[6] = { color, color, color, color, color, color };
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker int numMipLevels = ToolUtils::make_pixmaps(ct, kPremul_SkAlphaType, withMips, colors, pixmaps,
187*c8dee2aaSAndroid Build Coastguard Worker &memForPixmaps);
188*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(numMipLevels == 1 || numMipLevels == kNumMipLevels);
189*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(kImageSize == pixmaps[0].dimensions());
190*c8dee2aaSAndroid Build Coastguard Worker
191*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, recorder->updateBackendTexture(backendTex, pixmaps, numMipLevels));
192*c8dee2aaSAndroid Build Coastguard Worker }
193*c8dee2aaSAndroid Build Coastguard Worker
194*c8dee2aaSAndroid Build Coastguard Worker // case 1 (AHBs)
195*c8dee2aaSAndroid Build Coastguard Worker // To simulate the AHB use case this Mutator creates a BackendTexture and an SkImage that wraps
196*c8dee2aaSAndroid Build Coastguard Worker // it. To mutate the SkImage it simply updates the BackendTexture.
197*c8dee2aaSAndroid Build Coastguard Worker class UpdateBackendTextureMutator : public Mutator {
198*c8dee2aaSAndroid Build Coastguard Worker public:
Make(skiatest::Reporter * reporter,Recorder * recorder,bool withMips)199*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<Mutator> Make(skiatest::Reporter* reporter,
200*c8dee2aaSAndroid Build Coastguard Worker Recorder* recorder,
201*c8dee2aaSAndroid Build Coastguard Worker bool withMips) {
202*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<UpdateBackendTextureMutator>(reporter, recorder, withMips);
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker
UpdateBackendTextureMutator(skiatest::Reporter * reporter,Recorder * recorder,bool withMips)205*c8dee2aaSAndroid Build Coastguard Worker UpdateBackendTextureMutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
206*c8dee2aaSAndroid Build Coastguard Worker : Mutator(reporter, recorder, withMips) {
207*c8dee2aaSAndroid Build Coastguard Worker }
~UpdateBackendTextureMutator()208*c8dee2aaSAndroid Build Coastguard Worker ~UpdateBackendTextureMutator() override {
209*c8dee2aaSAndroid Build Coastguard Worker fRecorder->deleteBackendTexture(fBETexture);
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker
init(const Caps * caps)212*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> init(const Caps* caps) override {
213*c8dee2aaSAndroid Build Coastguard Worker skgpu::Protected isProtected = skgpu::Protected(caps->protectedSupport());
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker // Note: not renderable
216*c8dee2aaSAndroid Build Coastguard Worker TextureInfo info = caps->getDefaultSampledTextureInfo(kRGBA_8888_SkColorType,
217*c8dee2aaSAndroid Build Coastguard Worker fWithMips ? Mipmapped::kYes
218*c8dee2aaSAndroid Build Coastguard Worker : Mipmapped::kNo,
219*c8dee2aaSAndroid Build Coastguard Worker isProtected,
220*c8dee2aaSAndroid Build Coastguard Worker skgpu::Renderable::kNo);
221*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, info.isValid());
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker fBETexture = fRecorder->createBackendTexture(kImageSize, info);
224*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fBETexture.isValid());
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker update_backend_texture(fReporter, fRecorder, fBETexture, kRGBA_8888_SkColorType,
227*c8dee2aaSAndroid Build Coastguard Worker fWithMips, kInitialColor);
228*c8dee2aaSAndroid Build Coastguard Worker
229*c8dee2aaSAndroid Build Coastguard Worker fMutatingImg = SkImages::WrapTexture(fRecorder,
230*c8dee2aaSAndroid Build Coastguard Worker fBETexture,
231*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
232*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
233*c8dee2aaSAndroid Build Coastguard Worker /* colorSpace= */ nullptr);
234*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fMutatingImg);
235*c8dee2aaSAndroid Build Coastguard Worker
236*c8dee2aaSAndroid Build Coastguard Worker return fRecorder->snap();
237*c8dee2aaSAndroid Build Coastguard Worker }
238*c8dee2aaSAndroid Build Coastguard Worker
mutate(int mutationIndex)239*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> mutate(int mutationIndex) override {
240*c8dee2aaSAndroid Build Coastguard Worker update_backend_texture(fReporter, fRecorder, fBETexture, kRGBA_8888_SkColorType,
241*c8dee2aaSAndroid Build Coastguard Worker fWithMips, kMutationColors[mutationIndex]);
242*c8dee2aaSAndroid Build Coastguard Worker return fRecorder->snap();
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
getCase() const245*c8dee2aaSAndroid Build Coastguard Worker int getCase() const override { return 1; }
246*c8dee2aaSAndroid Build Coastguard Worker
247*c8dee2aaSAndroid Build Coastguard Worker private:
248*c8dee2aaSAndroid Build Coastguard Worker BackendTexture fBETexture;
249*c8dee2aaSAndroid Build Coastguard Worker };
250*c8dee2aaSAndroid Build Coastguard Worker
251*c8dee2aaSAndroid Build Coastguard Worker // case 2 (Volatile Promise Images)
252*c8dee2aaSAndroid Build Coastguard Worker // To simulate the hardware video decoder use case this Mutator creates a set of BackendTextures
253*c8dee2aaSAndroid Build Coastguard Worker // and fills them w/ different colors. A single volatile Promise Image is created and is
254*c8dee2aaSAndroid Build Coastguard Worker // fulfilled by the different BackendTextures.
255*c8dee2aaSAndroid Build Coastguard Worker class VolatilePromiseImageMutator : public Mutator {
256*c8dee2aaSAndroid Build Coastguard Worker public:
Make(skiatest::Reporter * reporter,Recorder * recorder,bool withMips)257*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<Mutator> Make(skiatest::Reporter* reporter,
258*c8dee2aaSAndroid Build Coastguard Worker Recorder* recorder,
259*c8dee2aaSAndroid Build Coastguard Worker bool withMips) {
260*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<VolatilePromiseImageMutator>(reporter, recorder, withMips);
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker
VolatilePromiseImageMutator(skiatest::Reporter * reporter,Recorder * recorder,bool withMips)263*c8dee2aaSAndroid Build Coastguard Worker VolatilePromiseImageMutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
264*c8dee2aaSAndroid Build Coastguard Worker : Mutator(reporter, recorder, withMips) {
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker
~VolatilePromiseImageMutator()267*c8dee2aaSAndroid Build Coastguard Worker ~VolatilePromiseImageMutator() override {
268*c8dee2aaSAndroid Build Coastguard Worker // We need to delete the mutating image first since it holds onto the backend texture
269*c8dee2aaSAndroid Build Coastguard Worker // that was last used to fulfill the volatile promise image.
270*c8dee2aaSAndroid Build Coastguard Worker fMutatingImg.reset();
271*c8dee2aaSAndroid Build Coastguard Worker
272*c8dee2aaSAndroid Build Coastguard Worker fCallbackTracker.finishedTest();
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumMutations+1; ++i) {
275*c8dee2aaSAndroid Build Coastguard Worker fRecorder->deleteBackendTexture(fBETextures[i]);
276*c8dee2aaSAndroid Build Coastguard Worker }
277*c8dee2aaSAndroid Build Coastguard Worker }
278*c8dee2aaSAndroid Build Coastguard Worker
fulfill(void * ctx)279*c8dee2aaSAndroid Build Coastguard Worker static std::tuple<BackendTexture, void*> fulfill(void* ctx) {
280*c8dee2aaSAndroid Build Coastguard Worker VolatilePromiseImageMutator* mutator = reinterpret_cast<VolatilePromiseImageMutator*>(ctx);
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard Worker int index = mutator->fCallbackTracker.onFulfillCB();
283*c8dee2aaSAndroid Build Coastguard Worker
284*c8dee2aaSAndroid Build Coastguard Worker return { mutator->fBETextures[index], &mutator->fCallbackTracker };
285*c8dee2aaSAndroid Build Coastguard Worker }
286*c8dee2aaSAndroid Build Coastguard Worker
imageRelease(void * ctx)287*c8dee2aaSAndroid Build Coastguard Worker static void imageRelease(void* ctx) {
288*c8dee2aaSAndroid Build Coastguard Worker VolatilePromiseImageMutator* mutator = reinterpret_cast<VolatilePromiseImageMutator*>(ctx);
289*c8dee2aaSAndroid Build Coastguard Worker
290*c8dee2aaSAndroid Build Coastguard Worker mutator->fCallbackTracker.onImageReleaseCB();
291*c8dee2aaSAndroid Build Coastguard Worker }
292*c8dee2aaSAndroid Build Coastguard Worker
textureRelease(void * ctx)293*c8dee2aaSAndroid Build Coastguard Worker static void textureRelease(void* ctx) {
294*c8dee2aaSAndroid Build Coastguard Worker CallbackTracker* callbackTracker = reinterpret_cast<CallbackTracker*>(ctx);
295*c8dee2aaSAndroid Build Coastguard Worker
296*c8dee2aaSAndroid Build Coastguard Worker callbackTracker->onTextureReleaseCB();
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker
init(const Caps * caps)299*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> init(const Caps* caps) override {
300*c8dee2aaSAndroid Build Coastguard Worker skgpu::Protected isProtected = skgpu::Protected(caps->protectedSupport());
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker // Note: not renderable
303*c8dee2aaSAndroid Build Coastguard Worker TextureInfo info = caps->getDefaultSampledTextureInfo(kRGBA_8888_SkColorType,
304*c8dee2aaSAndroid Build Coastguard Worker fWithMips ? Mipmapped::kYes
305*c8dee2aaSAndroid Build Coastguard Worker : Mipmapped::kNo,
306*c8dee2aaSAndroid Build Coastguard Worker isProtected,
307*c8dee2aaSAndroid Build Coastguard Worker skgpu::Renderable::kNo);
308*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, info.isValid());
309*c8dee2aaSAndroid Build Coastguard Worker
310*c8dee2aaSAndroid Build Coastguard Worker fBETextures[0] = fRecorder->createBackendTexture(kImageSize, info);
311*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fBETextures[0].isValid());
312*c8dee2aaSAndroid Build Coastguard Worker
313*c8dee2aaSAndroid Build Coastguard Worker update_backend_texture(fReporter, fRecorder, fBETextures[0], kRGBA_8888_SkColorType,
314*c8dee2aaSAndroid Build Coastguard Worker fWithMips, kInitialColor);
315*c8dee2aaSAndroid Build Coastguard Worker
316*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumMutations; ++i) {
317*c8dee2aaSAndroid Build Coastguard Worker fBETextures[i+1] = fRecorder->createBackendTexture(kImageSize, info);
318*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fBETextures[i+1].isValid());
319*c8dee2aaSAndroid Build Coastguard Worker
320*c8dee2aaSAndroid Build Coastguard Worker update_backend_texture(fReporter, fRecorder, fBETextures[i+1], kRGBA_8888_SkColorType,
321*c8dee2aaSAndroid Build Coastguard Worker fWithMips, kMutationColors[i]);
322*c8dee2aaSAndroid Build Coastguard Worker }
323*c8dee2aaSAndroid Build Coastguard Worker
324*c8dee2aaSAndroid Build Coastguard Worker fMutatingImg = SkImages::PromiseTextureFrom(fRecorder,
325*c8dee2aaSAndroid Build Coastguard Worker kImageSize,
326*c8dee2aaSAndroid Build Coastguard Worker info,
327*c8dee2aaSAndroid Build Coastguard Worker SkColorInfo(kRGBA_8888_SkColorType,
328*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
329*c8dee2aaSAndroid Build Coastguard Worker /* cs= */ nullptr),
330*c8dee2aaSAndroid Build Coastguard Worker Volatile::kYes,
331*c8dee2aaSAndroid Build Coastguard Worker fulfill,
332*c8dee2aaSAndroid Build Coastguard Worker imageRelease,
333*c8dee2aaSAndroid Build Coastguard Worker textureRelease,
334*c8dee2aaSAndroid Build Coastguard Worker this);
335*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fMutatingImg);
336*c8dee2aaSAndroid Build Coastguard Worker
337*c8dee2aaSAndroid Build Coastguard Worker return fRecorder->snap();
338*c8dee2aaSAndroid Build Coastguard Worker }
339*c8dee2aaSAndroid Build Coastguard Worker
mutate(int mutationIndex)340*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> mutate(int mutationIndex) override {
341*c8dee2aaSAndroid Build Coastguard Worker fCallbackTracker.onMutation();
342*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
343*c8dee2aaSAndroid Build Coastguard Worker }
344*c8dee2aaSAndroid Build Coastguard Worker
getCase() const345*c8dee2aaSAndroid Build Coastguard Worker int getCase() const override { return 2; }
346*c8dee2aaSAndroid Build Coastguard Worker
347*c8dee2aaSAndroid Build Coastguard Worker private:
348*c8dee2aaSAndroid Build Coastguard Worker class CallbackTracker {
349*c8dee2aaSAndroid Build Coastguard Worker public:
CallbackTracker()350*c8dee2aaSAndroid Build Coastguard Worker CallbackTracker() {
351*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumMutations+1; ++i) {
352*c8dee2aaSAndroid Build Coastguard Worker fFulfilled[i] = false;
353*c8dee2aaSAndroid Build Coastguard Worker fReleased[i] = false;
354*c8dee2aaSAndroid Build Coastguard Worker }
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker
onMutation()357*c8dee2aaSAndroid Build Coastguard Worker void onMutation() {
358*c8dee2aaSAndroid Build Coastguard Worker // In this use case, the active mutation occurs in the volatile promise image callbacks.
359*c8dee2aaSAndroid Build Coastguard Worker ++fMutationCount;
360*c8dee2aaSAndroid Build Coastguard Worker }
361*c8dee2aaSAndroid Build Coastguard Worker
onFulfillCB()362*c8dee2aaSAndroid Build Coastguard Worker int onFulfillCB() {
363*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fMutationCount < kNumMutations+1);
364*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fFulfilledCount == fMutationCount);
365*c8dee2aaSAndroid Build Coastguard Worker // For this unit test we should only be fulfilling with each backend texture only once
366*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fFulfilled[fFulfilledCount]);
367*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fReleased[fFulfilledCount]);
368*c8dee2aaSAndroid Build Coastguard Worker
369*c8dee2aaSAndroid Build Coastguard Worker fFulfilled[fFulfilledCount] = true;
370*c8dee2aaSAndroid Build Coastguard Worker return fFulfilledCount++;
371*c8dee2aaSAndroid Build Coastguard Worker }
372*c8dee2aaSAndroid Build Coastguard Worker
onImageReleaseCB()373*c8dee2aaSAndroid Build Coastguard Worker void onImageReleaseCB() {
374*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fImageReleased);
375*c8dee2aaSAndroid Build Coastguard Worker fImageReleased = true;
376*c8dee2aaSAndroid Build Coastguard Worker }
377*c8dee2aaSAndroid Build Coastguard Worker
onTextureReleaseCB()378*c8dee2aaSAndroid Build Coastguard Worker void onTextureReleaseCB() {
379*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fReleasedCount >= 0 && fReleasedCount < kNumMutations+1);
380*c8dee2aaSAndroid Build Coastguard Worker
381*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fFulfilled[fReleasedCount]);
382*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fReleased[fReleasedCount]);
383*c8dee2aaSAndroid Build Coastguard Worker fReleased[fReleasedCount] = true;
384*c8dee2aaSAndroid Build Coastguard Worker fReleasedCount++;
385*c8dee2aaSAndroid Build Coastguard Worker }
386*c8dee2aaSAndroid Build Coastguard Worker
finishedTest() const387*c8dee2aaSAndroid Build Coastguard Worker void finishedTest() const {
388*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fMutationCount == kNumMutations);
389*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fImageReleased);
390*c8dee2aaSAndroid Build Coastguard Worker
391*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumMutations+1; ++i) {
392*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fFulfilled[i]);
393*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fReleased[i]);
394*c8dee2aaSAndroid Build Coastguard Worker }
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker
397*c8dee2aaSAndroid Build Coastguard Worker private:
398*c8dee2aaSAndroid Build Coastguard Worker int fMutationCount = 0;
399*c8dee2aaSAndroid Build Coastguard Worker int fFulfilledCount = 0;
400*c8dee2aaSAndroid Build Coastguard Worker bool fImageReleased = false;
401*c8dee2aaSAndroid Build Coastguard Worker int fReleasedCount = 0;
402*c8dee2aaSAndroid Build Coastguard Worker bool fFulfilled[kNumMutations+1];
403*c8dee2aaSAndroid Build Coastguard Worker bool fReleased[kNumMutations+1];
404*c8dee2aaSAndroid Build Coastguard Worker };
405*c8dee2aaSAndroid Build Coastguard Worker
406*c8dee2aaSAndroid Build Coastguard Worker CallbackTracker fCallbackTracker;
407*c8dee2aaSAndroid Build Coastguard Worker
408*c8dee2aaSAndroid Build Coastguard Worker BackendTexture fBETextures[kNumMutations+1];
409*c8dee2aaSAndroid Build Coastguard Worker };
410*c8dee2aaSAndroid Build Coastguard Worker
411*c8dee2aaSAndroid Build Coastguard Worker // case 3 (Surface/Image pair)
412*c8dee2aaSAndroid Build Coastguard Worker // This mutator creates an SkSurface/SkImage pair that share the same backend object.
413*c8dee2aaSAndroid Build Coastguard Worker // Mutation is accomplished by simply drawing to the SkSurface.
414*c8dee2aaSAndroid Build Coastguard Worker class SurfaceMutator : public Mutator {
415*c8dee2aaSAndroid Build Coastguard Worker public:
Make(skiatest::Reporter * reporter,Recorder * recorder,bool withMips)416*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<Mutator> Make(skiatest::Reporter* reporter,
417*c8dee2aaSAndroid Build Coastguard Worker Recorder* recorder,
418*c8dee2aaSAndroid Build Coastguard Worker bool withMips) {
419*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<SurfaceMutator>(reporter, recorder, withMips);
420*c8dee2aaSAndroid Build Coastguard Worker }
421*c8dee2aaSAndroid Build Coastguard Worker
SurfaceMutator(skiatest::Reporter * reporter,Recorder * recorder,bool withMips)422*c8dee2aaSAndroid Build Coastguard Worker SurfaceMutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
423*c8dee2aaSAndroid Build Coastguard Worker : Mutator(reporter, recorder, withMips) {
424*c8dee2aaSAndroid Build Coastguard Worker }
425*c8dee2aaSAndroid Build Coastguard Worker
init(const Caps *)426*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> init(const Caps* /* caps */) override {
427*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo ii = SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
428*c8dee2aaSAndroid Build Coastguard Worker
429*c8dee2aaSAndroid Build Coastguard Worker fMutatingSurface = SkSurfaces::RenderTarget(
430*c8dee2aaSAndroid Build Coastguard Worker fRecorder, ii, fWithMips ? Mipmapped::kYes : Mipmapped::kNo);
431*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fMutatingSurface);
432*c8dee2aaSAndroid Build Coastguard Worker
433*c8dee2aaSAndroid Build Coastguard Worker fMutatingSurface->getCanvas()->clear(kInitialColor);
434*c8dee2aaSAndroid Build Coastguard Worker
435*c8dee2aaSAndroid Build Coastguard Worker fMutatingImg = SkSurfaces::AsImage(fMutatingSurface);
436*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(fReporter, fMutatingImg);
437*c8dee2aaSAndroid Build Coastguard Worker
438*c8dee2aaSAndroid Build Coastguard Worker return fRecorder->snap();
439*c8dee2aaSAndroid Build Coastguard Worker }
440*c8dee2aaSAndroid Build Coastguard Worker
mutate(int mutationIndex)441*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> mutate(int mutationIndex) override {
442*c8dee2aaSAndroid Build Coastguard Worker fMutatingSurface->getCanvas()->clear(kMutationColors[mutationIndex]);
443*c8dee2aaSAndroid Build Coastguard Worker return fRecorder->snap();
444*c8dee2aaSAndroid Build Coastguard Worker }
445*c8dee2aaSAndroid Build Coastguard Worker
getCase() const446*c8dee2aaSAndroid Build Coastguard Worker int getCase() const override { return 3; }
447*c8dee2aaSAndroid Build Coastguard Worker
448*c8dee2aaSAndroid Build Coastguard Worker private:
449*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> fMutatingSurface;
450*c8dee2aaSAndroid Build Coastguard Worker };
451*c8dee2aaSAndroid Build Coastguard Worker
452*c8dee2aaSAndroid Build Coastguard Worker using MutatorFactoryT = std::unique_ptr<Mutator> (*)(skiatest::Reporter*, Recorder*, bool withMips);
453*c8dee2aaSAndroid Build Coastguard Worker
run_test(skiatest::Reporter * reporter,Context * context,bool useTwoRecorders,bool withMips,MutatorFactoryT createMutator)454*c8dee2aaSAndroid Build Coastguard Worker void run_test(skiatest::Reporter* reporter,
455*c8dee2aaSAndroid Build Coastguard Worker Context* context,
456*c8dee2aaSAndroid Build Coastguard Worker bool useTwoRecorders,
457*c8dee2aaSAndroid Build Coastguard Worker bool withMips,
458*c8dee2aaSAndroid Build Coastguard Worker MutatorFactoryT createMutator) {
459*c8dee2aaSAndroid Build Coastguard Worker const Caps* caps = context->priv().caps();
460*c8dee2aaSAndroid Build Coastguard Worker
461*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorders[2];
462*c8dee2aaSAndroid Build Coastguard Worker recorders[0] = context->makeRecorder();
463*c8dee2aaSAndroid Build Coastguard Worker
464*c8dee2aaSAndroid Build Coastguard Worker Recorder* mutatorRecorder = recorders[0].get();
465*c8dee2aaSAndroid Build Coastguard Worker Recorder* redrawerRecorder = recorders[0].get();
466*c8dee2aaSAndroid Build Coastguard Worker
467*c8dee2aaSAndroid Build Coastguard Worker if (useTwoRecorders) {
468*c8dee2aaSAndroid Build Coastguard Worker recorders[1] = context->makeRecorder();
469*c8dee2aaSAndroid Build Coastguard Worker redrawerRecorder = recorders[1].get();
470*c8dee2aaSAndroid Build Coastguard Worker }
471*c8dee2aaSAndroid Build Coastguard Worker
472*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Mutator> mutator = createMutator(reporter, mutatorRecorder, withMips);
473*c8dee2aaSAndroid Build Coastguard Worker
474*c8dee2aaSAndroid Build Coastguard Worker {
475*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> imgCreationRecording = mutator->init(caps);
476*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, context->insertRecording({ imgCreationRecording.get() }));
477*c8dee2aaSAndroid Build Coastguard Worker }
478*c8dee2aaSAndroid Build Coastguard Worker
479*c8dee2aaSAndroid Build Coastguard Worker {
480*c8dee2aaSAndroid Build Coastguard Worker Redrawer redrawer(reporter, redrawerRecorder);
481*c8dee2aaSAndroid Build Coastguard Worker
482*c8dee2aaSAndroid Build Coastguard Worker redrawer.init(mutator->getMutatingImage());
483*c8dee2aaSAndroid Build Coastguard Worker
484*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, context->insertRecording({ redrawer.imgDrawRecording() }));
485*c8dee2aaSAndroid Build Coastguard Worker redrawer.checkResult(context, mutator->getCase(),
486*c8dee2aaSAndroid Build Coastguard Worker useTwoRecorders, withMips, kInitialColor);
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumMutations; ++i) {
489*c8dee2aaSAndroid Build Coastguard Worker {
490*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> imgMutationRecording = mutator->mutate(i);
491*c8dee2aaSAndroid Build Coastguard Worker if (imgMutationRecording) {
492*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
493*c8dee2aaSAndroid Build Coastguard Worker context->insertRecording({imgMutationRecording.get()}));
494*c8dee2aaSAndroid Build Coastguard Worker }
495*c8dee2aaSAndroid Build Coastguard Worker }
496*c8dee2aaSAndroid Build Coastguard Worker
497*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, context->insertRecording({ redrawer.imgDrawRecording() }));
498*c8dee2aaSAndroid Build Coastguard Worker redrawer.checkResult(context, mutator->getCase(),
499*c8dee2aaSAndroid Build Coastguard Worker useTwoRecorders, withMips, kMutationColors[i]);
500*c8dee2aaSAndroid Build Coastguard Worker }
501*c8dee2aaSAndroid Build Coastguard Worker }
502*c8dee2aaSAndroid Build Coastguard Worker }
503*c8dee2aaSAndroid Build Coastguard Worker
504*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
505*c8dee2aaSAndroid Build Coastguard Worker
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(MutableImagesTest,reporter,context,CtsEnforcement::kApiLevel_V)506*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(MutableImagesTest, reporter, context,
507*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
508*c8dee2aaSAndroid Build Coastguard Worker
509*c8dee2aaSAndroid Build Coastguard Worker for (bool useTwoRecorders : { false, true }) {
510*c8dee2aaSAndroid Build Coastguard Worker for (bool withMips : { false, true }) {
511*c8dee2aaSAndroid Build Coastguard Worker // case 1 (AHBs)
512*c8dee2aaSAndroid Build Coastguard Worker run_test(reporter, context, useTwoRecorders, withMips,
513*c8dee2aaSAndroid Build Coastguard Worker UpdateBackendTextureMutator::Make);
514*c8dee2aaSAndroid Build Coastguard Worker
515*c8dee2aaSAndroid Build Coastguard Worker // case 2 (Volatile Promise Images)
516*c8dee2aaSAndroid Build Coastguard Worker run_test(reporter, context, useTwoRecorders, withMips,
517*c8dee2aaSAndroid Build Coastguard Worker VolatilePromiseImageMutator::Make);
518*c8dee2aaSAndroid Build Coastguard Worker
519*c8dee2aaSAndroid Build Coastguard Worker // case 3 (Surface/Image pair)
520*c8dee2aaSAndroid Build Coastguard Worker if (!withMips) {
521*c8dee2aaSAndroid Build Coastguard Worker // TODO: allow the mipmapped version when we can automatically regenerate mipmaps
522*c8dee2aaSAndroid Build Coastguard Worker run_test(reporter, context, useTwoRecorders, withMips,
523*c8dee2aaSAndroid Build Coastguard Worker SurfaceMutator::Make);
524*c8dee2aaSAndroid Build Coastguard Worker }
525*c8dee2aaSAndroid Build Coastguard Worker }
526*c8dee2aaSAndroid Build Coastguard Worker }
527*c8dee2aaSAndroid Build Coastguard Worker }
528