render: remove TextureReservations
This commit is contained in:
parent
300deecc7d
commit
ea4a1f027b
20 changed files with 198 additions and 172 deletions
|
|
@ -9,7 +9,7 @@ use {
|
||||||
drm_feedback::DrmFeedback,
|
drm_feedback::DrmFeedback,
|
||||||
edid::Descriptor,
|
edid::Descriptor,
|
||||||
format::{Format, ARGB8888, XRGB8888},
|
format::{Format, ARGB8888, XRGB8888},
|
||||||
gfx_api::{GfxApiOpt, GfxContext, GfxFramebuffer, GfxRenderPass, GfxTexture},
|
gfx_api::{BufferResv, GfxApiOpt, GfxContext, GfxFramebuffer, GfxRenderPass, GfxTexture},
|
||||||
ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC},
|
ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC},
|
||||||
renderer::RenderResult,
|
renderer::RenderResult,
|
||||||
state::State,
|
state::State,
|
||||||
|
|
@ -350,9 +350,9 @@ pub struct DirectScanoutCache {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DirectScanoutData {
|
pub struct DirectScanoutData {
|
||||||
tex: Rc<dyn GfxTexture>,
|
tex: Rc<dyn GfxTexture>,
|
||||||
|
_resv: Option<Rc<dyn BufferResv>>,
|
||||||
fb: Rc<DrmFramebuffer>,
|
fb: Rc<DrmFramebuffer>,
|
||||||
dma_buf_id: DmaBufId,
|
dma_buf_id: DmaBufId,
|
||||||
acquired: Cell<bool>,
|
|
||||||
position: DirectScanoutPosition,
|
position: DirectScanoutPosition,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -366,14 +366,6 @@ pub struct DirectScanoutPosition {
|
||||||
pub crtc_height: i32,
|
pub crtc_height: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for DirectScanoutData {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if self.acquired.replace(false) {
|
|
||||||
self.tex.reservations().release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PresentFb {
|
pub struct PresentFb {
|
||||||
fb: Rc<DrmFramebuffer>,
|
fb: Rc<DrmFramebuffer>,
|
||||||
|
|
@ -532,9 +524,9 @@ impl MetalConnector {
|
||||||
if let Some(buffer) = cache.get(&dmabuf.id) {
|
if let Some(buffer) = cache.get(&dmabuf.id) {
|
||||||
return buffer.fb.as_ref().map(|fb| DirectScanoutData {
|
return buffer.fb.as_ref().map(|fb| DirectScanoutData {
|
||||||
tex: buffer.tex.upgrade().unwrap(),
|
tex: buffer.tex.upgrade().unwrap(),
|
||||||
|
_resv: ct.buffer_resv.clone(),
|
||||||
fb: fb.clone(),
|
fb: fb.clone(),
|
||||||
dma_buf_id: dmabuf.id,
|
dma_buf_id: dmabuf.id,
|
||||||
acquired: Default::default(),
|
|
||||||
position,
|
position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -556,9 +548,9 @@ impl MetalConnector {
|
||||||
let data = match self.dev.master.add_fb(dmabuf, Some(format.format)) {
|
let data = match self.dev.master.add_fb(dmabuf, Some(format.format)) {
|
||||||
Ok(fb) => Some(DirectScanoutData {
|
Ok(fb) => Some(DirectScanoutData {
|
||||||
tex: ct.tex.clone(),
|
tex: ct.tex.clone(),
|
||||||
|
_resv: ct.buffer_resv.clone(),
|
||||||
fb: Rc::new(fb),
|
fb: Rc::new(fb),
|
||||||
dma_buf_id: dmabuf.id,
|
dma_buf_id: dmabuf.id,
|
||||||
acquired: Default::default(),
|
|
||||||
position,
|
position,
|
||||||
}),
|
}),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -780,10 +772,6 @@ impl MetalConnector {
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
if let Some(fb) = new_fb {
|
if let Some(fb) = new_fb {
|
||||||
if let Some(dsd) = &fb.direct_scanout_data {
|
|
||||||
dsd.tex.reservations().acquire();
|
|
||||||
dsd.acquired.set(true);
|
|
||||||
}
|
|
||||||
self.next_framebuffer.set(Some(fb));
|
self.next_framebuffer.set(Some(fb));
|
||||||
}
|
}
|
||||||
self.can_present.set(false);
|
self.can_present.set(false);
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed
|
||||||
None,
|
None,
|
||||||
scale,
|
scale,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -391,7 +392,7 @@ impl Cursor for StaticCursor {
|
||||||
if let Some(img) = self.image.scales.get(&renderer.scale()) {
|
if let Some(img) = self.image.scales.get(&renderer.scale()) {
|
||||||
renderer
|
renderer
|
||||||
.base
|
.base
|
||||||
.render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None);
|
.render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -421,7 +422,7 @@ impl Cursor for AnimatedCursor {
|
||||||
if let Some(img) = img.scales.get(&renderer.scale()) {
|
if let Some(img) = img.scales.get(&renderer.scale()) {
|
||||||
renderer
|
renderer
|
||||||
.base
|
.base
|
||||||
.render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None);
|
.render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use {
|
||||||
state::State,
|
state::State,
|
||||||
theme::Color,
|
theme::Color,
|
||||||
tree::{Node, OutputNode},
|
tree::{Node, OutputNode},
|
||||||
utils::{numcell::NumCell, transform_ext::TransformExt},
|
utils::{clonecell::UnsafeCellCloneSafe, transform_ext::TransformExt},
|
||||||
video::{dmabuf::DmaBuf, gbm::GbmDevice, Modifier},
|
video::{dmabuf::DmaBuf, gbm::GbmDevice, Modifier},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
|
|
@ -21,9 +21,12 @@ use {
|
||||||
error::Error,
|
error::Error,
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
|
ops::Deref,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
sync::atomic::{AtomicU64, Ordering::Relaxed},
|
||||||
},
|
},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
|
uapi::OwnedFd,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum GfxApiOpt {
|
pub enum GfxApiOpt {
|
||||||
|
|
@ -141,6 +144,34 @@ pub struct CopyTexture {
|
||||||
pub tex: Rc<dyn GfxTexture>,
|
pub tex: Rc<dyn GfxTexture>,
|
||||||
pub source: SampleRect,
|
pub source: SampleRect,
|
||||||
pub target: FramebufferRect,
|
pub target: FramebufferRect,
|
||||||
|
pub buffer_resv: Option<Rc<dyn BufferResv>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct SyncFile(pub Rc<OwnedFd>);
|
||||||
|
|
||||||
|
impl Deref for SyncFile {
|
||||||
|
type Target = Rc<OwnedFd>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl UnsafeCellCloneSafe for SyncFile {}
|
||||||
|
|
||||||
|
pub trait BufferResv: Debug {
|
||||||
|
fn set_sync_file(&self, user: BufferResvUser, sync_file: &SyncFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct BufferResvUser(u64);
|
||||||
|
|
||||||
|
impl Default for BufferResvUser {
|
||||||
|
fn default() -> Self {
|
||||||
|
static NEXT_ID: AtomicU64 = AtomicU64::new(1);
|
||||||
|
Self(NEXT_ID.fetch_add(1, Relaxed))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
|
@ -210,7 +241,7 @@ impl dyn GfxFramebuffer {
|
||||||
let mut ops = self.take_render_ops();
|
let mut ops = self.take_render_ops();
|
||||||
let scale = Scale::from_int(1);
|
let scale = Scale::from_int(1);
|
||||||
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
||||||
renderer.render_texture(texture, x, y, None, None, scale, None);
|
renderer.render_texture(texture, x, y, None, None, scale, None, None);
|
||||||
let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT);
|
let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT);
|
||||||
self.render(ops, clear);
|
self.render(ops, clear);
|
||||||
}
|
}
|
||||||
|
|
@ -376,38 +407,6 @@ pub trait GfxImage {
|
||||||
fn height(&self) -> i32;
|
fn height(&self) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct TextureReservations {
|
|
||||||
reservations: NumCell<usize>,
|
|
||||||
on_release: Cell<Option<Box<dyn FnOnce()>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TextureReservations {
|
|
||||||
pub fn has_reservation(&self) -> bool {
|
|
||||||
self.reservations.get() != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn acquire(&self) {
|
|
||||||
self.reservations.fetch_add(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(&self) {
|
|
||||||
if self.reservations.fetch_sub(1) == 1 {
|
|
||||||
if let Some(cb) = self.on_release.take() {
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_released<C: FnOnce() + 'static>(&self, cb: C) {
|
|
||||||
if self.has_reservation() {
|
|
||||||
self.on_release.set(Some(Box::new(cb)));
|
|
||||||
} else {
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait GfxTexture: Debug {
|
pub trait GfxTexture: Debug {
|
||||||
fn size(&self) -> (i32, i32);
|
fn size(&self) -> (i32, i32);
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
|
@ -423,7 +422,6 @@ pub trait GfxTexture: Debug {
|
||||||
shm: &[Cell<u8>],
|
shm: &[Cell<u8>],
|
||||||
) -> Result<(), GfxError>;
|
) -> Result<(), GfxError>;
|
||||||
fn dmabuf(&self) -> Option<&DmaBuf>;
|
fn dmabuf(&self) -> Option<&DmaBuf>;
|
||||||
fn reservations(&self) -> &TextureReservations;
|
|
||||||
fn format(&self) -> &'static Format;
|
fn format(&self) -> &'static Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,6 @@ impl GlRenderContext {
|
||||||
Ok(Rc::new(Texture {
|
Ok(Rc::new(Texture {
|
||||||
ctx: self.clone(),
|
ctx: self.clone(),
|
||||||
gl,
|
gl,
|
||||||
resv: Default::default(),
|
|
||||||
format,
|
format,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ impl Image {
|
||||||
Ok(Rc::new(Texture {
|
Ok(Rc::new(Texture {
|
||||||
ctx: self.ctx.clone(),
|
ctx: self.ctx.clone(),
|
||||||
gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?,
|
gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?,
|
||||||
resv: Default::default(),
|
|
||||||
format: self.gl.dmabuf.format,
|
format: self.gl.dmabuf.format,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{GfxError, GfxTexture, TextureReservations},
|
gfx_api::{GfxError, GfxTexture},
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
gl::texture::GlTexture,
|
gl::texture::GlTexture,
|
||||||
renderer::{context::GlRenderContext, framebuffer::Framebuffer},
|
renderer::{context::GlRenderContext, framebuffer::Framebuffer},
|
||||||
|
|
@ -20,7 +20,6 @@ use {
|
||||||
pub struct Texture {
|
pub struct Texture {
|
||||||
pub(in crate::gfx_apis::gl) ctx: Rc<GlRenderContext>,
|
pub(in crate::gfx_apis::gl) ctx: Rc<GlRenderContext>,
|
||||||
pub(in crate::gfx_apis::gl) gl: GlTexture,
|
pub(in crate::gfx_apis::gl) gl: GlTexture,
|
||||||
pub(in crate::gfx_apis::gl) resv: TextureReservations,
|
|
||||||
pub(in crate::gfx_apis::gl) format: &'static Format,
|
pub(in crate::gfx_apis::gl) format: &'static Format,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,10 +78,6 @@ impl GfxTexture for Texture {
|
||||||
self.gl.img.as_ref().map(|i| &i.dmabuf)
|
self.gl.img.as_ref().map(|i| &i.dmabuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reservations(&self) -> &TextureReservations {
|
|
||||||
&self.resv
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format(&self) -> &'static Format {
|
fn format(&self) -> &'static Format {
|
||||||
self.format
|
self.format
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,8 +153,6 @@ pub enum VulkanError {
|
||||||
IoctlExportSyncFile(#[source] OsError),
|
IoctlExportSyncFile(#[source] OsError),
|
||||||
#[error("Could not import a sync file into a semaphore")]
|
#[error("Could not import a sync file into a semaphore")]
|
||||||
ImportSyncFile(#[source] vk::Result),
|
ImportSyncFile(#[source] vk::Result),
|
||||||
#[error("Could not import a sync file into a dma-buf")]
|
|
||||||
IoctlImportSyncFile(#[source] OsError),
|
|
||||||
#[error("Could not export a sync file from a semaphore")]
|
#[error("Could not export a sync file from a semaphore")]
|
||||||
ExportSyncFile(#[source] vk::Result),
|
ExportSyncFile(#[source] vk::Result),
|
||||||
#[error("Could not fetch the render node of the device")]
|
#[error("Could not fetch the render node of the device")]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
use {
|
use {
|
||||||
crate::gfx_apis::vulkan::{device::VulkanDevice, VulkanError},
|
crate::{
|
||||||
|
gfx_api::SyncFile,
|
||||||
|
gfx_apis::vulkan::{device::VulkanDevice, VulkanError},
|
||||||
|
},
|
||||||
ash::vk::{
|
ash::vk::{
|
||||||
ExportFenceCreateInfo, ExternalFenceHandleTypeFlags, Fence, FenceCreateInfo,
|
ExportFenceCreateInfo, ExternalFenceHandleTypeFlags, Fence, FenceCreateInfo,
|
||||||
FenceGetFdInfoKHR,
|
FenceGetFdInfoKHR,
|
||||||
|
|
@ -38,12 +41,12 @@ impl VulkanDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanFence {
|
impl VulkanFence {
|
||||||
pub fn export_syncfile(&self) -> Result<Rc<OwnedFd>, VulkanError> {
|
pub fn export_sync_file(&self) -> Result<SyncFile, VulkanError> {
|
||||||
let info = FenceGetFdInfoKHR::builder()
|
let info = FenceGetFdInfoKHR::builder()
|
||||||
.fence(self.fence)
|
.fence(self.fence)
|
||||||
.handle_type(ExternalFenceHandleTypeFlags::SYNC_FD);
|
.handle_type(ExternalFenceHandleTypeFlags::SYNC_FD);
|
||||||
let res = unsafe { self.device.external_fence_fd.get_fence_fd(&info) };
|
let res = unsafe { self.device.external_fence_fd.get_fence_fd(&info) };
|
||||||
res.map_err(VulkanError::ExportSyncFile)
|
res.map_err(VulkanError::ExportSyncFile)
|
||||||
.map(|fd| Rc::new(OwnedFd::new(fd)))
|
.map(|fd| SyncFile(Rc::new(OwnedFd::new(fd))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture, TextureReservations},
|
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture},
|
||||||
gfx_apis::vulkan::{
|
gfx_apis::vulkan::{
|
||||||
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanMaxExtents,
|
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanMaxExtents,
|
||||||
renderer::VulkanRenderer, util::OnDrop, VulkanError,
|
renderer::VulkanRenderer, util::OnDrop, VulkanError,
|
||||||
|
|
@ -53,7 +53,6 @@ pub struct VulkanImage {
|
||||||
pub(super) is_undefined: Cell<bool>,
|
pub(super) is_undefined: Cell<bool>,
|
||||||
pub(super) ty: VulkanImageMemory,
|
pub(super) ty: VulkanImageMemory,
|
||||||
pub(super) render_ops: CloneCell<Vec<GfxApiOpt>>,
|
pub(super) render_ops: CloneCell<Vec<GfxApiOpt>>,
|
||||||
pub(super) resv: TextureReservations,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum VulkanImageMemory {
|
pub enum VulkanImageMemory {
|
||||||
|
|
@ -212,7 +211,6 @@ impl VulkanRenderer {
|
||||||
is_undefined: Cell::new(true),
|
is_undefined: Cell::new(true),
|
||||||
ty: VulkanImageMemory::Internal(shm),
|
ty: VulkanImageMemory::Internal(shm),
|
||||||
render_ops: Default::default(),
|
render_ops: Default::default(),
|
||||||
resv: Default::default(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,7 +480,6 @@ impl VulkanDmaBufImageTemplate {
|
||||||
}),
|
}),
|
||||||
format: self.dmabuf.format,
|
format: self.dmabuf.format,
|
||||||
is_undefined: Cell::new(true),
|
is_undefined: Cell::new(true),
|
||||||
resv: Default::default(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -587,10 +584,6 @@ impl GfxTexture for VulkanImage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reservations(&self) -> &TextureReservations {
|
|
||||||
&self.resv
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format(&self) -> &'static Format {
|
fn format(&self) -> &'static Format {
|
||||||
self.format
|
self.format
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
async_engine::SpawnedFuture,
|
async_engine::SpawnedFuture,
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{GfxApiOpt, GfxFormat, GfxFramebuffer, GfxTexture},
|
gfx_api::{
|
||||||
|
BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer, GfxTexture, SyncFile,
|
||||||
|
},
|
||||||
gfx_apis::vulkan::{
|
gfx_apis::vulkan::{
|
||||||
allocator::VulkanAllocator,
|
allocator::VulkanAllocator,
|
||||||
command::{VulkanCommandBuffer, VulkanCommandPool},
|
command::{VulkanCommandBuffer, VulkanCommandPool},
|
||||||
|
|
@ -21,10 +23,7 @@ use {
|
||||||
io_uring::IoUring,
|
io_uring::IoUring,
|
||||||
theme::Color,
|
theme::Color,
|
||||||
utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, stack::Stack},
|
utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, stack::Stack},
|
||||||
video::dmabuf::{
|
video::dmabuf::{dma_buf_export_sync_file, DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE},
|
||||||
dma_buf_export_sync_file, dma_buf_import_sync_file, DMA_BUF_SYNC_READ,
|
|
||||||
DMA_BUF_SYNC_WRITE,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
ash::{
|
ash::{
|
||||||
|
|
@ -49,7 +48,6 @@ use {
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
slice,
|
slice,
|
||||||
},
|
},
|
||||||
uapi::OwnedFd,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct VulkanRenderer {
|
pub struct VulkanRenderer {
|
||||||
|
|
@ -66,6 +64,12 @@ pub struct VulkanRenderer {
|
||||||
pub(super) pending_frames: CopyHashMap<u64, Rc<PendingFrame>>,
|
pub(super) pending_frames: CopyHashMap<u64, Rc<PendingFrame>>,
|
||||||
pub(super) allocator: Rc<VulkanAllocator>,
|
pub(super) allocator: Rc<VulkanAllocator>,
|
||||||
pub(super) last_point: NumCell<u64>,
|
pub(super) last_point: NumCell<u64>,
|
||||||
|
pub(super) buffer_resv_user: BufferResvUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct UsedTexture {
|
||||||
|
tex: Rc<VulkanImage>,
|
||||||
|
resv: Option<Rc<dyn BufferResv>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -73,20 +77,20 @@ pub(super) struct Memory {
|
||||||
sample: Vec<Rc<VulkanImage>>,
|
sample: Vec<Rc<VulkanImage>>,
|
||||||
flush: Vec<Rc<VulkanImage>>,
|
flush: Vec<Rc<VulkanImage>>,
|
||||||
flush_staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>,
|
flush_staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>,
|
||||||
textures: Vec<Rc<VulkanImage>>,
|
textures: Vec<UsedTexture>,
|
||||||
image_barriers: Vec<ImageMemoryBarrier2>,
|
image_barriers: Vec<ImageMemoryBarrier2>,
|
||||||
shm_barriers: Vec<BufferMemoryBarrier2>,
|
shm_barriers: Vec<BufferMemoryBarrier2>,
|
||||||
wait_semaphores: Vec<Rc<VulkanSemaphore>>,
|
wait_semaphores: Vec<Rc<VulkanSemaphore>>,
|
||||||
wait_semaphore_infos: Vec<SemaphoreSubmitInfo>,
|
wait_semaphore_infos: Vec<SemaphoreSubmitInfo>,
|
||||||
release_fence: Option<Rc<VulkanFence>>,
|
release_fence: Option<Rc<VulkanFence>>,
|
||||||
release_syncfile: Option<Rc<OwnedFd>>,
|
release_sync_file: Option<SyncFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct PendingFrame {
|
pub(super) struct PendingFrame {
|
||||||
point: u64,
|
point: u64,
|
||||||
renderer: Rc<VulkanRenderer>,
|
renderer: Rc<VulkanRenderer>,
|
||||||
cmd: Cell<Option<Rc<VulkanCommandBuffer>>>,
|
cmd: Cell<Option<Rc<VulkanCommandBuffer>>>,
|
||||||
_textures: Vec<Rc<VulkanImage>>,
|
_textures: Vec<UsedTexture>,
|
||||||
_staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>,
|
_staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>,
|
||||||
wait_semaphores: Cell<Vec<Rc<VulkanSemaphore>>>,
|
wait_semaphores: Cell<Vec<Rc<VulkanSemaphore>>>,
|
||||||
waiter: Cell<Option<SpawnedFuture<()>>>,
|
waiter: Cell<Option<SpawnedFuture<()>>>,
|
||||||
|
|
@ -157,6 +161,7 @@ impl VulkanDevice {
|
||||||
pending_frames: Default::default(),
|
pending_frames: Default::default(),
|
||||||
allocator,
|
allocator,
|
||||||
last_point: Default::default(),
|
last_point: Default::default(),
|
||||||
|
buffer_resv_user: Default::default(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +182,10 @@ impl VulkanRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memory.textures.push(tex);
|
memory.textures.push(UsedTexture {
|
||||||
|
tex,
|
||||||
|
resv: c.buffer_resv.clone(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -537,7 +545,7 @@ impl VulkanRenderer {
|
||||||
let fd = dma_buf_export_sync_file(&plane.fd, flag)
|
let fd = dma_buf_export_sync_file(&plane.fd, flag)
|
||||||
.map_err(VulkanError::IoctlExportSyncFile)?;
|
.map_err(VulkanError::IoctlExportSyncFile)?;
|
||||||
let semaphore = self.allocate_semaphore()?;
|
let semaphore = self.allocate_semaphore()?;
|
||||||
semaphore.import_syncfile(fd)?;
|
semaphore.import_sync_file(fd)?;
|
||||||
infos.push(
|
infos.push(
|
||||||
SemaphoreSubmitInfo::builder()
|
SemaphoreSubmitInfo::builder()
|
||||||
.semaphore(semaphore.semaphore)
|
.semaphore(semaphore.semaphore)
|
||||||
|
|
@ -553,7 +561,7 @@ impl VulkanRenderer {
|
||||||
import(
|
import(
|
||||||
&mut memory.wait_semaphore_infos,
|
&mut memory.wait_semaphore_infos,
|
||||||
&mut memory.wait_semaphores,
|
&mut memory.wait_semaphores,
|
||||||
texture,
|
&texture.tex,
|
||||||
DMA_BUF_SYNC_READ,
|
DMA_BUF_SYNC_READ,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
@ -567,27 +575,25 @@ impl VulkanRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_release_semaphore(&self, fb: &VulkanImage) {
|
fn import_release_semaphore(&self, fb: &VulkanImage) {
|
||||||
let memory = self.memory.borrow();
|
let memory = &mut *self.memory.borrow_mut();
|
||||||
let syncfile = match memory.release_syncfile.as_ref() {
|
let sync_file = match memory.release_sync_file.as_ref() {
|
||||||
Some(syncfile) => syncfile,
|
Some(sync_file) => sync_file,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let import = |img: &VulkanImage, flag: u32| {
|
let import = |img: &VulkanImage, resv: Option<Rc<dyn BufferResv>>, flag: u32| {
|
||||||
if let VulkanImageMemory::DmaBuf(buf) = &img.ty {
|
if let Some(resv) = resv {
|
||||||
for plane in &buf.template.dmabuf.planes {
|
resv.set_sync_file(self.buffer_resv_user, sync_file);
|
||||||
let res = dma_buf_import_sync_file(&plane.fd, flag, &syncfile)
|
} else if let VulkanImageMemory::DmaBuf(buf) = &img.ty {
|
||||||
.map_err(VulkanError::IoctlImportSyncFile);
|
if let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file) {
|
||||||
if let Err(e) = res {
|
log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e));
|
||||||
log::error!("Could not import syncfile into dmabuf: {}", ErrorFmt(e));
|
log::warn!("Relying on implicit sync");
|
||||||
log::warn!("Relying on implicit sync");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for texture in &memory.textures {
|
for texture in &mut memory.textures {
|
||||||
import(texture, DMA_BUF_SYNC_WRITE);
|
import(&texture.tex, texture.resv.take(), DMA_BUF_SYNC_READ);
|
||||||
}
|
}
|
||||||
import(fb, DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE);
|
import(fb, None, DMA_BUF_SYNC_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
|
fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
|
||||||
|
|
@ -610,15 +616,15 @@ impl VulkanRenderer {
|
||||||
)
|
)
|
||||||
.map_err(VulkanError::Submit)?;
|
.map_err(VulkanError::Submit)?;
|
||||||
}
|
}
|
||||||
let release_syncfile = match release_fence.export_syncfile() {
|
let release_sync_file = match release_fence.export_sync_file() {
|
||||||
Ok(s) => Some(s),
|
Ok(s) => Some(s),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Could not export syncfile from fence: {}", ErrorFmt(e));
|
log::error!("Could not export sync file from fence: {}", ErrorFmt(e));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
memory.release_fence = Some(release_fence);
|
memory.release_fence = Some(release_fence);
|
||||||
memory.release_syncfile = release_syncfile;
|
memory.release_sync_file = release_sync_file;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -650,7 +656,7 @@ impl VulkanRenderer {
|
||||||
});
|
});
|
||||||
self.pending_frames.set(frame.point, frame.clone());
|
self.pending_frames.set(frame.point, frame.clone());
|
||||||
let future = self.device.instance.eng.spawn(await_release(
|
let future = self.device.instance.eng.spawn(await_release(
|
||||||
memory.release_syncfile.take(),
|
memory.release_sync_file.take(),
|
||||||
self.device.instance.ring.clone(),
|
self.device.instance.ring.clone(),
|
||||||
frame.clone(),
|
frame.clone(),
|
||||||
self.clone(),
|
self.clone(),
|
||||||
|
|
@ -769,7 +775,7 @@ impl VulkanRenderer {
|
||||||
let fd = dma_buf_export_sync_file(&plane.fd, DMA_BUF_SYNC_READ)
|
let fd = dma_buf_export_sync_file(&plane.fd, DMA_BUF_SYNC_READ)
|
||||||
.map_err(VulkanError::IoctlExportSyncFile)?;
|
.map_err(VulkanError::IoctlExportSyncFile)?;
|
||||||
let semaphore = self.allocate_semaphore()?;
|
let semaphore = self.allocate_semaphore()?;
|
||||||
semaphore.import_syncfile(fd)?;
|
semaphore.import_sync_file(fd)?;
|
||||||
let semaphore_info = SemaphoreSubmitInfo::builder()
|
let semaphore_info = SemaphoreSubmitInfo::builder()
|
||||||
.semaphore(semaphore.semaphore)
|
.semaphore(semaphore.semaphore)
|
||||||
.stage_mask(PipelineStageFlags2::TOP_OF_PIPE)
|
.stage_mask(PipelineStageFlags2::TOP_OF_PIPE)
|
||||||
|
|
@ -841,7 +847,7 @@ impl VulkanRenderer {
|
||||||
memory.sample.clear();
|
memory.sample.clear();
|
||||||
memory.wait_semaphores.clear();
|
memory.wait_semaphores.clear();
|
||||||
memory.release_fence.take();
|
memory.release_fence.take();
|
||||||
memory.release_syncfile.take();
|
memory.release_sync_file.take();
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
@ -964,14 +970,14 @@ fn image_barrier() -> ImageMemoryBarrier2Builder<'static> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn await_release(
|
async fn await_release(
|
||||||
syncfile: Option<Rc<OwnedFd>>,
|
sync_file: Option<SyncFile>,
|
||||||
ring: Rc<IoUring>,
|
ring: Rc<IoUring>,
|
||||||
frame: Rc<PendingFrame>,
|
frame: Rc<PendingFrame>,
|
||||||
renderer: Rc<VulkanRenderer>,
|
renderer: Rc<VulkanRenderer>,
|
||||||
) {
|
) {
|
||||||
let mut is_released = false;
|
let mut is_released = false;
|
||||||
if let Some(syncfile) = syncfile {
|
if let Some(sync_file) = sync_file {
|
||||||
if let Err(e) = ring.readable(&syncfile).await {
|
if let Err(e) = ring.readable(&sync_file).await {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Could not wait for release semaphore to be signaled: {}",
|
"Could not wait for release semaphore to be signaled: {}",
|
||||||
ErrorFmt(e)
|
ErrorFmt(e)
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ impl VulkanDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanSemaphore {
|
impl VulkanSemaphore {
|
||||||
pub fn import_syncfile(&self, syncfile: OwnedFd) -> Result<(), VulkanError> {
|
pub fn import_sync_file(&self, sync_file: OwnedFd) -> Result<(), VulkanError> {
|
||||||
let fd_info = ImportSemaphoreFdInfoKHR::builder()
|
let fd_info = ImportSemaphoreFdInfoKHR::builder()
|
||||||
.fd(syncfile.raw())
|
.fd(sync_file.raw())
|
||||||
.flags(SemaphoreImportFlags::TEMPORARY)
|
.flags(SemaphoreImportFlags::TEMPORARY)
|
||||||
.handle_type(ExternalSemaphoreHandleTypeFlags::SYNC_FD)
|
.handle_type(ExternalSemaphoreHandleTypeFlags::SYNC_FD)
|
||||||
.semaphore(self.semaphore);
|
.semaphore(self.semaphore);
|
||||||
|
|
@ -47,7 +47,7 @@ impl VulkanSemaphore {
|
||||||
.external_semaphore_fd
|
.external_semaphore_fd
|
||||||
.import_semaphore_fd(&fd_info)
|
.import_semaphore_fd(&fd_info)
|
||||||
};
|
};
|
||||||
mem::forget(syncfile);
|
mem::forget(sync_file);
|
||||||
res.map_err(VulkanError::ImportSyncFile)?;
|
res.map_err(VulkanError::ImportSyncFile)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ pub struct WlBuffer {
|
||||||
pub client: Rc<Client>,
|
pub client: Rc<Client>,
|
||||||
pub rect: Rect,
|
pub rect: Rect,
|
||||||
pub format: &'static Format,
|
pub format: &'static Format,
|
||||||
dmabuf: Option<DmaBuf>,
|
pub dmabuf: Option<DmaBuf>,
|
||||||
render_ctx_version: Cell<u32>,
|
render_ctx_version: Cell<u32>,
|
||||||
pub storage: RefCell<Option<WlBufferStorage>>,
|
pub storage: RefCell<Option<WlBufferStorage>>,
|
||||||
pub color: Option<Color>,
|
pub color: Option<Color>,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use {
|
||||||
client::{Client, ClientError, RequestParser},
|
client::{Client, ClientError, RequestParser},
|
||||||
drm_feedback::DrmFeedback,
|
drm_feedback::DrmFeedback,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
gfx_api::SampleRect,
|
gfx_api::{BufferResv, BufferResvUser, SampleRect, SyncFile},
|
||||||
ifs::{
|
ifs::{
|
||||||
wl_buffer::WlBuffer,
|
wl_buffer::WlBuffer,
|
||||||
wl_callback::WlCallback,
|
wl_callback::WlCallback,
|
||||||
|
|
@ -51,11 +51,13 @@ use {
|
||||||
cell_ext::CellExt,
|
cell_ext::CellExt,
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
copyhashmap::CopyHashMap,
|
copyhashmap::CopyHashMap,
|
||||||
|
errorfmt::ErrorFmt,
|
||||||
linkedlist::LinkedList,
|
linkedlist::LinkedList,
|
||||||
numcell::NumCell,
|
numcell::NumCell,
|
||||||
smallmap::SmallMap,
|
smallmap::SmallMap,
|
||||||
transform_ext::TransformExt,
|
transform_ext::TransformExt,
|
||||||
},
|
},
|
||||||
|
video::dmabuf::DMA_BUF_SYNC_READ,
|
||||||
wire::{
|
wire::{
|
||||||
wl_surface::*, WlOutputId, WlSurfaceId, ZwpIdleInhibitorV1Id,
|
wl_surface::*, WlOutputId, WlSurfaceId, ZwpIdleInhibitorV1Id,
|
||||||
ZwpLinuxDmabufFeedbackV1Id,
|
ZwpLinuxDmabufFeedbackV1Id,
|
||||||
|
|
@ -131,6 +133,39 @@ impl NodeVisitorBase for SurfaceSendPreferredTransformVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SurfaceBuffer {
|
||||||
|
pub buffer: Rc<WlBuffer>,
|
||||||
|
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for SurfaceBuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let sync_files = self.sync_files.take();
|
||||||
|
if let Some(dmabuf) = &self.buffer.dmabuf {
|
||||||
|
for (_, sync_file) in &sync_files {
|
||||||
|
if let Err(e) = dmabuf.import_sync_file(DMA_BUF_SYNC_READ, sync_file) {
|
||||||
|
log::error!("Could not import sync file: {}", ErrorFmt(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !self.buffer.destroyed() {
|
||||||
|
self.buffer.send_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for SurfaceBuffer {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("SurfaceBuffer").finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BufferResv for SurfaceBuffer {
|
||||||
|
fn set_sync_file(&self, user: BufferResvUser, sync_file: &SyncFile) {
|
||||||
|
self.sync_files.insert(user, sync_file.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WlSurface {
|
pub struct WlSurface {
|
||||||
pub id: WlSurfaceId,
|
pub id: WlSurfaceId,
|
||||||
pub node_id: SurfaceNodeId,
|
pub node_id: SurfaceNodeId,
|
||||||
|
|
@ -149,7 +184,7 @@ pub struct WlSurface {
|
||||||
pub extents: Cell<Rect>,
|
pub extents: Cell<Rect>,
|
||||||
pub buffer_abs_pos: Cell<Rect>,
|
pub buffer_abs_pos: Cell<Rect>,
|
||||||
pub need_extents_update: Cell<bool>,
|
pub need_extents_update: Cell<bool>,
|
||||||
pub buffer: CloneCell<Option<Rc<WlBuffer>>>,
|
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
|
||||||
pub buf_x: NumCell<i32>,
|
pub buf_x: NumCell<i32>,
|
||||||
pub buf_y: NumCell<i32>,
|
pub buf_y: NumCell<i32>,
|
||||||
pub children: RefCell<Option<Box<ParentData>>>,
|
pub children: RefCell<Option<Box<ParentData>>>,
|
||||||
|
|
@ -683,11 +718,7 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
*children = None;
|
*children = None;
|
||||||
}
|
}
|
||||||
if let Some(buffer) = self.buffer.set(None) {
|
self.buffer.set(None);
|
||||||
if !buffer.destroyed() {
|
|
||||||
buffer.send_release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(xwayland_serial) = self.xwayland_serial.get() {
|
if let Some(xwayland_serial) = self.xwayland_serial.get() {
|
||||||
self.client
|
self.client
|
||||||
.surfaces_by_xwayland_serial
|
.surfaces_by_xwayland_serial
|
||||||
|
|
@ -799,30 +830,15 @@ impl WlSurface {
|
||||||
if let Some(buffer_change) = pending.buffer.take() {
|
if let Some(buffer_change) = pending.buffer.take() {
|
||||||
buffer_changed = true;
|
buffer_changed = true;
|
||||||
if let Some(buffer) = self.buffer.take() {
|
if let Some(buffer) = self.buffer.take() {
|
||||||
old_raw_size = Some(buffer.rect);
|
old_raw_size = Some(buffer.buffer.rect);
|
||||||
if !buffer.destroyed() {
|
|
||||||
'handle_release: {
|
|
||||||
if let Some(tex) = buffer.texture.get() {
|
|
||||||
let resv = tex.reservations();
|
|
||||||
if resv.has_reservation() {
|
|
||||||
let buffer = Rc::downgrade(&buffer);
|
|
||||||
resv.on_released(move || {
|
|
||||||
if let Some(buffer) = buffer.upgrade() {
|
|
||||||
if !buffer.destroyed() {
|
|
||||||
buffer.send_release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break 'handle_release;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer.send_release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Some(buffer) = buffer_change {
|
if let Some(buffer) = buffer_change {
|
||||||
buffer.update_texture_or_log();
|
buffer.update_texture_or_log();
|
||||||
self.buffer.set(Some(buffer));
|
let surface_buffer = SurfaceBuffer {
|
||||||
|
buffer,
|
||||||
|
sync_files: Default::default(),
|
||||||
|
};
|
||||||
|
self.buffer.set(Some(Rc::new(surface_buffer)));
|
||||||
self.buf_x.fetch_add(dx);
|
self.buf_x.fetch_add(dx);
|
||||||
self.buf_y.fetch_add(dy);
|
self.buf_y.fetch_add(dy);
|
||||||
if (dx, dy) != (0, 0) {
|
if (dx, dy) != (0, 0) {
|
||||||
|
|
@ -872,8 +888,10 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
if let Some(buffer) = self.buffer.get() {
|
if let Some(buffer) = self.buffer.get() {
|
||||||
if new_size.is_none() {
|
if new_size.is_none() {
|
||||||
let (mut width, mut height) =
|
let (mut width, mut height) = self
|
||||||
self.buffer_transform.get().maybe_swap(buffer.rect.size());
|
.buffer_transform
|
||||||
|
.get()
|
||||||
|
.maybe_swap(buffer.buffer.rect.size());
|
||||||
let scale = self.buffer_scale.get();
|
let scale = self.buffer_scale.get();
|
||||||
if scale != 1 {
|
if scale != 1 {
|
||||||
width = (width + scale - 1) / scale;
|
width = (width + scale - 1) / scale;
|
||||||
|
|
@ -881,12 +899,14 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
new_size = Some((width, height));
|
new_size = Some((width, height));
|
||||||
}
|
}
|
||||||
if transform_changed || Some(buffer.rect) != old_raw_size {
|
if transform_changed || Some(buffer.buffer.rect) != old_raw_size {
|
||||||
let (x1, y1, x2, y2) = if self.src_rect.is_none() {
|
let (x1, y1, x2, y2) = if self.src_rect.is_none() {
|
||||||
(0.0, 0.0, 1.0, 1.0)
|
(0.0, 0.0, 1.0, 1.0)
|
||||||
} else {
|
} else {
|
||||||
let (width, height) =
|
let (width, height) = self
|
||||||
self.buffer_transform.get().maybe_swap(buffer.rect.size());
|
.buffer_transform
|
||||||
|
.get()
|
||||||
|
.maybe_swap(buffer.buffer.rect.size());
|
||||||
let width = width as f32;
|
let width = width as f32;
|
||||||
let height = height as f32;
|
let height = height as f32;
|
||||||
let x1 = buffer_points.x1 / width;
|
let x1 = buffer_points.x1 / width;
|
||||||
|
|
|
||||||
|
|
@ -350,9 +350,9 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) {
|
fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) {
|
||||||
let buffer = self.surface.buffer.get();
|
let buffer_is_some = self.surface.buffer.is_some();
|
||||||
if self.mapped.get() {
|
if self.mapped.get() {
|
||||||
if buffer.is_none() {
|
if !buffer_is_some {
|
||||||
self.destroy_node();
|
self.destroy_node();
|
||||||
} else {
|
} else {
|
||||||
let pos = self.pos.get();
|
let pos = self.pos.get();
|
||||||
|
|
@ -361,7 +361,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
||||||
self.compute_position();
|
self.compute_position();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if buffer.is_some() {
|
} else if buffer_is_some {
|
||||||
let layer = &self.output.layers[self.layer.get() as usize];
|
let layer = &self.output.layers[self.layer.get() as usize];
|
||||||
self.link.set(Some(layer.add_last(self.clone())));
|
self.link.set(Some(layer.add_last(self.clone())));
|
||||||
self.mapped.set(true);
|
self.mapped.set(true);
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ impl XdgToplevelDragV1 {
|
||||||
return Err(XdgToplevelDragV1Error::AlreadyDragged);
|
return Err(XdgToplevelDragV1Error::AlreadyDragged);
|
||||||
}
|
}
|
||||||
if let Some(prev) = self.toplevel.set(Some(toplevel)) {
|
if let Some(prev) = self.toplevel.set(Some(toplevel)) {
|
||||||
if prev.xdg.surface.buffer.get().is_some() {
|
if prev.xdg.surface.buffer.is_some() {
|
||||||
return Err(XdgToplevelDragV1Error::ToplevelAttached);
|
return Err(XdgToplevelDragV1Error::ToplevelAttached);
|
||||||
}
|
}
|
||||||
if prev.id != req.toplevel {
|
if prev.id != req.toplevel {
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,7 @@ impl GuiElement for Button {
|
||||||
None,
|
None,
|
||||||
r.scale(),
|
r.scale(),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -323,6 +324,7 @@ impl GuiElement for Label {
|
||||||
None,
|
None,
|
||||||
r.scale(),
|
r.scale(),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
gfx_api::{GfxApiOpt, SampleRect},
|
gfx_api::{GfxApiOpt, SampleRect},
|
||||||
ifs::{
|
ifs::{
|
||||||
wl_buffer::WlBuffer,
|
|
||||||
wl_callback::WlCallback,
|
wl_callback::WlCallback,
|
||||||
wl_surface::{
|
wl_surface::{
|
||||||
xdg_surface::XdgSurface, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, WlSurface,
|
xdg_surface::XdgSurface, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, SurfaceBuffer,
|
||||||
|
WlSurface,
|
||||||
},
|
},
|
||||||
wp_presentation_feedback::WpPresentationFeedback,
|
wp_presentation_feedback::WpPresentationFeedback,
|
||||||
},
|
},
|
||||||
|
|
@ -152,12 +152,12 @@ impl Renderer<'_> {
|
||||||
for title in &rd.titles {
|
for title in &rd.titles {
|
||||||
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
|
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
|
||||||
self.base
|
self.base
|
||||||
.render_texture(&title.tex, x, y, None, None, scale, None);
|
.render_texture(&title.tex, x, y, None, None, scale, None, None);
|
||||||
}
|
}
|
||||||
if let Some(status) = &rd.status {
|
if let Some(status) = &rd.status {
|
||||||
let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y);
|
let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y);
|
||||||
self.base
|
self.base
|
||||||
.render_texture(&status.tex.texture, x, y, None, None, scale, None);
|
.render_texture(&status.tex.texture, x, y, None, None, scale, None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ws) = output.workspace.get() {
|
if let Some(ws) = output.workspace.get() {
|
||||||
|
|
@ -194,7 +194,7 @@ impl Renderer<'_> {
|
||||||
let x = x + (pos.width() - tex_width) / 2;
|
let x = x + (pos.width() - tex_width) / 2;
|
||||||
let y = y + (pos.height() - tex_height) / 2;
|
let y = y + (pos.height() - tex_height) / 2;
|
||||||
self.base
|
self.base
|
||||||
.render_texture(&tex.texture, x, y, None, None, self.base.scale, None);
|
.render_texture(&tex.texture, x, y, None, None, self.base.scale, None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,6 +231,7 @@ impl Renderer<'_> {
|
||||||
None,
|
None,
|
||||||
self.base.scale,
|
self.base.scale,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -345,14 +346,14 @@ impl Renderer<'_> {
|
||||||
|
|
||||||
pub fn render_buffer(
|
pub fn render_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &WlBuffer,
|
buffer: &Rc<SurfaceBuffer>,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
tpoints: SampleRect,
|
tpoints: SampleRect,
|
||||||
tsize: (i32, i32),
|
tsize: (i32, i32),
|
||||||
bounds: Option<&Rect>,
|
bounds: Option<&Rect>,
|
||||||
) {
|
) {
|
||||||
if let Some(tex) = buffer.texture.get() {
|
if let Some(tex) = buffer.buffer.texture.get() {
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&tex,
|
&tex,
|
||||||
x,
|
x,
|
||||||
|
|
@ -361,8 +362,9 @@ impl Renderer<'_> {
|
||||||
Some(tsize),
|
Some(tsize),
|
||||||
self.base.scale,
|
self.base.scale,
|
||||||
bounds,
|
bounds,
|
||||||
|
Some(buffer.clone()),
|
||||||
);
|
);
|
||||||
} else if let Some(color) = &buffer.color {
|
} else if let Some(color) = &buffer.buffer.color {
|
||||||
if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {
|
if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {
|
||||||
let rect = match bounds {
|
let rect = match bounds {
|
||||||
None => rect,
|
None => rect,
|
||||||
|
|
@ -409,8 +411,16 @@ impl Renderer<'_> {
|
||||||
self.base.fill_boxes(&title_underline, &uc);
|
self.base.fill_boxes(&title_underline, &uc);
|
||||||
if let Some(title) = floating.title_textures.get(&self.base.scale) {
|
if let Some(title) = floating.title_textures.get(&self.base.scale) {
|
||||||
let (x, y) = self.base.scale_point(x + bw, y + bw);
|
let (x, y) = self.base.scale_point(x + bw, y + bw);
|
||||||
self.base
|
self.base.render_texture(
|
||||||
.render_texture(&title.texture, x, y, None, None, self.base.scale, None);
|
&title.texture,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
self.base.scale,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let body = Rect::new_sized(
|
let body = Rect::new_sized(
|
||||||
x + bw,
|
x + bw,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
gfx_api::{CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxTexture, SampleRect},
|
gfx_api::{
|
||||||
|
BufferResv, CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxTexture, SampleRect,
|
||||||
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
theme::Color,
|
theme::Color,
|
||||||
|
|
@ -130,6 +132,7 @@ impl RendererBase<'_> {
|
||||||
tsize: Option<(i32, i32)>,
|
tsize: Option<(i32, i32)>,
|
||||||
tscale: Scale,
|
tscale: Scale,
|
||||||
bounds: Option<&Rect>,
|
bounds: Option<&Rect>,
|
||||||
|
buffer_resv: Option<Rc<dyn BufferResv>>,
|
||||||
) {
|
) {
|
||||||
let mut texcoord = tpoints.unwrap_or_else(SampleRect::identity);
|
let mut texcoord = tpoints.unwrap_or_else(SampleRect::identity);
|
||||||
|
|
||||||
|
|
@ -154,18 +157,21 @@ impl RendererBase<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let target = FramebufferRect::new(
|
||||||
|
target_x[0] as f32,
|
||||||
|
target_y[0] as f32,
|
||||||
|
target_x[1] as f32,
|
||||||
|
target_y[1] as f32,
|
||||||
|
self.transform,
|
||||||
|
self.fb_width,
|
||||||
|
self.fb_height,
|
||||||
|
);
|
||||||
|
|
||||||
self.ops.push(GfxApiOpt::CopyTexture(CopyTexture {
|
self.ops.push(GfxApiOpt::CopyTexture(CopyTexture {
|
||||||
tex: texture.clone(),
|
tex: texture.clone(),
|
||||||
source: texcoord,
|
source: texcoord,
|
||||||
target: FramebufferRect::new(
|
target,
|
||||||
target_x[0] as f32,
|
buffer_resv,
|
||||||
target_y[0] as f32,
|
|
||||||
target_x[1] as f32,
|
|
||||||
target_y[1] as f32,
|
|
||||||
self.transform,
|
|
||||||
self.fb_width,
|
|
||||||
self.fb_height,
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -408,7 +408,7 @@ impl State {
|
||||||
}
|
}
|
||||||
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
||||||
if let Some(buffer) = node.buffer.get() {
|
if let Some(buffer) = node.buffer.get() {
|
||||||
buffer.handle_gfx_context_change();
|
buffer.buffer.handle_gfx_context_change();
|
||||||
}
|
}
|
||||||
node.node_visit_children(self);
|
node.node_visit_children(self);
|
||||||
}
|
}
|
||||||
|
|
@ -814,6 +814,7 @@ impl State {
|
||||||
size,
|
size,
|
||||||
Scale::from_int(1),
|
Scale::from_int(1),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
if render_hardware_cursors {
|
if render_hardware_cursors {
|
||||||
for seat in self.globals.lock_seats().values() {
|
for seat in self.globals.lock_seats().values() {
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,13 @@ impl DmaBuf {
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn import_sync_file(&self, flags: u32, sync_file: &OwnedFd) -> Result<(), OsError> {
|
||||||
|
for plane in &self.planes {
|
||||||
|
dma_buf_import_sync_file(&plane.fd, flags, sync_file)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DMA_BUF_BASE: u64 = b'b' as _;
|
const DMA_BUF_BASE: u64 = b'b' as _;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue