blob: cc5a1ba9665ca63333738e44a5803993a0520f9a [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_COMMON_RESOURCES_SHARED_IMAGE_FORMAT_H_
#define COMPONENTS_VIZ_COMMON_RESOURCES_SHARED_IMAGE_FORMAT_H_
#include <stdint.h>
#include "base/check.h"
#include "base/check_op.h"
#include "components/viz/common/resources/resource_format.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "mojo/public/cpp/bindings/union_traits.h"
namespace viz {
namespace mojom {
class SharedImageFormatDataView;
class MultiplanarFormatDataView;
} // namespace mojom
// This class represents the image format used by SharedImages for single plane
// images (eg. RGBA) or multiplanar images (eg. NV12). This format can be
// either ResourceFormat or MultiplanarFormat (PlaneConfig + Subsampling +
// ChannelFormat).
class SharedImageFormat {
public:
/**
* Specifies how YUV (and optionally A) are divided among planes. Planes are
* separated by underscores in the enum value names. Within each plane the
* pixmap/texture channels are mapped to the YUVA channels in the order
* specified, e.g. for kY_UV Y is in channel 0 of plane 0, U is in channel 0
* of plane 1, and V is in channel 1 of plane 1. Channel ordering within a
* pixmap/texture given the channels it contains:
* A: 0:A
* Luminance/Gray: 0:Gray
* Luminance/Gray + Alpha: 0:Gray, 1:A
* RG 0:R, 1:G
* RGB 0:R, 1:G, 2:B
* RGBA 0:R, 1:G, 2:B, 3:A
*/
enum class PlaneConfig : uint8_t {
kY_V_U, ///< Plane 0: Y, Plane 1: V, Plane 2: U
kY_UV, ///< Plane 0: Y, Plane 1: UV
};
/**
* UV subsampling is also specified in the enum value names using J:a:b
* notation (e.g. 4:2:0 is 1/2 horizontal and 1/2 vertical resolution for U
* and V). If alpha is present it is not sub- sampled. Note that Subsampling
* values other than k444 are only valid with PlaneConfig values that have U
* and V in different planes than Y (and A, if present).
*/
enum class Subsampling : uint8_t {
k420, ///< 1 set of UV values for each 2x2 block of Y values.
};
/**
* 8 bit, 10 bit, 16 bit unorn, 16 bit float channel formats.
* Specifies the channel format for Y plane in the YUV (and optionally A)
* plane config. The channel format for remaining planes are identified based
* on the planes in the PlaneConfig. For individual planes like Y_V_U, U and V
* are both 8 bit channel formats whereas for Y_UV, the UV plane contains 2
* channels with each being an 8 bit channel format.
* TODO(hitawala): Add a helper function that gets the channel format for UV
* plane.
*/
enum class ChannelFormat : uint8_t { k8, k10, k16, k16F };
SharedImageFormat() = default;
static constexpr SharedImageFormat SinglePlane(
ResourceFormat resource_format) {
return SharedImageFormat(resource_format);
}
static constexpr SharedImageFormat MultiPlane(PlaneConfig plane_config,
Subsampling subsampling,
ChannelFormat channel_format) {
return SharedImageFormat(plane_config, subsampling, channel_format);
}
ResourceFormat resource_format() const {
DCHECK(is_single_plane());
return format_.resource_format;
}
PlaneConfig plane_config() const {
DCHECK(is_multi_plane());
return format_.multiplanar_format.plane_config;
}
Subsampling subsampling() const {
DCHECK(is_multi_plane());
return format_.multiplanar_format.subsampling;
}
ChannelFormat channel_format() const {
DCHECK(is_multi_plane());
return format_.multiplanar_format.channel_format;
}
bool is_single_plane() const {
return plane_type_ == PlaneType::kSinglePlane;
}
bool is_multi_plane() const { return plane_type_ == PlaneType::kMultiPlane; }
// Returns whether the resource format can be used as a software bitmap for
// export to the display compositor.
bool IsBitmapFormatSupported() const;
bool operator==(const SharedImageFormat& o) const {
if (plane_type_ != o.plane_type())
return false;
switch (plane_type_) {
case PlaneType::kUnknown:
return true;
case PlaneType::kSinglePlane:
return resource_format() == o.resource_format();
case PlaneType::kMultiPlane:
return multiplanar_format() == o.multiplanar_format();
}
}
bool operator!=(const SharedImageFormat& o) const { return !operator==(o); }
private:
enum class PlaneType : uint8_t {
kUnknown,
kSinglePlane,
kMultiPlane,
};
union SharedImageFormatUnion {
// A struct for multiplanar format that is defined by the PlaneConfig,
// Subsampling and ChannelFormat it holds.
struct MultiplanarFormat {
PlaneConfig plane_config;
Subsampling subsampling;
ChannelFormat channel_format;
bool operator==(const MultiplanarFormat& o) const {
return plane_config == o.plane_config && subsampling == o.subsampling &&
channel_format == o.channel_format;
}
};
SharedImageFormatUnion() = default;
explicit constexpr SharedImageFormatUnion(ResourceFormat resource_format)
: resource_format(resource_format) {}
constexpr SharedImageFormatUnion(PlaneConfig plane_config,
Subsampling subsampling,
ChannelFormat channel_format)
: multiplanar_format({plane_config, subsampling, channel_format}) {}
ResourceFormat resource_format;
MultiplanarFormat multiplanar_format;
};
friend struct mojo::UnionTraits<mojom::SharedImageFormatDataView,
SharedImageFormat>;
friend struct mojo::StructTraits<mojom::MultiplanarFormatDataView,
SharedImageFormatUnion::MultiplanarFormat>;
explicit constexpr SharedImageFormat(ResourceFormat resource_format)
: plane_type_(PlaneType::kSinglePlane), format_(resource_format) {}
constexpr SharedImageFormat(PlaneConfig plane_config,
Subsampling subsampling,
ChannelFormat channel_format)
: plane_type_(PlaneType::kMultiPlane),
format_(plane_config, subsampling, channel_format) {}
PlaneType plane_type() const { return plane_type_; }
SharedImageFormatUnion::MultiplanarFormat multiplanar_format() const {
DCHECK(is_multi_plane());
return format_.multiplanar_format;
}
PlaneType plane_type_ = PlaneType::kUnknown;
// `format_` can only be ResourceFormat (for single plane, eg. RGBA) or
// MultiplanarFormat at any given time.
SharedImageFormatUnion format_;
};
static_assert(sizeof(SharedImageFormat) <= 8);
} // namespace viz
#endif // COMPONENTS_VIZ_COMMON_RESOURCES_SHARED_IMAGE_FORMAT_H_