Merge branch 'graphics_driver_api_refactor' into 'master'
A bunch of improvements to the graphics subsystem See merge request redox-os/drivers!246
This commit is contained in:
@@ -4,7 +4,7 @@ use std::collections::{BTreeSet, VecDeque};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::{cmp, ptr};
|
||||
|
||||
use graphics_ipc::legacy::Damage;
|
||||
use graphics_ipc::v1::Damage;
|
||||
use orbclient::FONT;
|
||||
|
||||
pub struct DisplayMap {
|
||||
@@ -221,7 +221,7 @@ impl TextScreen {
|
||||
} else {
|
||||
damage.push(Damage {
|
||||
x: 0,
|
||||
y: i32::try_from(change).unwrap() * 16,
|
||||
y: u32::try_from(change).unwrap() * 16,
|
||||
width,
|
||||
height: 16,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::io;
|
||||
|
||||
use graphics_ipc::legacy::Damage;
|
||||
use graphics_ipc::v1::Damage;
|
||||
use inputd::{VtEvent, VtEventKind};
|
||||
use libredox::errno::EOPNOTSUPP;
|
||||
use libredox::Fd;
|
||||
@@ -9,24 +9,23 @@ use redox_scheme::{RequestKind, Response, Scheme, SignalBehavior, Socket};
|
||||
use syscall::{Error, MapFlags, Result, EAGAIN, EBADF, EINVAL};
|
||||
|
||||
pub trait GraphicsAdapter {
|
||||
type Resource: Resource;
|
||||
type Framebuffer: Framebuffer;
|
||||
|
||||
fn displays(&self) -> Vec<usize>;
|
||||
fn display_size(&self, display_id: usize) -> (u32, u32);
|
||||
|
||||
fn create_resource(&mut self, width: u32, height: u32) -> Self::Resource;
|
||||
fn map_resource(&mut self, resource: &Self::Resource) -> *mut u8;
|
||||
fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer;
|
||||
fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8;
|
||||
|
||||
fn set_scanout(&mut self, display_id: usize, resource: &Self::Resource);
|
||||
fn flush_resource(
|
||||
fn update_plane(
|
||||
&mut self,
|
||||
display_id: usize,
|
||||
resource: &Self::Resource,
|
||||
damage: Option<&[Damage]>,
|
||||
framebuffer: &Self::Framebuffer,
|
||||
damage: &[Damage],
|
||||
);
|
||||
}
|
||||
|
||||
pub trait Resource {
|
||||
pub trait Framebuffer {
|
||||
fn width(&self) -> u32;
|
||||
fn height(&self) -> u32;
|
||||
}
|
||||
@@ -40,7 +39,7 @@ pub struct GraphicsScheme<T: GraphicsAdapter> {
|
||||
handles: BTreeMap<usize, Handle>,
|
||||
|
||||
active_vt: usize,
|
||||
vts_res: HashMap<usize, HashMap<usize, T::Resource>>,
|
||||
vts_fb: HashMap<usize, HashMap<usize, T::Framebuffer>>,
|
||||
}
|
||||
|
||||
enum Handle {
|
||||
@@ -59,7 +58,7 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
|
||||
next_id: 0,
|
||||
handles: BTreeMap::new(),
|
||||
active_vt: 0,
|
||||
vts_res: HashMap::new(),
|
||||
vts_fb: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,16 +80,16 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
|
||||
log::info!("activate {}", vt_event.vt);
|
||||
|
||||
for display_id in self.adapter.displays() {
|
||||
let resource = self
|
||||
.vts_res
|
||||
let framebuffer = self
|
||||
.vts_fb
|
||||
.entry(vt_event.vt)
|
||||
.or_default()
|
||||
.entry(display_id)
|
||||
.or_insert_with(|| {
|
||||
let (width, height) = self.adapter.display_size(display_id);
|
||||
self.adapter.create_resource(width, height)
|
||||
self.adapter.create_dumb_framebuffer(width, height)
|
||||
});
|
||||
self.adapter.set_scanout(display_id, resource);
|
||||
Self::update_whole_screen(&mut self.adapter, display_id, framebuffer);
|
||||
|
||||
self.active_vt = vt_event.vt;
|
||||
}
|
||||
@@ -140,6 +139,19 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_whole_screen(adapter: &mut T, screen: usize, framebuffer: &T::Framebuffer) {
|
||||
adapter.update_plane(
|
||||
screen,
|
||||
framebuffer,
|
||||
&[Damage {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: framebuffer.width(),
|
||||
height: framebuffer.height(),
|
||||
}],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: GraphicsAdapter> Scheme for GraphicsScheme<T> {
|
||||
@@ -160,13 +172,13 @@ impl<T: GraphicsAdapter> Scheme for GraphicsScheme<T> {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
self.vts_res
|
||||
self.vts_fb
|
||||
.entry(vt)
|
||||
.or_default()
|
||||
.entry(id)
|
||||
.or_insert_with(|| {
|
||||
let (width, height) = self.adapter.display_size(id);
|
||||
self.adapter.create_resource(width, height)
|
||||
self.adapter.create_dumb_framebuffer(width, height)
|
||||
});
|
||||
|
||||
self.next_id += 1;
|
||||
@@ -177,12 +189,12 @@ impl<T: GraphicsAdapter> Scheme for GraphicsScheme<T> {
|
||||
|
||||
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> syscall::Result<usize> {
|
||||
let Handle::Screen { vt, screen } = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
let resource = &self.vts_res[vt][screen];
|
||||
let framebuffer = &self.vts_fb[vt][screen];
|
||||
let path = format!(
|
||||
"{}:{vt}.{screen}/{}/{}",
|
||||
self.scheme_name,
|
||||
resource.width(),
|
||||
resource.height()
|
||||
framebuffer.width(),
|
||||
framebuffer.height()
|
||||
);
|
||||
buf[..path.len()].copy_from_slice(path.as_bytes());
|
||||
Ok(path.len())
|
||||
@@ -192,11 +204,11 @@ impl<T: GraphicsAdapter> Scheme for GraphicsScheme<T> {
|
||||
let Handle::Screen { vt, screen } = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
if *vt != self.active_vt {
|
||||
// This is a protection against background VT's spamming us with flush requests. We will
|
||||
// flush the resource on the next VT switch anyway
|
||||
// flush the framebuffer on the next VT switch anyway
|
||||
return Ok(0);
|
||||
}
|
||||
let resource = &self.vts_res[vt][screen];
|
||||
self.adapter.flush_resource(*screen, resource, None);
|
||||
let framebuffer = &self.vts_fb[vt][screen];
|
||||
Self::update_whole_screen(&mut self.adapter, *screen, framebuffer);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@@ -216,11 +228,11 @@ impl<T: GraphicsAdapter> Scheme for GraphicsScheme<T> {
|
||||
|
||||
if *vt != self.active_vt {
|
||||
// This is a protection against background VT's spamming us with flush requests. We will
|
||||
// flush the resource on the next VT switch anyway
|
||||
// flush the framebuffer on the next VT switch anyway
|
||||
return Ok(buf.len());
|
||||
}
|
||||
|
||||
let resource = &self.vts_res[vt][screen];
|
||||
let framebuffer = &self.vts_fb[vt][screen];
|
||||
|
||||
let damage = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
@@ -229,7 +241,7 @@ impl<T: GraphicsAdapter> Scheme for GraphicsScheme<T> {
|
||||
)
|
||||
};
|
||||
|
||||
self.adapter.flush_resource(*screen, resource, Some(damage));
|
||||
self.adapter.update_plane(*screen, framebuffer, damage);
|
||||
|
||||
Ok(buf.len())
|
||||
}
|
||||
@@ -248,8 +260,8 @@ impl<T: GraphicsAdapter> Scheme for GraphicsScheme<T> {
|
||||
log::info!("KSMSG MMAP {} {:?} {} {}", id, flags, offset, size);
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EINVAL))?;
|
||||
let Handle::Screen { vt, screen } = handle;
|
||||
let resource = &self.vts_res[vt][screen];
|
||||
let ptr = T::map_resource(&mut self.adapter, resource);
|
||||
let framebuffer = &self.vts_fb[vt][screen];
|
||||
let ptr = T::map_dumb_framebuffer(&mut self.adapter, framebuffer);
|
||||
Ok(ptr as usize)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use event::{user_data, EventQueue};
|
||||
use graphics_ipc::legacy::{Damage, LegacyGraphicsHandle};
|
||||
use graphics_ipc::v1::{Damage, V1GraphicsHandle};
|
||||
use inputd::ConsumerHandle;
|
||||
use libredox::errno::ESTALE;
|
||||
use orbclient::Event;
|
||||
@@ -22,7 +22,7 @@ fn read_to_slice<T: Copy>(
|
||||
}
|
||||
}
|
||||
|
||||
fn display_fd_map(display_handle: LegacyGraphicsHandle) -> io::Result<DisplayMap> {
|
||||
fn display_fd_map(display_handle: V1GraphicsHandle) -> io::Result<DisplayMap> {
|
||||
let display_map = display_handle.map_display()?;
|
||||
Ok(DisplayMap {
|
||||
display_handle: Arc::new(display_handle),
|
||||
@@ -31,8 +31,8 @@ fn display_fd_map(display_handle: LegacyGraphicsHandle) -> io::Result<DisplayMap
|
||||
}
|
||||
|
||||
pub struct DisplayMap {
|
||||
display_handle: Arc<LegacyGraphicsHandle>,
|
||||
pub inner: graphics_ipc::legacy::DisplayMap,
|
||||
display_handle: Arc<V1GraphicsHandle>,
|
||||
pub inner: graphics_ipc::v1::DisplayMap,
|
||||
}
|
||||
|
||||
enum DisplayCommand {
|
||||
@@ -50,7 +50,7 @@ impl Display {
|
||||
|
||||
let map = match input_handle.open_display() {
|
||||
Ok(display) => {
|
||||
let display_handle = LegacyGraphicsHandle::from_file(display)?;
|
||||
let display_handle = V1GraphicsHandle::from_file(display)?;
|
||||
Arc::new(Mutex::new(Some(
|
||||
display_fd_map(display_handle)
|
||||
.unwrap_or_else(|e| panic!("failed to map display: {e}")),
|
||||
@@ -102,7 +102,7 @@ impl Display {
|
||||
eprintln!("fbbootlogd: handoff requested");
|
||||
|
||||
let new_display_handle = match input_handle.open_display() {
|
||||
Ok(display) => LegacyGraphicsHandle::from_file(display).unwrap(),
|
||||
Ok(display) => V1GraphicsHandle::from_file(display).unwrap(),
|
||||
Err(err) => {
|
||||
println!("fbbootlogd: No display present yet: {err}");
|
||||
continue;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use graphics_ipc::legacy::{Damage, LegacyGraphicsHandle};
|
||||
use graphics_ipc::v1::{Damage, V1GraphicsHandle};
|
||||
use inputd::ConsumerHandle;
|
||||
use std::io;
|
||||
|
||||
@@ -8,8 +8,8 @@ pub struct Display {
|
||||
}
|
||||
|
||||
pub struct DisplayMap {
|
||||
display_handle: LegacyGraphicsHandle,
|
||||
pub inner: graphics_ipc::legacy::DisplayMap,
|
||||
display_handle: V1GraphicsHandle,
|
||||
pub inner: graphics_ipc::v1::DisplayMap,
|
||||
}
|
||||
|
||||
impl Display {
|
||||
@@ -63,10 +63,10 @@ impl Display {
|
||||
}
|
||||
}
|
||||
|
||||
fn open_display(input_handle: &ConsumerHandle) -> io::Result<LegacyGraphicsHandle> {
|
||||
fn open_display(input_handle: &ConsumerHandle) -> io::Result<V1GraphicsHandle> {
|
||||
let display_file = input_handle.open_display()?;
|
||||
|
||||
LegacyGraphicsHandle::from_file(display_file)
|
||||
V1GraphicsHandle::from_file(display_file)
|
||||
}
|
||||
|
||||
pub fn sync_rects(&mut self, sync_rects: Vec<Damage>) {
|
||||
|
||||
@@ -1 +1 @@
|
||||
pub mod legacy;
|
||||
pub mod v1;
|
||||
|
||||
@@ -4,17 +4,17 @@ use std::{cmp, io, mem, ptr, slice};
|
||||
|
||||
use libredox::flag;
|
||||
|
||||
/// A graphics handle using the legacy graphics API.
|
||||
/// A graphics handle using the v1 graphics API.
|
||||
///
|
||||
/// The legacy graphics API only allows a single framebuffer for each VT and supports neither page
|
||||
/// The v1 graphics API only allows a single framebuffer for each VT and supports neither page
|
||||
/// flipping nor cursor planes.
|
||||
pub struct LegacyGraphicsHandle {
|
||||
pub struct V1GraphicsHandle {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl LegacyGraphicsHandle {
|
||||
impl V1GraphicsHandle {
|
||||
pub fn from_file(file: File) -> io::Result<Self> {
|
||||
Ok(LegacyGraphicsHandle { file })
|
||||
Ok(V1GraphicsHandle { file })
|
||||
}
|
||||
|
||||
pub fn map_display(&self) -> io::Result<DisplayMap> {
|
||||
@@ -111,18 +111,20 @@ impl Drop for DisplayMap {
|
||||
}
|
||||
|
||||
// Keep synced with orbital's SyncRect
|
||||
// Technically orbital uses i32 rather than u32, but values larger than i32::MAX
|
||||
// would be a bug anyway.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(packed)]
|
||||
pub struct Damage {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl Damage {
|
||||
#[must_use]
|
||||
pub fn clip(mut self, width: i32, height: i32) -> Self {
|
||||
pub fn clip(mut self, width: u32, height: u32) -> Self {
|
||||
// Clip damage
|
||||
self.x = cmp::min(self.x, width);
|
||||
if self.x + self.width > width {
|
||||
@@ -2,8 +2,8 @@ use std::alloc::{self, Layout};
|
||||
use std::convert::TryInto;
|
||||
use std::ptr::{self, NonNull};
|
||||
|
||||
use driver_graphics::{GraphicsAdapter, Resource};
|
||||
use graphics_ipc::legacy::Damage;
|
||||
use driver_graphics::{Framebuffer, GraphicsAdapter};
|
||||
use graphics_ipc::v1::Damage;
|
||||
use syscall::PAGE_SIZE;
|
||||
|
||||
use crate::framebuffer::FrameBuffer;
|
||||
@@ -13,7 +13,7 @@ pub struct FbAdapter {
|
||||
}
|
||||
|
||||
impl GraphicsAdapter for FbAdapter {
|
||||
type Resource = GraphicScreen;
|
||||
type Framebuffer = GraphicScreen;
|
||||
|
||||
fn displays(&self) -> Vec<usize> {
|
||||
(0..self.framebuffers.len()).collect()
|
||||
@@ -26,40 +26,21 @@ impl GraphicsAdapter for FbAdapter {
|
||||
)
|
||||
}
|
||||
|
||||
fn create_resource(&mut self, width: u32, height: u32) -> Self::Resource {
|
||||
fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer {
|
||||
GraphicScreen::new(width as usize, height as usize)
|
||||
}
|
||||
|
||||
fn map_resource(&mut self, resource: &Self::Resource) -> *mut u8 {
|
||||
resource.ptr.as_ptr().cast::<u8>()
|
||||
fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 {
|
||||
framebuffer.ptr.as_ptr().cast::<u8>()
|
||||
}
|
||||
|
||||
fn set_scanout(&mut self, display_id: usize, resource: &Self::Resource) {
|
||||
self.flush_resource(display_id, resource, None);
|
||||
}
|
||||
|
||||
fn flush_resource(
|
||||
fn update_plane(
|
||||
&mut self,
|
||||
display_id: usize,
|
||||
resource: &Self::Resource,
|
||||
damage: Option<&[Damage]>,
|
||||
framebuffer: &Self::Framebuffer,
|
||||
damage: &[Damage],
|
||||
) {
|
||||
if let Some(damage) = damage {
|
||||
resource.sync(&mut self.framebuffers[display_id], damage)
|
||||
} else {
|
||||
let framebuffer: &mut FrameBuffer = &mut self.framebuffers[display_id];
|
||||
let width = resource.width.try_into().unwrap();
|
||||
let height = resource.height.try_into().unwrap();
|
||||
resource.sync(
|
||||
framebuffer,
|
||||
&[Damage {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width,
|
||||
height,
|
||||
}],
|
||||
);
|
||||
}
|
||||
framebuffer.sync(&mut self.framebuffers[display_id], damage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +78,7 @@ impl Drop for GraphicScreen {
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource for GraphicScreen {
|
||||
impl Framebuffer for GraphicScreen {
|
||||
fn width(&self) -> u32 {
|
||||
self.width as u32
|
||||
}
|
||||
@@ -115,10 +96,10 @@ impl GraphicScreen {
|
||||
self.height.try_into().unwrap(),
|
||||
);
|
||||
|
||||
let start_x: usize = sync_rect.x.try_into().unwrap_or(0);
|
||||
let start_y: usize = sync_rect.y.try_into().unwrap_or(0);
|
||||
let w: usize = sync_rect.width.try_into().unwrap_or(0);
|
||||
let h: usize = sync_rect.height.try_into().unwrap_or(0);
|
||||
let start_x: usize = sync_rect.x.try_into().unwrap();
|
||||
let start_y: usize = sync_rect.y.try_into().unwrap();
|
||||
let w: usize = sync_rect.width.try_into().unwrap();
|
||||
let h: usize = sync_rect.height.try_into().unwrap();
|
||||
|
||||
let offscreen_ptr = self.ptr.as_ptr() as *mut u32;
|
||||
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
|
||||
|
||||
@@ -109,6 +109,9 @@ pub enum CommandTy {
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<CommandTy>(), 4);
|
||||
|
||||
const VIRTIO_GPU_FLAG_FENCE: u32 = 1 << 0;
|
||||
//const VIRTIO_GPU_FLAG_INFO_RING_IDX: u32 = 1 << 1;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct ControlHeader {
|
||||
@@ -192,7 +195,7 @@ impl Default for GetDisplayInfo {
|
||||
|
||||
static RESOURCE_ALLOC: AtomicU32 = AtomicU32::new(1); // XXX: 0 is reserved for whatever that takes `resource_id`.
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct ResourceId(u32);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::{dma::Dma, sgl};
|
||||
use driver_graphics::{GraphicsAdapter, GraphicsScheme, Resource};
|
||||
use graphics_ipc::legacy::Damage;
|
||||
use driver_graphics::{Framebuffer, GraphicsAdapter, GraphicsScheme};
|
||||
use graphics_ipc::v1::Damage;
|
||||
use inputd::DisplayHandle;
|
||||
|
||||
use syscall::PAGE_SIZE;
|
||||
@@ -15,22 +15,22 @@ use crate::*;
|
||||
impl Into<GpuRect> for Damage {
|
||||
fn into(self) -> GpuRect {
|
||||
GpuRect {
|
||||
x: self.x as u32,
|
||||
y: self.y as u32,
|
||||
width: self.width as u32,
|
||||
height: self.height as u32,
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VirtGpuResource {
|
||||
pub struct VirtGpuFramebuffer {
|
||||
id: ResourceId,
|
||||
sgl: sgl::Sgl,
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
impl Resource for VirtGpuResource {
|
||||
impl Framebuffer for VirtGpuFramebuffer {
|
||||
fn width(&self) -> u32 {
|
||||
self.width
|
||||
}
|
||||
@@ -44,6 +44,7 @@ impl Resource for VirtGpuResource {
|
||||
pub struct Display {
|
||||
width: u32,
|
||||
height: u32,
|
||||
active_resource: Option<ResourceId>,
|
||||
}
|
||||
|
||||
pub struct VirtGpuAdapter<'a> {
|
||||
@@ -65,11 +66,16 @@ impl VirtGpuAdapter<'_> {
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
async fn flush_resource_inner(&self, flush: ResourceFlush) -> Result<(), Error> {
|
||||
let header = self.send_request(Dma::new(flush)?).await?;
|
||||
assert_eq!(header.ty, CommandTy::RespOkNodata);
|
||||
async fn send_request_fenced<T>(&self, request: Dma<T>) -> Result<Dma<ControlHeader>, Error> {
|
||||
let mut header = Dma::new(ControlHeader::default())?;
|
||||
header.flags |= VIRTIO_GPU_FLAG_FENCE;
|
||||
let command = ChainBuilder::new()
|
||||
.chain(Buffer::new(&request))
|
||||
.chain(Buffer::new(&header).flags(DescriptorFlags::WRITE_ONLY))
|
||||
.build();
|
||||
|
||||
Ok(())
|
||||
self.control_queue.send(command).await;
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
async fn get_display_info(&self) -> Result<Dma<GetDisplayInfo>, Error> {
|
||||
@@ -89,7 +95,7 @@ impl VirtGpuAdapter<'_> {
|
||||
}
|
||||
|
||||
impl GraphicsAdapter for VirtGpuAdapter<'_> {
|
||||
type Resource = VirtGpuResource;
|
||||
type Framebuffer = VirtGpuFramebuffer;
|
||||
|
||||
fn displays(&self) -> Vec<usize> {
|
||||
self.displays.iter().enumerate().map(|(i, _)| i).collect()
|
||||
@@ -102,7 +108,7 @@ impl GraphicsAdapter for VirtGpuAdapter<'_> {
|
||||
)
|
||||
}
|
||||
|
||||
fn create_resource(&mut self, width: u32, height: u32) -> Self::Resource {
|
||||
fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer {
|
||||
futures::executor::block_on(async {
|
||||
let bpp = 32;
|
||||
let fb_size = width as usize * height as usize * bpp / 8;
|
||||
@@ -151,7 +157,7 @@ impl GraphicsAdapter for VirtGpuAdapter<'_> {
|
||||
self.control_queue.send(command).await;
|
||||
assert_eq!(header.ty, CommandTy::RespOkNodata);
|
||||
|
||||
VirtGpuResource {
|
||||
VirtGpuFramebuffer {
|
||||
id: res_id,
|
||||
sgl,
|
||||
width,
|
||||
@@ -160,39 +166,24 @@ impl GraphicsAdapter for VirtGpuAdapter<'_> {
|
||||
})
|
||||
}
|
||||
|
||||
fn map_resource(&mut self, resource: &Self::Resource) -> *mut u8 {
|
||||
resource.sgl.as_ptr()
|
||||
fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 {
|
||||
framebuffer.sgl.as_ptr()
|
||||
}
|
||||
|
||||
fn set_scanout(&mut self, display_id: usize, resource: &Self::Resource) {
|
||||
futures::executor::block_on(async {
|
||||
let scanout_request = Dma::new(SetScanout::new(
|
||||
display_id as u32,
|
||||
resource.id,
|
||||
GpuRect::new(0, 0, resource.width, resource.height),
|
||||
))
|
||||
.unwrap();
|
||||
let header = self.send_request(scanout_request).await.unwrap();
|
||||
assert_eq!(header.ty, CommandTy::RespOkNodata);
|
||||
});
|
||||
|
||||
self.flush_resource(display_id, resource, None);
|
||||
}
|
||||
|
||||
fn flush_resource(
|
||||
fn update_plane(
|
||||
&mut self,
|
||||
_display_id: usize,
|
||||
resource: &Self::Resource,
|
||||
damage: Option<&[Damage]>,
|
||||
display_id: usize,
|
||||
framebuffer: &Self::Framebuffer,
|
||||
damage: &[Damage],
|
||||
) {
|
||||
futures::executor::block_on(async {
|
||||
let req = Dma::new(XferToHost2d::new(
|
||||
resource.id,
|
||||
framebuffer.id,
|
||||
GpuRect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: resource.width,
|
||||
height: resource.height,
|
||||
width: framebuffer.width,
|
||||
height: framebuffer.height,
|
||||
},
|
||||
0,
|
||||
))
|
||||
@@ -200,29 +191,26 @@ impl GraphicsAdapter for VirtGpuAdapter<'_> {
|
||||
let header = self.send_request(req).await.unwrap();
|
||||
assert_eq!(header.ty, CommandTy::RespOkNodata);
|
||||
|
||||
if let Some(damage) = damage {
|
||||
for damage in damage {
|
||||
self.flush_resource_inner(ResourceFlush::new(
|
||||
resource.id,
|
||||
damage
|
||||
.clip(resource.width as i32, resource.height as i32)
|
||||
.into(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
} else {
|
||||
self.flush_resource_inner(ResourceFlush::new(
|
||||
resource.id,
|
||||
GpuRect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: resource.width,
|
||||
height: resource.height,
|
||||
},
|
||||
// FIXME once we support resizing we also need to check that the current and target size match
|
||||
if self.displays[display_id].active_resource != Some(framebuffer.id) {
|
||||
let scanout_request = Dma::new(SetScanout::new(
|
||||
display_id as u32,
|
||||
framebuffer.id,
|
||||
GpuRect::new(0, 0, framebuffer.width, framebuffer.height),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
let header = self.send_request(scanout_request).await.unwrap();
|
||||
assert_eq!(header.ty, CommandTy::RespOkNodata);
|
||||
self.displays[display_id].active_resource = Some(framebuffer.id);
|
||||
}
|
||||
|
||||
for damage in damage {
|
||||
let flush = ResourceFlush::new(
|
||||
framebuffer.id,
|
||||
damage.clip(framebuffer.width, framebuffer.height).into(),
|
||||
);
|
||||
let header = self.send_request(Dma::new(flush).unwrap()).await.unwrap();
|
||||
assert_eq!(header.ty, CommandTy::RespOkNodata);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -261,11 +249,13 @@ impl<'a> GpuScheme {
|
||||
adapter.displays.push(Display {
|
||||
width: 640,
|
||||
height: 480,
|
||||
active_resource: None,
|
||||
});
|
||||
} else {
|
||||
adapter.displays.push(Display {
|
||||
width: info.rect.width,
|
||||
height: info.rect.height,
|
||||
active_resource: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user