mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-30 20:34:49 +01:00
Add custom modes
Custom modes from wlr-randr should work now. Still need to do custom mode*lines*. And add those API calls
This commit is contained in:
parent
4b3fbd716f
commit
34517fd111
5 changed files with 196 additions and 12 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -1393,6 +1393,11 @@ version = "0.2.154"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||
|
||||
[[package]]
|
||||
name = "libdisplay-info-sys"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Smithay/libdisplay-info-rs?rev=a482d0d#a482d0d4b71762c13d40fa394efe04473916f31c"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
|
@ -1851,8 +1856,10 @@ dependencies = [
|
|||
"clap",
|
||||
"cliclack",
|
||||
"dircpy",
|
||||
"drm-sys",
|
||||
"gag",
|
||||
"image",
|
||||
"libdisplay-info-sys",
|
||||
"pinnacle",
|
||||
"pinnacle-api",
|
||||
"pinnacle-api-defs",
|
||||
|
@ -2381,7 +2388,6 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
|
|||
[[package]]
|
||||
name = "smithay"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/Smithay/smithay?rev=900b938#900b938970081cb525dc94ff083d76aa07c60e54"
|
||||
dependencies = [
|
||||
"appendlist",
|
||||
"ash",
|
||||
|
|
|
@ -34,9 +34,9 @@ dircpy = "0.3.16"
|
|||
tempfile = "3.10.1"
|
||||
|
||||
[workspace.dependencies.smithay]
|
||||
git = "https://github.com/Smithay/smithay"
|
||||
rev = "900b938"
|
||||
# path = "../../git/smithay"
|
||||
# git = "https://github.com/Smithay/smithay"
|
||||
# rev = "900b938"
|
||||
path = "../../git/smithay"
|
||||
default-features = false
|
||||
features = [
|
||||
"desktop",
|
||||
|
@ -115,6 +115,8 @@ chrono = "0.4.38"
|
|||
bytemuck = "1.16.0"
|
||||
pinnacle-api = { path = "./api/rust" }
|
||||
gag = "1.0.0"
|
||||
drm-sys = "0.7.0"
|
||||
libdisplay-info-sys = { git = "https://github.com/Smithay/libdisplay-info-rs", rev = "a482d0d" }
|
||||
|
||||
[build-dependencies]
|
||||
vergen = { version = "8.3.1", features = ["git", "gitcl", "rustc", "cargo", "si"] }
|
||||
|
|
|
@ -28,6 +28,7 @@ pub struct Dummy {
|
|||
// pub dmabuf_state: (DmabufState, DmabufGlobal, Option<DmabufFeedback>),
|
||||
#[cfg(feature = "wlcs")]
|
||||
pub wlcs_state: Wlcs,
|
||||
pub output: Output,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
|
@ -49,8 +50,8 @@ impl BackendData for Dummy {
|
|||
|
||||
fn early_import(&mut self, _surface: &WlSurface) {}
|
||||
|
||||
fn set_output_mode(&mut self, _output: &Output, _mode: smithay::output::Mode) {
|
||||
// TODO:
|
||||
fn set_output_mode(&mut self, output: &Output, mode: smithay::output::Mode) {
|
||||
output.change_current_state(Some(mode), None, None, None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +88,7 @@ impl Dummy {
|
|||
// dmabuf_state,
|
||||
#[cfg(feature = "wlcs")]
|
||||
wlcs_state: Wlcs::default(),
|
||||
output: output.clone(),
|
||||
};
|
||||
|
||||
UninitBackend {
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::{anyhow, ensure, Context};
|
||||
use drm::set_crtc_active;
|
||||
use drm::{set_crtc_active, util::create_drm_mode};
|
||||
use pinnacle_api_defs::pinnacle::signal::v0alpha1::{
|
||||
OutputConnectResponse, OutputDisconnectResponse,
|
||||
};
|
||||
|
@ -703,8 +703,21 @@ impl BackendData for Udev {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: create new drm mode with cvt
|
||||
tracing::info!("no drm mode for mode");
|
||||
let new_mode = create_drm_mode(mode.size.w, mode.size.h, Some(mode.refresh as u32));
|
||||
|
||||
if let Some(render_surface) = render_surface_for_output(output, &mut self.backends) {
|
||||
match render_surface.compositor.use_mode(new_mode) {
|
||||
Ok(()) => {
|
||||
output.change_current_state(Some(mode), None, None, None);
|
||||
output.with_state_mut(|state| {
|
||||
if !state.modes.contains(&mode) {
|
||||
state.modes.push(mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => warn!("Failed to resize output: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
use std::num::NonZeroU32;
|
||||
use std::{ffi::CString, io::Write, mem::MaybeUninit, num::NonZeroU32};
|
||||
|
||||
use anyhow::Context;
|
||||
use smithay::reexports::drm::control::{connector, property, Device, ResourceHandle};
|
||||
use anyhow::{bail, Context};
|
||||
use drm_sys::{
|
||||
drm_mode_modeinfo, DRM_MODE_FLAG_NHSYNC, DRM_MODE_FLAG_NVSYNC, DRM_MODE_FLAG_PHSYNC,
|
||||
DRM_MODE_FLAG_PVSYNC, DRM_MODE_TYPE_USERDEF,
|
||||
};
|
||||
use libdisplay_info_sys::cvt::{
|
||||
di_cvt_compute, di_cvt_options, di_cvt_reduced_blanking_version_DI_CVT_REDUCED_BLANKING_NONE,
|
||||
di_cvt_timing,
|
||||
};
|
||||
use smithay::reexports::drm::{
|
||||
self,
|
||||
control::{connector, property, Device, ResourceHandle},
|
||||
};
|
||||
|
||||
use super::edid_manus::get_manufacturer;
|
||||
|
||||
|
@ -129,3 +140,153 @@ pub(super) fn get_drm_property(
|
|||
}
|
||||
anyhow::bail!("No prop found for {}", name)
|
||||
}
|
||||
|
||||
// From https://github.com/swaywm/sway/blob/2e9139df664f1e2dbe14b5df4a9646411b924c66/sway/commands/output/mode.c#L64
|
||||
fn parse_modeline_string(modeline: &str) -> anyhow::Result<drm_mode_modeinfo> {
|
||||
let mut args = modeline.split_whitespace();
|
||||
|
||||
let clock = args
|
||||
.next()
|
||||
.context("no clock specified")?
|
||||
.parse::<u32>()
|
||||
.context("failed to parse clock")?
|
||||
* 1000;
|
||||
let hdisplay = args
|
||||
.next()
|
||||
.context("no hdisplay specified")?
|
||||
.parse()
|
||||
.context("failed to parse hdisplay")?;
|
||||
let hsync_start = args
|
||||
.next()
|
||||
.context("no hsync_start specified")?
|
||||
.parse()
|
||||
.context("failed to parse hsync_start")?;
|
||||
let hsync_end = args
|
||||
.next()
|
||||
.context("no hsync_end specified")?
|
||||
.parse()
|
||||
.context("failed to parse hsync_end")?;
|
||||
let htotal = args
|
||||
.next()
|
||||
.context("no htotal specified")?
|
||||
.parse()
|
||||
.context("failed to parse htotal")?;
|
||||
let vdisplay = args
|
||||
.next()
|
||||
.context("no vdisplay specified")?
|
||||
.parse()
|
||||
.context("failed to parse vdisplay")?;
|
||||
let vsync_start = args
|
||||
.next()
|
||||
.context("no vsync_start specified")?
|
||||
.parse()
|
||||
.context("failed to parse vsync_start")?;
|
||||
let vsync_end = args
|
||||
.next()
|
||||
.context("no vsync_end specified")?
|
||||
.parse()
|
||||
.context("failed to parse vsync_end")?;
|
||||
let vtotal = args
|
||||
.next()
|
||||
.context("no vtotal specified")?
|
||||
.parse()
|
||||
.context("failed to parse vtotal")?;
|
||||
let vrefresh = clock * 1000 * 1000 / htotal as u32 / vtotal as u32;
|
||||
|
||||
let mut flags = 0;
|
||||
match args.next().context("no +/-hsync specified")? {
|
||||
"+hsync" => flags |= DRM_MODE_FLAG_PHSYNC,
|
||||
"-hsync" => flags |= DRM_MODE_FLAG_NHSYNC,
|
||||
_ => bail!("invalid hsync specifier"),
|
||||
};
|
||||
match args.next().context("no +/-vsync specified")? {
|
||||
"+vsync" => flags |= DRM_MODE_FLAG_PVSYNC,
|
||||
"-vsync" => flags |= DRM_MODE_FLAG_NVSYNC,
|
||||
_ => bail!("invalid vsync specifier"),
|
||||
};
|
||||
|
||||
let type_ = DRM_MODE_TYPE_USERDEF;
|
||||
|
||||
let name = CString::new(format!("{}x{}@{}", hdisplay, vdisplay, vrefresh / 1000)).unwrap();
|
||||
let mut name_buf = [0u8; 32];
|
||||
let _ = name_buf.as_mut_slice().write_all(name.as_bytes_with_nul());
|
||||
let name: [i8; 32] = bytemuck::cast(name_buf);
|
||||
|
||||
Ok(drm_mode_modeinfo {
|
||||
clock,
|
||||
hdisplay,
|
||||
hsync_start,
|
||||
hsync_end,
|
||||
htotal,
|
||||
hskew: 0,
|
||||
vdisplay,
|
||||
vsync_start,
|
||||
vsync_end,
|
||||
vtotal,
|
||||
vscan: 0,
|
||||
vrefresh,
|
||||
flags,
|
||||
type_,
|
||||
name,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a new drm mode from a given width, height, and optional refresh rate (defaults to 60Hz).
|
||||
pub fn create_drm_mode(width: i32, height: i32, refresh_mhz: Option<u32>) -> drm::control::Mode {
|
||||
drm::control::Mode::from(generate_cvt_mode(
|
||||
width,
|
||||
height,
|
||||
refresh_mhz.map(|refresh| refresh as f64 / 1000.0),
|
||||
))
|
||||
}
|
||||
|
||||
// From https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/95ac3e99242b4e7f59f00dd073ede405ff8e9e26/backend/drm/util.c#L247
|
||||
fn generate_cvt_mode(hdisplay: i32, vdisplay: i32, vrefresh: Option<f64>) -> drm_mode_modeinfo {
|
||||
let options: di_cvt_options = di_cvt_options {
|
||||
red_blank_ver: di_cvt_reduced_blanking_version_DI_CVT_REDUCED_BLANKING_NONE,
|
||||
h_pixels: hdisplay,
|
||||
v_lines: vdisplay,
|
||||
ip_freq_rqd: vrefresh.unwrap_or(60.0),
|
||||
video_opt: false,
|
||||
vblank: 0.0,
|
||||
additional_hblank: 0,
|
||||
early_vsync_rqd: false,
|
||||
int_rqd: false,
|
||||
margins_rqd: false,
|
||||
};
|
||||
|
||||
let mut timing = MaybeUninit::<di_cvt_timing>::zeroed();
|
||||
// SAFETY: is an ffi function
|
||||
unsafe { di_cvt_compute(timing.as_mut_ptr(), &options as *const _) };
|
||||
|
||||
// SAFETY: Initialized in the function above
|
||||
let timing = unsafe { timing.assume_init() };
|
||||
|
||||
let hsync_start = (hdisplay + timing.h_front_porch as i32) as u16;
|
||||
let vsync_start = (timing.v_lines_rnd + timing.v_front_porch) as u16;
|
||||
let hsync_end = hsync_start + timing.h_sync as u16;
|
||||
let vsync_end = vsync_start + timing.v_sync as u16;
|
||||
|
||||
let name = CString::new(format!("{}x{}", hdisplay, vdisplay)).unwrap();
|
||||
let mut name_buf = [0u8; 32];
|
||||
let _ = name_buf.as_mut_slice().write_all(name.as_bytes_with_nul());
|
||||
let name: [i8; 32] = bytemuck::cast(name_buf);
|
||||
|
||||
drm_mode_modeinfo {
|
||||
clock: f64::round(timing.act_pixel_freq * 1000.0) as u32,
|
||||
hdisplay: hdisplay as u16,
|
||||
hsync_start,
|
||||
hsync_end,
|
||||
htotal: hsync_end + timing.h_back_porch as u16,
|
||||
hskew: 0,
|
||||
vdisplay: timing.v_lines_rnd as u16,
|
||||
vsync_start,
|
||||
vsync_end,
|
||||
vtotal: vsync_end + timing.v_back_porch as u16,
|
||||
vscan: 0,
|
||||
vrefresh: f64::round(timing.act_frame_rate) as u32,
|
||||
flags: DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC,
|
||||
type_: DRM_MODE_TYPE_USERDEF,
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue