1
0
Fork 0
forked from wry/wry

render: use explicit sync for framebuffers

This commit is contained in:
Julian Orth 2024-09-16 15:28:44 +02:00
parent 1bc344dcc2
commit 386ee5120f
15 changed files with 235 additions and 64 deletions

View file

@ -9,7 +9,7 @@ use {
}, },
gfx_api::{ gfx_api::{
create_render_pass, AcquireSync, BufferResv, GfxApiOpt, GfxRenderPass, GfxTexture, create_render_pass, AcquireSync, BufferResv, GfxApiOpt, GfxRenderPass, GfxTexture,
SyncFile, ReleaseSync, SyncFile,
}, },
theme::Color, theme::Color,
time::Time, time::Time,
@ -43,7 +43,8 @@ pub struct DirectScanoutCache {
pub struct DirectScanoutData { pub struct DirectScanoutData {
tex: Rc<dyn GfxTexture>, tex: Rc<dyn GfxTexture>,
acquire_sync: AcquireSync, acquire_sync: AcquireSync,
_resv: Option<Rc<dyn BufferResv>>, release_sync: ReleaseSync,
resv: Option<Rc<dyn BufferResv>>,
fb: Rc<DrmFramebuffer>, fb: Rc<DrmFramebuffer>,
dma_buf_id: DmaBufId, dma_buf_id: DmaBufId,
position: DirectScanoutPosition, position: DirectScanoutPosition,
@ -618,7 +619,8 @@ impl MetalConnector {
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(),
acquire_sync: ct.acquire_sync.clone(), acquire_sync: ct.acquire_sync.clone(),
_resv: ct.buffer_resv.clone(), release_sync: ct.release_sync,
resv: ct.buffer_resv.clone(),
fb: fb.clone(), fb: fb.clone(),
dma_buf_id: dmabuf.id, dma_buf_id: dmabuf.id,
position, position,
@ -643,7 +645,8 @@ impl MetalConnector {
Ok(fb) => Some(DirectScanoutData { Ok(fb) => Some(DirectScanoutData {
tex: ct.tex.clone(), tex: ct.tex.clone(),
acquire_sync: ct.acquire_sync.clone(), acquire_sync: ct.acquire_sync.clone(),
_resv: ct.buffer_resv.clone(), release_sync: ct.release_sync,
resv: ct.buffer_resv.clone(),
fb: Rc::new(fb), fb: Rc::new(fb),
dma_buf_id: dmabuf.id, dma_buf_id: dmabuf.id,
position, position,
@ -708,7 +711,7 @@ impl MetalConnector {
None => { None => {
let sf = buffer let sf = buffer
.render_fb() .render_fb()
.perform_render_pass(pass) .perform_render_pass(AcquireSync::Unnecessary, ReleaseSync::Explicit, pass)
.map_err(MetalError::RenderFrame)?; .map_err(MetalError::RenderFrame)?;
sync_file = buffer.copy_to_dev(sf)?; sync_file = buffer.copy_to_dev(sf)?;
fb = buffer.drm.clone(); fb = buffer.drm.clone();
@ -748,11 +751,23 @@ impl MetalConnector {
let render_hardware_cursor = self.cursor_enabled.get(); let render_hardware_cursor = self.cursor_enabled.get();
match &fb.direct_scanout_data { match &fb.direct_scanout_data {
None => { None => {
output.perform_screencopies(&fb.tex, render_hardware_cursor, 0, 0, None); output.perform_screencopies(
&fb.tex,
None,
&AcquireSync::Unnecessary,
ReleaseSync::None,
render_hardware_cursor,
0,
0,
None,
);
} }
Some(dsd) => { Some(dsd) => {
output.perform_screencopies( output.perform_screencopies(
&dsd.tex, &dsd.tex,
dsd.resv.as_ref(),
&dsd.acquire_sync,
dsd.release_sync,
render_hardware_cursor, render_hardware_cursor,
dsd.position.crtc_x, dsd.position.crtc_x,
dsd.position.crtc_y, dsd.position.crtc_y,

View file

@ -2474,7 +2474,9 @@ impl MetalBackend {
Ok(fb) => fb, Ok(fb) => fb,
Err(e) => return Err(MetalError::ImportFb(e)), Err(e) => return Err(MetalError::ImportFb(e)),
}; };
dev_fb.clear().map_err(MetalError::Clear)?; dev_fb
.clear(AcquireSync::Unnecessary, ReleaseSync::None)
.map_err(MetalError::Clear)?;
let (dev_tex, render_tex, render_fb, render_bo) = if dev.id == render_ctx.dev_id { let (dev_tex, render_tex, render_fb, render_bo) = if dev.id == render_ctx.dev_id {
let render_tex = match dev_img.to_texture() { let render_tex = match dev_img.to_texture() {
Ok(fb) => fb, Ok(fb) => fb,
@ -2526,7 +2528,9 @@ impl MetalBackend {
Ok(fb) => fb, Ok(fb) => fb,
Err(e) => return Err(MetalError::ImportFb(e)), Err(e) => return Err(MetalError::ImportFb(e)),
}; };
render_fb.clear().map_err(MetalError::Clear)?; render_fb
.clear(AcquireSync::Unnecessary, ReleaseSync::None)
.map_err(MetalError::Clear)?;
let render_tex = match render_img.to_texture() { let render_tex = match render_img.to_texture() {
Ok(fb) => fb, Ok(fb) => fb,
Err(e) => return Err(MetalError::ImportTexture(e)), Err(e) => return Err(MetalError::ImportTexture(e)),
@ -2797,9 +2801,17 @@ impl RenderBuffer {
let Some(tex) = &self.dev_tex else { let Some(tex) = &self.dev_tex else {
return Ok(sync_file); return Ok(sync_file);
}; };
let acquire_point = AcquireSync::from_sync_file(sync_file);
self.dev_fb self.dev_fb
.copy_texture(tex, acquire_point, ReleaseSync::Implicit, 0, 0) .copy_texture(
AcquireSync::Unnecessary,
ReleaseSync::Explicit,
tex,
None,
AcquireSync::from_sync_file(sync_file),
ReleaseSync::None,
0,
0,
)
.map_err(MetalError::CopyToOutput) .map_err(MetalError::CopyToOutput)
} }
} }

View file

@ -10,7 +10,7 @@ use {
}, },
fixed::Fixed, fixed::Fixed,
format::XRGB8888, format::XRGB8888,
gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture}, gfx_api::{AcquireSync, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync},
ifs::wl_output::OutputId, ifs::wl_output::OutputId,
state::State, state::State,
utils::{ utils::{
@ -750,9 +750,14 @@ impl XBackend {
image.last_serial.set(serial); image.last_serial.set(serial);
if let Some(node) = self.state.root.outputs.get(&output.id) { if let Some(node) = self.state.root.outputs.get(&output.id) {
let res = self let res = self.state.present_output(
.state &node,
.present_output(&node, &image.fb.get(), &image.tex.get(), true); &image.fb.get(),
AcquireSync::Implicit,
ReleaseSync::Implicit,
&image.tex.get(),
true,
);
if let Err(e) = res { if let Err(e) = res {
log::error!("Could not render screen: {}", ErrorFmt(e)); log::error!("Could not render screen: {}", ErrorFmt(e));
return; return;

View file

@ -3,6 +3,7 @@ use {
backend::HardwareCursorUpdate, backend::HardwareCursorUpdate,
cursor::{Cursor, KnownCursor, DEFAULT_CURSOR_SIZE}, cursor::{Cursor, KnownCursor, DEFAULT_CURSOR_SIZE},
fixed::Fixed, fixed::Fixed,
gfx_api::{AcquireSync, ReleaseSync},
rect::Rect, rect::Rect,
scale::Scale, scale::Scale,
state::State, state::State,
@ -497,8 +498,14 @@ impl CursorUser {
} }
if render { if render {
let buffer = hc.get_buffer(); let buffer = hc.get_buffer();
let res = let res = buffer.render_hardware_cursor(
buffer.render_hardware_cursor(cursor.deref(), &self.group.state, scale, transform); AcquireSync::Unnecessary,
ReleaseSync::Explicit,
cursor.deref(),
&self.group.state,
scale,
transform,
);
match res { match res {
Ok(sync_file) => { Ok(sync_file) => {
hc.set_sync_file(sync_file); hc.set_sync_file(sync_file);

View file

@ -208,13 +208,13 @@ pub enum AcquireSync {
impl AcquireSync { impl AcquireSync {
pub fn from_sync_file(sync_file: Option<SyncFile>) -> Self { pub fn from_sync_file(sync_file: Option<SyncFile>) -> Self {
match sync_file { match sync_file {
None => Self::Implicit, None => Self::Unnecessary,
Some(sync_file) => Self::SyncFile { sync_file }, Some(sync_file) => Self::SyncFile { sync_file },
} }
} }
} }
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ReleaseSync { pub enum ReleaseSync {
None, None,
Implicit, Implicit,
@ -260,6 +260,8 @@ pub trait GfxFramebuffer: Debug {
fn render( fn render(
&self, &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<Option<SyncFile>, GfxError>; ) -> Result<Option<SyncFile>, GfxError>;
@ -279,12 +281,24 @@ pub trait GfxFramebuffer: Debug {
} }
impl dyn GfxFramebuffer { impl dyn GfxFramebuffer {
pub fn clear(&self) -> Result<Option<SyncFile>, GfxError> { pub fn clear(
self.clear_with(0.0, 0.0, 0.0, 0.0) &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
) -> Result<Option<SyncFile>, GfxError> {
self.clear_with(acquire_sync, release_sync, 0.0, 0.0, 0.0, 0.0)
} }
pub fn clear_with(&self, r: f32, g: f32, b: f32, a: f32) -> Result<Option<SyncFile>, GfxError> { pub fn clear_with(
self.render(&[], Some(&Color { r, g, b, a })) &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
r: f32,
g: f32,
b: f32,
a: f32,
) -> Result<Option<SyncFile>, GfxError> {
self.render(acquire_sync, release_sync, &[], Some(&Color { r, g, b, a }))
} }
pub fn logical_size(&self, transform: Transform) -> (i32, i32) { pub fn logical_size(&self, transform: Transform) -> (i32, i32) {
@ -302,7 +316,10 @@ impl dyn GfxFramebuffer {
pub fn copy_texture( pub fn copy_texture(
&self, &self,
fb_acquire_sync: AcquireSync,
fb_release_sync: ReleaseSync,
texture: &Rc<dyn GfxTexture>, texture: &Rc<dyn GfxTexture>,
resv: Option<&Rc<dyn BufferResv>>,
acquire_sync: AcquireSync, acquire_sync: AcquireSync,
release_sync: ReleaseSync, release_sync: ReleaseSync,
x: i32, x: i32,
@ -320,16 +337,18 @@ impl dyn GfxFramebuffer {
None, None,
scale, scale,
None, None,
None, resv.cloned(),
acquire_sync, acquire_sync,
release_sync, release_sync,
); );
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(fb_acquire_sync, fb_release_sync, &ops, clear)
} }
pub fn render_custom( pub fn render_custom(
&self, &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
scale: Scale, scale: Scale,
clear: Option<&Color>, clear: Option<&Color>,
f: &mut dyn FnMut(&mut RendererBase), f: &mut dyn FnMut(&mut RendererBase),
@ -337,7 +356,7 @@ impl dyn GfxFramebuffer {
let mut ops = vec![]; let mut ops = vec![];
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None); let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
f(&mut renderer); f(&mut renderer);
self.render(&ops, clear) self.render(acquire_sync, release_sync, &ops, clear)
} }
pub fn create_render_pass( pub fn create_render_pass(
@ -366,12 +385,19 @@ impl dyn GfxFramebuffer {
) )
} }
pub fn perform_render_pass(&self, pass: &GfxRenderPass) -> Result<Option<SyncFile>, GfxError> { pub fn perform_render_pass(
self.render(&pass.ops, pass.clear.as_ref()) &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
pass: &GfxRenderPass,
) -> Result<Option<SyncFile>, GfxError> {
self.render(acquire_sync, release_sync, &pass.ops, pass.clear.as_ref())
} }
pub fn render_output( pub fn render_output(
&self, &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
node: &OutputNode, node: &OutputNode,
state: &State, state: &State,
cursor_rect: Option<Rect>, cursor_rect: Option<Rect>,
@ -379,6 +405,8 @@ impl dyn GfxFramebuffer {
render_hardware_cursor: bool, render_hardware_cursor: bool,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
self.render_node( self.render_node(
acquire_sync,
release_sync,
node, node,
state, state,
cursor_rect, cursor_rect,
@ -392,6 +420,8 @@ impl dyn GfxFramebuffer {
pub fn render_node( pub fn render_node(
&self, &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
node: &dyn Node, node: &dyn Node,
state: &State, state: &State,
cursor_rect: Option<Rect>, cursor_rect: Option<Rect>,
@ -412,11 +442,13 @@ impl dyn GfxFramebuffer {
transform, transform,
None, None,
); );
self.perform_render_pass(&pass) self.perform_render_pass(acquire_sync, release_sync, &pass)
} }
pub fn render_hardware_cursor( pub fn render_hardware_cursor(
&self, &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
cursor: &dyn Cursor, cursor: &dyn Cursor,
state: &State, state: &State,
scale: Scale, scale: Scale,
@ -433,7 +465,7 @@ impl dyn GfxFramebuffer {
}, },
}; };
cursor.render_hardware_cursor(&mut renderer); cursor.render_hardware_cursor(&mut renderer);
self.render(&ops, Some(&Color::TRANSPARENT)) self.render(acquire_sync, release_sync, &ops, Some(&Color::TRANSPARENT))
} }
} }

View file

@ -73,6 +73,7 @@ use {
ReleaseSync, SyncFile, ReleaseSync, SyncFile,
}, },
gfx_apis::gl::{ gfx_apis::gl::{
egl::image::EglImage,
gl::texture::image_target, gl::texture::image_target,
renderer::{ renderer::{
context::{GlRenderContext, TexCopyType, TexSourceType}, context::{GlRenderContext, TexCopyType, TexSourceType},
@ -328,7 +329,7 @@ fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx)); assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx));
let gles = ctx.ctx.dpy.gles; let gles = ctx.ctx.dpy.gles;
unsafe { unsafe {
handle_explicit_sync(ctx, texture, &tex.acquire_sync); handle_explicit_sync(ctx, texture.gl.img.as_ref(), &tex.acquire_sync);
(gles.glActiveTexture)(GL_TEXTURE0); (gles.glActiveTexture)(GL_TEXTURE0);
@ -395,7 +396,7 @@ fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
} }
} }
fn handle_explicit_sync(ctx: &GlRenderContext, texture: &Texture, sync: &AcquireSync) { fn handle_explicit_sync(ctx: &GlRenderContext, img: Option<&Rc<EglImage>>, sync: &AcquireSync) {
let sync_file = match sync { let sync_file = match sync {
AcquireSync::None | AcquireSync::Implicit | AcquireSync::Unnecessary => return, AcquireSync::None | AcquireSync::Implicit | AcquireSync::Unnecessary => return,
AcquireSync::SyncFile { sync_file } => sync_file, AcquireSync::SyncFile { sync_file } => sync_file,
@ -417,7 +418,7 @@ fn handle_explicit_sync(ctx: &GlRenderContext, texture: &Texture, sync: &Acquire
}; };
sync.wait(); sync.wait();
} else { } else {
if let Some(img) = &texture.gl.img { if let Some(img) = img {
if let Err(e) = img.dmabuf.import_sync_file(DMA_BUF_SYNC_READ, &sync_file) { if let Err(e) = img.dmabuf.import_sync_file(DMA_BUF_SYNC_READ, &sync_file) {
log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e)); log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e));
} }

View file

@ -1,12 +1,13 @@
use { use {
crate::{ crate::{
format::Format, format::Format,
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, SyncFile}, gfx_api::{AcquireSync, GfxApiOpt, GfxError, GfxFramebuffer, ReleaseSync, SyncFile},
gfx_apis::gl::{ gfx_apis::gl::{
gl::{ gl::{
frame_buffer::GlFrameBuffer, frame_buffer::GlFrameBuffer,
sys::{GL_COLOR_BUFFER_BIT, GL_FRAMEBUFFER}, sys::{GL_COLOR_BUFFER_BIT, GL_FRAMEBUFFER},
}, },
handle_explicit_sync,
renderer::context::GlRenderContext, renderer::context::GlRenderContext,
run_ops, run_ops,
sys::{GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, sys::{GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
@ -69,11 +70,13 @@ impl Framebuffer {
pub fn render( pub fn render(
&self, &self,
acquire_sync: AcquireSync,
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<Option<SyncFile>, RenderError> { ) -> Result<Option<SyncFile>, RenderError> {
let gles = self.ctx.ctx.dpy.gles; let gles = self.ctx.ctx.dpy.gles;
self.ctx.ctx.with_current(|| { self.ctx.ctx.with_current(|| {
handle_explicit_sync(&self.ctx, self.gl.rb._img.as_ref(), &acquire_sync);
unsafe { unsafe {
(gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo); (gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo);
(gles.glViewport)(0, 0, self.gl.width, self.gl.height); (gles.glViewport)(0, 0, self.gl.width, self.gl.height);
@ -101,10 +104,12 @@ impl GfxFramebuffer for Framebuffer {
fn render( fn render(
&self, &self,
acquire_sync: AcquireSync,
_release_sync: ReleaseSync,
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
self.render(ops, clear).map_err(|e| e.into()) self.render(acquire_sync, ops, clear).map_err(|e| e.into())
} }
fn copy_to_shm( fn copy_to_shm(

View file

@ -3,9 +3,9 @@ use {
clientmem::ClientMemOffset, clientmem::ClientMemOffset,
format::Format, format::Format,
gfx_api::{ gfx_api::{
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, AsyncShmGfxTextureUploadCancellable, AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback,
GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture, PendingShmUpload, AsyncShmGfxTextureUploadCancellable, GfxApiOpt, GfxError, GfxFramebuffer, GfxImage,
ShmGfxTexture, SyncFile, GfxTexture, PendingShmUpload, ReleaseSync, ShmGfxTexture, SyncFile,
}, },
gfx_apis::vulkan::{ gfx_apis::vulkan::{
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanModifierLimits, allocator::VulkanAllocation, device::VulkanDevice, format::VulkanModifierLimits,
@ -465,11 +465,13 @@ impl GfxFramebuffer for VulkanImage {
fn render( fn render(
&self, &self,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
self.renderer self.renderer
.execute(self, ops, clear) .execute(self, acquire_sync, release_sync, ops, clear)
.map_err(|e| e.into()) .map_err(|e| e.into())
} }

View file

@ -643,7 +643,11 @@ impl VulkanRenderer {
} }
} }
fn create_wait_semaphores(&self, fb: &VulkanImage) -> Result<(), VulkanError> { fn create_wait_semaphores(
&self,
fb: &VulkanImage,
fb_acquire_sync: &AcquireSync,
) -> Result<(), VulkanError> {
zone!("create_wait_semaphores"); zone!("create_wait_semaphores");
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
let memory = &mut *memory; let memory = &mut *memory;
@ -699,13 +703,13 @@ impl VulkanRenderer {
&mut memory.wait_semaphore_infos, &mut memory.wait_semaphore_infos,
&mut memory.wait_semaphores, &mut memory.wait_semaphores,
fb, fb,
&AcquireSync::Implicit, fb_acquire_sync,
DMA_BUF_SYNC_WRITE, DMA_BUF_SYNC_WRITE,
)?; )?;
Ok(()) Ok(())
} }
fn import_release_semaphore(&self, fb: &VulkanImage) { fn import_release_semaphore(&self, fb: &VulkanImage, fb_release_sync: ReleaseSync) {
zone!("import_release_semaphore"); zone!("import_release_semaphore");
let memory = &mut *self.memory.borrow_mut(); let memory = &mut *self.memory.borrow_mut();
let sync_file = match memory.release_sync_file.as_ref() { let sync_file = match memory.release_sync_file.as_ref() {
@ -736,7 +740,7 @@ impl VulkanRenderer {
DMA_BUF_SYNC_READ, DMA_BUF_SYNC_READ,
); );
} }
import(fb, ReleaseSync::Implicit, None, DMA_BUF_SYNC_WRITE); import(fb, fb_release_sync, None, DMA_BUF_SYNC_WRITE);
} }
fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> { fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
@ -838,7 +842,10 @@ impl VulkanRenderer {
)?; )?;
(&*tmp_tex as &dyn GfxFramebuffer) (&*tmp_tex as &dyn GfxFramebuffer)
.copy_texture( .copy_texture(
AcquireSync::None,
ReleaseSync::None,
&(tex.clone() as _), &(tex.clone() as _),
None,
AcquireSync::None, AcquireSync::None,
ReleaseSync::None, ReleaseSync::None,
x, x,
@ -992,11 +999,13 @@ impl VulkanRenderer {
pub fn execute( pub fn execute(
self: &Rc<Self>, self: &Rc<Self>,
fb: &VulkanImage, fb: &VulkanImage,
fb_acquire_sync: AcquireSync,
fb_release_sync: ReleaseSync,
opts: &[GfxApiOpt], opts: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<Option<SyncFile>, VulkanError> { ) -> Result<Option<SyncFile>, VulkanError> {
zone!("execute"); zone!("execute");
let res = self.try_execute(fb, opts, clear); let res = self.try_execute(fb, fb_acquire_sync, fb_release_sync, opts, clear);
let sync_file = { let sync_file = {
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
memory.textures.clear(); memory.textures.clear();
@ -1032,6 +1041,8 @@ impl VulkanRenderer {
fn try_execute( fn try_execute(
self: &Rc<Self>, self: &Rc<Self>,
fb: &VulkanImage, fb: &VulkanImage,
fb_acquire_sync: AcquireSync,
fb_release_sync: ReleaseSync,
opts: &[GfxApiOpt], opts: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<(), VulkanError> { ) -> Result<(), VulkanError> {
@ -1047,9 +1058,9 @@ impl VulkanRenderer {
self.copy_bridge_to_dmabuf(buf.buffer, fb); self.copy_bridge_to_dmabuf(buf.buffer, fb);
self.final_barriers(buf.buffer, fb); self.final_barriers(buf.buffer, fb);
self.end_command_buffer(buf.buffer)?; self.end_command_buffer(buf.buffer)?;
self.create_wait_semaphores(fb)?; self.create_wait_semaphores(fb, &fb_acquire_sync)?;
self.submit(buf.buffer)?; self.submit(buf.buffer)?;
self.import_release_semaphore(fb); self.import_release_semaphore(fb, fb_release_sync);
self.store_layouts(fb); self.store_layouts(fb);
self.create_pending_frame(buf); self.create_pending_frame(buf);
Ok(()) Ok(())

View file

@ -3,7 +3,9 @@ use {
allocator::{AllocatorError, BufferObject, BO_USE_LINEAR, BO_USE_RENDERING}, allocator::{AllocatorError, BufferObject, BO_USE_LINEAR, BO_USE_RENDERING},
client::{Client, ClientError}, client::{Client, ClientError},
format::XRGB8888, format::XRGB8888,
gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture}, gfx_api::{
AcquireSync, BufferResv, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync,
},
ifs::{jay_output::JayOutput, jay_toplevel::JayToplevel, wl_buffer::WlBufferStorage}, ifs::{jay_output::JayOutput, jay_toplevel::JayToplevel, wl_buffer::WlBufferStorage},
leaks::Tracker, leaks::Tracker,
object::{Object, Version}, object::{Object, Version},
@ -189,6 +191,8 @@ impl JayScreencast {
for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() { for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() {
if buffer.free { if buffer.free {
let res = buffer.fb.render_node( let res = buffer.fb.render_node(
AcquireSync::Implicit,
ReleaseSync::Implicit,
tl.tl_as_node(), tl.tl_as_node(),
&self.client.state, &self.client.state,
Some(tl.node_absolute_position()), Some(tl.node_absolute_position()),
@ -298,6 +302,9 @@ impl JayScreencast {
&self, &self,
on: &OutputNode, on: &OutputNode,
texture: &Rc<dyn GfxTexture>, texture: &Rc<dyn GfxTexture>,
resv: Option<&Rc<dyn BufferResv>>,
acquire_sync: &AcquireSync,
release_sync: ReleaseSync,
render_hardware_cursors: bool, render_hardware_cursors: bool,
x_off: i32, x_off: i32,
y_off: i32, y_off: i32,
@ -320,7 +327,12 @@ impl JayScreencast {
if buffer.free { if buffer.free {
let res = self.client.state.perform_screencopy( let res = self.client.state.perform_screencopy(
texture, texture,
resv,
acquire_sync,
release_sync,
&buffer.fb, &buffer.fb,
AcquireSync::Implicit,
ReleaseSync::Implicit,
on.global.pos.get(), on.global.pos.get(),
render_hardware_cursors, render_hardware_cursors,
x_off, x_off,

View file

@ -5,9 +5,10 @@ use {
cpu_worker::CpuWorker, cpu_worker::CpuWorker,
format::{Format, ARGB8888, XRGB8888}, format::{Format, ARGB8888, XRGB8888},
gfx_api::{ gfx_api::{
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FillRect, FramebufferRect, AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FillRect,
GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage, GfxTexture, FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage,
GfxWriteModifier, PendingShmUpload, ResetStatus, ShmGfxTexture, SyncFile, GfxTexture, GfxWriteModifier, PendingShmUpload, ReleaseSync, ResetStatus,
ShmGfxTexture, SyncFile,
}, },
rect::{Rect, Region}, rect::{Rect, Region},
theme::Color, theme::Color,
@ -413,6 +414,8 @@ impl GfxFramebuffer for TestGfxFb {
fn render( fn render(
&self, &self,
_acquire_sync: AcquireSync,
_release_sync: ReleaseSync,
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {

View file

@ -635,13 +635,17 @@ impl WindowData {
return; return;
}; };
let res = buf let res = buf.fb.render_custom(
.fb AcquireSync::Implicit,
.render_custom(self.scale.get(), Some(&Color::from_gray(0)), &mut |r| { ReleaseSync::Implicit,
self.scale.get(),
Some(&Color::from_gray(0)),
&mut |r| {
if let Some(content) = self.content.get() { if let Some(content) = self.content.get() {
content.render_at(r, 0.0, 0.0) content.render_at(r, 0.0, 0.0)
} }
}); },
);
if let Err(e) = res { if let Err(e) = res {
log::error!("Could not render frame: {}", ErrorFmt(e)); log::error!("Could not render frame: {}", ErrorFmt(e));
return; return;

View file

@ -2,7 +2,7 @@ use {
crate::{ crate::{
allocator::{AllocatorError, BufferObject, BufferUsage, BO_USE_RENDERING}, allocator::{AllocatorError, BufferObject, BufferUsage, BO_USE_RENDERING},
format::XRGB8888, format::XRGB8888,
gfx_api::{needs_render_usage, GfxError}, gfx_api::{needs_render_usage, AcquireSync, GfxError, ReleaseSync},
scale::Scale, scale::Scale,
state::State, state::State,
video::drm::DrmError, video::drm::DrmError,
@ -77,6 +77,8 @@ pub fn take_screenshot(
)?; )?;
let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?; let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?;
fb.render_node( fb.render_node(
AcquireSync::Unnecessary,
ReleaseSync::Implicit,
state.root.deref(), state.root.deref(),
state, state,
Some(state.root.extents.get()), Some(state.root.extents.get()),

View file

@ -27,8 +27,8 @@ use {
forker::ForkerProxy, forker::ForkerProxy,
format::Format, format::Format,
gfx_api::{ gfx_api::{
AcquireSync, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync, SampleRect, AcquireSync, BufferResv, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync,
SyncFile, SampleRect, SyncFile,
}, },
gfx_apis::create_gfx_context, gfx_apis::create_gfx_context,
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal}, globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
@ -900,10 +900,14 @@ impl State {
&self, &self,
output: &OutputNode, output: &OutputNode,
fb: &Rc<dyn GfxFramebuffer>, fb: &Rc<dyn GfxFramebuffer>,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
tex: &Rc<dyn GfxTexture>, tex: &Rc<dyn GfxTexture>,
render_hw_cursor: bool, render_hw_cursor: bool,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
let sync_file = fb.render_output( let sync_file = fb.render_output(
acquire_sync,
release_sync,
output, output,
self, self,
Some(output.global.pos.get()), Some(output.global.pos.get()),
@ -911,14 +915,28 @@ impl State {
render_hw_cursor, render_hw_cursor,
)?; )?;
output.latched(); output.latched();
output.perform_screencopies(tex, !render_hw_cursor, 0, 0, None); output.perform_screencopies(
tex,
None,
&AcquireSync::Unnecessary,
ReleaseSync::None,
!render_hw_cursor,
0,
0,
None,
);
Ok(sync_file) Ok(sync_file)
} }
pub fn perform_screencopy( pub fn perform_screencopy(
&self, &self,
src: &Rc<dyn GfxTexture>, src: &Rc<dyn GfxTexture>,
resv: Option<&Rc<dyn BufferResv>>,
acquire_sync: &AcquireSync,
release_sync: ReleaseSync,
target: &Rc<dyn GfxFramebuffer>, target: &Rc<dyn GfxFramebuffer>,
target_acquire_sync: AcquireSync,
target_release_sync: ReleaseSync,
position: Rect, position: Rect,
render_hardware_cursors: bool, render_hardware_cursors: bool,
x_off: i32, x_off: i32,
@ -947,9 +965,9 @@ impl State {
size, size,
Scale::from_int(1), Scale::from_int(1),
None, None,
None, resv.cloned(),
AcquireSync::None, acquire_sync.clone(),
ReleaseSync::Implicit, release_sync,
); );
if render_hardware_cursors { if render_hardware_cursors {
if let Some(cursor_user_group) = self.cursor_user_group_hardware_cursor.get() { if let Some(cursor_user_group) = self.cursor_user_group_hardware_cursor.get() {
@ -963,7 +981,12 @@ impl State {
} }
} }
} }
target.render(&ops, Some(&Color::SOLID_BLACK)) target.render(
target_acquire_sync,
target_release_sync,
&ops,
Some(&Color::SOLID_BLACK),
)
} }
fn have_hardware_cursor(&self) -> bool { fn have_hardware_cursor(&self) -> bool {
@ -980,6 +1003,7 @@ impl State {
pub fn perform_shm_screencopy( pub fn perform_shm_screencopy(
&self, &self,
src: &Rc<dyn GfxTexture>, src: &Rc<dyn GfxTexture>,
acquire_sync: &AcquireSync,
position: Rect, position: Rect,
x_off: i32, x_off: i32,
y_off: i32, y_off: i32,
@ -1011,7 +1035,12 @@ impl State {
.map_err(ShmScreencopyError::CreateTemporaryFb)?; .map_err(ShmScreencopyError::CreateTemporaryFb)?;
self.perform_screencopy( self.perform_screencopy(
src, src,
None,
acquire_sync,
ReleaseSync::None,
&fb, &fb,
AcquireSync::Unnecessary,
ReleaseSync::None,
position, position,
true, true,
x_off - capture.rect.x1(), x_off - capture.rect.x1(),

View file

@ -4,7 +4,7 @@ use {
client::ClientId, client::ClientId,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_api::GfxTexture, gfx_api::{AcquireSync, BufferResv, GfxTexture, ReleaseSync},
ifs::{ ifs::{
jay_output::JayOutput, jay_output::JayOutput,
jay_screencast::JayScreencast, jay_screencast::JayScreencast,
@ -186,6 +186,9 @@ impl OutputNode {
pub fn perform_screencopies( pub fn perform_screencopies(
&self, &self,
tex: &Rc<dyn GfxTexture>, tex: &Rc<dyn GfxTexture>,
resv: Option<&Rc<dyn BufferResv>>,
acquire_sync: &AcquireSync,
release_sync: ReleaseSync,
render_hardware_cursor: bool, render_hardware_cursor: bool,
x_off: i32, x_off: i32,
y_off: i32, y_off: i32,
@ -196,15 +199,37 @@ impl OutputNode {
return; return;
} }
} }
self.perform_wlr_screencopies(tex, render_hardware_cursor, x_off, y_off, size); self.perform_wlr_screencopies(
tex,
resv,
acquire_sync,
release_sync,
render_hardware_cursor,
x_off,
y_off,
size,
);
for sc in self.screencasts.lock().values() { for sc in self.screencasts.lock().values() {
sc.copy_texture(self, tex, render_hardware_cursor, x_off, y_off, size); sc.copy_texture(
self,
tex,
resv,
acquire_sync,
release_sync,
render_hardware_cursor,
x_off,
y_off,
size,
);
} }
} }
pub fn perform_wlr_screencopies( pub fn perform_wlr_screencopies(
&self, &self,
tex: &Rc<dyn GfxTexture>, tex: &Rc<dyn GfxTexture>,
resv: Option<&Rc<dyn BufferResv>>,
acquire_sync: &AcquireSync,
release_sync: ReleaseSync,
render_hardware_cursors: bool, render_hardware_cursors: bool,
x_off: i32, x_off: i32,
y_off: i32, y_off: i32,
@ -232,6 +257,7 @@ impl OutputNode {
WlBufferStorage::Shm { mem, stride } => { WlBufferStorage::Shm { mem, stride } => {
let res = self.state.perform_shm_screencopy( let res = self.state.perform_shm_screencopy(
tex, tex,
acquire_sync,
self.global.pos.get(), self.global.pos.get(),
x_off, x_off,
y_off, y_off,
@ -259,7 +285,12 @@ impl OutputNode {
}; };
let res = self.state.perform_screencopy( let res = self.state.perform_screencopy(
tex, tex,
resv,
acquire_sync,
release_sync,
&fb, &fb,
AcquireSync::Implicit,
ReleaseSync::Implicit,
self.global.pos.get(), self.global.pos.get(),
render_hardware_cursors, render_hardware_cursors,
x_off - capture.rect.x1(), x_off - capture.rect.x1(),