1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkYUVAPixmaps.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/private/SkImageInfoPriv.h"
11cb93a386Sopenharmony_ci#include "src/core/SkConvertPixels.h"
12cb93a386Sopenharmony_ci#include "src/core/SkYUVAInfoLocation.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU
15cb93a386Sopenharmony_ci#include "include/private/GrImageContext.h"
16cb93a386Sopenharmony_ci#endif
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ciSkYUVAPixmapInfo::SupportedDataTypes::SupportedDataTypes(const GrImageContext& context) {
20cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU
21cb93a386Sopenharmony_ci    for (int n = 1; n <= 4; ++n) {
22cb93a386Sopenharmony_ci        if (context.defaultBackendFormat(DefaultColorTypeForDataType(DataType::kUnorm8, n),
23cb93a386Sopenharmony_ci                                         GrRenderable::kNo).isValid()) {
24cb93a386Sopenharmony_ci            this->enableDataType(DataType::kUnorm8, n);
25cb93a386Sopenharmony_ci        }
26cb93a386Sopenharmony_ci        if (context.defaultBackendFormat(DefaultColorTypeForDataType(DataType::kUnorm16, n),
27cb93a386Sopenharmony_ci                                         GrRenderable::kNo).isValid()) {
28cb93a386Sopenharmony_ci            this->enableDataType(DataType::kUnorm16, n);
29cb93a386Sopenharmony_ci        }
30cb93a386Sopenharmony_ci        if (context.defaultBackendFormat(DefaultColorTypeForDataType(DataType::kFloat16, n),
31cb93a386Sopenharmony_ci                                         GrRenderable::kNo).isValid()) {
32cb93a386Sopenharmony_ci            this->enableDataType(DataType::kFloat16, n);
33cb93a386Sopenharmony_ci        }
34cb93a386Sopenharmony_ci        if (context.defaultBackendFormat(DefaultColorTypeForDataType(DataType::kUnorm10_Unorm2, n),
35cb93a386Sopenharmony_ci                                         GrRenderable::kNo).isValid()) {
36cb93a386Sopenharmony_ci            this->enableDataType(DataType::kUnorm10_Unorm2, n);
37cb93a386Sopenharmony_ci        }
38cb93a386Sopenharmony_ci    }
39cb93a386Sopenharmony_ci#endif
40cb93a386Sopenharmony_ci}
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_civoid SkYUVAPixmapInfo::SupportedDataTypes::enableDataType(DataType type, int numChannels) {
43cb93a386Sopenharmony_ci    if (numChannels < 1 || numChannels > 4) {
44cb93a386Sopenharmony_ci        return;
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci    fDataTypeSupport[static_cast<size_t>(type) + (numChannels - 1)*kDataTypeCnt] = true;
47cb93a386Sopenharmony_ci}
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_cistd::tuple<int, SkYUVAPixmapInfo::DataType> SkYUVAPixmapInfo::NumChannelsAndDataType(
52cb93a386Sopenharmony_ci        SkColorType ct) {
53cb93a386Sopenharmony_ci    // We could allow BGR[A] color types, but then we'd have to decide whether B should be the 0th
54cb93a386Sopenharmony_ci    // or 2nd channel. Our docs currently say channel order is always R=0, G=1, B=2[, A=3].
55cb93a386Sopenharmony_ci    switch (ct) {
56cb93a386Sopenharmony_ci        case kAlpha_8_SkColorType:
57cb93a386Sopenharmony_ci        case kGray_8_SkColorType:    return {1, DataType::kUnorm8 };
58cb93a386Sopenharmony_ci        case kA16_unorm_SkColorType: return {1, DataType::kUnorm16};
59cb93a386Sopenharmony_ci        case kA16_float_SkColorType: return {1, DataType::kFloat16};
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci        case kR8G8_unorm_SkColorType:   return {2, DataType::kUnorm8  };
62cb93a386Sopenharmony_ci        case kR16G16_unorm_SkColorType: return {2, DataType::kUnorm16 };
63cb93a386Sopenharmony_ci        case kR16G16_float_SkColorType: return {2, DataType::kFloat16 };
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci        case kRGB_888x_SkColorType:    return {3, DataType::kUnorm8          };
66cb93a386Sopenharmony_ci        case kRGB_101010x_SkColorType: return {3, DataType::kUnorm10_Unorm2  };
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci        case kRGBA_8888_SkColorType:          return {4, DataType::kUnorm8  };
69cb93a386Sopenharmony_ci        case kR16G16B16A16_unorm_SkColorType: return {4, DataType::kUnorm16 };
70cb93a386Sopenharmony_ci        case kRGBA_F16_SkColorType:           return {4, DataType::kFloat16 };
71cb93a386Sopenharmony_ci        case kRGBA_F16Norm_SkColorType:       return {4, DataType::kFloat16 };
72cb93a386Sopenharmony_ci        case kRGBA_1010102_SkColorType:       return {4, DataType::kUnorm10_Unorm2 };
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci        default: return {0, DataType::kUnorm8 };
75cb93a386Sopenharmony_ci    }
76cb93a386Sopenharmony_ci}
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ciSkYUVAPixmapInfo::SkYUVAPixmapInfo(const SkYUVAInfo& yuvaInfo,
79cb93a386Sopenharmony_ci                                   const SkColorType colorTypes[kMaxPlanes],
80cb93a386Sopenharmony_ci                                   const size_t rowBytes[kMaxPlanes])
81cb93a386Sopenharmony_ci        : fYUVAInfo(yuvaInfo) {
82cb93a386Sopenharmony_ci    if (!yuvaInfo.isValid()) {
83cb93a386Sopenharmony_ci        *this = {};
84cb93a386Sopenharmony_ci        SkASSERT(!this->isValid());
85cb93a386Sopenharmony_ci        return;
86cb93a386Sopenharmony_ci    }
87cb93a386Sopenharmony_ci    SkISize planeDimensions[4];
88cb93a386Sopenharmony_ci    int n = yuvaInfo.planeDimensions(planeDimensions);
89cb93a386Sopenharmony_ci    size_t tempRowBytes[kMaxPlanes];
90cb93a386Sopenharmony_ci    if (!rowBytes) {
91cb93a386Sopenharmony_ci        for (int i = 0; i < n; ++i) {
92cb93a386Sopenharmony_ci            tempRowBytes[i] = SkColorTypeBytesPerPixel(colorTypes[i]) * planeDimensions[i].width();
93cb93a386Sopenharmony_ci        }
94cb93a386Sopenharmony_ci        rowBytes = tempRowBytes;
95cb93a386Sopenharmony_ci    }
96cb93a386Sopenharmony_ci    bool ok = true;
97cb93a386Sopenharmony_ci    for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
98cb93a386Sopenharmony_ci        fRowBytes[i] = rowBytes[i];
99cb93a386Sopenharmony_ci        // Use kUnpremul so that we never multiply alpha when copying data in.
100cb93a386Sopenharmony_ci        fPlaneInfos[i] = SkImageInfo::Make(planeDimensions[i],
101cb93a386Sopenharmony_ci                                           colorTypes[i],
102cb93a386Sopenharmony_ci                                           kUnpremul_SkAlphaType);
103cb93a386Sopenharmony_ci        int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
104cb93a386Sopenharmony_ci        SkASSERT(numRequiredChannels > 0);
105cb93a386Sopenharmony_ci        auto [numColorTypeChannels, colorTypeDataType] = NumChannelsAndDataType(colorTypes[i]);
106cb93a386Sopenharmony_ci        ok &= i == 0 || colorTypeDataType == fDataType;
107cb93a386Sopenharmony_ci        ok &= numColorTypeChannels >= numRequiredChannels;
108cb93a386Sopenharmony_ci        ok &= fPlaneInfos[i].validRowBytes(fRowBytes[i]);
109cb93a386Sopenharmony_ci        fDataType = colorTypeDataType;
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci    if (!ok) {
112cb93a386Sopenharmony_ci        *this = {};
113cb93a386Sopenharmony_ci        SkASSERT(!this->isValid());
114cb93a386Sopenharmony_ci    } else {
115cb93a386Sopenharmony_ci        SkASSERT(this->isValid());
116cb93a386Sopenharmony_ci    }
117cb93a386Sopenharmony_ci}
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ciSkYUVAPixmapInfo::SkYUVAPixmapInfo(const SkYUVAInfo& yuvaInfo,
120cb93a386Sopenharmony_ci                                   DataType dataType,
121cb93a386Sopenharmony_ci                                   const size_t rowBytes[kMaxPlanes]) {
122cb93a386Sopenharmony_ci    SkColorType colorTypes[kMaxPlanes] = {};
123cb93a386Sopenharmony_ci    int numPlanes = yuvaInfo.numPlanes();
124cb93a386Sopenharmony_ci    for (int i = 0; i < numPlanes; ++i) {
125cb93a386Sopenharmony_ci        int numChannels = yuvaInfo.numChannelsInPlane(i);
126cb93a386Sopenharmony_ci        colorTypes[i] = DefaultColorTypeForDataType(dataType, numChannels);
127cb93a386Sopenharmony_ci    }
128cb93a386Sopenharmony_ci    *this = SkYUVAPixmapInfo(yuvaInfo, colorTypes, rowBytes);
129cb93a386Sopenharmony_ci}
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_cibool SkYUVAPixmapInfo::operator==(const SkYUVAPixmapInfo& that) const {
132cb93a386Sopenharmony_ci    bool result = fYUVAInfo   == that.fYUVAInfo   &&
133cb93a386Sopenharmony_ci                  fPlaneInfos == that.fPlaneInfos &&
134cb93a386Sopenharmony_ci                  fRowBytes   == that.fRowBytes;
135cb93a386Sopenharmony_ci    SkASSERT(!result || fDataType == that.fDataType);
136cb93a386Sopenharmony_ci    return result;
137cb93a386Sopenharmony_ci}
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_cisize_t SkYUVAPixmapInfo::computeTotalBytes(size_t planeSizes[kMaxPlanes]) const {
140cb93a386Sopenharmony_ci    if (!this->isValid()) {
141cb93a386Sopenharmony_ci        if (planeSizes) {
142cb93a386Sopenharmony_ci            std::fill_n(planeSizes, kMaxPlanes, 0);
143cb93a386Sopenharmony_ci        }
144cb93a386Sopenharmony_ci        return 0;
145cb93a386Sopenharmony_ci    }
146cb93a386Sopenharmony_ci    return fYUVAInfo.computeTotalBytes(fRowBytes.data(), planeSizes);
147cb93a386Sopenharmony_ci}
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_cibool SkYUVAPixmapInfo::initPixmapsFromSingleAllocation(void* memory,
150cb93a386Sopenharmony_ci                                                       SkPixmap pixmaps[kMaxPlanes]) const {
151cb93a386Sopenharmony_ci    if (!this->isValid()) {
152cb93a386Sopenharmony_ci        return false;
153cb93a386Sopenharmony_ci    }
154cb93a386Sopenharmony_ci    SkASSERT(pixmaps);
155cb93a386Sopenharmony_ci    char* addr = static_cast<char*>(memory);
156cb93a386Sopenharmony_ci    int n = this->numPlanes();
157cb93a386Sopenharmony_ci    for (int i = 0; i < n; ++i) {
158cb93a386Sopenharmony_ci        SkASSERT(fPlaneInfos[i].validRowBytes(fRowBytes[i]));
159cb93a386Sopenharmony_ci        pixmaps[i].reset(fPlaneInfos[i], addr, fRowBytes[i]);
160cb93a386Sopenharmony_ci        size_t planeSize = pixmaps[i].rowBytes()*pixmaps[i].height();
161cb93a386Sopenharmony_ci        SkASSERT(planeSize);
162cb93a386Sopenharmony_ci        addr += planeSize;
163cb93a386Sopenharmony_ci    }
164cb93a386Sopenharmony_ci    for (int i = n; i < kMaxPlanes; ++i) {
165cb93a386Sopenharmony_ci        pixmaps[i] = {};
166cb93a386Sopenharmony_ci    }
167cb93a386Sopenharmony_ci    return true;
168cb93a386Sopenharmony_ci}
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_cibool SkYUVAPixmapInfo::isSupported(const SupportedDataTypes& supportedDataTypes) const {
171cb93a386Sopenharmony_ci    if (!this->isValid()) {
172cb93a386Sopenharmony_ci        return false;
173cb93a386Sopenharmony_ci    }
174cb93a386Sopenharmony_ci    return supportedDataTypes.supported(fYUVAInfo.planeConfig(), fDataType);
175cb93a386Sopenharmony_ci}
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ciSkColorType SkYUVAPixmaps::RecommendedRGBAColorType(DataType dataType) {
180cb93a386Sopenharmony_ci    switch (dataType) {
181cb93a386Sopenharmony_ci        case DataType::kUnorm8:         return kRGBA_8888_SkColorType;
182cb93a386Sopenharmony_ci        // F16 has better GPU support than 16 bit unorm. Often "16" bit unorm values are actually
183cb93a386Sopenharmony_ci        // lower precision.
184cb93a386Sopenharmony_ci        case DataType::kUnorm16:        return kRGBA_F16_SkColorType;
185cb93a386Sopenharmony_ci        case DataType::kFloat16:        return kRGBA_F16_SkColorType;
186cb93a386Sopenharmony_ci        case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
187cb93a386Sopenharmony_ci    }
188cb93a386Sopenharmony_ci    SkUNREACHABLE;
189cb93a386Sopenharmony_ci}
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ciSkYUVAPixmaps SkYUVAPixmaps::Allocate(const SkYUVAPixmapInfo& yuvaPixmapInfo) {
192cb93a386Sopenharmony_ci    if (!yuvaPixmapInfo.isValid()) {
193cb93a386Sopenharmony_ci        return {};
194cb93a386Sopenharmony_ci    }
195cb93a386Sopenharmony_ci    return SkYUVAPixmaps(yuvaPixmapInfo,
196cb93a386Sopenharmony_ci                         SkData::MakeUninitialized(yuvaPixmapInfo.computeTotalBytes()));
197cb93a386Sopenharmony_ci}
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ciSkYUVAPixmaps SkYUVAPixmaps::FromData(const SkYUVAPixmapInfo& yuvaPixmapInfo, sk_sp<SkData> data) {
200cb93a386Sopenharmony_ci    if (!yuvaPixmapInfo.isValid()) {
201cb93a386Sopenharmony_ci        return {};
202cb93a386Sopenharmony_ci    }
203cb93a386Sopenharmony_ci    if (yuvaPixmapInfo.computeTotalBytes() > data->size()) {
204cb93a386Sopenharmony_ci        return {};
205cb93a386Sopenharmony_ci    }
206cb93a386Sopenharmony_ci    return SkYUVAPixmaps(yuvaPixmapInfo, std::move(data));
207cb93a386Sopenharmony_ci}
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ciSkYUVAPixmaps SkYUVAPixmaps::MakeCopy(const SkYUVAPixmaps& src) {
210cb93a386Sopenharmony_ci    if (!src.isValid()) {
211cb93a386Sopenharmony_ci        return {};
212cb93a386Sopenharmony_ci    }
213cb93a386Sopenharmony_ci    SkYUVAPixmaps result = Allocate(src.pixmapsInfo());
214cb93a386Sopenharmony_ci    int n = result.numPlanes();
215cb93a386Sopenharmony_ci    for (int i = 0; i < n; ++i) {
216cb93a386Sopenharmony_ci        // We use SkRectMemCpy rather than readPixels to ensure that we don't do any alpha type
217cb93a386Sopenharmony_ci        // conversion.
218cb93a386Sopenharmony_ci        const SkPixmap& s = src.plane(i);
219cb93a386Sopenharmony_ci        const SkPixmap& d = result.plane(i);
220cb93a386Sopenharmony_ci        SkRectMemcpy(d.writable_addr(),
221cb93a386Sopenharmony_ci                     d.rowBytes(),
222cb93a386Sopenharmony_ci                     s.addr(),
223cb93a386Sopenharmony_ci                     s.rowBytes(),
224cb93a386Sopenharmony_ci                     s.info().minRowBytes(),
225cb93a386Sopenharmony_ci                     s.height());
226cb93a386Sopenharmony_ci    }
227cb93a386Sopenharmony_ci    return result;
228cb93a386Sopenharmony_ci}
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ciSkYUVAPixmaps SkYUVAPixmaps::FromExternalMemory(const SkYUVAPixmapInfo& yuvaPixmapInfo,
231cb93a386Sopenharmony_ci                                                void* memory) {
232cb93a386Sopenharmony_ci    if (!yuvaPixmapInfo.isValid()) {
233cb93a386Sopenharmony_ci        return {};
234cb93a386Sopenharmony_ci    }
235cb93a386Sopenharmony_ci    SkPixmap pixmaps[kMaxPlanes];
236cb93a386Sopenharmony_ci    yuvaPixmapInfo.initPixmapsFromSingleAllocation(memory, pixmaps);
237cb93a386Sopenharmony_ci    return SkYUVAPixmaps(yuvaPixmapInfo.yuvaInfo(), yuvaPixmapInfo.dataType(), pixmaps);
238cb93a386Sopenharmony_ci}
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_ciSkYUVAPixmaps SkYUVAPixmaps::FromExternalPixmaps(const SkYUVAInfo& yuvaInfo,
241cb93a386Sopenharmony_ci                                                 const SkPixmap pixmaps[kMaxPlanes]) {
242cb93a386Sopenharmony_ci    SkColorType colorTypes[kMaxPlanes] = {};
243cb93a386Sopenharmony_ci    size_t rowBytes[kMaxPlanes] = {};
244cb93a386Sopenharmony_ci    int numPlanes = yuvaInfo.numPlanes();
245cb93a386Sopenharmony_ci    for (int i = 0; i < numPlanes; ++i) {
246cb93a386Sopenharmony_ci        colorTypes[i] = pixmaps[i].colorType();
247cb93a386Sopenharmony_ci        rowBytes[i] = pixmaps[i].rowBytes();
248cb93a386Sopenharmony_ci    }
249cb93a386Sopenharmony_ci    SkYUVAPixmapInfo yuvaPixmapInfo(yuvaInfo, colorTypes, rowBytes);
250cb93a386Sopenharmony_ci    if (!yuvaPixmapInfo.isValid()) {
251cb93a386Sopenharmony_ci        return {};
252cb93a386Sopenharmony_ci    }
253cb93a386Sopenharmony_ci    return SkYUVAPixmaps(yuvaInfo, yuvaPixmapInfo.dataType(), pixmaps);
254cb93a386Sopenharmony_ci}
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ciSkYUVAPixmaps::SkYUVAPixmaps(const SkYUVAPixmapInfo& yuvaPixmapInfo, sk_sp<SkData> data)
257cb93a386Sopenharmony_ci        : fData(std::move(data))
258cb93a386Sopenharmony_ci        , fYUVAInfo(yuvaPixmapInfo.yuvaInfo())
259cb93a386Sopenharmony_ci        , fDataType(yuvaPixmapInfo.dataType()) {
260cb93a386Sopenharmony_ci    SkASSERT(yuvaPixmapInfo.isValid());
261cb93a386Sopenharmony_ci    SkASSERT(yuvaPixmapInfo.computeTotalBytes() <= fData->size());
262cb93a386Sopenharmony_ci    SkAssertResult(yuvaPixmapInfo.initPixmapsFromSingleAllocation(fData->writable_data(),
263cb93a386Sopenharmony_ci                                                                  fPlanes.data()));
264cb93a386Sopenharmony_ci}
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ciSkYUVAPixmaps::SkYUVAPixmaps(const SkYUVAInfo& yuvaInfo,
267cb93a386Sopenharmony_ci                             DataType dataType,
268cb93a386Sopenharmony_ci                             const SkPixmap pixmaps[kMaxPlanes])
269cb93a386Sopenharmony_ci        : fYUVAInfo(yuvaInfo), fDataType(dataType) {
270cb93a386Sopenharmony_ci    std::copy_n(pixmaps, yuvaInfo.numPlanes(), fPlanes.data());
271cb93a386Sopenharmony_ci}
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ciSkYUVAPixmapInfo SkYUVAPixmaps::pixmapsInfo() const {
274cb93a386Sopenharmony_ci    if (!this->isValid()) {
275cb93a386Sopenharmony_ci        return {};
276cb93a386Sopenharmony_ci    }
277cb93a386Sopenharmony_ci    SkColorType colorTypes[kMaxPlanes] = {};
278cb93a386Sopenharmony_ci    size_t rowBytes[kMaxPlanes] = {};
279cb93a386Sopenharmony_ci    int numPlanes = this->numPlanes();
280cb93a386Sopenharmony_ci    for (int i = 0; i < numPlanes; ++i) {
281cb93a386Sopenharmony_ci        colorTypes[i] = fPlanes[i].colorType();
282cb93a386Sopenharmony_ci        rowBytes[i] = fPlanes[i].rowBytes();
283cb93a386Sopenharmony_ci    }
284cb93a386Sopenharmony_ci    return {fYUVAInfo, colorTypes, rowBytes};
285cb93a386Sopenharmony_ci}
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ciSkYUVAInfo::YUVALocations SkYUVAPixmaps::toYUVALocations() const {
288cb93a386Sopenharmony_ci    uint32_t channelFlags[] = {SkColorTypeChannelFlags(fPlanes[0].colorType()),
289cb93a386Sopenharmony_ci                               SkColorTypeChannelFlags(fPlanes[1].colorType()),
290cb93a386Sopenharmony_ci                               SkColorTypeChannelFlags(fPlanes[2].colorType()),
291cb93a386Sopenharmony_ci                               SkColorTypeChannelFlags(fPlanes[3].colorType())};
292cb93a386Sopenharmony_ci    auto result = fYUVAInfo.toYUVALocations(channelFlags);
293cb93a386Sopenharmony_ci    SkDEBUGCODE(int numPlanes;)
294cb93a386Sopenharmony_ci    SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
295cb93a386Sopenharmony_ci    SkASSERT(numPlanes == this->numPlanes());
296cb93a386Sopenharmony_ci    return result;
297cb93a386Sopenharmony_ci}
298