blob: 8b5c3b3e79c7af8d36c80cf5a0fc087495d6b20e [file] [log] [blame]
#ifndef ANDROID_LIBVRFLINGER_HWCTYPES_H
#define ANDROID_LIBVRFLINGER_HWCTYPES_H
// General HWC type support. Hardware composer type support is a bit of a mess
// between HWC1, HWC2 C/C++11, and HIDL types. Particularly bothersome is the
// use of enum classes, which make analogous types between versions much
// harder to deal with in a uniform way.
//
// These utilities help address some of these pains by providing a type-safe,
// flexible interface to translate between different type spaces.
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
#include <hardware/hwcomposer2.h>
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
#include <string>
#include <type_traits>
namespace HWC {
// Value types derived from HWC HAL types. Some of these are stand-alone,
// while others are also wrapped in translator classes below.
using ColorMode = int32_t; // android_color_mode_t;
using Config = hwc2_config_t;
using ColorTransform =
std::underlying_type<android_color_transform_t>::type; // int32_t;
using Dataspace = std::underlying_type<android_dataspace_t>::type; // int32_t;
using DisplayId = hwc2_display_t;
using DisplayRequest = std::underlying_type<HWC2::DisplayRequest>::type;
using Hdr = std::underlying_type<android_hdr_t>::type; // int32_t;
using Layer = hwc2_layer_t;
using PixelFormat =
std::underlying_type<android_pixel_format_t>::type; // int32_t;
// Type traits and casting utilities.
// SFINAE utility to evaluate type expressions.
template <typename...>
using TestTypeExpression = void;
// Traits type to determine the underlying type of an enum, integer,
// or wrapper class.
template <typename T, typename = typename std::is_enum<T>::type,
typename = typename std::is_integral<T>::type, typename = void>
struct UnderlyingType {
using Type = T;
};
// Partial specialization that matches enum types. Captures the underlying type
// of the enum in member type Type.
template <typename T>
struct UnderlyingType<T, std::true_type, std::false_type> {
using Type = typename std::underlying_type<T>::type;
};
// Partial specialization that matches integral types. Captures the type of the
// integer in member type Type.
template <typename T>
struct UnderlyingType<T, std::false_type, std::true_type> {
using Type = T;
};
// Partial specialization that matches the wrapper types below. Captures
// wrapper member type ValueType in member type Type.
template <typename T>
struct UnderlyingType<T, std::false_type, std::false_type,
TestTypeExpression<typename T::ValueType>> {
using Type = typename T::ValueType;
};
// Enable if T is an enum with underlying type U.
template <typename T, typename U, typename ReturnType = void>
using EnableIfMatchingEnum = typename std::enable_if<
std::is_enum<T>::value &&
std::is_same<U, typename UnderlyingType<T>::Type>::value,
ReturnType>::type;
// Enable if T and U are the same size/alignment and have the same underlying
// type. Handles enum, integral, and wrapper classes below.
template <typename T, typename U, typename Return = void>
using EnableIfSafeCast = typename std::enable_if<
sizeof(T) == sizeof(U) && alignof(T) == alignof(U) &&
std::is_same<typename UnderlyingType<T>::Type,
typename UnderlyingType<U>::Type>::value,
Return>::type;
// Safely cast between std::vectors of matching enum/integer/wraper types.
// Normally this is not possible with pendantic compiler type checks. However,
// given the same size, alignment, and underlying type this is safe due to
// allocator requirements and array-like element access guarantees.
template <typename T, typename U>
EnableIfSafeCast<T, U, std::vector<T>*> VectorCast(std::vector<U>* in) {
return reinterpret_cast<std::vector<T>*>(in);
}
// Translator classes that wrap specific HWC types to make translating
// between different types (especially enum class) in code cleaner.
// Base type for the enum wrappers below. This type provides type definitions
// and implicit conversion logic common to each wrapper type.
template <typename EnumType>
struct Wrapper {
// Alias type of this instantiantion of Wrapper. Useful for inheriting
// constructors in subclasses via "using Base::Base;" statements.
using Base = Wrapper<EnumType>;
// The enum type wrapped by this instantiation of Wrapper.
using BaseType = EnumType;
// The underlying type of the base enum type.
using ValueType = typename UnderlyingType<BaseType>::Type;
// A default constructor is not defined here. Subclasses should define one
// as appropriate to define the correct inital value for the enum type.
// Default copy constructor.
Wrapper(const Wrapper&) = default;
// Implicit conversion from ValueType.
// NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(ValueType value) : value(value) {}
// Implicit conversion from BaseType.
// NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
// Implicit conversion from an enum type of the same underlying type.
template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
// NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
// Implicit conversion to BaseType.
// NOLINTNEXTLINE(google-explicit-constructor)
operator BaseType() const { return static_cast<BaseType>(value); }
// Implicit conversion to ValueType.
// NOLINTNEXTLINE(google-explicit-constructor)
operator ValueType() const { return value; }
template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
T cast() const {
return static_cast<T>(value);
}
// Converts to string using HWC2 stringification of BaseType.
std::string to_string() const {
return HWC2::to_string(static_cast<BaseType>(value));
}
bool operator!=(const Wrapper& other) const { return value != other.value; }
bool operator!=(ValueType other_value) const { return value != other_value; }
bool operator!=(BaseType other_value) const {
return static_cast<BaseType>(value) != other_value;
}
bool operator==(const Wrapper& other) const { return value == other.value; }
bool operator==(ValueType other_value) const { return value == other_value; }
bool operator==(BaseType other_value) const {
return static_cast<BaseType>(value) == other_value;
}
ValueType value;
};
struct Attribute final : public Wrapper<HWC2::Attribute> {
enum : ValueType {
Invalid = HWC2_ATTRIBUTE_INVALID,
Width = HWC2_ATTRIBUTE_WIDTH,
Height = HWC2_ATTRIBUTE_HEIGHT,
VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD,
DpiX = HWC2_ATTRIBUTE_DPI_X,
DpiY = HWC2_ATTRIBUTE_DPI_Y,
};
Attribute() : Base(Invalid) {}
using Base::Base;
};
struct BlendMode final : public Wrapper<HWC2::BlendMode> {
enum : ValueType {
Invalid = HWC2_BLEND_MODE_INVALID,
None = HWC2_BLEND_MODE_NONE,
Premultiplied = HWC2_BLEND_MODE_PREMULTIPLIED,
Coverage = HWC2_BLEND_MODE_COVERAGE,
};
BlendMode() : Base(Invalid) {}
using Base::Base;
};
struct Composition final : public Wrapper<HWC2::Composition> {
enum : ValueType {
Invalid = HWC2_COMPOSITION_INVALID,
Client = HWC2_COMPOSITION_CLIENT,
Device = HWC2_COMPOSITION_DEVICE,
SolidColor = HWC2_COMPOSITION_SOLID_COLOR,
Cursor = HWC2_COMPOSITION_CURSOR,
Sideband = HWC2_COMPOSITION_SIDEBAND,
};
Composition() : Base(Invalid) {}
using Base::Base;
};
struct DisplayType final : public Wrapper<HWC2::DisplayType> {
enum : ValueType {
Invalid = HWC2_DISPLAY_TYPE_INVALID,
Physical = HWC2_DISPLAY_TYPE_PHYSICAL,
Virtual = HWC2_DISPLAY_TYPE_VIRTUAL,
};
DisplayType() : Base(Invalid) {}
using Base::Base;
};
struct Error final : public Wrapper<HWC2::Error> {
enum : ValueType {
None = HWC2_ERROR_NONE,
BadConfig = HWC2_ERROR_BAD_CONFIG,
BadDisplay = HWC2_ERROR_BAD_DISPLAY,
BadLayer = HWC2_ERROR_BAD_LAYER,
BadParameter = HWC2_ERROR_BAD_PARAMETER,
HasChanges = HWC2_ERROR_HAS_CHANGES,
NoResources = HWC2_ERROR_NO_RESOURCES,
NotValidated = HWC2_ERROR_NOT_VALIDATED,
Unsupported = HWC2_ERROR_UNSUPPORTED,
};
Error() : Base(None) {}
using Base::Base;
};
struct LayerRequest final : public Wrapper<HWC2::LayerRequest> {
enum : ValueType {
ClearClientTarget = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET,
};
LayerRequest() : Base(0) {}
using Base::Base;
};
struct PowerMode final : public Wrapper<HWC2::PowerMode> {
enum : ValueType {
Off = HWC2_POWER_MODE_OFF,
DozeSuspend = HWC2_POWER_MODE_DOZE_SUSPEND,
Doze = HWC2_POWER_MODE_DOZE,
On = HWC2_POWER_MODE_ON,
};
PowerMode() : Base(Off) {}
using Base::Base;
};
struct Transform final : public Wrapper<HWC2::Transform> {
enum : ValueType {
None = 0,
FlipH = HWC_TRANSFORM_FLIP_H,
FlipV = HWC_TRANSFORM_FLIP_V,
Rotate90 = HWC_TRANSFORM_ROT_90,
Rotate180 = HWC_TRANSFORM_ROT_180,
Rotate270 = HWC_TRANSFORM_ROT_270,
FlipHRotate90 = HWC_TRANSFORM_FLIP_H_ROT_90,
FlipVRotate90 = HWC_TRANSFORM_FLIP_V_ROT_90,
};
Transform() : Base(None) {}
using Base::Base;
};
struct Vsync final : public Wrapper<HWC2::Vsync> {
enum : ValueType {
Invalid = HWC2_VSYNC_INVALID,
Enable = HWC2_VSYNC_ENABLE,
Disable = HWC2_VSYNC_DISABLE,
};
Vsync() : Base(Invalid) {}
using Base::Base;
};
// Utility color type.
struct Color final {
Color(const Color&) = default;
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
// NOLINTNEXTLINE(google-explicit-constructor)
Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
// NOLINTNEXTLINE(google-explicit-constructor)
operator hwc_color_t() const { return {r, g, b, a}; }
uint8_t r __attribute__((aligned(1)));
uint8_t g __attribute__((aligned(1)));
uint8_t b __attribute__((aligned(1)));
uint8_t a __attribute__((aligned(1)));
};
// Utility rectangle type.
struct Rect final {
// TODO(eieio): Implicit conversion to/from Android rect types.
int32_t left __attribute__((aligned(4)));
int32_t top __attribute__((aligned(4)));
int32_t right __attribute__((aligned(4)));
int32_t bottom __attribute__((aligned(4)));
};
} // namespace HWC
#endif // ANDROID_LIBVRFLINGER_HWCTYPES_H