Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ed63444

Browse files
bsalomonSkia Commit-Bot
authored andcommitted
Add idea of DataType to SkYUVAPixmapInfo.
DataType describes the data type of YUVA channels independent of how they are grouped into planes. Adds mapping functions between SkColorType/channel count and DataType. SkYUVAPixmapInfo can be constructed from DataType and will choose appropriate SkColorTypes for each plane. Valid SkYUVAPixmapInfos now have the same DataType for each plane (could relax this in the future, esp for alpha plane). SkYUVAPixmapInfo::SupportedDataTypes specifies the supported combinations of SkYUVAInfo::PlanarConfig and kYUVAPixmapInfo::DataType supported by a GrContext (based on supported texture formats). SkImageGenerator/SkCodec YUVA query API now takes a SupportedDataTypes. Change-Id: I8791234638e6ba3396d1e7960b7bc210edc6dd57 Bug: skia:10632 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314276 Reviewed-by: Leon Scroggins <scroggo@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
1 parent 1338a37 commit ed63444

19 files changed

+252
-74
lines changed

RELEASE_NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Milestone 87
2121
Doesn't assume 8bit planar values.
2222
https://review.skia.org/309658
2323
https://review.skia.org/312886
24+
https://review.skia.org/314276
2425

2526
* Added VkImageUsageFlags to GrVkImageInfo struct.
2627

