drm_hwcomposer: Implement getHdrCapabilities and getColorModes Retrieve color and HDR information from the EDID. Change-Id: I1aac27644d5c4fd5d5f295ca32b69ed69e94e0c6 Signed-off-by: Sasha McIntosh <sashamcintosh@google.com>
diff --git a/Android.bp b/Android.bp index fab7a98..796696c 100644 --- a/Android.bp +++ b/Android.bp
@@ -102,9 +102,9 @@ "hwc2_device/HwcLayer.cpp", "hwc2_device/hwc2_device.cpp", + "utils/LibdisplayEdidWrapper.cpp", "utils/fd.cpp", "utils/properties.cpp", - "utils/LibdisplayEdidWrapper.cpp", ], }
diff --git a/compositor/DisplayInfo.h b/compositor/DisplayInfo.h index 6ddc66f..f580d99 100644 --- a/compositor/DisplayInfo.h +++ b/compositor/DisplayInfo.h
@@ -18,6 +18,31 @@ #include <cstdint> +/* + * Display colorimetry enums. + */ +// NOLINTBEGIN(readability-identifier-naming) +enum class Colormode : int32_t { + kNative, + kBt601_625, + kBt601_625Unadjusted, + kBt601_525, + kBt601_525Unadjusted, + kBt709, + kDciP3, + kSrgb, + kAdobeRgb, + kDisplayP3, + kBt2020, + kBt2100Pq, + kBt2100Hlg, + kDisplayBt2020, +}; +// NOLINTEND(readability-identifier-naming) + +/** + * Display panel colorspace property values. + */ enum class Colorspace : int32_t { kDefault, kSmpte170MYcc,
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 5abbc4d..16d8bac 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp
@@ -613,11 +613,23 @@ } HWC2::Error HwcDisplay::GetColorModes(uint32_t *num_modes, int32_t *modes) { - if (!modes) - *num_modes = 1; + if (!modes) { + std::vector<Colormode> temp_modes; + GetEdid()->GetColorModes(temp_modes); + *num_modes = temp_modes.size(); + return HWC2::Error::None; + } - if (modes) - *modes = HAL_COLOR_MODE_NATIVE; + std::vector<Colormode> temp_modes; + std::vector<int32_t> out_modes(modes, modes + *num_modes); + GetEdid()->GetColorModes(temp_modes); + if (temp_modes.empty()) { + out_modes.emplace_back(HAL_COLOR_MODE_NATIVE); + return HWC2::Error::None; + } + + for (auto &c : temp_modes) + out_modes.emplace_back(static_cast<int32_t>(c)); return HWC2::Error::None; } @@ -733,12 +745,35 @@ return HWC2::Error::None; } -HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types, - int32_t * /*types*/, - float * /*max_luminance*/, - float * /*max_average_luminance*/, - float * /*min_luminance*/) { - *num_types = 0; +HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types, int32_t *types, + float *max_luminance, + float *max_average_luminance, + float *min_luminance) { + if (!types) { + std::vector<ui::Hdr> temp_types; + float lums[3] = {0.F}; + GetEdid()->GetHdrCapabilities(temp_types, &lums[0], &lums[1], &lums[2]); + *num_types = temp_types.size(); + return HWC2::Error::None; + } + + std::vector<ui::Hdr> temp_types; + std::vector<int32_t> out_types(types, types + *num_types); + GetEdid()->GetHdrCapabilities(temp_types, max_luminance, + max_average_luminance, min_luminance); + for (auto &t : temp_types) { + switch (t) { + case ui::Hdr::HDR10: + out_types.emplace_back(HAL_HDR_HDR10); + break; + case ui::Hdr::HLG: + out_types.emplace_back(HAL_HDR_HLG); + break; + default: + // Ignore any other HDR types + break; + } + } return HWC2::Error::None; } @@ -983,18 +1018,6 @@ staged_mode_change_time_ = change_time; staged_mode_config_id_ = config; - std::vector<ui::Hdr> hdr_types; - GetEdid()->GetSupportedHdrTypes(hdr_types); - if (hdr_types.empty()) { - hdr_metadata_.reset(); - colorspace_ = Colorspace::kDefault; - } else { - auto ret = SetHdrOutputMetadata(hdr_types.front()); - if (ret != HWC2::Error::None) - return ret; - colorspace_ = Colorspace::kBt2020Rgb; - } - return HWC2::Error::None; } @@ -1056,29 +1079,47 @@ /* Maps to the Colorspace DRM connector property: * https://elixir.bootlin.com/linux/v6.11/source/include/drm/drm_connector.h#L538 */ - if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_P3) + if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_BT2020) return HWC2::Error::BadParameter; switch (mode) { case HAL_COLOR_MODE_NATIVE: + hdr_metadata_.reset(); colorspace_ = Colorspace::kDefault; break; case HAL_COLOR_MODE_STANDARD_BT601_625: case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED: case HAL_COLOR_MODE_STANDARD_BT601_525: case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED: + hdr_metadata_.reset(); // The DP spec does not say whether this is the 525 or the 625 line version. colorspace_ = Colorspace::kBt601Ycc; break; case HAL_COLOR_MODE_STANDARD_BT709: case HAL_COLOR_MODE_SRGB: + hdr_metadata_.reset(); colorspace_ = Colorspace::kBt709Ycc; break; case HAL_COLOR_MODE_DCI_P3: case HAL_COLOR_MODE_DISPLAY_P3: + hdr_metadata_.reset(); colorspace_ = Colorspace::kDciP3RgbD65; break; + case HAL_COLOR_MODE_DISPLAY_BT2020: { + std::vector<ui::Hdr> hdr_types; + GetEdid()->GetSupportedHdrTypes(hdr_types); + if (!hdr_types.empty()) { + auto ret = SetHdrOutputMetadata(hdr_types.front()); + if (ret != HWC2::Error::None) + return ret; + } + colorspace_ = Colorspace::kBt2020Rgb; + break; + } case HAL_COLOR_MODE_ADOBE_RGB: + case HAL_COLOR_MODE_BT2020: + case HAL_COLOR_MODE_BT2100_PQ: + case HAL_COLOR_MODE_BT2100_HLG: default: return HWC2::Error::Unsupported; }
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index 24c7465..7522c8d 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h
@@ -22,6 +22,8 @@ #include <optional> #include <sstream> +#include <ui/GraphicTypes.h> + #include "HwcDisplayConfigs.h" #include "compositor/DisplayInfo.h" #include "compositor/FlatteningController.h"
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp index 04beb3a..ff3d42e 100644 --- a/hwc3/ComposerClient.cpp +++ b/hwc3/ComposerClient.cpp
@@ -941,8 +941,28 @@ return ToBinderStatus(hwc3::Error::kBadDisplay); } - /* No HDR capabilities */ - caps->types.clear(); + uint32_t num_types = 0; + hwc3::Error error = Hwc2toHwc3Error( + display->GetHdrCapabilities(&num_types, nullptr, nullptr, nullptr, + nullptr)); + if (error != hwc3::Error::kNone) { + return ToBinderStatus(error); + } + + std::vector<int32_t> out_types(num_types); + error = Hwc2toHwc3Error( + display->GetHdrCapabilities(&num_types, out_types.data(), + &caps->maxLuminance, + &caps->maxAverageLuminance, + &caps->minLuminance)); + if (error != hwc3::Error::kNone) { + return ToBinderStatus(error); + } + + caps->types.reserve(num_types); + for (const auto type : out_types) + caps->types.emplace_back(Hwc2HdrTypeToHwc3(type)); + return ndk::ScopedAStatus::ok(); }
diff --git a/hwc3/Utils.h b/hwc3/Utils.h index b322f5d..642c777 100644 --- a/hwc3/Utils.h +++ b/hwc3/Utils.h
@@ -16,6 +16,7 @@ #pragma once +#include <aidl/android/hardware/graphics/common/Hdr.h> #include <aidl/android/hardware/graphics/composer3/IComposerClient.h> #include <hardware/hwcomposer2.h> #include <log/log.h> @@ -165,4 +166,12 @@ return static_cast<int32_t>(dataspace); } -}; // namespace aidl::android::hardware::graphics::composer3 \ No newline at end of file +// Values appear to match. +// https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Hdr.aidl +// https://cs.android.com/android/platform/superproject/main/+/main:system/core/libsystem/include/system/graphics-base-v1.0.h;l=130;drc=7d940ae4afa450696afa25e07982f3a95e17e9b2 +// https://cs.android.com/android/platform/superproject/main/+/main:system/core/libsystem/include/system/graphics-base-v1.2.h;l=12;drc=af7be7616859f8e9e57710b9c37c66cf880a6643 +inline common::Hdr Hwc2HdrTypeToHwc3(int32_t hdr_type) { + return static_cast<common::Hdr>(hdr_type); +} + +}; // namespace aidl::android::hardware::graphics::composer3
diff --git a/utils/EdidWrapper.h b/utils/EdidWrapper.h index 867d1a0..30124d7 100644 --- a/utils/EdidWrapper.h +++ b/utils/EdidWrapper.h
@@ -16,8 +16,6 @@ #pragma once -#define LOG_TAG "drmhwc" - #if HAS_LIBDISPLAY_INFO extern "C" { #include <libdisplay-info/info.h> @@ -26,8 +24,8 @@ #include <ui/GraphicTypes.h> +#include "compositor/DisplayInfo.h" #include "drm/DrmUnique.h" -#include "utils/log.h" namespace android { @@ -47,6 +45,9 @@ const float * /*min_luminance*/) { GetSupportedHdrTypes(types); }; + virtual void GetColorModes(std::vector<Colormode> &color_modes) { + color_modes.clear(); + }; }; #if HAS_LIBDISPLAY_INFO @@ -67,6 +68,8 @@ const float *max_average_luminance, const float *min_luminance) override; + void GetColorModes(std::vector<Colormode> &color_modes) override; + private: LibdisplayEdidWrapper(di_info *info) : info_(std::move(info)) { }
diff --git a/utils/LibdisplayEdidWrapper.cpp b/utils/LibdisplayEdidWrapper.cpp index 5a17b93..d2d2a1c 100644 --- a/utils/LibdisplayEdidWrapper.cpp +++ b/utils/LibdisplayEdidWrapper.cpp
@@ -17,6 +17,7 @@ #define LOG_TAG "drmhwc" #if HAS_LIBDISPLAY_INFO + #include "utils/EdidWrapper.h" #include "utils/log.h" @@ -63,5 +64,36 @@ min_luminance = &hdr_static_meta->desired_content_min_luminance; } +void LibdisplayEdidWrapper::GetColorModes(std::vector<Colormode> &color_modes) { + color_modes.clear(); + color_modes.emplace_back(Colormode::kNative); + + const auto *hdr_static_meta = di_info_get_hdr_static_metadata(info_); + const auto *colorimetries = di_info_get_supported_signal_colorimetry(info_); + + /* Rec. ITU-R BT.2020 constant luminance YCbCr */ + /* Rec. ITU-R BT.2020 non-constant luminance YCbCr */ + if (colorimetries->bt2020_cycc || colorimetries->bt2020_ycc) + color_modes.emplace_back(Colormode::kBt2020); + + /* Rec. ITU-R BT.2020 RGB */ + if (colorimetries->bt2020_rgb) + color_modes.emplace_back(Colormode::kDisplayBt2020); + + /* SMPTE ST 2113 RGB: P3D65 and P3DCI */ + if (colorimetries->st2113_rgb) { + color_modes.emplace_back(Colormode::kDciP3); + color_modes.emplace_back(Colormode::kDisplayP3); + } + + /* Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG) */ + if (colorimetries->ictcp) { + if (hdr_static_meta->pq) + color_modes.emplace_back(Colormode::kBt2100Pq); + if (hdr_static_meta->hlg) + color_modes.emplace_back(Colormode::kBt2100Hlg); + } +} + } // namespace android #endif