1
0
Fork 0

drm_hwcomposer: Remove HWC2 SetPowerMode

drm-hwc only supports setting power mode on and off. Add a new function
to HwcDisplay to enable/disable the display, and implement the HWC API
in the frontends in terms of this.

Change-Id: I7a3d92140f4b98bbed9000489e06b8011546ce7e
Signed-off-by: Drew Davenport <ddavenport@google.com>
This commit is contained in:
Drew Davenport 2025-03-27 10:09:45 -06:00
parent 44a3351102
commit 12bca98c92
5 changed files with 71 additions and 63 deletions

View file

@ -483,6 +483,29 @@ void HwcDisplay::SetVsyncCallbacksEnabled(bool enabled) {
vsync_worker_->SetTimestampCallback(std::move(callback));
}
bool HwcDisplay::SetDisplayEnabled(bool enabled) {
if (IsInHeadlessMode()) {
return true;
}
if (enabled) {
/*
* Setting the display to active before we have a composition
* can break some drivers, so skip setting a_args.active to
* true, as the next composition frame will implicitly activate
* the display
*/
return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0;
};
// Disable the display.
AtomicCommitArgs a_args{};
a_args.active = false;
auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
ALOGE_IF(err != 0, "Failed to apply the dpms composition err=%d", err);
return err == 0;
}
void HwcDisplay::SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline) {
Deinit();
@ -1108,50 +1131,6 @@ bool HwcDisplay::CtmByGpu() {
return true;
}
HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
auto mode = static_cast<HWC2::PowerMode>(mode_in);
AtomicCommitArgs a_args{};
switch (mode) {
case HWC2::PowerMode::Off:
a_args.active = false;
break;
case HWC2::PowerMode::On:
a_args.active = true;
break;
case HWC2::PowerMode::Doze:
case HWC2::PowerMode::DozeSuspend:
return HWC2::Error::Unsupported;
default:
ALOGE("Incorrect power mode value (%d)\n", mode_in);
return HWC2::Error::BadParameter;
}
if (IsInHeadlessMode()) {
return HWC2::Error::None;
}
if (a_args.active && *a_args.active) {
/*
* Setting the display to active before we have a composition
* can break some drivers, so skip setting a_args.active to
* true, as the next composition frame will implicitly activate
* the display
*/
return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0
? HWC2::Error::None
: HWC2::Error::BadParameter;
};
auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
if (err) {
ALOGE("Failed to apply the dpms composition err=%d", err);
return HWC2::Error::BadParameter;
}
return HWC2::Error::None;
}
std::vector<HwcLayer *> HwcDisplay::GetOrderLayersByZPos() {
std::vector<HwcLayer *> ordered_layers;
ordered_layers.reserve(layers_.size());

View file

@ -136,6 +136,9 @@ class HwcDisplay {
// Enable or disable vsync callbacks.
void SetVsyncCallbacksEnabled(bool enabled);
// Enable or disable the display.
bool SetDisplayEnabled(bool enabled);
auto GetFrontendPrivateData() -> std::shared_ptr<FrontendDisplayBase> {
return frontend_private_data_;
}
@ -167,7 +170,6 @@ class HwcDisplay {
HWC2::Error ChosePreferredConfig();
HWC2::Error SetColorMode(int32_t mode);
HWC2::Error SetColorTransform(const float *matrix, int32_t hint);
HWC2::Error SetPowerMode(int32_t mode);
HwcLayer *get_layer(ILayerId layer) {
auto it = layers_.find(layer);
if (it == layers_.end())

View file

@ -475,6 +475,34 @@ static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
return static_cast<int32_t>(HWC2::Error::None);
}
static int32_t SetPowerMode(hwc2_device_t *device, hwc2_display_t display,
int32_t mode) {
ALOGV("SetPowerMode");
LOCK_COMPOSER(device);
GET_DISPLAY(display);
switch (mode) {
// Supported modes.
case static_cast<int32_t>(HWC2::PowerMode::Off):
case static_cast<int32_t>(HWC2::PowerMode::On):
break;
// Unsupported modes.
case static_cast<int32_t>(HWC2::PowerMode::Doze):
case static_cast<int32_t>(HWC2::PowerMode::DozeSuspend):
return static_cast<int32_t>(HWC2::Error::Unsupported);
// Bad parameter.
default:
ALOGE("Incorrect power mode value (%d)\n", mode);
return static_cast<int32_t>(HWC2::Error::BadParameter);
}
if (!idisplay->SetDisplayEnabled(mode ==
static_cast<int32_t>(HWC2::PowerMode::On))) {
return static_cast<int32_t>(HWC2::Error::BadParameter);
}
return static_cast<int32_t>(HWC2::Error::None);
}
static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display,
int32_t enabled) {
ALOGV("SetVsyncEnabled");
@ -1037,9 +1065,7 @@ static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device * /*dev*/,
case HWC2::FunctionDescriptor::SetOutputBuffer:
return (hwc2_function_pointer_t)SetOutputBuffer;
case HWC2::FunctionDescriptor::SetPowerMode:
return ToHook<HWC2_PFN_SET_POWER_MODE>(
DisplayHook<decltype(&HwcDisplay::SetPowerMode),
&HwcDisplay::SetPowerMode, int32_t>);
return (hwc2_function_pointer_t)SetPowerMode;
case HWC2::FunctionDescriptor::SetVsyncEnabled:
return (hwc2_function_pointer_t)SetVsyncEnabled;
case HWC2::FunctionDescriptor::ValidateDisplay:

View file

@ -1356,12 +1356,24 @@ ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display_id,
return ToBinderStatus(hwc3::Error::kBadDisplay);
}
if (mode == PowerMode::ON_SUSPEND) {
return ToBinderStatus(hwc3::Error::kUnsupported);
// Only OFF and ON are supported. VTS requires checking for invalid enum
// values.
switch (static_cast<int32_t>(mode)) {
case static_cast<int32_t>(PowerMode::OFF):
case static_cast<int32_t>(PowerMode::ON):
break;
case static_cast<int32_t>(PowerMode::DOZE):
case static_cast<int32_t>(PowerMode::DOZE_SUSPEND):
case static_cast<int32_t>(PowerMode::ON_SUSPEND):
return ToBinderStatus(hwc3::Error::kUnsupported);
default:
return ToBinderStatus(hwc3::Error::kBadParameter);
}
auto error = display->SetPowerMode(Hwc3PowerModeToHwc2(mode));
return ToBinderStatus(Hwc2toHwc3Error(error));
if (!display->SetDisplayEnabled(mode == PowerMode::ON)) {
return ToBinderStatus(hwc3::Error::kBadParameter);
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus ComposerClient::setReadbackBuffer(

View file

@ -100,17 +100,6 @@ inline int32_t Hwc3RenderIntentToHwc2(RenderIntent render_intent) {
return static_cast<int32_t>(render_intent);
}
// Values match up to DOZE_SUSPEND.
// https://android.googlesource.com/platform/hardware/interfaces/+/refs/heads/main/graphics/composer/aidl/android/hardware/graphics/composer3/PowerMode.aidl
// https://cs.android.com/android/platform/superproject/main/+/main:hardware/libhardware/include_all/hardware/hwcomposer2.h;l=348;drc=d783cabd4d9bddb4b83f2dd38300b7598bb58b24
inline int32_t Hwc3PowerModeToHwc2(PowerMode power_mode) {
if (power_mode > PowerMode::DOZE_SUSPEND) {
ALOGE("Unsupported HWC2 power mode. Could not translate: %d", power_mode);
return HWC2_POWER_MODE_ON;
}
return static_cast<int32_t>(power_mode);
}
// Values appear to match.
// https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
// https://cs.android.com/android/platform/superproject/main/+/main:system/core/libsystem/include/system/graphics-base-v1.0.h;l=43