wl_shm: use udmabuf directly as texture on integrated GPUs
This commit is contained in:
parent
da33f26918
commit
9abfe88b05
8 changed files with 213 additions and 70 deletions
|
|
@ -749,6 +749,8 @@ pub trait GfxContext: Debug {
|
||||||
|
|
||||||
fn formats(&self) -> Rc<AHashMap<u32, GfxFormat>>;
|
fn formats(&self) -> Rc<AHashMap<u32, GfxFormat>>;
|
||||||
|
|
||||||
|
fn fast_ram_access(&self) -> bool;
|
||||||
|
|
||||||
fn dmabuf_fb(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxFramebuffer>, GfxError> {
|
fn dmabuf_fb(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxFramebuffer>, GfxError> {
|
||||||
self.dmabuf_img(buf)?.to_framebuffer()
|
self.dmabuf_img(buf)?.to_framebuffer()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ pub struct EglDisplay {
|
||||||
pub gbm: Rc<GbmDevice>,
|
pub gbm: Rc<GbmDevice>,
|
||||||
pub dpy: EGLDisplay,
|
pub dpy: EGLDisplay,
|
||||||
pub explicit_sync: bool,
|
pub explicit_sync: bool,
|
||||||
|
pub fast_ram_access: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EglDisplay {
|
impl EglDisplay {
|
||||||
|
|
@ -106,16 +107,20 @@ impl EglDisplay {
|
||||||
gbm: Rc::new(gbm),
|
gbm: Rc::new(gbm),
|
||||||
dpy,
|
dpy,
|
||||||
explicit_sync: false,
|
explicit_sync: false,
|
||||||
|
fast_ram_access: false,
|
||||||
};
|
};
|
||||||
let mut major = 0;
|
let mut major = 0;
|
||||||
let mut minor = 0;
|
let mut minor = 0;
|
||||||
if (egl.eglInitialize)(dpy.dpy, &mut major, &mut minor) != EGL_TRUE {
|
if (egl.eglInitialize)(dpy.dpy, &mut major, &mut minor) != EGL_TRUE {
|
||||||
return Err(RenderError::Initialize);
|
return Err(RenderError::Initialize);
|
||||||
}
|
}
|
||||||
if !software && EXTS.contains(EXT_DEVICE_QUERY) {
|
if EXTS.contains(EXT_DEVICE_QUERY)
|
||||||
if get_device_ext(procs, dpy.dpy)?.contains(MESA_DEVICE_SOFTWARE) {
|
&& get_device_ext(procs, dpy.dpy)?.contains(MESA_DEVICE_SOFTWARE)
|
||||||
|
{
|
||||||
|
if !software {
|
||||||
return Err(RenderError::NoHardwareRenderer);
|
return Err(RenderError::NoHardwareRenderer);
|
||||||
}
|
}
|
||||||
|
dpy.fast_ram_access = true;
|
||||||
}
|
}
|
||||||
dpy.exts = get_display_ext(dpy.dpy);
|
dpy.exts = get_display_ext(dpy.dpy);
|
||||||
if !dpy.exts.intersects(KHR_IMAGE_BASE) {
|
if !dpy.exts.intersects(KHR_IMAGE_BASE) {
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,10 @@ impl GfxContext for GlRenderContext {
|
||||||
self.formats()
|
self.formats()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fast_ram_access(&self) -> bool {
|
||||||
|
self.ctx.dpy.fast_ram_access
|
||||||
|
}
|
||||||
|
|
||||||
fn dmabuf_fb(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxFramebuffer>, GfxError> {
|
fn dmabuf_fb(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxFramebuffer>, GfxError> {
|
||||||
(&self)
|
(&self)
|
||||||
.dmabuf_fb(buf)
|
.dmabuf_fb(buf)
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,10 @@ impl GfxContext for Context {
|
||||||
self.0.formats.clone()
|
self.0.formats.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fast_ram_access(&self) -> bool {
|
||||||
|
self.0.device.fast_ram_access
|
||||||
|
}
|
||||||
|
|
||||||
fn dmabuf_img(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxImage>, GfxError> {
|
fn dmabuf_img(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxImage>, GfxError> {
|
||||||
self.0
|
self.0
|
||||||
.import_dmabuf(buf)
|
.import_dmabuf(buf)
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ pub struct VulkanDevice {
|
||||||
pub(super) uniform_buffer_offset_mask: DeviceSize,
|
pub(super) uniform_buffer_offset_mask: DeviceSize,
|
||||||
pub(super) uniform_buffer_descriptor_size: usize,
|
pub(super) uniform_buffer_descriptor_size: usize,
|
||||||
pub(super) lost: Cell<bool>,
|
pub(super) lost: Cell<bool>,
|
||||||
|
pub(super) fast_ram_access: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VulkanDevice {
|
impl Drop for VulkanDevice {
|
||||||
|
|
@ -129,7 +130,7 @@ impl VulkanInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_dev(&self, drm: &Drm) -> Result<PhysicalDevice, VulkanError> {
|
fn find_dev(&self, drm: &Drm) -> Result<(PhysicalDevice, PhysicalDeviceType), VulkanError> {
|
||||||
let dev = drm.dev();
|
let dev = drm.dev();
|
||||||
log::log!(
|
log::log!(
|
||||||
self.log_level,
|
self.log_level,
|
||||||
|
|
@ -188,7 +189,7 @@ impl VulkanInstance {
|
||||||
Some(&extensions),
|
Some(&extensions),
|
||||||
Some(&driver_props),
|
Some(&driver_props),
|
||||||
);
|
);
|
||||||
return Ok(phy_dev);
|
return Ok((phy_dev, props.device_type));
|
||||||
}
|
}
|
||||||
devices.push((props, Some(extensions), Some(driver_props)));
|
devices.push((props, Some(extensions), Some(driver_props)));
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +211,7 @@ impl VulkanInstance {
|
||||||
Err(VulkanError::NoDeviceFound(dev))
|
Err(VulkanError::NoDeviceFound(dev))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_software_renderer(&self) -> Result<PhysicalDevice, VulkanError> {
|
fn find_software_renderer(&self) -> Result<(PhysicalDevice, PhysicalDeviceType), VulkanError> {
|
||||||
let phy_devs = unsafe { self.instance.enumerate_physical_devices() };
|
let phy_devs = unsafe { self.instance.enumerate_physical_devices() };
|
||||||
let phy_devs = match phy_devs {
|
let phy_devs = match phy_devs {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
|
|
@ -222,7 +223,7 @@ impl VulkanInstance {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if props.device_type == PhysicalDeviceType::CPU {
|
if props.device_type == PhysicalDeviceType::CPU {
|
||||||
return Ok(phy_dev);
|
return Ok((phy_dev, props.device_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(VulkanError::NoSoftwareRenderer)
|
Err(VulkanError::NoSoftwareRenderer)
|
||||||
|
|
@ -344,7 +345,7 @@ impl VulkanInstance {
|
||||||
.ok_or(VulkanError::NoRenderNode)
|
.ok_or(VulkanError::NoRenderNode)
|
||||||
.map(Rc::new)?;
|
.map(Rc::new)?;
|
||||||
let gbm = GbmDevice::new(drm).map_err(VulkanError::Gbm)?;
|
let gbm = GbmDevice::new(drm).map_err(VulkanError::Gbm)?;
|
||||||
let phy_dev = match software {
|
let (phy_dev, dev_ty) = match software {
|
||||||
true => self.find_software_renderer()?,
|
true => self.find_software_renderer()?,
|
||||||
false => self.find_dev(drm)?,
|
false => self.find_dev(drm)?,
|
||||||
};
|
};
|
||||||
|
|
@ -543,6 +544,11 @@ impl VulkanInstance {
|
||||||
"Created queues with priorities {max_graphics_priority:?}/{max_transfer_priority:?}",
|
"Created queues with priorities {max_graphics_priority:?}/{max_transfer_priority:?}",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
let fast_ram_access = match dev_ty {
|
||||||
|
PhysicalDeviceType::CPU => true,
|
||||||
|
PhysicalDeviceType::INTEGRATED_GPU => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
Ok(Rc::new(VulkanDevice {
|
Ok(Rc::new(VulkanDevice {
|
||||||
physical_device: phy_dev,
|
physical_device: phy_dev,
|
||||||
render_node,
|
render_node,
|
||||||
|
|
@ -572,6 +578,7 @@ impl VulkanInstance {
|
||||||
uniform_buffer_offset_mask,
|
uniform_buffer_offset_mask,
|
||||||
uniform_buffer_descriptor_size,
|
uniform_buffer_descriptor_size,
|
||||||
lost: Cell::new(false),
|
lost: Cell::new(false),
|
||||||
|
fast_ram_access,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ use {
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
rect::{Rect, Region},
|
rect::{Rect, Region},
|
||||||
utils::{errorfmt::ErrorFmt, page_size::page_size},
|
utils::{errorfmt::ErrorFmt, page_size::page_size},
|
||||||
video::dmabuf::DmaBuf,
|
video::{
|
||||||
|
LINEAR_MODIFIER,
|
||||||
|
dmabuf::{DmaBuf, DmaBufPlane},
|
||||||
|
},
|
||||||
wire::{WlBufferId, wl_buffer::*},
|
wire::{WlBufferId, wl_buffer::*},
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
|
|
@ -41,6 +44,8 @@ pub struct DmabufBufferParams {
|
||||||
udmabuf_impossible: bool,
|
udmabuf_impossible: bool,
|
||||||
host_buffer: Option<Rc<dyn GfxBuffer>>,
|
host_buffer: Option<Rc<dyn GfxBuffer>>,
|
||||||
host_buffer_impossible: bool,
|
host_buffer_impossible: bool,
|
||||||
|
tex: Option<Rc<dyn GfxTexture>>,
|
||||||
|
tex_impossible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WlBuffer {
|
pub struct WlBuffer {
|
||||||
|
|
@ -120,15 +125,18 @@ impl WlBuffer {
|
||||||
if (stride as u64) < min_row_size {
|
if (stride as u64) < min_row_size {
|
||||||
return Err(WlBufferError::StrideTooSmall);
|
return Err(WlBufferError::StrideTooSmall);
|
||||||
}
|
}
|
||||||
|
let udmabuf_impossible = !mem.pool().is_sealed_memfd();
|
||||||
let dmabuf_buffer_params = match udmabuf {
|
let dmabuf_buffer_params = match udmabuf {
|
||||||
None => DmabufBufferParams {
|
None => DmabufBufferParams {
|
||||||
size: bytes as usize,
|
size: bytes as usize,
|
||||||
udmabuf: None,
|
udmabuf: None,
|
||||||
udmabuf_offset: 0,
|
udmabuf_offset: 0,
|
||||||
udmabuf_size: 0,
|
udmabuf_size: 0,
|
||||||
udmabuf_impossible: !mem.pool().is_sealed_memfd(),
|
udmabuf_impossible,
|
||||||
host_buffer: None,
|
host_buffer: None,
|
||||||
host_buffer_impossible: !mem.pool().is_sealed_memfd(),
|
host_buffer_impossible: udmabuf_impossible,
|
||||||
|
tex: None,
|
||||||
|
tex_impossible: udmabuf_impossible,
|
||||||
},
|
},
|
||||||
Some((udmabuf, size)) => DmabufBufferParams {
|
Some((udmabuf, size)) => DmabufBufferParams {
|
||||||
size,
|
size,
|
||||||
|
|
@ -138,6 +146,8 @@ impl WlBuffer {
|
||||||
udmabuf_impossible: false,
|
udmabuf_impossible: false,
|
||||||
host_buffer: None,
|
host_buffer: None,
|
||||||
host_buffer_impossible: false,
|
host_buffer_impossible: false,
|
||||||
|
tex: None,
|
||||||
|
tex_impossible: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
@ -209,20 +219,22 @@ impl WlBuffer {
|
||||||
udmabuf_impossible,
|
udmabuf_impossible,
|
||||||
host_buffer,
|
host_buffer,
|
||||||
host_buffer_impossible,
|
host_buffer_impossible,
|
||||||
|
tex,
|
||||||
|
tex_impossible,
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
host_buffer.take();
|
host_buffer.take();
|
||||||
*host_buffer_impossible = *udmabuf_impossible;
|
*host_buffer_impossible = *udmabuf_impossible;
|
||||||
return match surface {
|
let mut had_texture = tex.take().is_some();
|
||||||
Some(s) => {
|
*tex_impossible = *udmabuf_impossible;
|
||||||
s.shm_staging.take();
|
if let Some(s) = surface {
|
||||||
s.shm_textures.back().tex.take();
|
s.shm_staging.take();
|
||||||
s.shm_textures.front().tex.take().is_some()
|
s.shm_textures.back().tex.take();
|
||||||
}
|
had_texture |= s.shm_textures.front().tex.take().is_some();
|
||||||
None => false,
|
}
|
||||||
};
|
return had_texture;
|
||||||
}
|
}
|
||||||
WlBufferStorage::Dmabuf { tex, .. } => tex.is_some(),
|
WlBufferStorage::Dmabuf { tex, .. } => tex.is_some(),
|
||||||
};
|
};
|
||||||
|
|
@ -255,7 +267,13 @@ impl WlBuffer {
|
||||||
match &*self.storage.borrow() {
|
match &*self.storage.borrow() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(s) => match s {
|
Some(s) => match s {
|
||||||
WlBufferStorage::Shm { .. } => {
|
WlBufferStorage::Shm {
|
||||||
|
dmabuf_buffer_params,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if let Some(tex) = &dmabuf_buffer_params.tex {
|
||||||
|
return Some(tex.clone());
|
||||||
|
}
|
||||||
surface.shm_textures.front().tex.get().map(|t| t as _)
|
surface.shm_textures.front().tex.get().map(|t| t as _)
|
||||||
}
|
}
|
||||||
WlBufferStorage::Dmabuf { tex, .. } => tex.clone(),
|
WlBufferStorage::Dmabuf { tex, .. } => tex.clone(),
|
||||||
|
|
@ -269,20 +287,57 @@ impl WlBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_gfx_buffer(
|
pub fn get_udmabuf(
|
||||||
self: &Rc<Self>,
|
&self,
|
||||||
ctx: &Rc<dyn GfxContext>,
|
|
||||||
mem: &Rc<ClientMemOffset>,
|
mem: &Rc<ClientMemOffset>,
|
||||||
dmabuf_buffer_params: &mut DmabufBufferParams,
|
dmabuf_buffer_params: &mut DmabufBufferParams,
|
||||||
) -> Option<Rc<dyn GfxBuffer>> {
|
) -> Option<Rc<OwnedFd>> {
|
||||||
let DmabufBufferParams {
|
let DmabufBufferParams {
|
||||||
size,
|
size,
|
||||||
udmabuf,
|
udmabuf,
|
||||||
udmabuf_offset,
|
udmabuf_offset,
|
||||||
udmabuf_size,
|
udmabuf_size,
|
||||||
udmabuf_impossible,
|
udmabuf_impossible,
|
||||||
|
..
|
||||||
|
} = dmabuf_buffer_params;
|
||||||
|
if let Some(b) = udmabuf {
|
||||||
|
return Some(b.clone());
|
||||||
|
}
|
||||||
|
if *udmabuf_impossible {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let dev = self.client.state.udmabuf.get()?;
|
||||||
|
let mask = page_size() - 1;
|
||||||
|
let offset = mem.offset() & mask;
|
||||||
|
let base = mem.offset() & !mask;
|
||||||
|
let end = (mem.offset() + *size + mask) & !mask;
|
||||||
|
let len = end - base;
|
||||||
|
match dev.create_dmabuf_from_memfd(mem.pool().fd(), base, len) {
|
||||||
|
Ok(b) => {
|
||||||
|
let b = Rc::new(b);
|
||||||
|
*udmabuf_offset = offset;
|
||||||
|
*udmabuf_size = len;
|
||||||
|
*udmabuf = Some(b.clone());
|
||||||
|
Some(b)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
*udmabuf_impossible = true;
|
||||||
|
log::debug!("Could not create udmabuf: {}", ErrorFmt(e));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_gfx_buffer(
|
||||||
|
&self,
|
||||||
|
ctx: &Rc<dyn GfxContext>,
|
||||||
|
mem: &Rc<ClientMemOffset>,
|
||||||
|
dmabuf_buffer_params: &mut DmabufBufferParams,
|
||||||
|
) -> Option<Rc<dyn GfxBuffer>> {
|
||||||
|
let DmabufBufferParams {
|
||||||
host_buffer,
|
host_buffer,
|
||||||
host_buffer_impossible,
|
host_buffer_impossible,
|
||||||
|
..
|
||||||
} = dmabuf_buffer_params;
|
} = dmabuf_buffer_params;
|
||||||
if let Some(hb) = host_buffer {
|
if let Some(hb) = host_buffer {
|
||||||
return Some(hb.clone());
|
return Some(hb.clone());
|
||||||
|
|
@ -290,36 +345,14 @@ impl WlBuffer {
|
||||||
if *host_buffer_impossible {
|
if *host_buffer_impossible {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let udmabuf = 'udmabuf: {
|
let udmabuf = self.get_udmabuf(mem, dmabuf_buffer_params)?;
|
||||||
if let Some(b) = udmabuf {
|
let DmabufBufferParams {
|
||||||
break 'udmabuf b.clone();
|
udmabuf_offset,
|
||||||
}
|
udmabuf_size,
|
||||||
if *udmabuf_impossible {
|
host_buffer,
|
||||||
return None;
|
host_buffer_impossible,
|
||||||
}
|
..
|
||||||
let Some(dev) = self.client.state.udmabuf.get() else {
|
} = dmabuf_buffer_params;
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let mask = page_size() - 1;
|
|
||||||
let offset = mem.offset() & mask;
|
|
||||||
let base = mem.offset() & !mask;
|
|
||||||
let end = (mem.offset() + *size + mask) & !mask;
|
|
||||||
let len = end - base;
|
|
||||||
match dev.create_dmabuf_from_memfd(mem.pool().fd(), base, len) {
|
|
||||||
Ok(b) => {
|
|
||||||
let b = Rc::new(b);
|
|
||||||
*udmabuf_offset = offset;
|
|
||||||
*udmabuf_size = len;
|
|
||||||
*udmabuf = Some(b.clone());
|
|
||||||
b
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
*udmabuf_impossible = true;
|
|
||||||
log::debug!("Could not create udmabuf: {}", ErrorFmt(e));
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let hb =
|
let hb =
|
||||||
match ctx.create_dmabuf_buffer(&udmabuf, *udmabuf_offset, *udmabuf_size, self.format) {
|
match ctx.create_dmabuf_buffer(&udmabuf, *udmabuf_offset, *udmabuf_size, self.format) {
|
||||||
Ok(hb) => hb,
|
Ok(hb) => hb,
|
||||||
|
|
@ -333,6 +366,67 @@ impl WlBuffer {
|
||||||
Some(hb)
|
Some(hb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn import_udmabuf_texture(
|
||||||
|
&self,
|
||||||
|
ctx: &Rc<dyn GfxContext>,
|
||||||
|
mem: &Rc<ClientMemOffset>,
|
||||||
|
stride: i32,
|
||||||
|
dmabuf_buffer_params: &mut DmabufBufferParams,
|
||||||
|
) -> bool {
|
||||||
|
let DmabufBufferParams {
|
||||||
|
tex,
|
||||||
|
tex_impossible,
|
||||||
|
..
|
||||||
|
} = dmabuf_buffer_params;
|
||||||
|
if tex.is_some() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if *tex_impossible {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let Some(udmabuf) = self.get_udmabuf(mem, dmabuf_buffer_params) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let DmabufBufferParams {
|
||||||
|
udmabuf_offset,
|
||||||
|
tex,
|
||||||
|
tex_impossible,
|
||||||
|
..
|
||||||
|
} = dmabuf_buffer_params;
|
||||||
|
let mut dmabuf = DmaBuf {
|
||||||
|
id: self.client.state.dma_buf_ids.next(),
|
||||||
|
width: self.width,
|
||||||
|
height: self.height,
|
||||||
|
format: self.format,
|
||||||
|
modifier: LINEAR_MODIFIER,
|
||||||
|
planes: Default::default(),
|
||||||
|
is_disjoint: Default::default(),
|
||||||
|
};
|
||||||
|
dmabuf.planes.push(DmaBufPlane {
|
||||||
|
offset: *udmabuf_offset as _,
|
||||||
|
stride: stride as _,
|
||||||
|
fd: udmabuf,
|
||||||
|
});
|
||||||
|
let img = match ctx.clone().dmabuf_img(&dmabuf) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(e) => {
|
||||||
|
*tex_impossible = true;
|
||||||
|
log::debug!("Could not import udmabuf as GfxImage: {}", ErrorFmt(e));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let tex_ = match img.to_texture() {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(e) => {
|
||||||
|
*tex_impossible = true;
|
||||||
|
log::debug!("Could not import udmabuf as GfxTexture: {}", ErrorFmt(e));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*tex = Some(tex_);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn update_texture(&self, surface: &WlSurface, sync_shm: bool) -> Result<(), WlBufferError> {
|
fn update_texture(&self, surface: &WlSurface, sync_shm: bool) -> Result<(), WlBufferError> {
|
||||||
let storage = &mut *self.storage.borrow_mut();
|
let storage = &mut *self.storage.borrow_mut();
|
||||||
let storage = match storage {
|
let storage = match storage {
|
||||||
|
|
@ -340,19 +434,33 @@ impl WlBuffer {
|
||||||
_ => return Ok(()),
|
_ => return Ok(()),
|
||||||
};
|
};
|
||||||
match storage {
|
match storage {
|
||||||
WlBufferStorage::Shm { mem, stride, .. } => {
|
WlBufferStorage::Shm {
|
||||||
if sync_shm && let Some(ctx) = self.client.state.render_ctx.get() {
|
mem,
|
||||||
let tex = ctx.async_shmem_texture(
|
stride,
|
||||||
self.format,
|
dmabuf_buffer_params,
|
||||||
self.width,
|
..
|
||||||
self.height,
|
} => {
|
||||||
*stride,
|
if !sync_shm {
|
||||||
&self.client.state.cpu_worker,
|
return Ok(());
|
||||||
)?;
|
|
||||||
mem.access(|mem| tex.clone().sync_upload(mem, Region::new(self.rect)))??;
|
|
||||||
surface.shm_textures.front().tex.set(Some(tex));
|
|
||||||
surface.shm_textures.front().damage.clear();
|
|
||||||
}
|
}
|
||||||
|
let Some(ctx) = self.client.state.render_ctx.get() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
if ctx.fast_ram_access()
|
||||||
|
&& self.import_udmabuf_texture(&ctx, mem, *stride, dmabuf_buffer_params)
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let tex = ctx.async_shmem_texture(
|
||||||
|
self.format,
|
||||||
|
self.width,
|
||||||
|
self.height,
|
||||||
|
*stride,
|
||||||
|
&self.client.state.cpu_worker,
|
||||||
|
)?;
|
||||||
|
mem.access(|mem| tex.clone().sync_upload(mem, Region::new(self.rect)))??;
|
||||||
|
surface.shm_textures.front().tex.set(Some(tex));
|
||||||
|
surface.shm_textures.front().damage.clear();
|
||||||
}
|
}
|
||||||
WlBufferStorage::Dmabuf { img, tex, .. } => {
|
WlBufferStorage::Dmabuf { img, tex, .. } => {
|
||||||
if tex.is_none() {
|
if tex.is_none() {
|
||||||
|
|
|
||||||
|
|
@ -608,6 +608,20 @@ fn schedule_async_upload(
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let back = surface.shm_textures.back();
|
let back = surface.shm_textures.back();
|
||||||
|
let state = &surface.client.state;
|
||||||
|
let ctx = state
|
||||||
|
.render_ctx
|
||||||
|
.get()
|
||||||
|
.ok_or(WlSurfaceError::NoRenderContext)?;
|
||||||
|
if ctx.fast_ram_access() && buf.import_udmabuf_texture(&ctx, mem, *stride, dmabuf_buffer_params)
|
||||||
|
{
|
||||||
|
back.damage.clear();
|
||||||
|
back.tex.take();
|
||||||
|
if surface.shm_textures.front().tex.is_none() {
|
||||||
|
surface.shm_staging.take();
|
||||||
|
}
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
let mut back_tex_opt = back.tex.get();
|
let mut back_tex_opt = back.tex.get();
|
||||||
if let Some(back_tex) = &back_tex_opt
|
if let Some(back_tex) = &back_tex_opt
|
||||||
&& !back_tex.compatible_with(buf.format, buf.rect.width(), buf.rect.height(), *stride)
|
&& !back_tex.compatible_with(buf.format, buf.rect.width(), buf.rect.height(), *stride)
|
||||||
|
|
@ -618,11 +632,6 @@ fn schedule_async_upload(
|
||||||
back.damage.clear();
|
back.damage.clear();
|
||||||
back.damage.damage(slice::from_ref(&buf.rect));
|
back.damage.damage(slice::from_ref(&buf.rect));
|
||||||
};
|
};
|
||||||
let state = &surface.client.state;
|
|
||||||
let ctx = state
|
|
||||||
.render_ctx
|
|
||||||
.get()
|
|
||||||
.ok_or(WlSurfaceError::NoRenderContext)?;
|
|
||||||
let back_tex = match back_tex_opt {
|
let back_tex = match back_tex_opt {
|
||||||
Some(b) => {
|
Some(b) => {
|
||||||
if pending.damage_full || pending.surface_damage.is_not_empty() {
|
if pending.damage_full || pending.surface_damage.is_not_empty() {
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,10 @@ impl GfxContext for TestGfxCtx {
|
||||||
self.formats.clone()
|
self.formats.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fast_ram_access(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn dmabuf_img(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxImage>, GfxError> {
|
fn dmabuf_img(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxImage>, GfxError> {
|
||||||
Ok(Rc::new(TestGfxImage::DmaBuf(TestDmaBufGfxImage {
|
Ok(Rc::new(TestGfxImage::DmaBuf(TestDmaBufGfxImage {
|
||||||
buf: buf.clone(),
|
buf: buf.clone(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue