Coverage Report

Created: 2024-05-20 07:14

/src/skia/tools/gpu/YUVUtils.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2019 Google Inc.
3
 *
4
 * Use of this source code is governed by a BSD-style license that can be
5
 * found in the LICENSE file.
6
 */
7
8
#include "tools/gpu/YUVUtils.h"
9
10
#include "include/core/SkBitmap.h"
11
#include "include/core/SkCanvas.h"
12
#include "include/core/SkColorFilter.h"
13
#include "include/core/SkColorPriv.h"
14
#include "include/core/SkData.h"
15
#include "include/core/SkSurface.h"
16
#include "include/gpu/GrRecordingContext.h"
17
#include "include/gpu/GrYUVABackendTextures.h"
18
#include "include/gpu/ganesh/SkImageGanesh.h"
19
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
20
#include "src/codec/SkCodecImageGenerator.h"
21
#include "src/core/SkYUVAInfoLocation.h"
22
#include "src/core/SkYUVMath.h"
23
#include "src/gpu/ganesh/GrDirectContextPriv.h"
24
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
25
#include "src/image/SkImage_Base.h"
26
#include "tools/gpu/ManagedBackendTexture.h"
27
28
#ifdef SK_GRAPHITE
29
#include "include/gpu/graphite/Image.h"
30
#include "include/gpu/graphite/YUVABackendTextures.h"
31
#include "include/private/base/SkTArray.h"
32
#include "src/core/SkAutoPixmapStorage.h"
33
#endif
34
35
namespace {
36
37
0
static SkPMColor convert_yuva_to_rgba(const float mtx[20], uint8_t yuva[4]) {
38
0
    uint8_t y = yuva[0];
39
0
    uint8_t u = yuva[1];
40
0
    uint8_t v = yuva[2];
41
0
    uint8_t a = yuva[3];
42
43
0
    uint8_t r = SkTPin(SkScalarRoundToInt(mtx[ 0]*y + mtx[ 1]*u + mtx[ 2]*v + mtx[ 4]*255), 0, 255);
44
0
    uint8_t g = SkTPin(SkScalarRoundToInt(mtx[ 5]*y + mtx[ 6]*u + mtx[ 7]*v + mtx[ 9]*255), 0, 255);
45
0
    uint8_t b = SkTPin(SkScalarRoundToInt(mtx[10]*y + mtx[11]*u + mtx[12]*v + mtx[14]*255), 0, 255);
46
47
0
    return SkPremultiplyARGBInline(a, r, g, b);
48
0
}
49
50
0
static uint8_t look_up(SkPoint normPt, const SkPixmap& pmap, SkColorChannel channel) {
51
0
    SkASSERT(normPt.x() > 0 && normPt.x() < 1.0f);
52
0
    SkASSERT(normPt.y() > 0 && normPt.y() < 1.0f);
53
0
    int x = SkScalarFloorToInt(normPt.x() * pmap.width());
54
0
    int y = SkScalarFloorToInt(normPt.y() * pmap.height());
55
56
0
    auto ii = pmap.info().makeColorType(kRGBA_8888_SkColorType).makeWH(1, 1);
57
0
    uint32_t pixel;
58
0
    SkAssertResult(pmap.readPixels(ii, &pixel, sizeof(pixel), x, y));
59
0
    int shift = static_cast<int>(channel) * 8;
60
0
    return static_cast<uint8_t>((pixel >> shift) & 0xff);
61
0
}
Unexecuted instantiation: YUVUtils.cpp:(anonymous namespace)::look_up(SkPoint, SkPixmap const&, SkColorChannel)
Unexecuted instantiation: YUVUtils.cpp:(anonymous namespace)::look_up(SkPoint, SkPixmap const&, SkColorChannel)
62
63
class Generator : public SkImageGenerator {
64
public:
65
    Generator(SkYUVAPixmaps pixmaps, sk_sp<SkColorSpace> cs)
66
            : SkImageGenerator(SkImageInfo::Make(pixmaps.yuvaInfo().dimensions(),
67
                                                 kN32_SkColorType,
68
                                                 kPremul_SkAlphaType,
69
                                                 std::move(cs)))
70
0
            , fPixmaps(std::move(pixmaps)) {}
71
72
protected:
73
    bool onGetPixels(const SkImageInfo& info,
74
                     void* pixels,
75
                     size_t rowBytes,
76
0
                     const Options&) override {
77
0
        if (kUnknown_SkColorType == fFlattened.colorType()) {
78
0
            fFlattened.allocPixels(info);
79
0
            SkASSERT(info == this->getInfo());
80
81
0
            float mtx[20];
82
0
            SkColorMatrix_YUV2RGB(fPixmaps.yuvaInfo().yuvColorSpace(), mtx);
83
0
            SkYUVAInfo::YUVALocations yuvaLocations = fPixmaps.toYUVALocations();
84
0
            SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(yuvaLocations));
85
86
0
            SkMatrix om = fPixmaps.yuvaInfo().originMatrix();
87
0
            SkAssertResult(om.invert(&om));
88
0
            float normX = 1.f/info.width();
89
0
            float normY = 1.f/info.height();
90
0
            if (SkEncodedOriginSwapsWidthHeight(fPixmaps.yuvaInfo().origin())) {
91
0
                using std::swap;
92
0
                swap(normX, normY);
93
0
            }
94
0
            for (int y = 0; y < info.height(); ++y) {
95
0
                for (int x = 0; x < info.width(); ++x) {
96
0
                    SkPoint xy1 {(x + 0.5f),
97
0
                                 (y + 0.5f)};
98
0
                    xy1 = om.mapPoint(xy1);
99
0
                    xy1.fX *= normX;
100
0
                    xy1.fY *= normY;
101
102
0
                    uint8_t yuva[4] = {0, 0, 0, 255};
103
104
0
                    for (auto c : {SkYUVAInfo::YUVAChannels::kY,
105
0
                                   SkYUVAInfo::YUVAChannels::kU,
106
0
                                   SkYUVAInfo::YUVAChannels::kV}) {
107
0
                        const auto& pmap = fPixmaps.plane(yuvaLocations[c].fPlane);
108
0
                        yuva[c] = look_up(xy1, pmap, yuvaLocations[c].fChannel);
109
0
                    }
110
0
                    auto [aPlane, aChan] = yuvaLocations[SkYUVAInfo::YUVAChannels::kA];
111
0
                    if (aPlane >= 0) {
112
0
                        const auto& pmap = fPixmaps.plane(aPlane);
113
0
                        yuva[3] = look_up(xy1, pmap, aChan);
114
0
                    }
115
116
                    // Making premul here.
117
0
                    *fFlattened.getAddr32(x, y) = convert_yuva_to_rgba(mtx, yuva);
118
0
                }
119
0
            }
120
0
        }
121
122
0
        return fFlattened.readPixels(info, pixels, rowBytes, 0, 0);
123
0
    }
Unexecuted instantiation: YUVUtils.cpp:(anonymous namespace)::Generator::onGetPixels(SkImageInfo const&, void*, unsigned long, SkImageGenerator::Options const&)
Unexecuted instantiation: YUVUtils.cpp:(anonymous namespace)::Generator::onGetPixels(SkImageInfo const&, void*, unsigned long, SkImageGenerator::Options const&)
124
125
    bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& types,
126
0
                         SkYUVAPixmapInfo* info) const override {
127
0
        *info = fPixmaps.pixmapsInfo();
128
0
        return info->isValid();
129
0
    }