dm/DMSrcSink.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,7 +1814,8 @@ Result GPUDDLSink::ddlDraw(const Src& src,
18141814
// this is our ultimate final drawing area/rect
18151815
SkIRect viewport = SkIRect::MakeWH(size.fWidth, size.fHeight);
18161816

1817-
DDLPromiseImageHelper promiseImageHelper;
1817+
SkYUVAPixmapInfo::SupportedDataTypes supportedYUVADataTypes(*gpuThreadCtx);
1818+
DDLPromiseImageHelper promiseImageHelper(supportedYUVADataTypes);
18181819
sk_sp<SkData> compressedPictureData = promiseImageHelper.deflateSKP(inputPicture.get());
18191820
if (!compressedPictureData) {
18201821
return Result::Fatal("GPUDDLSink: Couldn't deflate SkPicture");
@@ -2270,7 +2271,7 @@ Result ViaDDL::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkStrin
22702271
// this is our ultimate final drawing area/rect
22712272
SkIRect viewport = SkIRect::MakeWH(size.fWidth, size.fHeight);
22722273

2273-
DDLPromiseImageHelper promiseImageHelper;
2274+
DDLPromiseImageHelper promiseImageHelper(SkYUVAPixmapInfo::SupportedDataTypes::All());
22742275
sk_sp<SkData> compressedPictureData = promiseImageHelper.deflateSKP(inputPicture.get());
22752276
if (!compressedPictureData) {
22762277
return Result::Fatal("ViaDDL: Couldn't deflate SkPicture");

include/codec/SkCodec.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,11 +381,18 @@ class SK_API SkCodec : SkNoncopyable {
381381
}
382382

383383
/**
384-
* If decoding to YUVA is supported, this returns true and updates yuvaPixmapInfo to be a
385-
* specification of the planar layout, YUVA->RGBA transformation, per-plane color types and row
386-
* bytes. If YUVA decoding is not supported then returns false.
384+
* If decoding to YUV is supported, this returns true. Otherwise, this
385+
* returns false and the caller will ignore output parameter yuvaPixmapInfo.
386+
*
387+
* @param supportedDataTypes Indicates the data type/planar config combinations that are
388+
* supported by the caller. If the generator supports decoding to
389+
* YUV(A), but not as a type in supportedDataTypes, this method
390+
* returns false.
391+
* @param yuvaPixmapInfo Output parameter that specifies the planar configuration, subsampling,
392+
* orientation, chroma siting, plane color types, and row bytes.
387393
*/
388-
bool queryYUVAInfo(SkYUVAPixmapInfo* yuvaPixmapInfo) const;
394+
bool queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
395+
SkYUVAPixmapInfo* yuvaPixmapInfo) const;
389396

390397
/**
391398
* Returns kSuccess, or another value explaining the type of failure.
@@ -732,7 +739,8 @@ class SK_API SkCodec : SkNoncopyable {
732739
void* pixels, size_t rowBytes, const Options&,
733740
int* rowsDecoded) = 0;
734741

735-
virtual bool onQueryYUVAInfo(SkYUVAPixmapInfo*) const { return false; }
742+
virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
743+
SkYUVAPixmapInfo*) const { return false; }
736744

737745
virtual Result onGetYUVAPlanes(const SkYUVAPixmaps&) { return kUnimplemented; }
738746

include/core/SkImageGenerator.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,17 @@ class SK_API SkImageGenerator {
9191

9292
/**
9393
* If decoding to YUV is supported, this returns true. Otherwise, this
94-
* returns false and does not modify yuvaPixmapInfo.
95-
*
96-
* @param yuvaPixmapInfo Specifies the planar configuration, subsampling, orientation,
97-
* chroma siting, plane color types, and row bytes.
94+
* returns false and the caller will ignore output parameter yuvaPixmapInfo.
95+
*
96+
* @param supportedDataTypes Indicates the data type/planar config combinations that are
97+
* supported by the caller. If the generator supports decoding to
98+
* YUV(A), but not as a type in supportedDataTypes, this method
99+
* returns false.
100+
* @param yuvaPixmapInfo Output parameter that specifies the planar configuration, subsampling,
101+
* orientation, chroma siting, plane color types, and row bytes.
98102
*/
99-
bool queryYUVAInfo(SkYUVAPixmapInfo* yuvaPixmapInfo) const;
103+
bool queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
104+
SkYUVAPixmapInfo* yuvaPixmapInfo) const;
100105

101106
/**
102107
* Returns true on success and false on failure.
@@ -204,7 +209,8 @@ class SK_API SkImageGenerator {
204209
struct Options {};
205210
virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) { return false; }
206211
virtual bool onIsValid(GrRecordingContext*) const { return true; }
207-
virtual bool onQueryYUVAInfo(SkYUVAPixmapInfo*) const { return false; }
212+
virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
213+
SkYUVAPixmapInfo*) const { return false; }
208214
virtual bool onGetYUVAPlanes(const SkYUVAPixmaps&) { return false; }
209215
virtual bool onQueryYUVA8(SkYUVASizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount],
210216
SkYUVColorSpace*) const { return false; }

include/core/SkYUVAPixmaps.h

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include "include/private/SkTo.h"
1616

1717
#include <array>
18+
#include <bitset>
1819

20+
class GrImageContext;
1921
struct SkYUVASizeInfo;
2022
struct SkYUVAIndex;
2123

@@ -27,44 +29,113 @@ class SK_API SkYUVAPixmapInfo {
2729
public:
2830
static constexpr auto kMaxPlanes = SkYUVAInfo::kMaxPlanes;
2931

32+
using PlanarConfig = SkYUVAInfo::PlanarConfig;
33+
34+
/**
35+
* Data type for Y, U, V, and possibly A channels independent of how values are packed into
36+
* planes.
37+
**/
38+
enum class DataType {
39+
kUnorm8, ///< 8 bit unsigned normalized
40+
kUnorm16, ///< 16 bit unsigned normalized
41+
kFloat16, ///< 16 bit (half) floating point
42+
43+
kLast = kFloat16
44+
};
45+
static constexpr int kDataTypeCnt = static_cast<int>(DataType::kLast) + 1;
46+
47+
class SupportedDataTypes {
48+
public:
49+
/** Defaults to nothing supported. */
50+
constexpr SupportedDataTypes() = default;
51+
52+
/** Init based on texture formats supported by the context. */
53+
SupportedDataTypes(const GrImageContext&);
54+
55+
/** All combinations of PlanarConfig and DataType are supported. */
56+
static constexpr SupportedDataTypes All() {
57+
SupportedDataTypes combinations;
58+
combinations.fDataTypeSupport = std::bitset<kDataTypeCnt>(~(0ULL));
59+
return combinations;
60+
}
61+
62+
constexpr bool supported(PlanarConfig, DataType type) const {
63+
return fDataTypeSupport[static_cast<size_t>(type)];
64+
}
65+
66+
/**
67+
* Update to add support for pixmaps with numChannel channels where each channel is
68+
* represented as DataType.
69+
*/
70+
void enableDataType(DataType, int numChannels);
71+
72+
private:
73+
// Because all of our PlanarConfigs are currently single channel per-plane, we just need to
74+
// keep track of whether each data type is supported (implicitly as a single channel plane).
75+
// As we add multi-channel per-plane PlanarConfigs this will have to change.
76+
std::bitset<kDataTypeCnt> fDataTypeSupport = {};
77+
};
78+
79+
/**
80+
* Gets the default SkColorType to use with numChannels channels, each represented as DataType.
81+
* Returns kUnknown_SkColorType if no such color type.
82+
*/
83+
static SkColorType DefaultColorTypeForDataType(DataType dataType, int numChannels);
84+
85+
/**
86+
* If the SkColorType is supported for YUVA pixmaps this will return the number of YUVA channels
87+
* that can be stored in a plane of this color type and what the DataType is of those channels.
88+
* If the SkColorType is not supported as a YUVA plane the number of channels is reported as 0
89+
* and the DataType returned should be ignored.
90+
*/
91+
static std::tuple<int, DataType> NumChannelsAndDataType(SkColorType);
92+
3093
/** Default SkYUVAPixmapInfo is invalid. */
3194
SkYUVAPixmapInfo() = default;
3295

3396
/**
3497
* Initializes the SkYUVAPixmapInfo from a SkYUVAInfo with per-plane color types and row bytes.
3598
* This will be invalid if the colorTypes aren't compatible with the SkYUVAInfo or if a
3699
* rowBytes entry is not valid for the plane dimensions and color type. Color type and
37-
* row byte values beyond the number of planes in SkYUVAInfo are ignored.
100+
* row byte values beyond the number of planes in SkYUVAInfo are ignored. All SkColorTypes
101+
* must have the same DataType or this will be invalid.
38102
*
39103
* If rowBytes is nullptr then bpp*width is assumed for each plane.
40104
*/
41105
SkYUVAPixmapInfo(const SkYUVAInfo&,
42106
const SkColorType[kMaxPlanes],
43107
const size_t rowBytes[kMaxPlanes]);
44108
/**
45-
* Like above but uses the same color type for all planes.
109+
* Like above but uses DefaultColorTypeForDataType to determine each plane's SkColorType. If
110+
* rowBytes is nullptr then bpp*width is assumed for each plane.
46111
*/
47-
SkYUVAPixmapInfo(const SkYUVAInfo&, SkColorType, const size_t rowBytes[kMaxPlanes]);
112+
SkYUVAPixmapInfo(const SkYUVAInfo&, DataType, const size_t rowBytes[kMaxPlanes]);
48113

49114
SkYUVAPixmapInfo(const SkYUVAPixmapInfo&) = default;
50115

51116
SkYUVAPixmapInfo& operator=(const SkYUVAPixmapInfo&) = default;
52117

118+
bool operator==(const SkYUVAPixmapInfo&) const;
119+
bool operator!=(const SkYUVAPixmapInfo& that) const { return !(*this == that); }
120+
53121
const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
54122

55123
SkYUVColorSpace yuvColorSpace() const { return fYUVAInfo.yuvColorSpace(); }
56124

57125
/** The number of SkPixmap planes, 0 if this SkYUVAPixmapInfo is invalid. */
58126
int numPlanes() const { return this->isValid() ? fYUVAInfo.numPlanes() : 0; }
59127

128+
/** The per-YUV[A] channel data type. */
129+
DataType dataType() const { return fDataType; }
130+
60131
/**
61132
* Row bytes for the ith plane. Returns zero if i >= numPlanes() or this SkYUVAPixmapInfo is
62133
* invalid.
63134
*/
64-
size_t rowBytes(int i) const { return fRowBytes[i]; }
135+
size_t rowBytes(int i) const { return fRowBytes[static_cast<size_t>(i)]; }
65136

66137
/** Image info for the ith plane, or default SkImageInfo if i >= numPlanes() */
67-
const SkImageInfo& planeInfo(int i) const { return fPlaneInfos[i]; }
138+
const SkImageInfo& planeInfo(int i) const { return fPlaneInfos[static_cast<size_t>(i)]; }
68139

69140
/**
70141
* Determine size to allocate for all planes. Optionally retrieves the per-plane sizes in
@@ -86,10 +157,14 @@ class SK_API SkYUVAPixmapInfo {
86157
*/
87158
bool isValid() const { return fPlaneInfos[0].colorType() != kUnknown_SkColorType; }
88159

160+
/** Is this valid and does it use color types allowed by the passed SupportedDataTypes? */
161+
bool isSupported(const SupportedDataTypes&) const;
162+
89163
private:
90164
SkYUVAInfo fYUVAInfo;
91-
SkImageInfo fPlaneInfos[kMaxPlanes] = {};
92-
size_t fRowBytes[kMaxPlanes] = {};
165+
std::array<SkImageInfo, kMaxPlanes> fPlaneInfos = {};
166+
std::array<size_t, kMaxPlanes> fRowBytes = {};
167+
DataType fDataType = DataType::kUnorm8;
93168
static_assert(kUnknown_SkColorType == 0, "default init isn't kUnknown");
94169
};
95170

