drivers/graphics: Use drm dumb buffer ioctls
This commit is contained in:
Generated
+3
@@ -719,6 +719,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"console-draw",
|
||||
"daemon",
|
||||
"drm",
|
||||
"graphics-ipc",
|
||||
"inputd",
|
||||
"libredox",
|
||||
@@ -736,6 +737,7 @@ dependencies = [
|
||||
"common",
|
||||
"console-draw",
|
||||
"daemon",
|
||||
"drm",
|
||||
"graphics-ipc",
|
||||
"inputd",
|
||||
"libredox",
|
||||
@@ -925,6 +927,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"common",
|
||||
"drm",
|
||||
"drm-fourcc",
|
||||
"libredox",
|
||||
"log",
|
||||
"redox-ioctl",
|
||||
|
||||
@@ -83,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>>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -463,6 +463,10 @@ 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
|
||||
@@ -596,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);
|
||||
@@ -634,70 +682,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
data.set_modifier([0; 4]);
|
||||
Ok(0)
|
||||
}),
|
||||
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));
|
||||
@@ -713,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));
|
||||
};
|
||||
|
||||
@@ -747,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 {
|
||||
@@ -55,24 +70,27 @@ impl FbbootlogScheme {
|
||||
let (width, height) = new_display_handle
|
||||
.display_size(new_display_handle.first_display().unwrap())
|
||||
.unwrap();
|
||||
let fb = new_display_handle
|
||||
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) {
|
||||
@@ -127,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;
|
||||
@@ -151,11 +165,15 @@ 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,45 +187,47 @@ impl FbbootlogScheme {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,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 {
|
||||
@@ -36,28 +51,29 @@ impl Display {
|
||||
let (width, height) = new_display_handle
|
||||
.display_size(new_display_handle.first_display().unwrap())
|
||||
.unwrap();
|
||||
let fb = new_display_handle
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
@@ -69,43 +85,44 @@ impl Display {
|
||||
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)
|
||||
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!("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);
|
||||
}
|
||||
@@ -115,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);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ 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/redox-os/relibc.git" }
|
||||
|
||||
@@ -1,12 +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 drm::control::connector::{self, State};
|
||||
use drm::control::dumbbuffer::{DumbBuffer, DumbMapping};
|
||||
use drm::control::Device as _;
|
||||
use drm::{ClientCapability, Device as _, DriverCapability};
|
||||
use libredox::flag;
|
||||
use drm_fourcc::DrmFourcc;
|
||||
|
||||
pub use crate::common::{Damage, DisplayMap};
|
||||
|
||||
@@ -79,75 +80,22 @@ impl V2GraphicsHandle {
|
||||
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,
|
||||
@@ -166,34 +114,11 @@ pub mod ipc {
|
||||
pub use redox_ioctl::drm::*;
|
||||
|
||||
// FIXME replace these with proper drm interfaces
|
||||
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