1 #ifndef ANDROID_LIBVRFLINGER_HWCTYPES_H
2 #define ANDROID_LIBVRFLINGER_HWCTYPES_H
3 
4 // General HWC type support. Hardware composer type support is a bit of a mess
5 // between HWC1, HWC2 C/C++11, and HIDL types. Particularly bothersome is the
6 // use of enum classes, which make analogous types between versions much
7 // harder to deal with in a uniform way.
8 //
9 // These utilities help address some of these pains by providing a type-safe,
10 // flexible interface to translate between different type spaces.
11 
12 #define HWC2_INCLUDE_STRINGIFICATION
13 #define HWC2_USE_CPP11
14 #include <hardware/hwcomposer2.h>
15 #undef HWC2_INCLUDE_STRINGIFICATION
16 #undef HWC2_USE_CPP11
17 
18 #include <string>
19 #include <type_traits>
20 
21 namespace HWC {
22 
23 // Value types derived from HWC HAL types. Some of these are stand-alone,
24 // while others are also wrapped in translator classes below.
25 using ColorMode = int32_t;  // android_color_mode_t;
26 using Config = hwc2_config_t;
27 using ColorTransform =
28     std::underlying_type<android_color_transform_t>::type;          // int32_t;
29 using Dataspace = std::underlying_type<android_dataspace_t>::type;  // int32_t;
30 using DisplayId = hwc2_display_t;
31 using DisplayRequest = std::underlying_type<HWC2::DisplayRequest>::type;
32 using Hdr = std::underlying_type<android_hdr_t>::type;  // int32_t;
33 using Layer = hwc2_layer_t;
34 using PixelFormat =
35     std::underlying_type<android_pixel_format_t>::type;  // int32_t;
36 
37 // Type traits and casting utilities.
38 
39 // SFINAE utility to evaluate type expressions.
40 template <typename...>
41 using TestTypeExpression = void;
42 
43 // Traits type to determine the underlying type of an enum, integer,
44 // or wrapper class.
45 template <typename T, typename = typename std::is_enum<T>::type,
46           typename = typename std::is_integral<T>::type, typename = void>
47 struct UnderlyingType {
48   using Type = T;
49 };
50 // Partial specialization that matches enum types. Captures the underlying type
51 // of the enum in member type Type.
52 template <typename T>
53 struct UnderlyingType<T, std::true_type, std::false_type> {
54   using Type = typename std::underlying_type<T>::type;
55 };
56 // Partial specialization that matches integral types. Captures the type of the
57 // integer in member type Type.
58 template <typename T>
59 struct UnderlyingType<T, std::false_type, std::true_type> {
60   using Type = T;
61 };
62 // Partial specialization that matches the wrapper types below. Captures
63 // wrapper member type ValueType in member type Type.
64 template <typename T>
65 struct UnderlyingType<T, std::false_type, std::false_type,
66                       TestTypeExpression<typename T::ValueType>> {
67   using Type = typename T::ValueType;
68 };
69 
70 // Enable if T is an enum with underlying type U.
71 template <typename T, typename U, typename ReturnType = void>
72 using EnableIfMatchingEnum = typename std::enable_if<
73     std::is_enum<T>::value &&
74         std::is_same<U, typename UnderlyingType<T>::Type>::value,
75     ReturnType>::type;
76 
77 // Enable if T and U are the same size/alignment and have the same underlying
78 // type. Handles enum, integral, and wrapper classes below.
79 template <typename T, typename U, typename Return = void>
80 using EnableIfSafeCast = typename std::enable_if<
81     sizeof(T) == sizeof(U) && alignof(T) == alignof(U) &&
82         std::is_same<typename UnderlyingType<T>::Type,
83                      typename UnderlyingType<U>::Type>::value,
84     Return>::type;
85 
86 // Safely cast between std::vectors of matching enum/integer/wraper types.
87 // Normally this is not possible with pendantic compiler type checks. However,
88 // given the same size, alignment, and underlying type this is safe due to
89 // allocator requirements and array-like element access guarantees.
90 template <typename T, typename U>
91 EnableIfSafeCast<T, U, std::vector<T>*> VectorCast(std::vector<U>* in) {
92   return reinterpret_cast<std::vector<T>*>(in);
93 }
94 
95 // Translator classes that wrap specific HWC types to make translating
96 // between different types (especially enum class) in code cleaner.
97 
98 // Base type for the enum wrappers below. This type provides type definitions
99 // and implicit conversion logic common to each wrapper type.
100 template <typename EnumType>
101 struct Wrapper {
102   // Alias type of this instantiantion of Wrapper. Useful for inheriting
103   // constructors in subclasses via "using Base::Base;" statements.
104   using Base = Wrapper<EnumType>;
105 
106   // The enum type wrapped by this instantiation of Wrapper.
107   using BaseType = EnumType;
108 
109   // The underlying type of the base enum type.
110   using ValueType = typename UnderlyingType<BaseType>::Type;
111 
112   // A default constructor is not defined here. Subclasses should define one
113   // as appropriate to define the correct inital value for the enum type.
114 
115   // Default copy constructor.
116   Wrapper(const Wrapper&) = default;
117 
118   // Implicit conversion from ValueType.
119   // NOLINTNEXTLINE(google-explicit-constructor)
120   Wrapper(ValueType value) : value(value) {}
121 
122   // Implicit conversion from BaseType.
123   // NOLINTNEXTLINE(google-explicit-constructor)
124   Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
125 
126   // Implicit conversion from an enum type of the same underlying type.
127   template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
128   // NOLINTNEXTLINE(google-explicit-constructor)
129   Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
130 
131   // Implicit conversion to BaseType.
132   // NOLINTNEXTLINE(google-explicit-constructor)
133   operator BaseType() const { return static_cast<BaseType>(value); }
134 
135   // Implicit conversion to ValueType.
136   // NOLINTNEXTLINE(google-explicit-constructor)
137   operator ValueType() const { return value; }
138 
139   template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
140   T cast() const {
141     return static_cast<T>(value);
142   }
143 
144   // Converts to string using HWC2 stringification of BaseType.
145   std::string to_string() const {
146     return HWC2::to_string(static_cast<BaseType>(value));
147   }
148 
149   bool operator!=(const Wrapper& other) const { return value != other.value; }
150   bool operator!=(ValueType other_value) const { return value != other_value; }
151   bool operator!=(BaseType other_value) const {
152     return static_cast<BaseType>(value) != other_value;
153   }
154   bool operator==(const Wrapper& other) const { return value == other.value; }
155   bool operator==(ValueType other_value) const { return value == other_value; }
156   bool operator==(BaseType other_value) const {
157     return static_cast<BaseType>(value) == other_value;
158   }
159 
160   ValueType value;
161 };
162 
163 struct Attribute final : public Wrapper<HWC2::Attribute> {
164   enum : ValueType {
165     Invalid = HWC2_ATTRIBUTE_INVALID,
166     Width = HWC2_ATTRIBUTE_WIDTH,
167     Height = HWC2_ATTRIBUTE_HEIGHT,
168     VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD,
169     DpiX = HWC2_ATTRIBUTE_DPI_X,
170     DpiY = HWC2_ATTRIBUTE_DPI_Y,
171   };
172 
173   Attribute() : Base(Invalid) {}
174   using Base::Base;
175 };
176 
177 struct BlendMode final : public Wrapper<HWC2::BlendMode> {
178   enum : ValueType {
179     Invalid = HWC2_BLEND_MODE_INVALID,
180     None = HWC2_BLEND_MODE_NONE,
181     Premultiplied = HWC2_BLEND_MODE_PREMULTIPLIED,
182     Coverage = HWC2_BLEND_MODE_COVERAGE,
183   };
184 
185   BlendMode() : Base(Invalid) {}
186   using Base::Base;
187 };
188 
189 struct Composition final : public Wrapper<HWC2::Composition> {
190   enum : ValueType {
191     Invalid = HWC2_COMPOSITION_INVALID,
192     Client = HWC2_COMPOSITION_CLIENT,
193     Device = HWC2_COMPOSITION_DEVICE,
194     SolidColor = HWC2_COMPOSITION_SOLID_COLOR,
195     Cursor = HWC2_COMPOSITION_CURSOR,
196     Sideband = HWC2_COMPOSITION_SIDEBAND,
197   };
198 
199   Composition() : Base(Invalid) {}
200   using Base::Base;
201 };
202 
203 struct DisplayType final : public Wrapper<HWC2::DisplayType> {
204   enum : ValueType {
205     Invalid = HWC2_DISPLAY_TYPE_INVALID,
206     Physical = HWC2_DISPLAY_TYPE_PHYSICAL,
207     Virtual = HWC2_DISPLAY_TYPE_VIRTUAL,
208   };
209 
210   DisplayType() : Base(Invalid) {}
211   using Base::Base;
212 };
213 
214 struct Error final : public Wrapper<HWC2::Error> {
215   enum : ValueType {
216     None = HWC2_ERROR_NONE,
217     BadConfig = HWC2_ERROR_BAD_CONFIG,
218     BadDisplay = HWC2_ERROR_BAD_DISPLAY,
219     BadLayer = HWC2_ERROR_BAD_LAYER,
220     BadParameter = HWC2_ERROR_BAD_PARAMETER,
221     HasChanges = HWC2_ERROR_HAS_CHANGES,
222     NoResources = HWC2_ERROR_NO_RESOURCES,
223     NotValidated = HWC2_ERROR_NOT_VALIDATED,
224     Unsupported = HWC2_ERROR_UNSUPPORTED,
225   };
226 
227   Error() : Base(None) {}
228   using Base::Base;
229 };
230 
231 struct LayerRequest final : public Wrapper<HWC2::LayerRequest> {
232   enum : ValueType {
233     ClearClientTarget = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET,
234   };
235 
236   LayerRequest() : Base(0) {}
237   using Base::Base;
238 };
239 
240 struct PowerMode final : public Wrapper<HWC2::PowerMode> {
241   enum : ValueType {
242     Off = HWC2_POWER_MODE_OFF,
243     DozeSuspend = HWC2_POWER_MODE_DOZE_SUSPEND,
244     Doze = HWC2_POWER_MODE_DOZE,
245     On = HWC2_POWER_MODE_ON,
246   };
247 
248   PowerMode() : Base(Off) {}
249   using Base::Base;
250 };
251 
252 struct Transform final : public Wrapper<HWC2::Transform> {
253   enum : ValueType {
254     None = 0,
255     FlipH = HWC_TRANSFORM_FLIP_H,
256     FlipV = HWC_TRANSFORM_FLIP_V,
257     Rotate90 = HWC_TRANSFORM_ROT_90,
258     Rotate180 = HWC_TRANSFORM_ROT_180,
259     Rotate270 = HWC_TRANSFORM_ROT_270,
260     FlipHRotate90 = HWC_TRANSFORM_FLIP_H_ROT_90,
261     FlipVRotate90 = HWC_TRANSFORM_FLIP_V_ROT_90,
262   };
263 
264   Transform() : Base(None) {}
265   using Base::Base;
266 };
267 
268 struct Vsync final : public Wrapper<HWC2::Vsync> {
269   enum : ValueType {
270     Invalid = HWC2_VSYNC_INVALID,
271     Enable = HWC2_VSYNC_ENABLE,
272     Disable = HWC2_VSYNC_DISABLE,
273   };
274 
275   Vsync() : Base(Invalid) {}
276   using Base::Base;
277 };
278 
279 // Utility color type.
280 struct Color final {
281   Color(const Color&) = default;
282   Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
283   // NOLINTNEXTLINE(google-explicit-constructor)
284   Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
285 
286   // NOLINTNEXTLINE(google-explicit-constructor)
287   operator hwc_color_t() const { return {r, g, b, a}; }
288 
289   uint8_t r __attribute__((aligned(1)));
290   uint8_t g __attribute__((aligned(1)));
291   uint8_t b __attribute__((aligned(1)));
292   uint8_t a __attribute__((aligned(1)));
293 };
294 
295 // Utility rectangle type.
296 struct Rect final {
297   // TODO(eieio): Implicit conversion to/from Android rect types.
298 
299   int32_t left __attribute__((aligned(4)));
300   int32_t top __attribute__((aligned(4)));
301   int32_t right __attribute__((aligned(4)));
302   int32_t bottom __attribute__((aligned(4)));
303 };
304 
305 }  // namespace HWC
306 
307 #endif  // ANDROID_LIBVRFLINGER_HWCTYPES_H
308