From a7cb2ee42a123d563ae731fef4848b91e8c8a2d1 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 20 Feb 2025 18:29:48 +0100 Subject: [PATCH] gfx: add GfxBlendBuffer --- src/backends/metal/present.rs | 1 + src/backends/x.rs | 1 + src/gfx_api.rs | 55 ++++++++++++++++--- src/gfx_apis/gl.rs | 2 + src/gfx_apis/gl/renderer/context.rs | 12 +++- src/gfx_apis/gl/renderer/framebuffer.rs | 7 ++- src/gfx_apis/vulkan.rs | 16 +++++- src/gfx_apis/vulkan/image.rs | 7 ++- .../ext_image_copy_capture_frame_v1.rs | 1 + src/ifs/jay_screencast.rs | 1 + src/it/test_gfx_api.rs | 18 +++++- src/portal/ptr_gui.rs | 1 + src/screenshoter.rs | 1 + src/state.rs | 7 ++- 14 files changed, 107 insertions(+), 23 deletions(-) diff --git a/src/backends/metal/present.rs b/src/backends/metal/present.rs index 7bd59489..2fa31861 100644 --- a/src/backends/metal/present.rs +++ b/src/backends/metal/present.rs @@ -749,6 +749,7 @@ impl MetalConnector { ReleaseSync::Explicit, &latched.pass, &latched.damage, + None, ) .map_err(MetalError::RenderFrame)?; sync_file = buffer.copy_to_dev(sf)?; diff --git a/src/backends/x.rs b/src/backends/x.rs index 48ae4284..6bfd3aae 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -755,6 +755,7 @@ impl XBackend { ReleaseSync::Implicit, &image.tex.get(), true, + None, ); if let Err(e) = res { log::error!("Could not render screen: {}", ErrorFmt(e)); diff --git a/src/gfx_api.rs b/src/gfx_api.rs index cc0522ec..ed17464a 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -267,6 +267,8 @@ pub enum ResetStatus { Other(u32), } +pub trait GfxBlendBuffer: Debug {} + pub trait GfxFramebuffer: Debug { fn physical_size(&self) -> (i32, i32); @@ -277,6 +279,7 @@ pub trait GfxFramebuffer: Debug { ops: &[GfxApiOpt], clear: Option<&Color>, region: &Region, + blend_buffer: Option<&Rc>, ) -> Result, GfxError>; fn format(&self) -> &'static Format; @@ -304,9 +307,16 @@ impl dyn GfxFramebuffer { release_sync: ReleaseSync, ops: &[GfxApiOpt], clear: Option<&Color>, + blend_buffer: Option<&Rc>, ) -> Result, GfxError> { - self.clone() - .render_with_region(acquire_sync, release_sync, ops, clear, &self.full_region()) + self.clone().render_with_region( + acquire_sync, + release_sync, + ops, + clear, + &self.full_region(), + blend_buffer, + ) } fn full_region(&self) -> Region { @@ -331,7 +341,13 @@ impl dyn GfxFramebuffer { b: f32, a: f32, ) -> Result, GfxError> { - self.render(acquire_sync, release_sync, &[], Some(&Color { r, g, b, a })) + self.render( + acquire_sync, + release_sync, + &[], + Some(&Color { r, g, b, a }), + None, + ) } pub fn logical_size(&self, transform: Transform) -> (i32, i32) { @@ -376,7 +392,7 @@ impl dyn GfxFramebuffer { false, ); let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT); - self.render(fb_acquire_sync, fb_release_sync, &ops, clear) + self.render(fb_acquire_sync, fb_release_sync, &ops, clear, None) } pub fn render_custom( @@ -385,12 +401,13 @@ impl dyn GfxFramebuffer { release_sync: ReleaseSync, scale: Scale, clear: Option<&Color>, + blend_buffer: Option<&Rc>, f: &mut dyn FnMut(&mut RendererBase), ) -> Result, GfxError> { let mut ops = vec![]; let mut renderer = self.renderer_base(&mut ops, scale, Transform::None); f(&mut renderer); - self.render(acquire_sync, release_sync, &ops, clear) + self.render(acquire_sync, release_sync, &ops, clear, blend_buffer) } pub fn create_render_pass( @@ -427,6 +444,7 @@ impl dyn GfxFramebuffer { release_sync: ReleaseSync, pass: &GfxRenderPass, region: &Region, + blend_buffer: Option<&Rc>, ) -> Result, GfxError> { self.clone().render_with_region( acquire_sync, @@ -434,6 +452,7 @@ impl dyn GfxFramebuffer { &pass.ops, pass.clear.as_ref(), region, + blend_buffer, ) } @@ -447,6 +466,7 @@ impl dyn GfxFramebuffer { scale: Scale, render_hardware_cursor: bool, fill_black_in_grace_period: bool, + blend_buffer: Option<&Rc>, ) -> Result, GfxError> { self.render_node( acquire_sync, @@ -460,6 +480,7 @@ impl dyn GfxFramebuffer { node.has_fullscreen(), fill_black_in_grace_period, node.global.persistent.transform.get(), + blend_buffer, ) } @@ -476,6 +497,7 @@ impl dyn GfxFramebuffer { black_background: bool, fill_black_in_grace_period: bool, transform: Transform, + blend_buffer: Option<&Rc>, ) -> Result, GfxError> { let pass = self.create_render_pass( node, @@ -489,7 +511,13 @@ impl dyn GfxFramebuffer { transform, None, ); - self.perform_render_pass(acquire_sync, release_sync, &pass, &self.full_region()) + self.perform_render_pass( + acquire_sync, + release_sync, + &pass, + &self.full_region(), + blend_buffer, + ) } pub fn render_hardware_cursor( @@ -512,7 +540,13 @@ impl dyn GfxFramebuffer { }, }; cursor.render_hardware_cursor(&mut renderer); - self.render(acquire_sync, release_sync, &ops, Some(&Color::TRANSPARENT)) + self.render( + acquire_sync, + release_sync, + &ops, + Some(&Color::TRANSPARENT), + None, + ) } } @@ -679,6 +713,13 @@ pub trait GfxContext: Debug { } Rc::new(Dummy(size)) } + + #[expect(dead_code)] + fn acquire_blend_buffer( + &self, + width: i32, + height: i32, + ) -> Result, GfxError>; } #[derive(Clone, Debug)] diff --git a/src/gfx_apis/gl.rs b/src/gfx_apis/gl.rs index bb3609bf..f10acb32 100644 --- a/src/gfx_apis/gl.rs +++ b/src/gfx_apis/gl.rs @@ -197,6 +197,8 @@ enum RenderError { UnsupportedShmFormat(&'static str), #[error("Could not access the client memory")] AccessFailed(#[source] Box), + #[error("OpenGL does not support blend buffers")] + NoBlendBuffer, } #[derive(Default)] diff --git a/src/gfx_apis/gl/renderer/context.rs b/src/gfx_apis/gl/renderer/context.rs index 59dbbfe4..cd824c05 100644 --- a/src/gfx_apis/gl/renderer/context.rs +++ b/src/gfx_apis/gl/renderer/context.rs @@ -4,8 +4,8 @@ use { cpu_worker::CpuWorker, format::{Format, XRGB8888}, gfx_api::{ - AsyncShmGfxTexture, BufferResvUser, GfxContext, GfxError, GfxFormat, GfxFramebuffer, - GfxImage, GfxInternalFramebuffer, ResetStatus, ShmGfxTexture, + AsyncShmGfxTexture, BufferResvUser, GfxBlendBuffer, GfxContext, GfxError, GfxFormat, + GfxFramebuffer, GfxImage, GfxInternalFramebuffer, ResetStatus, ShmGfxTexture, }, gfx_apis::gl::{ GfxGlState, RenderError, Texture, @@ -339,4 +339,12 @@ impl GfxContext for GlRenderContext { fn sync_obj_ctx(&self) -> Option<&Rc> { Some(&self.sync_ctx) } + + fn acquire_blend_buffer( + &self, + _width: i32, + _height: i32, + ) -> Result, GfxError> { + Err(GfxError(Box::new(RenderError::NoBlendBuffer))) + } } diff --git a/src/gfx_apis/gl/renderer/framebuffer.rs b/src/gfx_apis/gl/renderer/framebuffer.rs index edd03187..7c0c968d 100644 --- a/src/gfx_apis/gl/renderer/framebuffer.rs +++ b/src/gfx_apis/gl/renderer/framebuffer.rs @@ -2,9 +2,9 @@ use { crate::{ format::Format, gfx_api::{ - AcquireSync, AsyncShmGfxTextureCallback, GfxApiOpt, GfxError, GfxFramebuffer, - GfxInternalFramebuffer, GfxStagingBuffer, PendingShmTransfer, ReleaseSync, ShmMemory, - SyncFile, + AcquireSync, AsyncShmGfxTextureCallback, GfxApiOpt, GfxBlendBuffer, GfxError, + GfxFramebuffer, GfxInternalFramebuffer, GfxStagingBuffer, PendingShmTransfer, + ReleaseSync, ShmMemory, SyncFile, }, gfx_apis::gl::{ RenderError, @@ -106,6 +106,7 @@ impl GfxFramebuffer for Framebuffer { ops: &[GfxApiOpt], clear: Option<&Color>, _region: &Region, + _blend_buffer: Option<&Rc>, ) -> Result, GfxError> { (*self) .render(acquire_sync, ops, clear) diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index d48e9526..6f6c5988 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -24,9 +24,9 @@ use { cpu_worker::{CpuWorker, jobs::read_write::ReadWriteJobError}, format::Format, gfx_api::{ - AsyncShmGfxTexture, GfxContext, GfxError, GfxFormat, GfxImage, GfxInternalFramebuffer, - GfxStagingBuffer, ResetStatus, STAGING_DOWNLOAD, STAGING_UPLOAD, ShmGfxTexture, - StagingBufferUsecase, + AsyncShmGfxTexture, GfxBlendBuffer, GfxContext, GfxError, GfxFormat, GfxImage, + GfxInternalFramebuffer, GfxStagingBuffer, ResetStatus, STAGING_DOWNLOAD, + STAGING_UPLOAD, ShmGfxTexture, StagingBufferUsecase, }, gfx_apis::vulkan::{ image::VulkanImageMemory, instance::VulkanInstance, renderer::VulkanRenderer, @@ -204,6 +204,8 @@ pub enum VulkanError { UndefinedContents, #[error("The framebuffer is being used by the transfer queue")] BusyInTransfer, + #[error("Vulkan does not support blend buffers")] + NoBlendBuffer, } impl From for GfxError { @@ -350,6 +352,14 @@ impl GfxContext for Context { .device .create_staging_shell(size as u64, upload, download) } + + fn acquire_blend_buffer( + &self, + _width: i32, + _height: i32, + ) -> Result, GfxError> { + Err(GfxError(Box::new(VulkanError::NoBlendBuffer))) + } } impl Drop for Context { diff --git a/src/gfx_apis/vulkan/image.rs b/src/gfx_apis/vulkan/image.rs index c0746361..969a008f 100644 --- a/src/gfx_apis/vulkan/image.rs +++ b/src/gfx_apis/vulkan/image.rs @@ -3,9 +3,9 @@ use { format::Format, gfx_api::{ AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, - AsyncShmGfxTextureTransferCancellable, GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, - GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture, PendingShmTransfer, ReleaseSync, - ShmGfxTexture, ShmMemory, SyncFile, + AsyncShmGfxTextureTransferCancellable, GfxApiOpt, GfxBlendBuffer, GfxError, + GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture, + PendingShmTransfer, ReleaseSync, ShmGfxTexture, ShmMemory, SyncFile, }, gfx_apis::vulkan::{ VulkanError, allocator::VulkanAllocation, device::VulkanDevice, @@ -539,6 +539,7 @@ impl GfxFramebuffer for VulkanImage { ops: &[GfxApiOpt], clear: Option<&Color>, region: &Region, + _blend_buffer: Option<&Rc>, ) -> Result, GfxError> { self.renderer .execute(&self, acquire_sync, release_sync, ops, clear, region) diff --git a/src/ifs/ext_image_copy/ext_image_copy_capture_frame_v1.rs b/src/ifs/ext_image_copy/ext_image_copy_capture_frame_v1.rs index 3eb3f7af..ce4ee503 100644 --- a/src/ifs/ext_image_copy/ext_image_copy_capture_frame_v1.rs +++ b/src/ifs/ext_image_copy/ext_image_copy_capture_frame_v1.rs @@ -245,6 +245,7 @@ impl ExtImageCopyCaptureFrameV1 { true, false, jay_config::video::Transform::None, + None, ) }); } diff --git a/src/ifs/jay_screencast.rs b/src/ifs/jay_screencast.rs index a436ec68..bde24705 100644 --- a/src/ifs/jay_screencast.rs +++ b/src/ifs/jay_screencast.rs @@ -202,6 +202,7 @@ impl JayScreencast { false, false, Transform::None, + None, ); match res { Ok(_) => { diff --git a/src/it/test_gfx_api.rs b/src/it/test_gfx_api.rs index e9d9c6b8..6d5be8e7 100644 --- a/src/it/test_gfx_api.rs +++ b/src/it/test_gfx_api.rs @@ -5,9 +5,10 @@ use { format::{ARGB8888, Format, XRGB8888}, gfx_api::{ AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FillRect, - FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage, - GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture, GfxWriteModifier, - PendingShmTransfer, ReleaseSync, ResetStatus, ShmGfxTexture, ShmMemory, SyncFile, + FramebufferRect, GfxApiOpt, GfxBlendBuffer, GfxContext, GfxError, GfxFormat, + GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture, + GfxWriteModifier, PendingShmTransfer, ReleaseSync, ResetStatus, ShmGfxTexture, + ShmMemory, SyncFile, }, rect::{Rect, Region}, theme::Color, @@ -37,6 +38,8 @@ enum TestGfxError { ImportDmaBuf(#[source] AllocatorError), #[error("Could not access the client memory")] AccessFailed(#[source] Box), + #[error("Text API does not support blend buffers")] + NoBlendBuffer, } impl From for GfxError { @@ -189,6 +192,14 @@ impl GfxContext for TestGfxCtx { fn sync_obj_ctx(&self) -> Option<&Rc> { None } + + fn acquire_blend_buffer( + &self, + _width: i32, + _height: i32, + ) -> Result, GfxError> { + Err(GfxError(Box::new(TestGfxError::NoBlendBuffer))) + } } enum TestGfxImage { @@ -383,6 +394,7 @@ impl GfxFramebuffer for TestGfxFb { ops: &[GfxApiOpt], clear: Option<&Color>, _region: &Region, + _blend_buffer: Option<&Rc>, ) -> Result, GfxError> { let fb_points = |width: i32, height: i32, rect: &FramebufferRect| { let points = rect.to_points(); diff --git a/src/portal/ptr_gui.rs b/src/portal/ptr_gui.rs index 635a4fd8..8d3630d9 100644 --- a/src/portal/ptr_gui.rs +++ b/src/portal/ptr_gui.rs @@ -636,6 +636,7 @@ impl WindowData { ReleaseSync::Implicit, self.scale.get(), Some(&Color::from_gray(0)), + None, &mut |r| { if let Some(content) = self.content.get() { content.render_at(r, 0.0, 0.0) diff --git a/src/screenshoter.rs b/src/screenshoter.rs index ad613c9f..657551d4 100644 --- a/src/screenshoter.rs +++ b/src/screenshoter.rs @@ -88,6 +88,7 @@ pub fn take_screenshot( false, false, Transform::None, + None, )?; let drm = match allocator.drm() { Some(drm) => Some(drm.dup_render()?.fd().clone()), diff --git a/src/state.rs b/src/state.rs index 6b0b4a8a..d3b2694d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -27,8 +27,8 @@ use { forker::ForkerProxy, format::Format, gfx_api::{ - AcquireSync, BufferResv, GfxContext, GfxError, GfxFramebuffer, GfxTexture, - PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD, SampleRect, SyncFile, + AcquireSync, BufferResv, GfxBlendBuffer, GfxContext, GfxError, GfxFramebuffer, + GfxTexture, PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD, SampleRect, SyncFile, }, gfx_apis::create_gfx_context, globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal}, @@ -979,6 +979,7 @@ impl State { release_sync: ReleaseSync, tex: &Rc, render_hw_cursor: bool, + blend_buffer: Option<&Rc>, ) -> Result, GfxError> { let sync_file = fb.render_output( acquire_sync, @@ -989,6 +990,7 @@ impl State { output.global.persistent.scale.get(), render_hw_cursor, true, + blend_buffer, )?; output.latched(false); output.perform_screencopies( @@ -1065,6 +1067,7 @@ impl State { target_release_sync, &ops, Some(&Color::SOLID_BLACK), + None, ) }