src/codec/SkCodec.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,13 @@ SkCodec::SkCodec(SkEncodedInfo&& info, XformFormat srcFormat, std::unique_ptr<Sk
167167

168168
SkCodec::~SkCodec() {}
169169

170-
bool SkCodec::queryYUVAInfo(SkYUVAPixmapInfo* yuvaPixmapInfo) const {
170+
bool SkCodec::queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
171+
SkYUVAPixmapInfo* yuvaPixmapInfo) const {
171172
if (!yuvaPixmapInfo) {
172173
return false;
173174
}
174-
return this->onQueryYUVAInfo(yuvaPixmapInfo) && yuvaPixmapInfo->isValid();
175+
return this->onQueryYUVAInfo(supportedDataTypes, yuvaPixmapInfo) &&
176+
yuvaPixmapInfo->isSupported(supportedDataTypes);
175177
}
176178

177179
SkCodec::Result SkCodec::getYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {

src/codec/SkCodecImageGenerator.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* re
6969
return this->getPixels(requestInfo, requestPixels, requestRowBytes, nullptr);
7070
}
7171

72-
bool SkCodecImageGenerator::onQueryYUVAInfo(SkYUVAPixmapInfo* yuvaPixmapInfo) const {
73-
return fCodec->queryYUVAInfo(yuvaPixmapInfo);
72+
bool SkCodecImageGenerator::onQueryYUVAInfo(
73+
const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
74+
SkYUVAPixmapInfo* yuvaPixmapInfo) const {
75+
return fCodec->queryYUVAInfo(supportedDataTypes, yuvaPixmapInfo);
7476
}
7577

7678
bool SkCodecImageGenerator::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {

src/codec/SkCodecImageGenerator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ class SkCodecImageGenerator : public SkImageGenerator {
9898
size_t rowBytes,
9999
const Options& opts) override;
100100

101-
bool onQueryYUVAInfo(SkYUVAPixmapInfo* yuvaPixmapInfo) const override;
101+
bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
102+
SkYUVAPixmapInfo*) const override;
102103

103104
bool onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) override;
104105

src/codec/SkJpegCodec.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ bool SkJpegCodec::onSkipScanlines(int count) {
745745

746746
static bool is_yuv_supported(const jpeg_decompress_struct* dinfo,
747747
const SkJpegCodec& codec,
748+
const SkYUVAPixmapInfo::SupportedDataTypes* supportedDataTypes,
748749
SkYUVAPixmapInfo* yuvaPixmapInfo) {
749750
// Scaling is not supported in raw data mode.
750751
SkASSERT(dinfo->scale_num == dinfo->scale_denom);
@@ -811,6 +812,10 @@ static bool is_yuv_supported(const jpeg_decompress_struct* dinfo,
811812
} else {
812813
return false;
813814
}
815+
if (supportedDataTypes &&
816+
!supportedDataTypes->supported(tempPlanarConfig, SkYUVAPixmapInfo::DataType::kUnorm8)) {
817+
return false;
818+
}
814819
if (yuvaPixmapInfo) {
815820
SkColorType colorTypes[SkYUVAPixmapInfo::kMaxPlanes];
816821
size_t rowBytes[SkYUVAPixmapInfo::kMaxPlanes];
@@ -829,15 +834,16 @@ static bool is_yuv_supported(const jpeg_decompress_struct* dinfo,
829834
return true;
830835
}
831836

832-
bool SkJpegCodec::onQueryYUVAInfo(SkYUVAPixmapInfo* yuvaPixmapInfo) const {
837+
bool SkJpegCodec::onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
838+
SkYUVAPixmapInfo* yuvaPixmapInfo) const {
833839
jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
834-
return is_yuv_supported(dinfo, *this, yuvaPixmapInfo);
840+
return is_yuv_supported(dinfo, *this, &supportedDataTypes, yuvaPixmapInfo);
835841
}
836842

837843
SkCodec::Result SkJpegCodec::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
838844
// Get a pointer to the decompress info since we will use it quite frequently
839845
jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
840-
if (!is_yuv_supported(dinfo, *this, nullptr)) {
846+
if (!is_yuv_supported(dinfo, *this, nullptr, nullptr)) {
841847
return fDecoderMgr->returnFailure("onGetYUVAPlanes", kInvalidInput);
842848
}
843849
// Set the jump location for libjpeg errors
@@ -860,7 +866,7 @@ SkCodec::Result SkJpegCodec::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
860866
// was caused by a bug in the old code, but we'll be safe and check here.
861867
// Also check that pixmap properties agree with expectations.
862868
SkYUVAPixmapInfo info;
863-
SkASSERT(is_yuv_supported(dinfo, *this, &info));
869+
SkASSERT(is_yuv_supported(dinfo, *this, nullptr, &info));
864870
SkASSERT(info.yuvaInfo() == yuvaPixmaps.yuvaInfo());
865871
for (int i = 0; i < info.numPlanes(); ++i) {
866872
SkASSERT(planes[i].colorType() == kAlpha_8_SkColorType);

src/codec/SkJpegCodec.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class SkJpegCodec : public SkCodec {
4444
Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
4545
int*) override;
4646

47-
bool onQueryYUVAInfo(SkYUVAPixmapInfo*) const override;
47+
bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
48+
SkYUVAPixmapInfo*) const override;
4849

4950
Result onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) override;
5051

0 commit comments

Comments
 (0)