Merge pull request #798 from mahkoh/jorth/render-only
metal: add support for render-only devices
This commit is contained in:
commit
6e400655c6
5 changed files with 156 additions and 110 deletions
|
|
@ -44,10 +44,10 @@ use {
|
||||||
INVALID_MODIFIER, Modifier,
|
INVALID_MODIFIER, Modifier,
|
||||||
dmabuf::DmaBufId,
|
dmabuf::DmaBufId,
|
||||||
drm::{
|
drm::{
|
||||||
ConnectorStatus, ConnectorType, DRM_CLIENT_CAP_ATOMIC, DrmBlob, DrmConnector,
|
ConnectorStatus, ConnectorType, DRM_CLIENT_CAP_ATOMIC, DrmBlob, DrmCardResources,
|
||||||
DrmCrtc, DrmEncoder, DrmError, DrmEvent, DrmFb, DrmLease, DrmMaster, DrmModeInfo,
|
DrmConnector, DrmCrtc, DrmEncoder, DrmError, DrmEvent, DrmFb, DrmLease, DrmMaster,
|
||||||
DrmObject, DrmPlane, DrmProperty, DrmPropertyDefinition, DrmPropertyType,
|
DrmModeInfo, DrmObject, DrmPlane, DrmProperty, DrmPropertyDefinition,
|
||||||
DrmVersion, HDMI_EOTF_TRADITIONAL_GAMMA_SDR, drm_mode_modeinfo,
|
DrmPropertyType, DrmVersion, HDMI_EOTF_TRADITIONAL_GAMMA_SDR, drm_mode_modeinfo,
|
||||||
hdr_output_metadata,
|
hdr_output_metadata,
|
||||||
},
|
},
|
||||||
gbm::GbmDevice,
|
gbm::GbmDevice,
|
||||||
|
|
@ -105,13 +105,10 @@ pub struct MetalDrmDevice {
|
||||||
pub devnum: c::dev_t,
|
pub devnum: c::dev_t,
|
||||||
pub devnode: CString,
|
pub devnode: CString,
|
||||||
pub master: Rc<DrmMaster>,
|
pub master: Rc<DrmMaster>,
|
||||||
|
pub supports_kms: bool,
|
||||||
pub crtcs: AHashMap<DrmCrtc, Rc<MetalCrtc>>,
|
pub crtcs: AHashMap<DrmCrtc, Rc<MetalCrtc>>,
|
||||||
pub encoders: AHashMap<DrmEncoder, Rc<MetalEncoder>>,
|
pub encoders: AHashMap<DrmEncoder, Rc<MetalEncoder>>,
|
||||||
pub planes: AHashMap<DrmPlane, Rc<MetalPlane>>,
|
pub planes: AHashMap<DrmPlane, Rc<MetalPlane>>,
|
||||||
pub _min_width: u32,
|
|
||||||
pub _max_width: u32,
|
|
||||||
pub _min_height: u32,
|
|
||||||
pub _max_height: u32,
|
|
||||||
pub cursor_width: u64,
|
pub cursor_width: u64,
|
||||||
pub cursor_height: u64,
|
pub cursor_height: u64,
|
||||||
pub supports_async_commit: bool,
|
pub supports_async_commit: bool,
|
||||||
|
|
@ -1822,6 +1819,9 @@ impl MetalBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_drm_change_(self: &Rc<Self>, dev: &Rc<MetalDrmDeviceData>) -> Result<(), MetalError> {
|
fn handle_drm_change_(self: &Rc<Self>, dev: &Rc<MetalDrmDeviceData>) -> Result<(), MetalError> {
|
||||||
|
if !dev.dev.supports_kms {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
if let Err(e) = self.update_device_properties(dev) {
|
if let Err(e) = self.update_device_properties(dev) {
|
||||||
return Err(MetalError::UpdateProperties(e));
|
return Err(MetalError::UpdateProperties(e));
|
||||||
}
|
}
|
||||||
|
|
@ -1982,46 +1982,44 @@ impl MetalBackend {
|
||||||
pending: PendingDrmDevice,
|
pending: PendingDrmDevice,
|
||||||
master: &Rc<DrmMaster>,
|
master: &Rc<DrmMaster>,
|
||||||
) -> Result<Rc<MetalDrmDeviceData>, MetalError> {
|
) -> Result<Rc<MetalDrmDeviceData>, MetalError> {
|
||||||
if let Err(e) = master.set_client_cap(DRM_CLIENT_CAP_ATOMIC, 2) {
|
let mut resources = DrmCardResources::default();
|
||||||
return Err(MetalError::AtomicModesetting(e));
|
let mut planes = AHashMap::new();
|
||||||
}
|
let mut crtcs = AHashMap::new();
|
||||||
let resources = master.get_resources()?;
|
let mut encoders = AHashMap::new();
|
||||||
|
let (mut cursor_width, mut cursor_height) = (1, 1);
|
||||||
let (cursor_width, cursor_height) = match master.get_cursor_size() {
|
let supports_kms = master.supports_get_resources()?;
|
||||||
Ok(s) => s,
|
if supports_kms {
|
||||||
Err(e) => {
|
if let Err(e) = master.set_client_cap(DRM_CLIENT_CAP_ATOMIC, 2) {
|
||||||
|
return Err(MetalError::AtomicModesetting(e));
|
||||||
|
}
|
||||||
|
resources = master.get_resources()?;
|
||||||
|
(cursor_width, cursor_height) = master.get_cursor_size().unwrap_or_else(|e| {
|
||||||
log::warn!("Can't determine size of cursor planes: {}", ErrorFmt(e));
|
log::warn!("Can't determine size of cursor planes: {}", ErrorFmt(e));
|
||||||
(64, 64)
|
(64, 64)
|
||||||
}
|
});
|
||||||
};
|
for plane in master.get_planes()? {
|
||||||
|
match create_plane(plane, master) {
|
||||||
let mut planes = AHashMap::new();
|
Ok(p) => {
|
||||||
for plane in master.get_planes()? {
|
planes.insert(p.id, Rc::new(p));
|
||||||
match create_plane(plane, master) {
|
}
|
||||||
Ok(p) => {
|
Err(e) => return Err(MetalError::CreatePlane(e)),
|
||||||
planes.insert(p.id, Rc::new(p));
|
|
||||||
}
|
}
|
||||||
Err(e) => return Err(MetalError::CreatePlane(e)),
|
|
||||||
}
|
}
|
||||||
}
|
for (idx, crtc) in resources.crtcs.iter().copied().enumerate() {
|
||||||
|
match create_crtc(crtc, idx, master, &planes) {
|
||||||
let mut crtcs = AHashMap::new();
|
Ok(c) => {
|
||||||
for (idx, crtc) in resources.crtcs.iter().copied().enumerate() {
|
crtcs.insert(c.id, Rc::new(c));
|
||||||
match create_crtc(crtc, idx, master, &planes) {
|
}
|
||||||
Ok(c) => {
|
Err(e) => return Err(MetalError::CreateCrtc(e)),
|
||||||
crtcs.insert(c.id, Rc::new(c));
|
|
||||||
}
|
}
|
||||||
Err(e) => return Err(MetalError::CreateCrtc(e)),
|
|
||||||
}
|
}
|
||||||
}
|
for encoder in resources.encoders {
|
||||||
|
match create_encoder(encoder, master, &crtcs) {
|
||||||
let mut encoders = AHashMap::new();
|
Ok(e) => {
|
||||||
for encoder in resources.encoders {
|
encoders.insert(e.id, Rc::new(e));
|
||||||
match create_encoder(encoder, master, &crtcs) {
|
}
|
||||||
Ok(e) => {
|
Err(e) => return Err(MetalError::CreateEncoder(e)),
|
||||||
encoders.insert(e.id, Rc::new(e));
|
|
||||||
}
|
}
|
||||||
Err(e) => return Err(MetalError::CreateEncoder(e)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2072,13 +2070,10 @@ impl MetalBackend {
|
||||||
devnum: pending.devnum,
|
devnum: pending.devnum,
|
||||||
devnode: pending.devnode,
|
devnode: pending.devnode,
|
||||||
master: master.clone(),
|
master: master.clone(),
|
||||||
|
supports_kms,
|
||||||
crtcs,
|
crtcs,
|
||||||
encoders,
|
encoders,
|
||||||
planes,
|
planes,
|
||||||
_min_width: resources.min_width,
|
|
||||||
_max_width: resources.max_width,
|
|
||||||
_min_height: resources.min_height,
|
|
||||||
_max_height: resources.max_height,
|
|
||||||
cursor_width,
|
cursor_width,
|
||||||
cursor_height,
|
cursor_height,
|
||||||
supports_async_commit: master.supports_async_commit(),
|
supports_async_commit: master.supports_async_commit(),
|
||||||
|
|
@ -2099,7 +2094,11 @@ impl MetalBackend {
|
||||||
min_post_commit_margin: Cell::new(DEFAULT_POST_COMMIT_MARGIN),
|
min_post_commit_margin: Cell::new(DEFAULT_POST_COMMIT_MARGIN),
|
||||||
});
|
});
|
||||||
|
|
||||||
let (connectors, futures) = get_connectors(self, &dev, &resources.connectors)?;
|
let mut connectors = CopyHashMap::new();
|
||||||
|
let mut futures = CopyHashMap::new();
|
||||||
|
if supports_kms {
|
||||||
|
(connectors, futures) = get_connectors(self, &dev, &resources.connectors)?;
|
||||||
|
}
|
||||||
|
|
||||||
let slf = Rc::new(MetalDrmDeviceData {
|
let slf = Rc::new(MetalDrmDeviceData {
|
||||||
dev: dev.clone(),
|
dev: dev.clone(),
|
||||||
|
|
@ -2574,6 +2573,9 @@ impl MetalBackend {
|
||||||
|
|
||||||
fn init_drm_device(&self, dev: &Rc<MetalDrmDeviceData>) -> Result<(), MetalError> {
|
fn init_drm_device(&self, dev: &Rc<MetalDrmDeviceData>) -> Result<(), MetalError> {
|
||||||
self.break_leases(dev);
|
self.break_leases(dev);
|
||||||
|
if dev.connectors.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
enum Quirks {
|
enum Quirks {
|
||||||
DirectScanout,
|
DirectScanout,
|
||||||
NonDefaultFormat,
|
NonDefaultFormat,
|
||||||
|
|
|
||||||
|
|
@ -408,50 +408,57 @@ impl EgvRenderer {
|
||||||
.enumerate_physical_devices()
|
.enumerate_physical_devices()
|
||||||
.map_err(EgvError::EnumeratePhysicalDevice)?
|
.map_err(EgvError::EnumeratePhysicalDevice)?
|
||||||
};
|
};
|
||||||
'outer: for phy in devices {
|
for software in [false, true] {
|
||||||
let res = unsafe { instance.enumerate_device_extension_properties(phy) };
|
'outer: for &phy in &devices {
|
||||||
let exts = match res {
|
let res = unsafe { instance.enumerate_device_extension_properties(phy) };
|
||||||
Ok(res) => map_extension_properties(res),
|
let exts = match res {
|
||||||
Err(e) => {
|
Ok(res) => map_extension_properties(res),
|
||||||
log::error!(
|
Err(e) => {
|
||||||
"Could not enumerate extensions of physical device: {}",
|
log::error!(
|
||||||
ErrorFmt(e),
|
"Could not enumerate extensions of physical device: {}",
|
||||||
);
|
ErrorFmt(e),
|
||||||
continue;
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut drm_props = PhysicalDeviceDrmPropertiesEXT::default();
|
||||||
|
let mut props = PhysicalDeviceProperties2::default().push_next(&mut drm_props);
|
||||||
|
unsafe {
|
||||||
|
instance.get_physical_device_properties2(phy, &mut props);
|
||||||
}
|
}
|
||||||
};
|
let props = props.properties;
|
||||||
let mut drm_props = PhysicalDeviceDrmPropertiesEXT::default();
|
physical_device = phy;
|
||||||
let mut props = PhysicalDeviceProperties2::default().push_next(&mut drm_props);
|
device_extensions = exts;
|
||||||
unsafe {
|
device_properties = props;
|
||||||
instance.get_physical_device_properties2(phy, &mut props);
|
if let Some(dev) = dev
|
||||||
}
|
&& !software
|
||||||
let props = props.properties;
|
{
|
||||||
physical_device = phy;
|
if device_extensions.not_contains_key(physical_device_drm::NAME) {
|
||||||
device_extensions = exts;
|
continue 'outer;
|
||||||
device_properties = props;
|
}
|
||||||
if let Some(dev) = dev {
|
let major = uapi::major(dev) as i64;
|
||||||
if device_extensions.not_contains_key(physical_device_drm::NAME) {
|
let minor = uapi::minor(dev) as i64;
|
||||||
continue 'outer;
|
let matches = (drm_props.has_primary == vk::TRUE
|
||||||
}
|
&& drm_props.primary_major == major
|
||||||
let major = uapi::major(dev) as i64;
|
&& drm_props.primary_minor == minor)
|
||||||
let minor = uapi::minor(dev) as i64;
|
|| (drm_props.has_render == vk::TRUE
|
||||||
let matches = (drm_props.has_primary == vk::TRUE
|
&& drm_props.render_major == major
|
||||||
&& drm_props.primary_major == major
|
&& drm_props.render_minor == minor);
|
||||||
&& drm_props.primary_minor == minor)
|
if matches {
|
||||||
|| (drm_props.has_render == vk::TRUE
|
break 'find_device;
|
||||||
&& drm_props.render_major == major
|
}
|
||||||
&& drm_props.render_minor == minor);
|
} else {
|
||||||
if matches {
|
if device_properties.device_type == PhysicalDeviceType::CPU {
|
||||||
break 'find_device;
|
break 'find_device;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if device_properties.device_type == PhysicalDeviceType::CPU {
|
|
||||||
break 'find_device;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(EgvError::NoVulkanDevice);
|
return Err(EgvError::NoVulkanDevice);
|
||||||
}
|
}
|
||||||
|
if device_properties.device_type == PhysicalDeviceType::CPU && dev.is_some() {
|
||||||
|
log::warn!("Using software rendering");
|
||||||
|
}
|
||||||
if device_properties.api_version < VULKAN_API_VERSION {
|
if device_properties.api_version < VULKAN_API_VERSION {
|
||||||
return Err(EgvError::NoVulkan13);
|
return Err(EgvError::NoVulkan13);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ use {
|
||||||
get_version, mode_addfb2, mode_atomic, mode_create_blob, mode_destroy_blob,
|
get_version, mode_addfb2, mode_atomic, mode_create_blob, mode_destroy_blob,
|
||||||
mode_get_resources, mode_getconnector, mode_getencoder, mode_getplane,
|
mode_get_resources, mode_getconnector, mode_getencoder, mode_getplane,
|
||||||
mode_getplaneresources, mode_getprobblob, mode_getproperty, mode_obj_getproperties,
|
mode_getplaneresources, mode_getprobblob, mode_getproperty, mode_obj_getproperties,
|
||||||
mode_rmfb, prime_fd_to_handle, queue_sequence, revoke_lease, set_client_cap,
|
mode_rmfb, mode_supports_get_resources, prime_fd_to_handle, queue_sequence,
|
||||||
|
revoke_lease, set_client_cap,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -168,11 +169,13 @@ fn reopen(fd: c::c_int, need_primary: bool) -> Result<Rc<OwnedFd>, DrmError> {
|
||||||
return Ok(Rc::new(fd));
|
return Ok(Rc::new(fd));
|
||||||
}
|
}
|
||||||
let path = 'path: {
|
let path = 'path: {
|
||||||
if get_node_type_from_fd(fd).map_err(DrmError::GetDeviceType)? == NodeType::Render {
|
if !need_primary {
|
||||||
break 'path uapi::format_ustr!("/proc/self/fd/{}", fd);
|
if get_node_type_from_fd(fd).map_err(DrmError::GetDeviceType)? == NodeType::Render {
|
||||||
}
|
break 'path uapi::format_ustr!("/proc/self/fd/{}", fd);
|
||||||
if !need_primary && let Ok(path) = render_node_name(fd) {
|
}
|
||||||
break 'path path;
|
if let Ok(path) = render_node_name(fd) {
|
||||||
|
break 'path path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
device_node_name(fd)?
|
device_node_name(fd)?
|
||||||
};
|
};
|
||||||
|
|
@ -212,6 +215,10 @@ impl Drm {
|
||||||
self.fd.raw()
|
self.fd.raw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dup_primary(&self) -> Result<Self, DrmError> {
|
||||||
|
Self::reopen(self.fd.raw(), true)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dup_render(&self) -> Result<Self, DrmError> {
|
pub fn dup_render(&self) -> Result<Self, DrmError> {
|
||||||
Self::reopen(self.fd.raw(), false)
|
Self::reopen(self.fd.raw(), false)
|
||||||
}
|
}
|
||||||
|
|
@ -333,6 +340,10 @@ impl DrmMaster {
|
||||||
mode_get_resources(self.raw())
|
mode_get_resources(self.raw())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn supports_get_resources(&self) -> Result<bool, DrmError> {
|
||||||
|
mode_supports_get_resources(self.raw())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_cap(&self, cap: u64) -> Result<u64, OsError> {
|
pub fn get_cap(&self, cap: u64) -> Result<u64, OsError> {
|
||||||
get_cap(self.raw(), cap)
|
get_cap(self.raw(), cap)
|
||||||
}
|
}
|
||||||
|
|
@ -745,12 +756,12 @@ drm_obj!(DrmFb, DRM_MODE_OBJECT_FB);
|
||||||
drm_obj!(DrmBlob, DRM_MODE_OBJECT_BLOB);
|
drm_obj!(DrmBlob, DRM_MODE_OBJECT_BLOB);
|
||||||
drm_obj!(DrmPlane, DRM_MODE_OBJECT_PLANE);
|
drm_obj!(DrmPlane, DRM_MODE_OBJECT_PLANE);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct DrmCardResources {
|
pub struct DrmCardResources {
|
||||||
pub min_width: u32,
|
pub _min_width: u32,
|
||||||
pub max_width: u32,
|
pub _max_width: u32,
|
||||||
pub min_height: u32,
|
pub _min_height: u32,
|
||||||
pub max_height: u32,
|
pub _max_height: u32,
|
||||||
pub _fbs: Vec<DrmFb>,
|
pub _fbs: Vec<DrmFb>,
|
||||||
pub crtcs: Vec<DrmCrtc>,
|
pub crtcs: Vec<DrmCrtc>,
|
||||||
pub connectors: Vec<DrmConnector>,
|
pub connectors: Vec<DrmConnector>,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@ use {
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
io::{BufRead, BufReader},
|
io::{BufRead, BufReader},
|
||||||
},
|
},
|
||||||
uapi::{OwnedFd, Pod, Ustring, c, pod_zeroed},
|
uapi::{
|
||||||
|
OwnedFd, Pod, Ustring,
|
||||||
|
c::{self, c_int},
|
||||||
|
pod_zeroed,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub unsafe fn ioctl<T>(fd: c::c_int, request: c::c_ulong, t: &mut T) -> Result<c::c_int, OsError> {
|
pub unsafe fn ioctl<T>(fd: c::c_int, request: c::c_ulong, t: &mut T) -> Result<c::c_int, OsError> {
|
||||||
|
|
@ -546,10 +550,10 @@ pub fn mode_get_resources(fd: c::c_int) -> Result<DrmCardResources, DrmError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DrmCardResources {
|
Ok(DrmCardResources {
|
||||||
min_width: res.min_width,
|
_min_width: res.min_width,
|
||||||
max_width: res.max_width,
|
_max_width: res.max_width,
|
||||||
min_height: res.min_height,
|
_min_height: res.min_height,
|
||||||
max_height: res.max_height,
|
_max_height: res.max_height,
|
||||||
_fbs: fbs,
|
_fbs: fbs,
|
||||||
crtcs,
|
crtcs,
|
||||||
connectors,
|
connectors,
|
||||||
|
|
@ -557,6 +561,16 @@ pub fn mode_get_resources(fd: c::c_int) -> Result<DrmCardResources, DrmError> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mode_supports_get_resources(fd: c_int) -> Result<bool, DrmError> {
|
||||||
|
let mut res = drm_mode_card_res::default();
|
||||||
|
let res = unsafe { ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &mut res) };
|
||||||
|
match res {
|
||||||
|
Ok(_) => Ok(true),
|
||||||
|
Err(e) if e.0 == c::EOPNOTSUPP => Ok(false),
|
||||||
|
Err(e) => Err(DrmError::GetResources(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct drm_mode_get_plane_res {
|
struct drm_mode_get_plane_res {
|
||||||
plane_id_ptr: u64,
|
plane_id_ptr: u64,
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ use {
|
||||||
BO_USE_RENDERING, BO_USE_SCANOUT, BO_USE_WRITE, BufferObject, BufferUsage,
|
BO_USE_RENDERING, BO_USE_SCANOUT, BO_USE_WRITE, BufferObject, BufferUsage,
|
||||||
MappedBuffer,
|
MappedBuffer,
|
||||||
},
|
},
|
||||||
format::{Format, formats},
|
format::{Format, XRGB8888, formats},
|
||||||
utils::oserror::OsError,
|
utils::{errorfmt::ErrorFmt, oserror::OsError},
|
||||||
video::{
|
video::{
|
||||||
INVALID_MODIFIER, Modifier,
|
INVALID_MODIFIER, Modifier,
|
||||||
dmabuf::{DmaBuf, DmaBufIds, DmaBufPlane, PlaneVec},
|
dmabuf::{DmaBuf, DmaBufIds, DmaBufPlane, PlaneVec},
|
||||||
|
|
@ -214,14 +214,26 @@ unsafe fn export_bo(dmabuf_ids: &DmaBufIds, bo: *mut Bo) -> Result<DmaBuf, GbmEr
|
||||||
|
|
||||||
impl GbmDevice {
|
impl GbmDevice {
|
||||||
pub fn new(drm: &Drm) -> Result<Self, GbmError> {
|
pub fn new(drm: &Drm) -> Result<Self, GbmError> {
|
||||||
let drm = drm.dup_render()?;
|
let open = |drm: Drm| {
|
||||||
let dev = unsafe { gbm_create_device(drm.raw()) };
|
let dev = unsafe { gbm_create_device(drm.raw()) };
|
||||||
if dev.is_null() {
|
if dev.is_null() {
|
||||||
Err(GbmError::CreateDevice)
|
Err(GbmError::CreateDevice)
|
||||||
} else {
|
} else {
|
||||||
let dev = Rc::new(DeviceHolder { dev });
|
let dev = Rc::new(DeviceHolder { dev });
|
||||||
Ok(Self { drm, dev })
|
Ok(Self { drm, dev })
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
let dma_buf_ids = DmaBufIds::default();
|
||||||
|
let create_bo =
|
||||||
|
|gbm: &GbmDevice| gbm.create_bo(&dma_buf_ids, 1, 1, XRGB8888, &[INVALID_MODIFIER], 0);
|
||||||
|
let gbm = open(drm.dup_render()?)?;
|
||||||
|
match create_bo(&gbm) {
|
||||||
|
Ok(..) => return Ok(gbm),
|
||||||
|
Err(e) => log::warn!("Render node cannot allocate buffers: {}", ErrorFmt(e)),
|
||||||
|
};
|
||||||
|
let gbm = open(drm.dup_primary()?)?;
|
||||||
|
create_bo(&gbm)?;
|
||||||
|
Ok(gbm)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw(&self) -> *mut Device {
|
pub fn raw(&self) -> *mut Device {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue