1
0
Fork 0

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>
This commit is contained in:
Sasha McIntosh 2024-12-04 17:14:55 -05:00
parent f9062b6964
commit 851ea4dc26
8 changed files with 162 additions and 30 deletions

View file

@ -102,9 +102,9 @@ filegroup {
"hwc2_device/HwcLayer.cpp",
"hwc2_device/hwc2_device.cpp",
"utils/LibdisplayEdidWrapper.cpp",
"utils/fd.cpp",
"utils/properties.cpp",
"utils/LibdisplayEdidWrapper.cpp",
],
}

View file

@ -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,

View file

@ -613,11 +613,23 @@ HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height,
}
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 @@ HWC2::Error HwcDisplay::GetDozeSupport(int32_t *support) {
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 @@ HWC2::Error HwcDisplay::SetActiveConfigInternal(uint32_t config,
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 @@ HWC2::Error HwcDisplay::SetColorMode(int32_t mode) {
/* 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;
}

View file

@ -22,6 +22,8 @@
#include <optional>
#include <sstream>
#include <ui/GraphicTypes.h>
#include "HwcDisplayConfigs.h"
#include "compositor/DisplayInfo.h"
#include "compositor/FlatteningController.h"

View file

@ -941,8 +941,28 @@ ndk::ScopedAStatus ComposerClient::getHdrCapabilities(int64_t display_id,
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();
}

View file

@ -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 @@ inline int32_t Hwc3DataspaceToHwc2(common::Dataspace dataspace) {
return static_cast<int32_t>(dataspace);
}
}; // namespace aidl::android::hardware::graphics::composer3
// 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

View file

@ -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 @@ extern "C" {
#include <ui/GraphicTypes.h>
#include "compositor/DisplayInfo.h"
#include "drm/DrmUnique.h"
#include "utils/log.h"
namespace android {
@ -47,6 +45,9 @@ class EdidWrapper {
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 @@ class LibdisplayEdidWrapper final : public EdidWrapper {
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)) {
}

View file

@ -17,6 +17,7 @@
#define LOG_TAG "drmhwc"
#if HAS_LIBDISPLAY_INFO
#include "utils/EdidWrapper.h"
#include "utils/log.h"
@ -63,5 +64,36 @@ void LibdisplayEdidWrapper::GetHdrCapabilities(
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