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