summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/include/core/SkYUVAPixmaps.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/include/core/SkYUVAPixmaps.h')
-rw-r--r--gfx/skia/skia/include/core/SkYUVAPixmaps.h336
1 files changed, 336 insertions, 0 deletions
diff --git a/gfx/skia/skia/include/core/SkYUVAPixmaps.h b/gfx/skia/skia/include/core/SkYUVAPixmaps.h
new file mode 100644
index 0000000000..f75b314c00
--- /dev/null
+++ b/gfx/skia/skia/include/core/SkYUVAPixmaps.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkYUVAPixmaps_DEFINED
+#define SkYUVAPixmaps_DEFINED
+
+#include "include/core/SkData.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkYUVAInfo.h"
+#include "include/private/base/SkTo.h"
+
+#include <array>
+#include <bitset>
+
+class GrImageContext;
+
+/**
+ * SkYUVAInfo combined with per-plane SkColorTypes and row bytes. Fully specifies the SkPixmaps
+ * for a YUVA image without the actual pixel memory and data.
+ */
+class SK_API SkYUVAPixmapInfo {
+public:
+ static constexpr auto kMaxPlanes = SkYUVAInfo::kMaxPlanes;
+
+ using PlaneConfig = SkYUVAInfo::PlaneConfig;
+ using Subsampling = SkYUVAInfo::Subsampling;
+
+ /**
+ * Data type for Y, U, V, and possibly A channels independent of how values are packed into
+ * planes.
+ **/
+ enum class DataType {
+ kUnorm8, ///< 8 bit unsigned normalized
+ kUnorm16, ///< 16 bit unsigned normalized
+ kFloat16, ///< 16 bit (half) floating point
+ kUnorm10_Unorm2, ///< 10 bit unorm for Y, U, and V. 2 bit unorm for alpha (if present).
+
+ kLast = kUnorm10_Unorm2
+ };
+ static constexpr int kDataTypeCnt = static_cast<int>(DataType::kLast) + 1;
+
+ class SK_API SupportedDataTypes {
+ public:
+ /** Defaults to nothing supported. */
+ constexpr SupportedDataTypes() = default;
+
+ /** Init based on texture formats supported by the context. */
+ SupportedDataTypes(const GrImageContext&);
+
+ /** All legal combinations of PlaneConfig and DataType are supported. */
+ static constexpr SupportedDataTypes All();
+
+ /**
+ * Checks whether there is a supported combination of color types for planes structured
+ * as indicated by PlaneConfig with channel data types as indicated by DataType.
+ */
+ constexpr bool supported(PlaneConfig, DataType) const;
+
+ /**
+ * Update to add support for pixmaps with numChannel channels where each channel is
+ * represented as DataType.
+ */
+ void enableDataType(DataType, int numChannels);
+
+ private:
+ // The bit for DataType dt with n channels is at index kDataTypeCnt*(n-1) + dt.
+ std::bitset<kDataTypeCnt*4> fDataTypeSupport = {};
+ };
+
+ /**
+ * Gets the default SkColorType to use with numChannels channels, each represented as DataType.
+ * Returns kUnknown_SkColorType if no such color type.
+ */
+ static constexpr SkColorType DefaultColorTypeForDataType(DataType dataType, int numChannels);
+
+ /**
+ * If the SkColorType is supported for YUVA pixmaps this will return the number of YUVA channels
+ * that can be stored in a plane of this color type and what the DataType is of those channels.
+ * If the SkColorType is not supported as a YUVA plane the number of channels is reported as 0
+ * and the DataType returned should be ignored.
+ */
+ static std::tuple<int, DataType> NumChannelsAndDataType(SkColorType);
+
+ /** Default SkYUVAPixmapInfo is invalid. */
+ SkYUVAPixmapInfo() = default;
+
+ /**
+ * Initializes the SkYUVAPixmapInfo from a SkYUVAInfo with per-plane color types and row bytes.
+ * This will be invalid if the colorTypes aren't compatible with the SkYUVAInfo or if a
+ * rowBytes entry is not valid for the plane dimensions and color type. Color type and
+ * row byte values beyond the number of planes in SkYUVAInfo are ignored. All SkColorTypes
+ * must have the same DataType or this will be invalid.
+ *
+ * If rowBytes is nullptr then bpp*width is assumed for each plane.
+ */
+ SkYUVAPixmapInfo(const SkYUVAInfo&,
+ const SkColorType[kMaxPlanes],
+ const size_t rowBytes[kMaxPlanes]);
+ /**
+ * Like above but uses DefaultColorTypeForDataType to determine each plane's SkColorType. If
+ * rowBytes is nullptr then bpp*width is assumed for each plane.
+ */
+ SkYUVAPixmapInfo(const SkYUVAInfo&, DataType, const size_t rowBytes[kMaxPlanes]);
+
+ SkYUVAPixmapInfo(const SkYUVAPixmapInfo&) = default;
+
+ SkYUVAPixmapInfo& operator=(const SkYUVAPixmapInfo&) = default;
+
+ bool operator==(const SkYUVAPixmapInfo&) const;
+ bool operator!=(const SkYUVAPixmapInfo& that) const { return !(*this == that); }
+
+ const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
+
+ SkYUVColorSpace yuvColorSpace() const { return fYUVAInfo.yuvColorSpace(); }
+
+ /** The number of SkPixmap planes, 0 if this SkYUVAPixmapInfo is invalid. */
+ int numPlanes() const { return fYUVAInfo.numPlanes(); }
+
+ /** The per-YUV[A] channel data type. */
+ DataType dataType() const { return fDataType; }
+
+ /**
+ * Row bytes for the ith plane. Returns zero if i >= numPlanes() or this SkYUVAPixmapInfo is
+ * invalid.
+ */
+ size_t rowBytes(int i) const { return fRowBytes[static_cast<size_t>(i)]; }
+
+ /** Image info for the ith plane, or default SkImageInfo if i >= numPlanes() */
+ const SkImageInfo& planeInfo(int i) const { return fPlaneInfos[static_cast<size_t>(i)]; }
+
+ /**
+ * Determine size to allocate for all planes. Optionally retrieves the per-plane sizes in
+ * planeSizes if not null. If total size overflows will return SIZE_MAX and set all planeSizes
+ * to SIZE_MAX. Returns 0 and fills planesSizes with 0 if this SkYUVAPixmapInfo is not valid.
+ */
+ size_t computeTotalBytes(size_t planeSizes[kMaxPlanes] = nullptr) const;
+
+ /**
+ * Takes an allocation that is assumed to be at least computeTotalBytes() in size and configures
+ * the first numPlanes() entries in pixmaps array to point into that memory. The remaining
+ * entries of pixmaps are default initialized. Fails if this SkYUVAPixmapInfo not valid.
+ */
+ bool initPixmapsFromSingleAllocation(void* memory, SkPixmap pixmaps[kMaxPlanes]) const;
+
+ /**
+ * Returns true if this has been configured with a non-empty dimensioned SkYUVAInfo with
+ * compatible color types and row bytes.
+ */
+ bool isValid() const { return fYUVAInfo.isValid(); }
+
+ /** Is this valid and does it use color types allowed by the passed SupportedDataTypes? */
+ bool isSupported(const SupportedDataTypes&) const;
+
+private:
+ SkYUVAInfo fYUVAInfo;
+ std::array<SkImageInfo, kMaxPlanes> fPlaneInfos = {};
+ std::array<size_t, kMaxPlanes> fRowBytes = {};
+ DataType fDataType = DataType::kUnorm8;
+ static_assert(kUnknown_SkColorType == 0, "default init isn't kUnknown");
+};
+
+/**
+ * Helper to store SkPixmap planes as described by a SkYUVAPixmapInfo. Can be responsible for
+ * allocating/freeing memory for pixmaps or use external memory.
+ */
+class SK_API SkYUVAPixmaps {
+public:
+ using DataType = SkYUVAPixmapInfo::DataType;
+ static constexpr auto kMaxPlanes = SkYUVAPixmapInfo::kMaxPlanes;
+
+ static SkColorType RecommendedRGBAColorType(DataType);
+
+ /** Allocate space for pixmaps' pixels in the SkYUVAPixmaps. */
+ static SkYUVAPixmaps Allocate(const SkYUVAPixmapInfo& yuvaPixmapInfo);
+
+ /**
+ * Use storage in SkData as backing store for pixmaps' pixels. SkData is retained by the
+ * SkYUVAPixmaps.
+ */
+ static SkYUVAPixmaps FromData(const SkYUVAPixmapInfo&, sk_sp<SkData>);
+
+ /**
+ * Makes a deep copy of the src SkYUVAPixmaps. The returned SkYUVAPixmaps owns its planes'
+ * backing stores.
+ */
+ static SkYUVAPixmaps MakeCopy(const SkYUVAPixmaps& src);
+
+ /**
+ * Use passed in memory as backing store for pixmaps' pixels. Caller must ensure memory remains
+ * allocated while pixmaps are in use. There must be at least
+ * SkYUVAPixmapInfo::computeTotalBytes() allocated starting at memory.
+ */
+ static SkYUVAPixmaps FromExternalMemory(const SkYUVAPixmapInfo&, void* memory);
+
+ /**
+ * Wraps existing SkPixmaps. The SkYUVAPixmaps will have no ownership of the SkPixmaps' pixel
+ * memory so the caller must ensure it remains valid. Will return an invalid SkYUVAPixmaps if
+ * the SkYUVAInfo isn't compatible with the SkPixmap array (number of planes, plane dimensions,
+ * sufficient color channels in planes, ...).
+ */
+ static SkYUVAPixmaps FromExternalPixmaps(const SkYUVAInfo&, const SkPixmap[kMaxPlanes]);
+
+ /** Default SkYUVAPixmaps is invalid. */
+ SkYUVAPixmaps() = default;
+ ~SkYUVAPixmaps() = default;
+
+ SkYUVAPixmaps(SkYUVAPixmaps&& that) = default;
+ SkYUVAPixmaps& operator=(SkYUVAPixmaps&& that) = default;
+ SkYUVAPixmaps(const SkYUVAPixmaps&) = default;
+ SkYUVAPixmaps& operator=(const SkYUVAPixmaps& that) = default;
+
+ /** Does have initialized pixmaps compatible with its SkYUVAInfo. */
+ bool isValid() const { return !fYUVAInfo.dimensions().isEmpty(); }
+
+ const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
+
+ DataType dataType() const { return fDataType; }
+
+ SkYUVAPixmapInfo pixmapsInfo() const;
+
+ /** Number of pixmap planes or 0 if this SkYUVAPixmaps is invalid. */
+ int numPlanes() const { return this->isValid() ? fYUVAInfo.numPlanes() : 0; }
+
+ /**
+ * Access the SkPixmap planes. They are default initialized if this is not a valid
+ * SkYUVAPixmaps.
+ */
+ const std::array<SkPixmap, kMaxPlanes>& planes() const { return fPlanes; }
+
+ /**
+ * Get the ith SkPixmap plane. SkPixmap will be default initialized if i >= numPlanes or this
+ * SkYUVAPixmaps is invalid.
+ */
+ const SkPixmap& plane(int i) const { return fPlanes[SkToSizeT(i)]; }
+
+ /**
+ * Computes a YUVALocations representation of the planar layout. The result is guaranteed to be
+ * valid if this->isValid().
+ */
+ SkYUVAInfo::YUVALocations toYUVALocations() const;
+
+ /** Does this SkPixmaps own the backing store of the planes? */
+ bool ownsStorage() const { return SkToBool(fData); }
+
+private:
+ SkYUVAPixmaps(const SkYUVAPixmapInfo&, sk_sp<SkData>);
+ SkYUVAPixmaps(const SkYUVAInfo&, DataType, const SkPixmap[kMaxPlanes]);
+
+ std::array<SkPixmap, kMaxPlanes> fPlanes = {};
+ sk_sp<SkData> fData;
+ SkYUVAInfo fYUVAInfo;
+ DataType fDataType;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+constexpr SkYUVAPixmapInfo::SupportedDataTypes SkYUVAPixmapInfo::SupportedDataTypes::All() {
+ using ULL = unsigned long long; // bitset cons. takes this.
+ ULL bits = 0;
+ for (ULL c = 1; c <= 4; ++c) {
+ for (ULL dt = 0; dt <= ULL(kDataTypeCnt); ++dt) {
+ if (DefaultColorTypeForDataType(static_cast<DataType>(dt),
+ static_cast<int>(c)) != kUnknown_SkColorType) {
+ bits |= ULL(1) << (dt + static_cast<ULL>(kDataTypeCnt)*(c - 1));
+ }
+ }
+ }
+ SupportedDataTypes combinations;
+ combinations.fDataTypeSupport = bits;
+ return combinations;
+}
+
+constexpr bool SkYUVAPixmapInfo::SupportedDataTypes::supported(PlaneConfig config,
+ DataType type) const {
+ int n = SkYUVAInfo::NumPlanes(config);
+ for (int i = 0; i < n; ++i) {
+ auto c = static_cast<size_t>(SkYUVAInfo::NumChannelsInPlane(config, i));
+ SkASSERT(c >= 1 && c <= 4);
+ if (!fDataTypeSupport[static_cast<size_t>(type) +
+ (c - 1)*static_cast<size_t>(kDataTypeCnt)]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+constexpr SkColorType SkYUVAPixmapInfo::DefaultColorTypeForDataType(DataType dataType,
+ int numChannels) {
+ switch (numChannels) {
+ case 1:
+ switch (dataType) {
+ case DataType::kUnorm8: return kGray_8_SkColorType;
+ case DataType::kUnorm16: return kA16_unorm_SkColorType;
+ case DataType::kFloat16: return kA16_float_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kUnknown_SkColorType;
+ }
+ break;
+ case 2:
+ switch (dataType) {
+ case DataType::kUnorm8: return kR8G8_unorm_SkColorType;
+ case DataType::kUnorm16: return kR16G16_unorm_SkColorType;
+ case DataType::kFloat16: return kR16G16_float_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kUnknown_SkColorType;
+ }
+ break;
+ case 3:
+ // None of these are tightly packed. The intended use case is for interleaved YUVA
+ // planes where we're forcing opaqueness by ignoring the alpha values.
+ // There are "x" rather than "A" variants for Unorm8 and Unorm10_Unorm2 but we don't
+ // choose them because 1) there is no inherent advantage and 2) there is better support
+ // in the GPU backend for the "A" versions.
+ switch (dataType) {
+ case DataType::kUnorm8: return kRGBA_8888_SkColorType;
+ case DataType::kUnorm16: return kR16G16B16A16_unorm_SkColorType;
+ case DataType::kFloat16: return kRGBA_F16_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
+ }
+ break;
+ case 4:
+ switch (dataType) {
+ case DataType::kUnorm8: return kRGBA_8888_SkColorType;
+ case DataType::kUnorm16: return kR16G16B16A16_unorm_SkColorType;
+ case DataType::kFloat16: return kRGBA_F16_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
+ }
+ break;
+ }
+ return kUnknown_SkColorType;
+}
+
+#endif