| /* | 
 |  * Copyright 2020 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #pragma once | 
 |  | 
 | #include <cstdint> | 
 | #include <ostream> | 
 | #include <string> | 
 |  | 
 | #include <ftl/optional.h> | 
 |  | 
 | namespace android { | 
 |  | 
 | // ID of a physical or a virtual display. This class acts as a type safe wrapper around uint64_t. | 
 | // The encoding of the ID is type-specific for bits 0 to 61. | 
 | struct DisplayId { | 
 |     // Flag indicating that the display is virtual. | 
 |     static constexpr uint64_t FLAG_VIRTUAL = 1ULL << 63; | 
 |  | 
 |     // Flag indicating that the ID is stable across reboots. | 
 |     static constexpr uint64_t FLAG_STABLE = 1ULL << 62; | 
 |  | 
 |     // TODO(b/162612135) Remove default constructor | 
 |     DisplayId() = default; | 
 |     constexpr DisplayId(const DisplayId&) = default; | 
 |     DisplayId& operator=(const DisplayId&) = default; | 
 |  | 
 |     uint64_t value; | 
 |  | 
 |     // For deserialization. | 
 |     static constexpr std::optional<DisplayId> fromValue(uint64_t); | 
 |  | 
 |     // As above, but also upcast to Id. | 
 |     template <typename Id> | 
 |     static constexpr std::optional<Id> fromValue(uint64_t value) { | 
 |         if (const auto id = Id::tryCast(DisplayId(value))) { | 
 |             return id; | 
 |         } | 
 |         return {}; | 
 |     } | 
 |  | 
 | protected: | 
 |     explicit constexpr DisplayId(uint64_t id) : value(id) {} | 
 | }; | 
 |  | 
 | inline bool operator==(DisplayId lhs, DisplayId rhs) { | 
 |     return lhs.value == rhs.value; | 
 | } | 
 |  | 
 | inline bool operator!=(DisplayId lhs, DisplayId rhs) { | 
 |     return !(lhs == rhs); | 
 | } | 
 |  | 
 | inline std::string to_string(DisplayId displayId) { | 
 |     return std::to_string(displayId.value); | 
 | } | 
 |  | 
 | // For tests. | 
 | inline std::ostream& operator<<(std::ostream& stream, DisplayId displayId) { | 
 |     return stream << "DisplayId{" << displayId.value << '}'; | 
 | } | 
 |  | 
 | // DisplayId of a physical display, such as the internal display or externally connected display. | 
 | struct PhysicalDisplayId : DisplayId { | 
 |     static constexpr ftl::Optional<PhysicalDisplayId> tryCast(DisplayId id) { | 
 |         if (id.value & FLAG_VIRTUAL) { | 
 |             return std::nullopt; | 
 |         } | 
 |         return {PhysicalDisplayId(id)}; | 
 |     } | 
 |  | 
 |     // Returns a stable ID based on EDID information. | 
 |     static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId, | 
 |                                                 uint32_t modelHash) { | 
 |         return PhysicalDisplayId(FLAG_STABLE, port, manufacturerId, modelHash); | 
 |     } | 
 |  | 
 |     // Returns an unstable ID. If EDID is available using "fromEdid" is preferred. | 
 |     static constexpr PhysicalDisplayId fromPort(uint8_t port) { | 
 |         constexpr uint16_t kManufacturerId = 0; | 
 |         constexpr uint32_t kModelHash = 0; | 
 |         return PhysicalDisplayId(0, port, kManufacturerId, kModelHash); | 
 |     } | 
 |  | 
 |     // TODO(b/162612135) Remove default constructor | 
 |     PhysicalDisplayId() = default; | 
 |  | 
 |     constexpr uint16_t getManufacturerId() const { return static_cast<uint16_t>(value >> 40); } | 
 |     constexpr uint8_t getPort() const { return static_cast<uint8_t>(value); } | 
 |  | 
 | private: | 
 |     constexpr PhysicalDisplayId(uint64_t flags, uint8_t port, uint16_t manufacturerId, | 
 |                                 uint32_t modelHash) | 
 |           : DisplayId(flags | (static_cast<uint64_t>(manufacturerId) << 40) | | 
 |                       (static_cast<uint64_t>(modelHash) << 8) | port) {} | 
 |  | 
 |     explicit constexpr PhysicalDisplayId(DisplayId other) : DisplayId(other) {} | 
 | }; | 
 |  | 
 | struct VirtualDisplayId : DisplayId { | 
 |     using BaseId = uint32_t; | 
 |  | 
 |     // Flag indicating that this virtual display is backed by the GPU. | 
 |     static constexpr uint64_t FLAG_GPU = 1ULL << 61; | 
 |  | 
 |     static constexpr std::optional<VirtualDisplayId> tryCast(DisplayId id) { | 
 |         if (id.value & FLAG_VIRTUAL) { | 
 |             return {VirtualDisplayId(id)}; | 
 |         } | 
 |         return std::nullopt; | 
 |     } | 
 |  | 
 | protected: | 
 |     constexpr VirtualDisplayId(uint64_t flags, BaseId baseId) | 
 |           : DisplayId(DisplayId::FLAG_VIRTUAL | flags | baseId) {} | 
 |  | 
 |     explicit constexpr VirtualDisplayId(DisplayId other) : DisplayId(other) {} | 
 | }; | 
 |  | 
 | struct HalVirtualDisplayId : VirtualDisplayId { | 
 |     explicit constexpr HalVirtualDisplayId(BaseId baseId) : VirtualDisplayId(0, baseId) {} | 
 |  | 
 |     static constexpr std::optional<HalVirtualDisplayId> tryCast(DisplayId id) { | 
 |         if ((id.value & FLAG_VIRTUAL) && !(id.value & VirtualDisplayId::FLAG_GPU)) { | 
 |             return {HalVirtualDisplayId(id)}; | 
 |         } | 
 |         return std::nullopt; | 
 |     } | 
 |  | 
 | private: | 
 |     explicit constexpr HalVirtualDisplayId(DisplayId other) : VirtualDisplayId(other) {} | 
 | }; | 
 |  | 
 | struct GpuVirtualDisplayId : VirtualDisplayId { | 
 |     explicit constexpr GpuVirtualDisplayId(BaseId baseId) | 
 |           : VirtualDisplayId(VirtualDisplayId::FLAG_GPU, baseId) {} | 
 |  | 
 |     static constexpr std::optional<GpuVirtualDisplayId> tryCast(DisplayId id) { | 
 |         if ((id.value & FLAG_VIRTUAL) && (id.value & VirtualDisplayId::FLAG_GPU)) { | 
 |             return {GpuVirtualDisplayId(id)}; | 
 |         } | 
 |         return std::nullopt; | 
 |     } | 
 |  | 
 | private: | 
 |     explicit constexpr GpuVirtualDisplayId(DisplayId other) : VirtualDisplayId(other) {} | 
 | }; | 
 |  | 
 | // HalDisplayId is the ID of a display which is managed by HWC. | 
 | // PhysicalDisplayId and HalVirtualDisplayId are implicitly convertible to HalDisplayId. | 
 | struct HalDisplayId : DisplayId { | 
 |     constexpr HalDisplayId(HalVirtualDisplayId other) : DisplayId(other) {} | 
 |     constexpr HalDisplayId(PhysicalDisplayId other) : DisplayId(other) {} | 
 |  | 
 |     static constexpr std::optional<HalDisplayId> tryCast(DisplayId id) { | 
 |         if (GpuVirtualDisplayId::tryCast(id)) { | 
 |             return std::nullopt; | 
 |         } | 
 |         return {HalDisplayId(id)}; | 
 |     } | 
 |  | 
 | private: | 
 |     explicit constexpr HalDisplayId(DisplayId other) : DisplayId(other) {} | 
 | }; | 
 |  | 
 | constexpr std::optional<DisplayId> DisplayId::fromValue(uint64_t value) { | 
 |     if (const auto id = fromValue<PhysicalDisplayId>(value)) { | 
 |         return id; | 
 |     } | 
 |     if (const auto id = fromValue<VirtualDisplayId>(value)) { | 
 |         return id; | 
 |     } | 
 |     return {}; | 
 | } | 
 |  | 
 | static_assert(sizeof(DisplayId) == sizeof(uint64_t)); | 
 | static_assert(sizeof(HalDisplayId) == sizeof(uint64_t)); | 
 | static_assert(sizeof(VirtualDisplayId) == sizeof(uint64_t)); | 
 |  | 
 | static_assert(sizeof(PhysicalDisplayId) == sizeof(uint64_t)); | 
 | static_assert(sizeof(HalVirtualDisplayId) == sizeof(uint64_t)); | 
 | static_assert(sizeof(GpuVirtualDisplayId) == sizeof(uint64_t)); | 
 |  | 
 | } // namespace android | 
 |  | 
 | namespace std { | 
 |  | 
 | template <> | 
 | struct hash<android::DisplayId> { | 
 |     size_t operator()(android::DisplayId displayId) const { | 
 |         return hash<uint64_t>()(displayId.value); | 
 |     } | 
 | }; | 
 |  | 
 | template <> | 
 | struct hash<android::PhysicalDisplayId> : hash<android::DisplayId> {}; | 
 |  | 
 | template <> | 
 | struct hash<android::HalVirtualDisplayId> : hash<android::DisplayId> {}; | 
 |  | 
 | template <> | 
 | struct hash<android::GpuVirtualDisplayId> : hash<android::DisplayId> {}; | 
 |  | 
 | template <> | 
 | struct hash<android::HalDisplayId> : hash<android::DisplayId> {}; | 
 |  | 
 | } // namespace std |