1
0
Fork 0

drm_hwcomposer: Remove SetColorMode HWC2 API

Add generic API for Set/GetColorMode and move HWC2 specific behavior to
hwc2_device.

Remove HwcDisplay::SetColorModeWithIntent, as the only supported intent
is colormetric.

Rename Colormode to ColorMode.

Fix contract between color mode and render intent. All supported color
modes should have a supported render intent (COLORMETRIC at least).

Change-Id: Ic1002b630f925e1ea75cb6ad7822b1384010143e
Signed-off-by: Sasha McIntosh <sashamcintosh@google.com>
This commit is contained in:
Sasha McIntosh 2025-05-05 16:26:44 -04:00
parent 93132f482c
commit 574a22f721
8 changed files with 164 additions and 172 deletions

View file

@ -639,33 +639,51 @@ auto HwcDisplay::DestroyLayer(ILayerId layer_id) -> bool {
return count != 0;
}
HWC2::Error HwcDisplay::GetColorModes(uint32_t *num_modes, int32_t *modes) {
if (IsInHeadlessMode()) {
*num_modes = 1;
if (modes)
modes[0] = HAL_COLOR_MODE_NATIVE;
return HWC2::Error::None;
auto HwcDisplay::GetColorModes() -> std::vector<ColorMode> {
if (IsInHeadlessMode())
return {ColorMode::kNative};
std::vector<ColorMode> modes;
GetEdid()->GetColorModes(modes);
if (modes.empty())
modes.emplace_back(ColorMode::kNative);
return modes;
}
void HwcDisplay::SetColorMode(ColorMode mode) {
/* Maps to the Colorspace DRM connector property:
* https://elixir.bootlin.com/linux/v6.11/source/include/drm/drm_connector.h#L538
*/
switch (mode) {
case ColorMode::kNative:
colorspace_ = Colorspace::kDefault;
break;
case ColorMode::kBt601_625:
case ColorMode::kBt601_625Unadjusted:
case ColorMode::kBt601_525:
case ColorMode::kBt601_525Unadjusted:
// The DP spec does not say whether this is the 525 or the 625 line version.
colorspace_ = Colorspace::kBt601Ycc;
break;
case ColorMode::kBt709:
case ColorMode::kSrgb:
colorspace_ = Colorspace::kBt709Ycc;
break;
case ColorMode::kDciP3:
case ColorMode::kDisplayP3:
colorspace_ = Colorspace::kDciP3RgbD65;
break;
case ColorMode::kDisplayBt2020:
case ColorMode::kAdobeRgb:
case ColorMode::kBt2020:
case ColorMode::kBt2100Pq:
case ColorMode::kBt2100Hlg:
// HDR color modes should be requested during modeset
ALOGW("HDR color modes are not supported with this API.");
return;
}
if (!modes) {
std::vector<Colormode> temp_modes;
GetEdid()->GetColorModes(temp_modes);
*num_modes = temp_modes.size();
return HWC2::Error::None;
}
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;
}
HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types, int32_t *types,
@ -924,45 +942,6 @@ bool HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
return true;
}
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_BT2020)
return HWC2::Error::BadParameter;
switch (mode) {
case HAL_COLOR_MODE_NATIVE:
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:
// 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:
colorspace_ = Colorspace::kBt709Ycc;
break;
case HAL_COLOR_MODE_DCI_P3:
case HAL_COLOR_MODE_DISPLAY_P3:
colorspace_ = Colorspace::kDciP3RgbD65;
break;
case HAL_COLOR_MODE_DISPLAY_BT2020:
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;
}
color_mode_ = mode;
return HWC2::Error::None;
}
HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) {
if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
@ -1132,40 +1111,6 @@ HWC2::Error HwcDisplay::SetHdrOutputMetadata(ui::Hdr type) {
return HWC2::Error::None;
}
#if __ANDROID_API__ > 27
HWC2::Error HwcDisplay::GetRenderIntents(
int32_t mode, uint32_t *outNumIntents,
int32_t * /*android_render_intent_v1_1_t*/ outIntents) {
if (mode != HAL_COLOR_MODE_NATIVE) {
return HWC2::Error::BadParameter;
}
if (outIntents == nullptr) {
*outNumIntents = 1;
return HWC2::Error::None;
}
*outNumIntents = 1;
outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC;
return HWC2::Error::None;
}
HWC2::Error HwcDisplay::SetColorModeWithIntent(int32_t mode, int32_t intent) {
if (intent < HAL_RENDER_INTENT_COLORIMETRIC ||
intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE)
return HWC2::Error::BadParameter;
if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
return HWC2::Error::Unsupported;
auto err = SetColorMode(mode);
if (err != HWC2::Error::None) return err;
return HWC2::Error::None;
}
#endif /* __ANDROID_API__ > 27 */
const Backend *HwcDisplay::backend() const {
return backend_.get();
}

View file

@ -151,18 +151,14 @@ class HwcDisplay {
auto CreateLayer(ILayerId new_layer_id) -> bool;
auto DestroyLayer(ILayerId layer_id) -> bool;
auto GetColorModes() -> std::vector<ColorMode>;
void SetColorMode(ColorMode color_mode);
// HWC2 Hooks - these should not be used outside of the hwc2 device.
HWC2::Error GetColorModes(uint32_t *num_modes, int32_t *modes);
#if __ANDROID_API__ > 27
HWC2::Error GetRenderIntents(int32_t mode, uint32_t *outNumIntents,
int32_t *outIntents);
HWC2::Error SetColorModeWithIntent(int32_t mode, int32_t intent);
#endif
HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types,
float *max_luminance,
float *max_average_luminance,
float *min_luminance);
HWC2::Error SetColorMode(int32_t mode);
HWC2::Error SetColorTransform(const float *matrix, int32_t hint);
bool IsWritebackSupported();
@ -264,7 +260,6 @@ class HwcDisplay {
std::unique_ptr<HwcLayer> writeback_layer_;
uint16_t virtual_disp_width_{};
uint16_t virtual_disp_height_{};
int32_t color_mode_{};
std::shared_ptr<drm_color_ctm> color_matrix_;
std::shared_ptr<drm_color_ctm> identity_color_matrix_;
android_color_transform_t color_transform_hint_{};

View file

@ -17,6 +17,7 @@
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
// #define LOG_NDEBUG 0 // Uncomment to see HWC2 API calls in logcat
#include "system/graphics-base-v1.1.h"
#define LOG_TAG "drmhwc"
#include <cassert>
@ -467,6 +468,24 @@ static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
return 0;
}
static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display,
uint32_t *num_modes, int32_t *out_modes) {
ALOGV("GetColorModes");
LOCK_COMPOSER(device);
GET_DISPLAY(display);
const std::vector<ColorMode> modes = idisplay->GetColorModes();
if (modes.empty())
return static_cast<int32_t>(HWC2::Error::BadConfig);
for (uint32_t i = 0; i < modes.size(); ++i) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic):
out_modes[i] = static_cast<int32_t>(modes[i]);
}
*num_modes = modes.size();
return 0;
}
static int32_t GetDisplayAttribute(hwc2_device_t *device,
hwc2_display_t display, hwc2_config_t config,
int32_t attribute, int32_t *value) {
@ -577,6 +596,32 @@ static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display,
strncpy(name, name_str.c_str(), *size);
return 0;
}
static int32_t SetColorMode(hwc2_device_t *device, hwc2_display_t display, int32_t mode) {
ALOGV("SetColorMode");
if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_BT2020)
return static_cast<int32_t>(HWC2::Error::BadParameter);
// HDR color modes should be requested during modeset
if (mode == HAL_COLOR_MODE_DISPLAY_BT2020 ||
mode == HAL_COLOR_MODE_ADOBE_RGB ||
mode == HAL_COLOR_MODE_BT2020 ||
mode == HAL_COLOR_MODE_BT2100_PQ ||
mode == HAL_COLOR_MODE_BT2100_HLG) {
return static_cast<int32_t>(HWC2::Error::Unsupported);
}
LOCK_COMPOSER(device);
GET_DISPLAY(display);
// Values for color modes match across HWC versions, so static cast is safe:
// https://android.googlesource.com/platform/hardware/interfaces/+/refs/heads/main/graphics/composer/aidl/android/hardware/graphics/composer3/ColorMode.aidl
// https://cs.android.com/android/platform/superproject/main/+/main:system/core/libsystem/include/system/graphics-base-v1.0.h;drc=7d940ae4afa450696afa25e07982f3a95e17e9b2;l=118
// https://cs.android.com/android/platform/superproject/main/+/main:system/core/libsystem/include/system/graphics-base-v1.1.h;drc=7d940ae4afa450696afa25e07982f3a95e17e9b2;l=35
idisplay->SetColorMode(static_cast<ColorMode>(mode));
return 0;
}
static int32_t SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
buffer_handle_t buffer, int32_t release_fence) {
ALOGV("SetOutputBuffer");
@ -786,6 +831,36 @@ static int32_t SetDisplayBrightness(hwc2_device_t * /*device*/,
return static_cast<int32_t>(HWC2::Error::Unsupported);
}
static int32_t GetRenderIntents(hwc2_device_t * /*device*/,
hwc2_display_t /*display*/, int32_t mode,
uint32_t *num_intents, int32_t *intents) {
ALOGV("GetRenderIntents");
if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_BT2020)
return static_cast<int32_t>(HWC2::Error::BadParameter);
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic):
intents[0] = static_cast<int32_t>(HAL_RENDER_INTENT_COLORIMETRIC);
*num_intents = 1;
return 0;
}
static int32_t SetColorModeWithRenderIntent(hwc2_device_t *device,
hwc2_display_t display,
int32_t mode, int32_t intent) {
ALOGV("SetColorModeWithRenderIntent");
if (mode < HAL_RENDER_INTENT_COLORIMETRIC ||
mode > HAL_RENDER_INTENT_TONE_MAP_ENHANCE) {
return static_cast<int32_t>(HWC2::Error::BadParameter);
}
if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
return static_cast<int32_t>(HWC2::Error::Unsupported);
return SetColorMode(device, display, mode);
}
static int32_t GetDisplayIdentificationData(hwc2_device_t *device,
hwc2_display_t display,
uint8_t *out_port,
@ -1216,9 +1291,7 @@ static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device * /*dev*/,
case HWC2::FunctionDescriptor::GetClientTargetSupport:
return (hwc2_function_pointer_t)GetClientTargetSupport;
case HWC2::FunctionDescriptor::GetColorModes:
return ToHook<HWC2_PFN_GET_COLOR_MODES>(
DisplayHook<decltype(&HwcDisplay::GetColorModes),
&HwcDisplay::GetColorModes, uint32_t *, int32_t *>);
return (hwc2_function_pointer_t)GetColorModes;
case HWC2::FunctionDescriptor::GetDisplayAttribute:
return (hwc2_function_pointer_t)GetDisplayAttribute;
case HWC2::FunctionDescriptor::GetDisplayConfigs:
@ -1245,9 +1318,7 @@ static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device * /*dev*/,
case HWC2::FunctionDescriptor::SetClientTarget:
return (hwc2_function_pointer_t)SetClientTarget;
case HWC2::FunctionDescriptor::SetColorMode:
return ToHook<HWC2_PFN_SET_COLOR_MODE>(
DisplayHook<decltype(&HwcDisplay::SetColorMode),
&HwcDisplay::SetColorMode, int32_t>);
return (hwc2_function_pointer_t)SetColorMode;
case HWC2::FunctionDescriptor::SetColorTransform:
return ToHook<HWC2_PFN_SET_COLOR_TRANSFORM>(
DisplayHook<decltype(&HwcDisplay::SetColorTransform),
@ -1262,14 +1333,9 @@ static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device * /*dev*/,
return (hwc2_function_pointer_t)ValidateDisplay;
#if __ANDROID_API__ > 27
case HWC2::FunctionDescriptor::GetRenderIntents:
return ToHook<HWC2_PFN_GET_RENDER_INTENTS>(
DisplayHook<decltype(&HwcDisplay::GetRenderIntents),
&HwcDisplay::GetRenderIntents, int32_t, uint32_t *,
int32_t *>);
return (hwc2_function_pointer_t)GetRenderIntents;
case HWC2::FunctionDescriptor::SetColorModeWithRenderIntent:
return ToHook<HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT>(
DisplayHook<decltype(&HwcDisplay::SetColorModeWithIntent),
&HwcDisplay::SetColorModeWithIntent, int32_t, int32_t>);
return (hwc2_function_pointer_t)SetColorModeWithRenderIntent;
#endif
#if __ANDROID_API__ > 28
case HWC2::FunctionDescriptor::GetDisplayIdentificationData: