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