xref: /aosp_15_r20/external/skia/tests/graphite/MutableImagesTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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