130
131
0
    bool onGetYUVAPlanes(const SkYUVAPixmaps& pixmaps) override {
132
0
        SkASSERT(pixmaps.yuvaInfo() == fPixmaps.yuvaInfo());
133
0
        for (int i = 0; i < pixmaps.numPlanes(); ++i) {
134
0
            SkASSERT(fPixmaps.plane(i).colorType() == pixmaps.plane(i).colorType());
135
0
            SkASSERT(fPixmaps.plane(i).dimensions() == pixmaps.plane(i).dimensions());
136
0
            SkASSERT(fPixmaps.plane(i).rowBytes() == pixmaps.plane(i).rowBytes());
137
0
            fPixmaps.plane(i).readPixels(pixmaps.plane(i));
138
0
        }
139
0
        return true;
140
0
    }
Unexecuted instantiation: YUVUtils.cpp:(anonymous namespace)::Generator::onGetYUVAPlanes(SkYUVAPixmaps const&)
Unexecuted instantiation: YUVUtils.cpp:(anonymous namespace)::Generator::onGetYUVAPlanes(SkYUVAPixmaps const&)
141
142
private:
143
    SkYUVAPixmaps fPixmaps;
144
    SkBitmap      fFlattened;
145
};
146
147
}  // anonymous namespace
148
149
namespace sk_gpu_test {
150
151
std::tuple<std::array<sk_sp<SkImage>, SkYUVAInfo::kMaxPlanes>, SkYUVAInfo>
152
MakeYUVAPlanesAsA8(SkImage* src,
153
                   SkYUVColorSpace cs,
154
                   SkYUVAInfo::Subsampling ss,
155
0
                   GrRecordingContext* rContext) {
156
0
    float rgbToYUV[20];
157
0
    SkColorMatrix_RGB2YUV(cs, rgbToYUV);
158
159
0
    SkYUVAInfo::PlaneConfig config = src->isOpaque() ? SkYUVAInfo::PlaneConfig::kY_U_V
160
0
                                                     : SkYUVAInfo::PlaneConfig::kY_U_V_A;
161
0
    SkISize dims[SkYUVAInfo::kMaxPlanes];
162
0
    int n = SkYUVAInfo::PlaneDimensions(src->dimensions(),
163
0
                                        config,
164
0
                                        ss,
165
0
                                        kTopLeft_SkEncodedOrigin,
166
0
                                        dims);
167
0
    std::array<sk_sp<SkImage>, 4> planes;
168
0
    for (int i = 0; i < n; ++i) {
169
0
        SkImageInfo info = SkImageInfo::MakeA8(dims[i]);
170
0
        sk_sp<SkSurface> surf;
171
0
        if (rContext) {
172
0
            surf = SkSurfaces::RenderTarget(rContext, skgpu::Budgeted::kYes, info, 1, nullptr);
173
0
        } else {
174
0
            surf = SkSurfaces::Raster(info);
175
0
        }
176
0
        if (!surf) {
177
0
            return {};
178
0
        }
179
180
0
        SkPaint paint;
181
0
        paint.setBlendMode(SkBlendMode::kSrc);
182
183
        // Make a matrix with the ith row of rgbToYUV copied to the A row since we're drawing to A8.
184
0
        float m[20] = {};
185
0
        std::copy_n(rgbToYUV + 5*i, 5, m + 15);
186
0
        paint.setColorFilter(SkColorFilters::Matrix(m));
187
0
        surf->getCanvas()->drawImageRect(src,
188
0
                                         SkRect::Make(dims[i]),
189
0
                                         SkSamplingOptions(SkFilterMode::kLinear),
190
0
                                         &paint);
191
0
        planes[i] = surf->makeImageSnapshot();
192
0
        if (!planes[i]) {
193
0
            return {};
194
0
        }
195
0
    }
196
0
    SkYUVAInfo info(src->dimensions(), config, ss, cs);
197
0
    return {planes, info};
198
0
}
199
200
std::unique_ptr<LazyYUVImage> LazyYUVImage::Make(sk_sp<SkData> data,
201
                                                 skgpu::Mipmapped mipmapped,
202
0
                                                 sk_sp<SkColorSpace> cs) {
203
0
    std::unique_ptr<LazyYUVImage> image(new LazyYUVImage());
204
0
    if (image->reset(std::move(data), mipmapped, std::move(cs))) {
205
0
        return image;
206
0
    } else {
207
0
        return nullptr;
208
0
    }
209
0
}
210
211
std::unique_ptr<LazyYUVImage> LazyYUVImage::Make(SkYUVAPixmaps pixmaps,
212
                                                 skgpu::Mipmapped mipmapped,
213
0
                                                 sk_sp<SkColorSpace> cs) {
214
0
    std::unique_ptr<LazyYUVImage> image(new LazyYUVImage());
215
0
    if (image->reset(std::move(pixmaps), mipmapped, std::move(cs))) {
216
0
        return image;
217
0
    } else {
218
0
        return nullptr;
219
0
    }
220
0
}
221
222
0
sk_sp<SkImage> LazyYUVImage::refImage(GrRecordingContext* rContext, Type type) {
223
0
    if (this->ensureYUVImage(rContext, type)) {
224
0
        size_t idx = static_cast<size_t>(type);
225
0
        SkASSERT(idx < std::size(fYUVImage));
226
0
        return fYUVImage[idx];
227
0
    } else {
228
0
        return nullptr;
229
0
    }
230
0
}
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::refImage(GrRecordingContext*, sk_gpu_test::LazyYUVImage::Type)
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::refImage(GrRecordingContext*, sk_gpu_test::LazyYUVImage::Type)
231
232
#if defined(SK_GRAPHITE)
233
0
sk_sp<SkImage> LazyYUVImage::refImage(skgpu::graphite::Recorder* recorder, Type type) {
234
0
    if (this->ensureYUVImage(recorder, type)) {
235
0
        size_t idx = static_cast<size_t>(type);
236
0
        SkASSERT(idx < std::size(fYUVImage));
237
0
        return fYUVImage[idx];
238
0
    } else {
239
0
        return nullptr;
240
0
    }
241
0
}
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::refImage(skgpu::graphite::Recorder*, sk_gpu_test::LazyYUVImage::Type)
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::refImage(skgpu::graphite::Recorder*, sk_gpu_test::LazyYUVImage::Type)
242
#endif
243
244
0
bool LazyYUVImage::reset(sk_sp<SkData> data, skgpu::Mipmapped mipmapped, sk_sp<SkColorSpace> cs) {
245
0
    fMipmapped = mipmapped;
246
0
    auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(data);
247
0
    if (!codec) {
248
0
        return false;
249
0
    }
250
251
0
    SkYUVAPixmapInfo yuvaPixmapInfo;
252
0
    if (!codec->queryYUVAInfo(SkYUVAPixmapInfo::SupportedDataTypes::All(), &yuvaPixmapInfo)) {
253
0
        return false;
254
0
    }
255
0
    fPixmaps = SkYUVAPixmaps::Allocate(yuvaPixmapInfo);
256
0
    if (!fPixmaps.isValid()) {
257
0
        return false;
258
0
    }
259
260
0
    if (!codec->getYUVAPlanes(fPixmaps)) {
261
0
        return false;
262
0
    }
263
264
0
    fColorSpace = std::move(cs);
265
266
    // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
267
0
    return true;
268
0
}
269
270
bool LazyYUVImage::reset(SkYUVAPixmaps pixmaps,
271
                         skgpu::Mipmapped mipmapped,
272
0
                         sk_sp<SkColorSpace> cs) {
273
0
    if (!pixmaps.isValid()) {
274
0
        return false;
275
0
    }
276
0
    fMipmapped = mipmapped;
277
0
    if (pixmaps.ownsStorage()) {
278
0
        fPixmaps = std::move(pixmaps);
279
0
    } else {
280
0
        fPixmaps = SkYUVAPixmaps::MakeCopy(std::move(pixmaps));
281
0
    }
282
0
    fColorSpace = std::move(cs);
283
    // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
284
0
    return true;
285
0
}
286
287
0
bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext, Type type) {
288
0
    size_t idx = static_cast<size_t>(type);
289
0
    SkASSERT(idx < std::size(fYUVImage));
290
0
    if (fYUVImage[idx] && fYUVImage[idx]->isValid(rContext)) {
291
0
        return true;  // Have already made a YUV image valid for this context.
292
0
    }
293
    // Try to make a new YUV image for this context.
294
0
    switch (type) {
295
0
        case Type::kFromPixmaps:
296
0
            if (!rContext || rContext->abandoned()) {
297
0
                return false;
298
0
            }
299
0
            fYUVImage[idx] = SkImages::TextureFromYUVAPixmaps(rContext,
300
0
                                                              fPixmaps,
301
0
                                                              fMipmapped,
302
0
                                                              /*limit to max tex size*/ false,
303
0
                                                              fColorSpace);
304
0
            break;
305
0
        case Type::kFromGenerator: {
306
            // Make sure the generator has ownership of its backing planes.
307
0
            auto generator = std::make_unique<Generator>(fPixmaps, fColorSpace);
308
0
            fYUVImage[idx] = SkImages::DeferredFromGenerator(std::move(generator));
309
0
            break;
310
0
        }
311
0
        case Type::kFromTextures:
312
0
            if (!rContext || rContext->abandoned()) {
313
0
                return false;
314
0
            }
315
0
            if (auto direct = rContext->asDirectContext()) {
316
0
                sk_sp<sk_gpu_test::ManagedBackendTexture> mbets[SkYUVAInfo::kMaxPlanes];
317
0
                GrBackendTexture textures[SkYUVAInfo::kMaxPlanes];
318
0
                for (int i = 0; i < fPixmaps.numPlanes(); ++i) {
319
0
                    mbets[i] = sk_gpu_test::ManagedBackendTexture::MakeFromPixmap(
320
0
                            direct,
321
0
                            fPixmaps.plane(i),
322
0
                            fMipmapped,
323
0
                            skgpu::Renderable::kNo,
324
0
                            skgpu::Protected::kNo);
325
0
                    if (mbets[i]) {
326
0
                        textures[i] = mbets[i]->texture();
327
0
                    } else {
328
0
                        return false;
329
0
                    }
330
0
                }
331
0
                GrYUVABackendTextures yuvaTextures(fPixmaps.yuvaInfo(),
332
0
                                                   textures,
333
0
                                                   kTopLeft_GrSurfaceOrigin);
334
0
                if (!yuvaTextures.isValid()) {
335
0
                    return false;
336
0
                }
337
0
                void* planeRelContext =
338
0
                        sk_gpu_test::ManagedBackendTexture::MakeYUVAReleaseContext(mbets);
339
0
                fYUVImage[idx] = SkImages::TextureFromYUVATextures(
340
0
                        direct,
341
0
                        yuvaTextures,
342
0
                        fColorSpace,
343
0
                        sk_gpu_test::ManagedBackendTexture::ReleaseProc,
344
0
                        planeRelContext);
345
0
            }
346
0
            break;
347
0
        case Type::kFromImages:
348
            // Not supported in Ganesh
349
0
            return false;
350
0
    }
351
0
    return fYUVImage[idx] != nullptr;
352
0
}
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::ensureYUVImage(GrRecordingContext*, sk_gpu_test::LazyYUVImage::Type)
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::ensureYUVImage(GrRecordingContext*, sk_gpu_test::LazyYUVImage::Type)
353
354
#if defined(SK_GRAPHITE)
355
using BackendTexture = skgpu::graphite::BackendTexture;
356
using Recorder = skgpu::graphite::Recorder;
357
using YUVABackendTextures = skgpu::graphite::YUVABackendTextures;
358
359
0
bool LazyYUVImage::ensureYUVImage(Recorder* recorder, Type type) {
360
0
    size_t idx = static_cast<size_t>(type);
361
0
    SkASSERT(idx < std::size(fYUVImage));
362
0
    if (fYUVImage[idx] && as_IB(fYUVImage[idx])->isGraphiteBacked()) {
363
0
        return true;  // Have already made a YUV image suitable for Graphite.
364
0
    }
365
    // Try to make a new Graphite YUV image
366
0
    switch (type) {
367
0
        case Type::kFromPixmaps:
368
0
            if (!recorder) {
369
0
                return false;
370
0
            }
371
0
            fYUVImage[idx] =
372
0
                    SkImages::TextureFromYUVAPixmaps(recorder,
373
0
                                                     fPixmaps,
374
0
                                                     {fMipmapped == skgpu::Mipmapped::kYes},
375
0
                                                     /*limitToMaxTextureSize=*/false,
376
0
                                                     fColorSpace);
377
0
            break;
378
0
        case Type::kFromGenerator: {
379
            // Make sure the generator has ownership of its backing planes.
380
0
            auto generator = std::make_unique<Generator>(fPixmaps, fColorSpace);
381
0
            fYUVImage[idx] = SkImages::DeferredFromGenerator(std::move(generator));
382
0
            break;
383
0
        }
384
0
        case Type::kFromTextures: {
385
0
            if (!recorder) {
386
0
                return false;
387
0
            }
388
389
0
            sk_sp<sk_gpu_test::ManagedGraphiteTexture> mbets[SkYUVAInfo::kMaxPlanes];
390
0
            BackendTexture textures[SkYUVAInfo::kMaxPlanes];
391
0
            for (int i = 0; i < fPixmaps.numPlanes(); ++i) {
392
                // MakeFromPixmap will handle generating the upper mipmap levels if necessary.
393
0
                mbets[i] = sk_gpu_test::ManagedGraphiteTexture::MakeFromPixmap(
394
0
                        recorder,
395
0
                        fPixmaps.plane(i),
396
0
                        fMipmapped,
397
0
                        skgpu::Renderable::kNo,
398
0
                        skgpu::Protected::kNo);
399
0
                if (mbets[i]) {
400
0
                    textures[i] = mbets[i]->texture();
401
0
                } else {
402
0
                    return false;
403
0
                }
404
0
            }
405
0
            YUVABackendTextures yuvaTextures(recorder,
406
0
                                             fPixmaps.yuvaInfo(),
407
0
                                             textures);
408
0
            if (!yuvaTextures.isValid()) {
409
0
                return false;
410
0
            }
411
0
            void* imageRelContext =
412
0
                    sk_gpu_test::ManagedGraphiteTexture::MakeYUVAReleaseContext(mbets);
413
0
            fYUVImage[idx] = SkImages::TextureFromYUVATextures(
414
0
                    recorder,
415
0
                    yuvaTextures,
416
0
                    fColorSpace,
417
0
                    sk_gpu_test::ManagedGraphiteTexture::ImageReleaseProc,
418
0
                    imageRelContext);
419
0
            break;
420
0
        }
421
0
        case Type::kFromImages: {
422
0
            if (!recorder) {
423
0
                return false;
424
0
            }
425
426
0
            sk_sp<SkImage> planeImgs[SkYUVAInfo::kMaxPlanes];
427
428
0
            using SkImages::GenerateMipmapsFromBase;
429
0
            GenerateMipmapsFromBase genMipmaps = GenerateMipmapsFromBase::kNo;
430
0
            if (fMipmapped == skgpu::Mipmapped::kYes) {
431
0
                genMipmaps = GenerateMipmapsFromBase::kYes;
432
0
            }
433
434
0
            for (int i = 0; i < fPixmaps.numPlanes(); ++i) {
435
0
                const auto& plane = fPixmaps.plane(i);
436
0
                sk_sp<ManagedGraphiteTexture> mbet;
437
0
                if (fMipmapped == skgpu::Mipmapped::kYes) {
438
0
                    mbet = ManagedGraphiteTexture::MakeUnInit(recorder,
439
0
                                                              plane.info(),
440
0
                                                              skgpu::Mipmapped::kYes,
441
0
                                                              skgpu::Renderable::kNo);
442
                    // We allocate a full mip set because updateBackendTexture requires it. However,
443
                    // the non-base levels are cleared to red. We rely on SkImages::WrapTexture
444
                    // to actually generate the contents from the base level for each plane on the
445
                    // GPU. This exercises the case where the client wants a mipmapped YUV image but
446
                    // only provides the base level contents.
447
0
                    int levelCnt = SkMipmap::ComputeLevelCount(plane.dimensions());
448
0
                    skia_private::TArray<SkAutoPixmapStorage> levelStorage(levelCnt);
449
0
                    skia_private::TArray<SkPixmap> levels(levelCnt + 1);
450
0
                    levels.push_back(plane);
451
0
                    for (int l = 0; l < levelCnt; ++l) {
452
0
                        SkISize dims = SkMipmap::ComputeLevelSize(plane.dimensions(), l);
453
0
                        SkAutoPixmapStorage level;
454
0
                        level.alloc(plane.info().makeDimensions(dims));
455
0
                        level.erase(SK_ColorRED);
456
0
                        levels.push_back(level);
457
0
                        levelStorage.push_back(std::move(level));
458
0
                    }
459
0
                    if (!mbet || !recorder->updateBackendTexture(mbet->texture(),
460
0
                                                                 levels.data(),
461
0
                                                                 levels.size())) {
462
0
                        return false;
463
0
                    }
464
0
                } else {
465
0
                    mbet = ManagedGraphiteTexture::MakeFromPixmap(recorder,
466
0
                                                                  plane,
467
0
                                                                  skgpu::Mipmapped::kNo,
468
0
                                                                  skgpu::Renderable::kNo);
469
0
                    if (!mbet) {
470
0
                        return false;
471
0
                    }
472
0
                }
473
0
                planeImgs[i] = SkImages::WrapTexture(recorder,
474
0
                                                     mbet->texture(),
475
0
                                                     plane.colorType(),
476
0
                                                     plane.alphaType(),
477
0
                                                     fColorSpace,
478
0
                                                     skgpu::Origin::kTopLeft,
479
0
                                                     genMipmaps,
480
0
                                                     ManagedGraphiteTexture::ImageReleaseProc,
481
0
                                                     mbet->releaseContext());
482
0
            }
483
484
0
            fYUVImage[idx] = SkImages::TextureFromYUVAImages(
485
0
                    recorder,
486
0
                    fPixmaps.yuvaInfo(),
487
0
                    planeImgs,
488
0
                    fColorSpace);
489
0
            break;
490
0
        }
491
0
    }
492
0
    return fYUVImage[idx] != nullptr;
493
0
}
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::ensureYUVImage(skgpu::graphite::Recorder*, sk_gpu_test::LazyYUVImage::Type)
Unexecuted instantiation: sk_gpu_test::LazyYUVImage::ensureYUVImage(skgpu::graphite::Recorder*, sk_gpu_test::LazyYUVImage::Type)
494
#endif
495
496
} // namespace sk_gpu_test