Merge branch 'gpu_drm7' into 'main'
Mostly use drm ioctls in graphics_ipc::v2 See merge request redox-os/base!72
This commit is contained in:
Generated
+172
-12
@@ -156,7 +156,7 @@ version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -167,7 +167,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -326,6 +326,26 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck_derive"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
@@ -596,14 +616,42 @@ dependencies = [
|
||||
"redox_syscall 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "drm"
|
||||
version = "0.14.1"
|
||||
source = "git+https://github.com/Smithay/drm-rs.git#c51297961755fa9eb3941fdd60bf2b69979cb403"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"bytemuck",
|
||||
"bytemuck_derive",
|
||||
"drm-ffi",
|
||||
"drm-fourcc",
|
||||
"libc",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "drm-ffi"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/Smithay/drm-rs.git#c51297961755fa9eb3941fdd60bf2b69979cb403"
|
||||
dependencies = [
|
||||
"drm-sys",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "drm-fourcc"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4"
|
||||
|
||||
[[package]]
|
||||
name = "drm-sys"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bafb66c8dbc944d69e15cfcc661df7e703beffbaec8bd63151368b06c5f9858c"
|
||||
source = "git+https://github.com/Smithay/drm-rs.git#c51297961755fa9eb3941fdd60bf2b69979cb403"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"linux-raw-sys 0.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -640,6 +688,16 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "executor"
|
||||
version = "0.1.0"
|
||||
@@ -661,6 +719,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"console-draw",
|
||||
"daemon",
|
||||
"drm",
|
||||
"graphics-ipc",
|
||||
"inputd",
|
||||
"libredox",
|
||||
@@ -678,6 +737,7 @@ dependencies = [
|
||||
"common",
|
||||
"console-draw",
|
||||
"daemon",
|
||||
"drm",
|
||||
"graphics-ipc",
|
||||
"inputd",
|
||||
"libredox",
|
||||
@@ -813,7 +873,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "generic-rt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#3ebd43b4ceb77bfee2a9c155993ec2fb5843ad6b"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#13b93e0f901ea61358d80b4cd177601872ef830e"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
@@ -866,6 +926,8 @@ name = "graphics-ipc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"common",
|
||||
"drm",
|
||||
"drm-fourcc",
|
||||
"libredox",
|
||||
"log",
|
||||
"redox-ioctl",
|
||||
@@ -1103,9 +1165,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.6.5"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7"
|
||||
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "lived"
|
||||
@@ -1619,7 +1687,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "redox-ioctl"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/Ibuki.O/relibc.git?branch=replace-unlink-rmdir-with-unlinkat#daf01ee12975a5481d2c1302e19eab45013427f4"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#13b93e0f901ea61358d80b4cd177601872ef830e"
|
||||
dependencies = [
|
||||
"drm-sys",
|
||||
"redox_syscall 0.6.0",
|
||||
@@ -1637,16 +1705,23 @@ dependencies = [
|
||||
"termion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox-path"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
|
||||
|
||||
[[package]]
|
||||
name = "redox-rt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#3ebd43b4ceb77bfee2a9c155993ec2fb5843ad6b"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#13b93e0f901ea61358d80b4cd177601872ef830e"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"generic-rt",
|
||||
"goblin",
|
||||
"plain",
|
||||
"redox_syscall 0.5.18",
|
||||
"redox-path",
|
||||
"redox_syscall 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1815,6 +1890,18 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.2"
|
||||
source = "git+https://github.com/jackpot51/rustix.git?branch=redox-ioctl#e7e66bc77455251463336582c0b97df01054ccb8"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.11.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
@@ -2510,7 +2597,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2578,6 +2665,15 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
@@ -2587,6 +2683,70 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.40"
|
||||
|
||||
@@ -76,6 +76,11 @@ exclude = ["bootstrap"]
|
||||
libc = { git = "https://gitlab.redox-os.org/redox-os/liblibc.git", branch = "redox-0.2" }
|
||||
orbclient = { git = "https://gitlab.redox-os.org/redox-os/orbclient.git", version = "0.3.44" }
|
||||
|
||||
# Rustix doesn't support ioctls on Redox OS
|
||||
rustix = { git = "https://github.com/jackpot51/rustix.git", branch = "redox-ioctl" }
|
||||
drm = { git = "https://github.com/Smithay/drm-rs.git" }
|
||||
drm-sys = { git = "https://github.com/Smithay/drm-rs.git" }
|
||||
|
||||
[patch."https://gitlab.redox-os.org/redox-os/relibc.git"]
|
||||
#redox-rt = { path = "../../relibc/source/redox-rt" }
|
||||
#redox-ioctl = { path = "../../relibc/source/redox-ioctl" }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#![feature(slice_as_array)]
|
||||
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::ffi::c_char;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Write};
|
||||
use std::mem;
|
||||
@@ -82,8 +83,8 @@ enum Handle<T: GraphicsAdapter> {
|
||||
},
|
||||
V2 {
|
||||
vt: usize,
|
||||
next_id: usize,
|
||||
fbs: HashMap<usize, Arc<T::Framebuffer>>,
|
||||
next_id: u32,
|
||||
fbs: HashMap<u32, Arc<T::Framebuffer>>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -462,6 +463,44 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
id_index(i) | (1 << 13)
|
||||
}
|
||||
|
||||
fn dumb_buffer_id(i: u32) -> u32 {
|
||||
id_index(i) | (1 << 14)
|
||||
}
|
||||
|
||||
fn modeinfo_for_size(width: u32, height: u32) -> drm_sys::drm_mode_modeinfo {
|
||||
let mut modeinfo = drm_sys::drm_mode_modeinfo {
|
||||
// The actual visible display size
|
||||
hdisplay: width as u16,
|
||||
vdisplay: height as u16,
|
||||
|
||||
// These are used to calculate the refresh rate
|
||||
clock: 60 * width * height / 1000,
|
||||
htotal: width as u16,
|
||||
vtotal: height as u16,
|
||||
vscan: 0,
|
||||
vrefresh: 60,
|
||||
|
||||
type_: drm_sys::DRM_MODE_TYPE_PREFERRED | drm_sys::DRM_MODE_TYPE_DRIVER,
|
||||
name: [0; 32],
|
||||
|
||||
// These only matter when modesetting physical display adapters. For
|
||||
// those we should be able to parse the EDID blob.
|
||||
hsync_start: width as u16,
|
||||
hsync_end: width as u16,
|
||||
hskew: 0,
|
||||
vsync_start: height as u16,
|
||||
vsync_end: height as u16,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let name = format!("{width}x{height}").into_bytes();
|
||||
for (to, from) in modeinfo.name.iter_mut().zip(name) {
|
||||
*to = from as c_char;
|
||||
}
|
||||
|
||||
modeinfo
|
||||
}
|
||||
|
||||
match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
|
||||
Handle::V1Screen { .. } => {
|
||||
return Err(Error::new(EOPNOTSUPP));
|
||||
@@ -543,7 +582,8 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
ipc::MODE_GET_CONNECTOR => ipc::DrmModeGetConnector::with(payload, |mut data| {
|
||||
let i = id_index(data.connector_id());
|
||||
let (width, height) = self.adapter.display_size(i as usize);
|
||||
data.set_modes_ptr(&[]);
|
||||
data.set_connection(1 /* connected */);
|
||||
data.set_modes_ptr(&[modeinfo_for_size(width, height)]);
|
||||
data.set_props_ptr(&[]);
|
||||
data.set_prop_values_ptr(&[]);
|
||||
data.set_encoders_ptr(&[enc_id(i)]);
|
||||
@@ -560,6 +600,50 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
data.set_handle(fb_handle_id(i));
|
||||
Ok(0)
|
||||
}),
|
||||
ipc::MODE_CREATE_DUMB => ipc::DrmModeCreateDumb::with(payload, |mut data| {
|
||||
if data.bpp() != 32 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
let fb = self
|
||||
.adapter
|
||||
.create_dumb_framebuffer(data.width(), data.height());
|
||||
|
||||
*next_id += 1;
|
||||
fbs.insert(*next_id, Arc::new(fb));
|
||||
data.set_handle(dumb_buffer_id(*next_id as u32));
|
||||
data.set_pitch(data.width() * 4);
|
||||
data.set_size(u64::from(data.width()) * u64::from(data.height()) * 4);
|
||||
Ok(0)
|
||||
}),
|
||||
ipc::MODE_MAP_DUMB => ipc::DrmModeMapDumb::with(payload, |mut data| {
|
||||
if data.offset() != 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
let fb_id = id_index(data.handle());
|
||||
|
||||
if !fbs.contains_key(&fb_id) {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
// FIXME use a better scheme for creating map offsets
|
||||
assert!(
|
||||
((fbs[&fb_id].width() * fbs[&fb_id].height() * 4) as usize)
|
||||
< MAP_FAKE_OFFSET_MULTIPLIER
|
||||
);
|
||||
|
||||
data.set_offset((fb_id as usize * MAP_FAKE_OFFSET_MULTIPLIER) as u64);
|
||||
|
||||
Ok(0)
|
||||
}),
|
||||
ipc::MODE_DESTROY_DUMB => ipc::DrmModeDestroyDumb::with(payload, |data| {
|
||||
let fb_id = id_index(data.handle());
|
||||
if fbs.remove(&fb_id).is_none() {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
Ok(0)
|
||||
}),
|
||||
ipc::MODE_GET_PLANE_RES => ipc::DrmModeGetPlaneRes::with(payload, |mut data| {
|
||||
let count = self.adapter.display_count();
|
||||
let mut ids = Vec::with_capacity(count);
|
||||
@@ -598,100 +682,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
data.set_modifier([0; 4]);
|
||||
Ok(0)
|
||||
}),
|
||||
ipc::DISPLAY_COUNT => {
|
||||
if payload.len() < size_of::<ipc::DisplayCount>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let payload = unsafe {
|
||||
transmute::<&mut [u8; size_of::<ipc::DisplayCount>()], &mut ipc::DisplayCount>(
|
||||
payload.as_mut_array().unwrap(),
|
||||
)
|
||||
};
|
||||
payload.count = self.adapter.display_count();
|
||||
Ok(size_of::<ipc::DisplayCount>())
|
||||
}
|
||||
ipc::DISPLAY_SIZE => {
|
||||
if payload.len() < size_of::<ipc::DisplaySize>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let payload = unsafe {
|
||||
transmute::<&mut [u8; size_of::<ipc::DisplaySize>()], &mut ipc::DisplaySize>(
|
||||
payload.as_mut_array().unwrap(),
|
||||
)
|
||||
};
|
||||
let display_id = payload.display_id;
|
||||
if display_id >= self.adapter.display_count() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let (width, height) = self.adapter.display_size(display_id);
|
||||
payload.width = width;
|
||||
payload.height = height;
|
||||
Ok(size_of::<ipc::DisplaySize>())
|
||||
}
|
||||
ipc::CREATE_DUMB_FRAMEBUFFER => {
|
||||
if payload.len() < size_of::<ipc::CreateDumbFramebuffer>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let payload = unsafe {
|
||||
transmute::<
|
||||
&mut [u8; size_of::<ipc::CreateDumbFramebuffer>()],
|
||||
&mut ipc::CreateDumbFramebuffer,
|
||||
>(payload.as_mut_array().unwrap())
|
||||
};
|
||||
|
||||
let fb = self
|
||||
.adapter
|
||||
.create_dumb_framebuffer(payload.width, payload.height);
|
||||
|
||||
*next_id += 1;
|
||||
fbs.insert(*next_id, Arc::new(fb));
|
||||
payload.fb_id = *next_id;
|
||||
Ok(size_of::<ipc::CreateDumbFramebuffer>())
|
||||
}
|
||||
ipc::DUMB_FRAMEBUFFER_MAP_OFFSET => {
|
||||
if payload.len() < size_of::<ipc::DumbFramebufferMapOffset>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let payload = unsafe {
|
||||
transmute::<
|
||||
&mut [u8; size_of::<ipc::DumbFramebufferMapOffset>()],
|
||||
&mut ipc::DumbFramebufferMapOffset,
|
||||
>(payload.as_mut_array().unwrap())
|
||||
};
|
||||
|
||||
let fb_id = payload.fb_id;
|
||||
|
||||
if !fbs.contains_key(&fb_id) {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
// FIXME use a better scheme for creating map offsets
|
||||
assert!(
|
||||
((fbs[&fb_id].width() * fbs[&fb_id].height() * 4) as usize)
|
||||
< MAP_FAKE_OFFSET_MULTIPLIER
|
||||
);
|
||||
|
||||
payload.offset = fb_id * MAP_FAKE_OFFSET_MULTIPLIER;
|
||||
|
||||
Ok(size_of::<ipc::DumbFramebufferMapOffset>())
|
||||
}
|
||||
ipc::DESTROY_DUMB_FRAMEBUFFER => {
|
||||
if payload.len() < size_of::<ipc::DestroyDumbFramebuffer>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let payload = unsafe {
|
||||
transmute::<
|
||||
&mut [u8; size_of::<ipc::DestroyDumbFramebuffer>()],
|
||||
&mut ipc::DestroyDumbFramebuffer,
|
||||
>(payload.as_mut_array().unwrap())
|
||||
};
|
||||
|
||||
if fbs.remove(&{ payload.fb_id }).is_none() {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
|
||||
Ok(size_of::<ipc::DestroyDumbFramebuffer>())
|
||||
}
|
||||
ipc::UPDATE_PLANE => {
|
||||
if payload.len() < size_of::<ipc::UpdatePlane>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
@@ -707,7 +697,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
let Some(framebuffer) = fbs.get(&{ payload.fb_id }) else {
|
||||
let Some(framebuffer) = fbs.get(&id_index(payload.fb_id)) else {
|
||||
return Err(Error::new(EINVAL));
|
||||
};
|
||||
|
||||
@@ -741,7 +731,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
next_id: _,
|
||||
fbs,
|
||||
} => (
|
||||
fbs.get(&(offset as usize / MAP_FAKE_OFFSET_MULTIPLIER))
|
||||
fbs.get(&((offset as usize / MAP_FAKE_OFFSET_MULTIPLIER) as u32))
|
||||
.ok_or(Error::new(EINVAL))
|
||||
.unwrap(),
|
||||
offset & (MAP_FAKE_OFFSET_MULTIPLIER as u64 - 1),
|
||||
|
||||
@@ -4,6 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
drm = "0.14.1"
|
||||
orbclient = "0.3.27"
|
||||
ransid = "0.4"
|
||||
redox_event = "0.4"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::{cmp, ptr};
|
||||
use std::{cmp, mem, ptr};
|
||||
|
||||
use console_draw::TextScreen;
|
||||
use drm::buffer::Buffer;
|
||||
use drm::control::dumbbuffer::{DumbBuffer, DumbMapping};
|
||||
use graphics_ipc::v2::V2GraphicsHandle;
|
||||
use inputd::ConsumerHandle;
|
||||
use orbclient::{Event, EventOption};
|
||||
@@ -12,8 +14,21 @@ use syscall::{Error, Result, EINVAL, ENOENT};
|
||||
|
||||
pub struct DisplayMap {
|
||||
display_handle: V2GraphicsHandle,
|
||||
fb: usize,
|
||||
inner: graphics_ipc::v1::DisplayMap,
|
||||
fb: DumbBuffer,
|
||||
mapping: DumbMapping<'static>,
|
||||
}
|
||||
|
||||
impl DisplayMap {
|
||||
unsafe fn console_map(&mut self) -> console_draw::DisplayMap {
|
||||
console_draw::DisplayMap {
|
||||
offscreen: ptr::slice_from_raw_parts_mut(
|
||||
self.mapping.as_mut_ptr() as *mut u32,
|
||||
self.mapping.len() / 4,
|
||||
),
|
||||
width: self.fb.size().0 as usize,
|
||||
height: self.fb.size().1 as usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FbbootlogScheme {
|
||||
@@ -52,25 +67,30 @@ impl FbbootlogScheme {
|
||||
}
|
||||
};
|
||||
|
||||
let (width, height) = new_display_handle.display_size(0).unwrap();
|
||||
let fb = new_display_handle
|
||||
let (width, height) = new_display_handle
|
||||
.display_size(new_display_handle.first_display().unwrap())
|
||||
.unwrap();
|
||||
let mut fb = new_display_handle
|
||||
.create_dumb_framebuffer(width, height)
|
||||
.unwrap();
|
||||
|
||||
match new_display_handle.map_dumb_framebuffer(fb, width, height) {
|
||||
Ok(display_map) => {
|
||||
self.display_map = Some(DisplayMap {
|
||||
display_handle: new_display_handle,
|
||||
fb,
|
||||
inner: display_map,
|
||||
});
|
||||
|
||||
eprintln!("fbbootlogd: mapped display");
|
||||
}
|
||||
let display_map = match new_display_handle.map_dumb_framebuffer(&mut fb) {
|
||||
Ok(display_map) => unsafe {
|
||||
mem::transmute::<DumbMapping<'_>, DumbMapping<'static>>(display_map)
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("fbbootlogd: failed to open display: {}", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.display_map = Some(DisplayMap {
|
||||
display_handle: new_display_handle,
|
||||
mapping: display_map,
|
||||
fb,
|
||||
});
|
||||
|
||||
eprintln!("fbbootlogd: mapped display");
|
||||
}
|
||||
|
||||
pub fn handle_input(&mut self, ev: &Event) {
|
||||
@@ -125,11 +145,7 @@ impl FbbootlogScheme {
|
||||
return;
|
||||
};
|
||||
let buffer_len = self.text_buffer.lines.len();
|
||||
let dmap = &mut console_draw::DisplayMap {
|
||||
offscreen: map.inner.ptr_mut(),
|
||||
width: map.inner.width(),
|
||||
height: map.inner.height(),
|
||||
};
|
||||
let dmap = unsafe { &mut map.console_map() };
|
||||
// for both extra space on wrapping text and a scrollback indicator
|
||||
let spare_lines = 3;
|
||||
self.is_scrollback = true;
|
||||
@@ -149,59 +165,69 @@ impl FbbootlogScheme {
|
||||
if i == buffer_len || yd + spare_lines * 16 > dmap.height {
|
||||
// render until end of screen
|
||||
damage.height = (dmap.height as u32) - damage.y;
|
||||
map.display_handle.update_plane(0, map.fb, damage).unwrap();
|
||||
map.display_handle
|
||||
.update_plane(0, u32::from(map.fb.handle()), damage)
|
||||
.unwrap();
|
||||
self.is_scrollback = i < buffer_len;
|
||||
break;
|
||||
} else {
|
||||
map.display_handle.update_plane(0, map.fb, damage).unwrap();
|
||||
map.display_handle
|
||||
.update_plane(0, u32::from(map.fb.handle()), damage)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) {
|
||||
let (width, height) = match map.display_handle.display_size(0) {
|
||||
let (width, height) = match map
|
||||
.display_handle
|
||||
.first_display()
|
||||
.and_then(|handle| map.display_handle.display_size(handle))
|
||||
{
|
||||
Ok((width, height)) => (width, height),
|
||||
Err(err) => {
|
||||
eprintln!("fbbootlogd: failed to get display size: {}", err);
|
||||
(map.inner.width() as u32, map.inner.height() as u32)
|
||||
map.fb.size()
|
||||
}
|
||||
};
|
||||
|
||||
if width as usize != map.inner.width() || height as usize != map.inner.height() {
|
||||
if (width, height) != map.fb.size() {
|
||||
match map.display_handle.create_dumb_framebuffer(width, height) {
|
||||
Ok(fb) => match map.display_handle.map_dumb_framebuffer(fb, width, height) {
|
||||
Ok(mut new_map) => {
|
||||
let count = new_map.ptr().len();
|
||||
unsafe {
|
||||
ptr::write_bytes(new_map.ptr_mut() as *mut u32, 0, count);
|
||||
Ok(mut fb) => {
|
||||
let mut new_map = match map.display_handle.map_dumb_framebuffer(&mut fb) {
|
||||
Ok(new_map) => unsafe {
|
||||
mem::transmute::<DumbMapping<'_>, DumbMapping<'static>>(new_map)
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("fbbootlogd: failed to open display: {}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
text_screen.resize(
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: map.inner.ptr_mut(),
|
||||
width: map.inner.width(),
|
||||
height: map.inner.height(),
|
||||
},
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: new_map.ptr_mut(),
|
||||
width: new_map.width(),
|
||||
height: new_map.height(),
|
||||
},
|
||||
);
|
||||
new_map.fill(0);
|
||||
|
||||
let _ = map.display_handle.destroy_dumb_framebuffer(map.fb);
|
||||
text_screen.resize(
|
||||
unsafe { &mut map.console_map() },
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: ptr::slice_from_raw_parts_mut(
|
||||
new_map.as_mut_ptr() as *mut u32,
|
||||
new_map.len() / 4,
|
||||
),
|
||||
width: fb.size().0 as usize,
|
||||
height: fb.size().1 as usize,
|
||||
},
|
||||
);
|
||||
|
||||
map.fb = fb;
|
||||
map.inner = new_map;
|
||||
let old_fb = mem::replace(&mut map.fb, fb);
|
||||
map.mapping = new_map;
|
||||
|
||||
eprintln!("fbbootlogd: mapped display");
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("fbbootlogd: failed to open display: {}", err);
|
||||
}
|
||||
},
|
||||
let _ = map.display_handle.destroy_dumb_framebuffer(old_fb);
|
||||
|
||||
eprintln!("fbbootlogd: mapped display");
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("fbbootlogd: failed to create framebuffer: {}", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,17 +287,15 @@ impl SchemeSync for FbbootlogScheme {
|
||||
|
||||
if !self.is_scrollback {
|
||||
let damage = self.text_screen.write(
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: map.inner.ptr_mut(),
|
||||
width: map.inner.width(),
|
||||
height: map.inner.height(),
|
||||
},
|
||||
unsafe { &mut map.console_map() },
|
||||
buf,
|
||||
&mut VecDeque::new(),
|
||||
);
|
||||
|
||||
if let Some(map) = &self.display_map {
|
||||
map.display_handle.update_plane(0, map.fb, damage).unwrap();
|
||||
map.display_handle
|
||||
.update_plane(0, u32::from(map.fb.handle()), damage)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
drm = "0.14.1"
|
||||
log = "0.4"
|
||||
orbclient = "0.3.27"
|
||||
ransid = "0.4"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use console_draw::TextScreen;
|
||||
use drm::buffer::Buffer;
|
||||
use drm::control::dumbbuffer::{DumbBuffer, DumbMapping};
|
||||
use graphics_ipc::v2::{Damage, V2GraphicsHandle};
|
||||
use inputd::ConsumerHandle;
|
||||
use std::{io, ptr};
|
||||
use std::{io, mem, ptr};
|
||||
|
||||
pub struct Display {
|
||||
pub input_handle: ConsumerHandle,
|
||||
@@ -10,8 +12,21 @@ pub struct Display {
|
||||
|
||||
pub struct DisplayMap {
|
||||
display_handle: V2GraphicsHandle,
|
||||
fb: usize,
|
||||
pub inner: graphics_ipc::v2::DisplayMap,
|
||||
fb: DumbBuffer,
|
||||
mapping: DumbMapping<'static>,
|
||||
}
|
||||
|
||||
impl DisplayMap {
|
||||
pub unsafe fn console_map(&mut self) -> console_draw::DisplayMap {
|
||||
console_draw::DisplayMap {
|
||||
offscreen: ptr::slice_from_raw_parts_mut(
|
||||
self.mapping.as_mut_ptr() as *mut u32,
|
||||
self.mapping.len() / 4,
|
||||
),
|
||||
width: self.fb.size().0 as usize,
|
||||
height: self.fb.size().1 as usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display {
|
||||
@@ -33,73 +48,81 @@ impl Display {
|
||||
|
||||
log::debug!("fbcond: Opened new display");
|
||||
|
||||
let (width, height) = new_display_handle.display_size(0).unwrap();
|
||||
let fb = new_display_handle
|
||||
let (width, height) = new_display_handle
|
||||
.display_size(new_display_handle.first_display().unwrap())
|
||||
.unwrap();
|
||||
let mut fb = new_display_handle
|
||||
.create_dumb_framebuffer(width, height)
|
||||
.unwrap();
|
||||
|
||||
match new_display_handle.map_dumb_framebuffer(fb, width, height) {
|
||||
Ok(map) => {
|
||||
log::debug!(
|
||||
"fbcond: Mapped new display with size {}x{}",
|
||||
map.width(),
|
||||
map.height()
|
||||
);
|
||||
|
||||
self.map = Some(DisplayMap {
|
||||
display_handle: new_display_handle,
|
||||
fb,
|
||||
inner: map,
|
||||
});
|
||||
}
|
||||
let map = match new_display_handle.map_dumb_framebuffer(&mut fb) {
|
||||
Ok(map) => unsafe { mem::transmute::<DumbMapping<'_>, DumbMapping<'static>>(map) },
|
||||
Err(err) => {
|
||||
log::error!("failed to map display: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) {
|
||||
let (width, height) = match map.display_handle.display_size(0) {
|
||||
Ok((width, height)) => (width, height),
|
||||
Err(err) => {
|
||||
log::error!("fbcond: failed to get display size: {}", err);
|
||||
(map.inner.width() as u32, map.inner.height() as u32)
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if width as usize != map.inner.width() || height as usize != map.inner.height() {
|
||||
log::debug!(
|
||||
"fbcond: Mapped new display with size {}x{}",
|
||||
fb.size().0,
|
||||
fb.size().1,
|
||||
);
|
||||
|
||||
self.map = Some(DisplayMap {
|
||||
display_handle: new_display_handle,
|
||||
fb,
|
||||
mapping: map,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) {
|
||||
let (width, height) = match map
|
||||
.display_handle
|
||||
.first_display()
|
||||
.and_then(|handle| map.display_handle.display_size(handle))
|
||||
{
|
||||
Ok((width, height)) => (width, height),
|
||||
Err(err) => {
|
||||
log::error!("fbcond: failed to get display size: {}", err);
|
||||
map.fb.size()
|
||||
}
|
||||
};
|
||||
|
||||
if (width, height) != map.fb.size() {
|
||||
match map.display_handle.create_dumb_framebuffer(width, height) {
|
||||
Ok(fb) => match map.display_handle.map_dumb_framebuffer(fb, width, height) {
|
||||
Ok(mut new_map) => {
|
||||
let count = new_map.ptr().len();
|
||||
unsafe {
|
||||
ptr::write_bytes(new_map.ptr_mut() as *mut u32, 0, count);
|
||||
Ok(mut fb) => {
|
||||
let mut new_map = match map.display_handle.map_dumb_framebuffer(&mut fb) {
|
||||
Ok(new_map) => unsafe {
|
||||
mem::transmute::<DumbMapping<'_>, DumbMapping<'static>>(new_map)
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("fbcond: failed to open display: {}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
text_screen.resize(
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: map.inner.ptr_mut(),
|
||||
width: map.inner.width(),
|
||||
height: map.inner.height(),
|
||||
},
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: new_map.ptr_mut(),
|
||||
width: new_map.width(),
|
||||
height: new_map.height(),
|
||||
},
|
||||
);
|
||||
new_map.fill(0);
|
||||
|
||||
let _ = map.display_handle.destroy_dumb_framebuffer(map.fb);
|
||||
text_screen.resize(
|
||||
unsafe { &mut map.console_map() },
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: ptr::slice_from_raw_parts_mut(
|
||||
new_map.as_mut_ptr() as *mut u32,
|
||||
new_map.len() / 4,
|
||||
),
|
||||
width: fb.size().0 as usize,
|
||||
height: fb.size().1 as usize,
|
||||
},
|
||||
);
|
||||
|
||||
map.fb = fb;
|
||||
map.inner = new_map;
|
||||
let old_fb = mem::replace(&mut map.fb, fb);
|
||||
map.mapping = new_map;
|
||||
|
||||
log::debug!("fbcond: mapped display");
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("fbcond: failed to open display: {}", err);
|
||||
}
|
||||
},
|
||||
let _ = map.display_handle.destroy_dumb_framebuffer(old_fb);
|
||||
|
||||
eprintln!("fbcond: mapped display");
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("fbcond: failed to create framebuffer: {}", err);
|
||||
}
|
||||
@@ -109,7 +132,9 @@ impl Display {
|
||||
|
||||
pub fn sync_rect(&mut self, damage: Damage) {
|
||||
if let Some(map) = &self.map {
|
||||
map.display_handle.update_plane(0, map.fb, damage).unwrap();
|
||||
map.display_handle
|
||||
.update_plane(0, u32::from(map.fb.handle()), damage)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,15 +124,9 @@ impl TextScreen {
|
||||
if let Some(map) = &mut self.display.map {
|
||||
Display::handle_resize(map, &mut self.inner);
|
||||
|
||||
let damage = self.inner.write(
|
||||
&mut console_draw::DisplayMap {
|
||||
offscreen: map.inner.ptr_mut(),
|
||||
width: map.inner.width(),
|
||||
height: map.inner.height(),
|
||||
},
|
||||
buf,
|
||||
&mut self.input,
|
||||
);
|
||||
let damage = self
|
||||
.inner
|
||||
.write(unsafe { &mut map.console_map() }, buf, &mut self.input);
|
||||
|
||||
self.display.sync_rect(damage);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
drm = "0.14"
|
||||
drm-fourcc = "2.2.0"
|
||||
log = "0.4"
|
||||
libredox = "0.1.3"
|
||||
redox-ioctl = { git = "https://gitlab.redox-os.org/Ibuki.O/relibc.git", branch = "replace-unlink-rmdir-with-unlinkat" }
|
||||
redox-ioctl = { git = "https://gitlab.redox-os.org/redox-os/relibc.git" }
|
||||
redox_syscall = "0.6"
|
||||
|
||||
common = { path = "../../common" }
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
use std::fs::File;
|
||||
use std::os::fd::{AsFd, BorrowedFd};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::{io, mem, ptr};
|
||||
use std::{io, mem};
|
||||
|
||||
use libredox::flag;
|
||||
use drm::control::connector::{self, State};
|
||||
use drm::control::dumbbuffer::{DumbBuffer, DumbMapping};
|
||||
use drm::control::Device as _;
|
||||
use drm::{ClientCapability, Device as _, DriverCapability};
|
||||
use drm_fourcc::DrmFourcc;
|
||||
|
||||
pub use crate::common::{Damage, DisplayMap};
|
||||
|
||||
@@ -44,100 +49,53 @@ pub struct V2GraphicsHandle {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl AsFd for V2GraphicsHandle {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.file.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl drm::Device for V2GraphicsHandle {}
|
||||
impl drm::control::Device for V2GraphicsHandle {}
|
||||
|
||||
impl V2GraphicsHandle {
|
||||
pub fn from_file(file: File) -> io::Result<Self> {
|
||||
Ok(V2GraphicsHandle { file })
|
||||
let handle = V2GraphicsHandle { file };
|
||||
handle.set_client_capability(ClientCapability::CursorPlaneHotspot, true)?;
|
||||
assert!(handle.get_driver_capability(DriverCapability::DumbBuffer)? == 1);
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
pub fn display_count(&self) -> io::Result<usize> {
|
||||
let mut cmd = ipc::DisplayCount { count: 0 };
|
||||
unsafe {
|
||||
sys_call(&self.file, &mut cmd, 0, &[ipc::DISPLAY_COUNT, 0, 0])?;
|
||||
pub fn first_display(&self) -> io::Result<connector::Handle> {
|
||||
for &connector in self.resource_handles().unwrap().connectors() {
|
||||
if self.get_connector(connector, true)?.state() == State::Connected {
|
||||
return Ok(connector);
|
||||
}
|
||||
}
|
||||
Ok(cmd.count)
|
||||
Err(io::Error::other("no connected display"))
|
||||
}
|
||||
|
||||
pub fn display_size(&self, id: usize) -> io::Result<(u32, u32)> {
|
||||
let mut cmd = ipc::DisplaySize {
|
||||
display_id: id,
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
unsafe {
|
||||
sys_call(&self.file, &mut cmd, 0, &[ipc::DISPLAY_SIZE, 0, 0])?;
|
||||
}
|
||||
Ok((cmd.width, cmd.height))
|
||||
pub fn display_size(&self, handle: connector::Handle) -> io::Result<(u32, u32)> {
|
||||
let (width, height) = self.get_connector(handle, true)?.modes()[0].size();
|
||||
Ok((u32::from(width), u32::from(height)))
|
||||
}
|
||||
|
||||
pub fn create_dumb_framebuffer(&self, width: u32, height: u32) -> io::Result<usize> {
|
||||
let mut cmd = ipc::CreateDumbFramebuffer {
|
||||
width,
|
||||
height,
|
||||
|
||||
fb_id: 0,
|
||||
};
|
||||
unsafe {
|
||||
sys_call(
|
||||
&self.file,
|
||||
&mut cmd,
|
||||
0,
|
||||
&[ipc::CREATE_DUMB_FRAMEBUFFER, 0, 0],
|
||||
)?;
|
||||
}
|
||||
Ok(cmd.fb_id)
|
||||
pub fn create_dumb_framebuffer(&self, width: u32, height: u32) -> io::Result<DumbBuffer> {
|
||||
self.create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32)
|
||||
}
|
||||
|
||||
pub fn map_dumb_framebuffer(
|
||||
pub fn map_dumb_framebuffer<'a>(
|
||||
&self,
|
||||
id: usize,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> io::Result<DisplayMap> {
|
||||
let mut cmd = ipc::DumbFramebufferMapOffset {
|
||||
fb_id: id,
|
||||
offset: 0,
|
||||
};
|
||||
unsafe {
|
||||
sys_call(
|
||||
&self.file,
|
||||
&mut cmd,
|
||||
0,
|
||||
&[ipc::DUMB_FRAMEBUFFER_MAP_OFFSET, 0, 0],
|
||||
)?;
|
||||
}
|
||||
|
||||
let display_ptr = unsafe {
|
||||
libredox::call::mmap(libredox::call::MmapArgs {
|
||||
fd: self.file.as_raw_fd() as usize,
|
||||
offset: cmd.offset as u64,
|
||||
length: (width * height * 4) as usize,
|
||||
prot: flag::PROT_READ | flag::PROT_WRITE,
|
||||
flags: flag::MAP_SHARED,
|
||||
addr: core::ptr::null_mut(),
|
||||
})?
|
||||
};
|
||||
let offscreen = ptr::slice_from_raw_parts_mut(
|
||||
display_ptr as *mut u32,
|
||||
width as usize * height as usize,
|
||||
);
|
||||
|
||||
Ok(unsafe { DisplayMap::new(offscreen, width as usize, height as usize) })
|
||||
buffer: &'a mut DumbBuffer,
|
||||
) -> io::Result<DumbMapping<'a>> {
|
||||
self.map_dumb_buffer(buffer)
|
||||
}
|
||||
|
||||
pub fn destroy_dumb_framebuffer(&self, id: usize) -> io::Result<usize> {
|
||||
let mut cmd = ipc::DestroyDumbFramebuffer { fb_id: id };
|
||||
unsafe {
|
||||
sys_call(
|
||||
&self.file,
|
||||
&mut cmd,
|
||||
0,
|
||||
&[ipc::DESTROY_DUMB_FRAMEBUFFER, 0, 0],
|
||||
)?;
|
||||
}
|
||||
Ok(cmd.fb_id)
|
||||
pub fn destroy_dumb_framebuffer(&self, buffer: DumbBuffer) -> io::Result<()> {
|
||||
self.destroy_dumb_buffer(buffer)
|
||||
}
|
||||
|
||||
pub fn update_plane(&self, display_id: usize, fb_id: usize, damage: Damage) -> io::Result<()> {
|
||||
pub fn update_plane(&self, display_id: usize, fb_id: u32, damage: Damage) -> io::Result<()> {
|
||||
let mut cmd = ipc::UpdatePlane {
|
||||
display_id,
|
||||
fb_id,
|
||||
@@ -156,49 +114,11 @@ pub mod ipc {
|
||||
pub use redox_ioctl::drm::*;
|
||||
|
||||
// FIXME replace these with proper drm interfaces
|
||||
pub const DISPLAY_COUNT: u64 = 1;
|
||||
#[repr(C, packed)]
|
||||
pub struct DisplayCount {
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
pub const DISPLAY_SIZE: u64 = 2;
|
||||
#[repr(C, packed)]
|
||||
pub struct DisplaySize {
|
||||
pub display_id: usize,
|
||||
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
pub const CREATE_DUMB_FRAMEBUFFER: u64 = 3;
|
||||
#[repr(C, packed)]
|
||||
pub struct CreateDumbFramebuffer {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
|
||||
pub fb_id: usize,
|
||||
}
|
||||
|
||||
pub const DUMB_FRAMEBUFFER_MAP_OFFSET: u64 = 4;
|
||||
#[repr(C, packed)]
|
||||
pub struct DumbFramebufferMapOffset {
|
||||
pub fb_id: usize,
|
||||
|
||||
pub offset: usize,
|
||||
}
|
||||
|
||||
pub const DESTROY_DUMB_FRAMEBUFFER: u64 = 5;
|
||||
#[repr(C, packed)]
|
||||
pub struct DestroyDumbFramebuffer {
|
||||
pub fb_id: usize,
|
||||
}
|
||||
|
||||
pub const UPDATE_PLANE: u64 = 6;
|
||||
#[repr(C, packed)]
|
||||
pub struct UpdatePlane {
|
||||
pub display_id: usize,
|
||||
pub fb_id: usize,
|
||||
pub fb_id: u32,
|
||||
pub damage: Damage,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user