Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Implement a vulkan renderer #71

Merged
merged 15 commits into from
Feb 14, 2024
Merged
Prev Previous commit
Next Next commit
metal: use IN_FORMATS plane property
  • Loading branch information
mahkoh committed Feb 8, 2024
commit e0ed29038eadbe4d3467ed410e89b48d0e299cd2
96 changes: 62 additions & 34 deletions src/backends/metal/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use {
DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT,
},
gbm::{GbmDevice, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING, GBM_BO_USE_SCANOUT},
ModifiedFormat, INVALID_MODIFIER,
Modifier,
},
},
ahash::{AHashMap, AHashSet},
Expand Down Expand Up @@ -505,6 +505,12 @@ pub enum PlaneType {
Cursor,
}

#[derive(Debug)]
pub struct PlaneFormat {
_format: &'static Format,
modifiers: Vec<Modifier>,
}

#[derive(Debug)]
pub struct MetalPlane {
pub id: DrmPlane,
Expand All @@ -513,7 +519,7 @@ pub struct MetalPlane {
pub ty: PlaneType,

pub possible_crtcs: u32,
pub formats: AHashMap<u32, &'static Format>,
pub formats: AHashMap<u32, PlaneFormat>,

pub assigned: Cell<bool>,

Expand Down Expand Up @@ -755,19 +761,36 @@ fn create_crtc(

fn create_plane(plane: DrmPlane, master: &Rc<DrmMaster>) -> Result<MetalPlane, DrmError> {
let info = master.get_plane_info(plane)?;
let props = collect_properties(master, plane)?;
let mut formats = AHashMap::new();
for format in info.format_types {
if let Some(f) = crate::format::formats().get(&format) {
formats.insert(format, *f);
} else {
// log::warn!(
// "{:?} supports unknown format '{:?}'",
// plane,
// crate::format::debug(format)
// );
if let Some((_, v)) = props.props.get(b"IN_FORMATS".as_bstr()) {
for format in master.get_in_formats(*v as _)? {
if format.modifiers.is_empty() {
continue;
}
if let Some(f) = crate::format::formats().get(&format.format) {
formats.insert(
format.format,
PlaneFormat {
_format: f,
modifiers: format.modifiers,
},
);
}
}
} else {
for format in info.format_types {
if let Some(f) = crate::format::formats().get(&format) {
formats.insert(
format,
PlaneFormat {
_format: f,
modifiers: vec![],
},
);
}
}
}
let props = collect_properties(master, plane)?;
let ty = match props.props.get(b"type".as_bstr()) {
Some((def, val)) => match &def.ty {
DrmPropertyType::Enum { values, .. } => 'ty: {
Expand Down Expand Up @@ -1569,30 +1592,33 @@ impl MetalBackend {
fn create_scanout_buffers(
&self,
dev: &Rc<MetalDrmDevice>,
format: &ModifiedFormat,
format: &Format,
modifiers: &[Modifier],
width: i32,
height: i32,
ctx: &MetalRenderContext,
cursor: bool,
) -> Result<[RenderBuffer; 2], MetalError> {
let create = || self.create_scanout_buffer(dev, format, width, height, ctx, cursor);
let create =
|| self.create_scanout_buffer(dev, format, modifiers, width, height, ctx, cursor);
Ok([create()?, create()?])
}

fn create_scanout_buffer(
&self,
dev: &Rc<MetalDrmDevice>,
format: &ModifiedFormat,
format: &Format,
modifiers: &[Modifier],
width: i32,
height: i32,
render_ctx: &MetalRenderContext,
cursor: bool,
) -> Result<RenderBuffer, MetalError> {
let mut usage = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT;
if cursor {
if cursor && modifiers.is_empty() {
usage |= GBM_BO_USE_LINEAR;
};
let dev_bo = dev.gbm.create_bo(width, height, format, usage);
let dev_bo = dev.gbm.create_bo(width, height, format, modifiers, usage);
let dev_bo = match dev_bo {
Ok(b) => b,
Err(e) => return Err(MetalError::ScanoutBuffer(e)),
Expand All @@ -1619,7 +1645,10 @@ impl MetalBackend {
} else {
// Create a _bridge_ BO in the render device
usage = GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR;
let render_bo = render_ctx.gfx.gbm().create_bo(width, height, format, usage);
let render_bo = render_ctx
.gfx
.gbm()
.create_bo(width, height, format, &[], usage);
let render_bo = match render_bo {
Ok(b) => b,
Err(e) => return Err(MetalError::ScanoutBuffer(e)),
Expand Down Expand Up @@ -1716,46 +1745,45 @@ impl MetalBackend {
return Ok(());
}
};
let primary_plane = 'primary_plane: {
let (primary_plane, primary_modifiers) = 'primary_plane: {
for plane in crtc.possible_planes.values() {
if plane.ty == PlaneType::Primary
&& !plane.assigned.get()
&& plane.formats.contains_key(&XRGB8888.drm)
{
break 'primary_plane plane.clone();
if plane.ty == PlaneType::Primary && !plane.assigned.get() {
if let Some(format) = plane.formats.get(&XRGB8888.drm) {
break 'primary_plane (plane.clone(), &format.modifiers);
}
}
}
return Err(MetalError::NoPrimaryPlaneForConnector);
};
let buffers = Rc::new(self.create_scanout_buffers(
&connector.dev,
&ModifiedFormat {
format: XRGB8888,
modifier: INVALID_MODIFIER,
},
XRGB8888,
primary_modifiers,
mode.hdisplay as _,
mode.vdisplay as _,
ctx,
false,
)?);
let mut cursor_plane = None;
let mut cursor_modifiers = &[][..];
for plane in crtc.possible_planes.values() {
if plane.ty == PlaneType::Cursor
&& !plane.assigned.get()
&& plane.formats.contains_key(&ARGB8888.drm)
{
cursor_plane = Some(plane.clone());
break;
if let Some(format) = plane.formats.get(&ARGB8888.drm) {
cursor_plane = Some(plane.clone());
cursor_modifiers = &format.modifiers[..];
break;
}
}
}
let mut cursor_buffers = None;
if cursor_plane.is_some() {
let res = self.create_scanout_buffers(
&connector.dev,
&ModifiedFormat {
format: ARGB8888,
modifier: INVALID_MODIFIER,
},
ARGB8888,
cursor_modifiers,
connector.dev.cursor_width as _,
connector.dev.cursor_height as _,
ctx,
Expand Down
7 changes: 1 addition & 6 deletions src/backends/x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use {
video::{
drm::{ConnectorType, Drm, DrmError, DrmVersion},
gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING},
ModifiedFormat, INVALID_MODIFIER,
},
wire_xcon::{
ChangeProperty, ChangeWindowAttributes, ConfigureNotify, CreateCursor, CreatePixmap,
Expand Down Expand Up @@ -376,15 +375,11 @@ impl XBackend {
width: i32,
height: i32,
) -> Result<[XImage; 2], XBackendError> {
let format = ModifiedFormat {
format: XRGB8888,
modifier: INVALID_MODIFIER,
};
let mut images = [None, None];
for image in &mut images {
let bo = self
.gbm
.create_bo(width, height, &format, GBM_BO_USE_RENDERING)?;
.create_bo(width, height, XRGB8888, &[], GBM_BO_USE_RENDERING)?;
let dma = bo.dmabuf();
assert!(dma.planes.len() == 1);
let plane = dma.planes.first().unwrap();
Expand Down
7 changes: 1 addition & 6 deletions src/ifs/jay_screencast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use {
video::{
dmabuf::DmaBuf,
gbm::{GbmError, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING},
ModifiedFormat, INVALID_MODIFIER,
},
wire::{jay_screencast::*, JayScreencastId},
},
Expand Down Expand Up @@ -199,17 +198,13 @@ impl JayScreencast {
let mode = output.global.mode.get();
let num = 3;
for _ in 0..num {
let format = ModifiedFormat {
format: XRGB8888,
modifier: INVALID_MODIFIER,
};
let mut flags = GBM_BO_USE_RENDERING;
if self.linear.get() {
flags |= GBM_BO_USE_LINEAR;
}
let buffer = ctx
.gbm()
.create_bo(mode.width, mode.height, &format, flags)?;
.create_bo(mode.width, mode.height, XRGB8888, &[], flags)?;
let fb = ctx.clone().dmabuf_img(buffer.dmabuf())?.to_framebuffer()?;
buffers.push(ScreencastBuffer {
dmabuf: buffer.dmabuf().clone(),
Expand Down
29 changes: 13 additions & 16 deletions src/portal/ptr_gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use {
asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap,
errorfmt::ErrorFmt, rc_eq::rc_eq,
},
video::{gbm::GBM_BO_USE_RENDERING, ModifiedFormat, INVALID_MODIFIER},
video::gbm::GBM_BO_USE_RENDERING,
wire::{
wp_fractional_scale_v1::PreferredScale, zwlr_layer_surface_v1::Configure,
ZwpLinuxBufferParamsV1Id,
Expand Down Expand Up @@ -694,21 +694,18 @@ impl WindowData {
let width = (self.width.get() as f64 * self.scale.get().to_f64()).round() as i32;
let height = (self.height.get() as f64 * self.scale.get().to_f64()).round() as i32;
for _ in 0..NUM_BUFFERS {
let format = ModifiedFormat {
format: ARGB8888,
modifier: INVALID_MODIFIER,
};
let bo = match ctx
.ctx
.gbm()
.create_bo(width, height, &format, GBM_BO_USE_RENDERING)
{
Ok(b) => b,
Err(e) => {
log::error!("Could not allocate dmabuf: {}", ErrorFmt(e));
return;
}
};
let bo =
match ctx
.ctx
.gbm()
.create_bo(width, height, ARGB8888, &[], GBM_BO_USE_RENDERING)
{
Ok(b) => b,
Err(e) => {
log::error!("Could not allocate dmabuf: {}", ErrorFmt(e));
return;
}
};
let img = match ctx.ctx.clone().dmabuf_img(bo.dmabuf()) {
Ok(b) => b,
Err(e) => {
Expand Down
8 changes: 2 additions & 6 deletions src/screenshoter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use {
video::{
drm::DrmError,
gbm::{GbmBo, GbmError, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING},
ModifiedFormat, INVALID_MODIFIER,
},
},
std::{ops::Deref, rc::Rc},
Expand Down Expand Up @@ -43,15 +42,12 @@ pub fn take_screenshot(state: &State) -> Result<Screenshot, ScreenshooterError>
if extents.is_empty() {
return Err(ScreenshooterError::EmptyDisplay);
}
let format = ModifiedFormat {
format: XRGB8888,
modifier: INVALID_MODIFIER,
};
let gbm = ctx.gbm();
let bo = gbm.create_bo(
extents.width(),
extents.height(),
&format,
XRGB8888,
&[],
GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR,
)?;
let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?;
Expand Down
8 changes: 0 additions & 8 deletions src/video.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use crate::format::Format;

pub mod dmabuf;
pub mod drm;
pub mod gbm;
Expand All @@ -9,9 +7,3 @@ pub type Modifier = u64;
pub const INVALID_MODIFIER: Modifier = 0x00ff_ffff_ffff_ffff;
#[allow(dead_code)]
pub const LINEAR_MODIFIER: Modifier = 0;

#[derive(Copy, Clone)]
pub struct ModifiedFormat {
pub format: &'static Format,
pub modifier: Modifier,
}
Loading