Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP DPMS with wlr-output-power-management-unstable-v1 protocol #741

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ids1024
Copy link
Member

@ids1024 ids1024 commented Aug 17, 2024

This works to set DPMS on or off. It still needs to track the DPMS state and send events to clients when the mode changes. And otherwise be cleaned up a bit.

Components like cosmic-greeter may make use of this.

This can be tested with the below code (which also works on Sway):

use std::{env, process};
use wayland_client::{
    delegate_noop,
    globals::{registry_queue_init, GlobalListContents},
    protocol::{wl_output, wl_registry},
    Connection, Dispatch, Proxy, QueueHandle,
};
use wayland_protocols_wlr::output_power_management::v1::client::{
    zwlr_output_power_manager_v1, zwlr_output_power_v1,
};

struct State;

fn main() {
    let mode = match env::args().skip(1).next().as_ref().map(|x| x.as_str()) {
        Some("on") => zwlr_output_power_v1::Mode::On,
        Some("off") => zwlr_output_power_v1::Mode::Off,
        _ => {
            eprintln!("Usage: dpms on|off");
            process::exit(1);
        }
    };

    let connection = Connection::connect_to_env().unwrap();
    let (globals, mut event_queue) = registry_queue_init::<State>(&connection).unwrap();
    let qh = event_queue.handle();

    let outputs = globals.contents().with_list(|list| {
        list.iter()
            .filter(|global| global.interface == wl_output::WlOutput::interface().name)
            .map(|global| globals.registry().bind(global.name, global.version, &qh, ()))
            .collect::<Vec<wl_output::WlOutput>>()
    });

    let output_power_manager = globals
        .bind::<zwlr_output_power_manager_v1::ZwlrOutputPowerManagerV1, _, _>(&qh, 1..=1, ())
        .unwrap();

    for output in &outputs {
        let output_power = output_power_manager.get_output_power(output, &qh, ());
        output_power.set_mode(mode);
    }
    event_queue.roundtrip(&mut State).unwrap();
}

impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for State {
    fn event(
        _: &mut Self,
        _: &wl_registry::WlRegistry,
        _: wl_registry::Event,
        _: &GlobalListContents,
        _: &Connection,
        _: &QueueHandle<Self>,
    ) {
    }
}

delegate_noop!(State: ignore wl_output::WlOutput);
delegate_noop!(State: zwlr_output_power_manager_v1::ZwlrOutputPowerManagerV1);
delegate_noop!(State: ignore zwlr_output_power_v1::ZwlrOutputPowerV1);

@ids1024
Copy link
Member Author

ids1024 commented Aug 26, 2024

With this current, simple, way of settings the DPMS state, it does seem to spend .5 to 1 second in the call for some reason... seems excessive, but definitely should be handled in the render thread of that surface anyway.

I also see page flip errors. Presumably we just shouldn't attempt page flips when we have DPMS set to off. (And also disable/throttle frame callbacks. And don't actually try to render.)

@ids1024
Copy link
Member Author

ids1024 commented Aug 27, 2024

Looking at wlroots/mutter/kwin and DRM documentation, I guess we shouldn't set the DPMS property (unless we're using legacy modesetting) and should set ACTIVE as part of an atomic modeset.

DPMS:

Legacy property for setting the power state of the connector. For atomic drivers this is only provided for backwards compatibility with existing drivers, it remaps to controlling the “ACTIVE” property on the CRTC the connector is linked to. Drivers should never set this property directly, it is handled by the DRM core by calling the drm_connector_funcs.dpms callback. For atomic drivers the remapping to the “ACTIVE” property is implemented in the DRM core. This is the only standard connector property that userspace can change.

Note that this property cannot be set through the MODE_ATOMIC ioctl, userspace must use “ACTIVE” on the CRTC instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant