1
0
Fork 0
forked from wry/wry

gfx: add GfxBlendBuffer

This commit is contained in:
Julian Orth 2025-02-20 18:29:48 +01:00
parent 446779ab83
commit a7cb2ee42a
14 changed files with 107 additions and 23 deletions

View file

@ -749,6 +749,7 @@ impl MetalConnector {
ReleaseSync::Explicit, ReleaseSync::Explicit,
&latched.pass, &latched.pass,
&latched.damage, &latched.damage,
None,
) )
.map_err(MetalError::RenderFrame)?; .map_err(MetalError::RenderFrame)?;
sync_file = buffer.copy_to_dev(sf)?; sync_file = buffer.copy_to_dev(sf)?;

View file

@ -755,6 +755,7 @@ impl XBackend {
ReleaseSync::Implicit, ReleaseSync::Implicit,
&image.tex.get(), &image.tex.get(),
true, true,
None,
); );
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));

View file

@ -267,6 +267,8 @@ pub enum ResetStatus {
Other(u32), Other(u32),
} }
pub trait GfxBlendBuffer: Debug {}
pub trait GfxFramebuffer: Debug { pub trait GfxFramebuffer: Debug {
fn physical_size(&self) -> (i32, i32); fn physical_size(&self) -> (i32, i32);
@ -277,6 +279,7 @@ pub trait GfxFramebuffer: Debug {
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
region: &Region, region: &Region,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError>; ) -> Result<Option<SyncFile>, GfxError>;
fn format(&self) -> &'static Format; fn format(&self) -> &'static Format;
@ -304,9 +307,16 @@ impl dyn GfxFramebuffer {
release_sync: ReleaseSync, release_sync: ReleaseSync,
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
self.clone() self.clone().render_with_region(
.render_with_region(acquire_sync, release_sync, ops, clear, &self.full_region()) acquire_sync,
release_sync,
ops,
clear,
&self.full_region(),
blend_buffer,
)
} }
fn full_region(&self) -> Region { fn full_region(&self) -> Region {
@ -331,7 +341,13 @@ impl dyn GfxFramebuffer {
b: f32, b: f32,
a: f32, a: f32,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, 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) { pub fn logical_size(&self, transform: Transform) -> (i32, i32) {
@ -376,7 +392,7 @@ impl dyn GfxFramebuffer {
false, false,
); );
let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT); 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( pub fn render_custom(
@ -385,12 +401,13 @@ impl dyn GfxFramebuffer {
release_sync: ReleaseSync, release_sync: ReleaseSync,
scale: Scale, scale: Scale,
clear: Option<&Color>, clear: Option<&Color>,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
f: &mut dyn FnMut(&mut RendererBase), f: &mut dyn FnMut(&mut RendererBase),
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
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(acquire_sync, release_sync, &ops, clear) self.render(acquire_sync, release_sync, &ops, clear, blend_buffer)
} }
pub fn create_render_pass( pub fn create_render_pass(
@ -427,6 +444,7 @@ impl dyn GfxFramebuffer {
release_sync: ReleaseSync, release_sync: ReleaseSync,
pass: &GfxRenderPass, pass: &GfxRenderPass,
region: &Region, region: &Region,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
self.clone().render_with_region( self.clone().render_with_region(
acquire_sync, acquire_sync,
@ -434,6 +452,7 @@ impl dyn GfxFramebuffer {
&pass.ops, &pass.ops,
pass.clear.as_ref(), pass.clear.as_ref(),
region, region,
blend_buffer,
) )
} }
@ -447,6 +466,7 @@ impl dyn GfxFramebuffer {
scale: Scale, scale: Scale,
render_hardware_cursor: bool, render_hardware_cursor: bool,
fill_black_in_grace_period: bool, fill_black_in_grace_period: bool,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
self.render_node( self.render_node(
acquire_sync, acquire_sync,
@ -460,6 +480,7 @@ impl dyn GfxFramebuffer {
node.has_fullscreen(), node.has_fullscreen(),
fill_black_in_grace_period, fill_black_in_grace_period,
node.global.persistent.transform.get(), node.global.persistent.transform.get(),
blend_buffer,
) )
} }
@ -476,6 +497,7 @@ impl dyn GfxFramebuffer {
black_background: bool, black_background: bool,
fill_black_in_grace_period: bool, fill_black_in_grace_period: bool,
transform: Transform, transform: Transform,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
let pass = self.create_render_pass( let pass = self.create_render_pass(
node, node,
@ -489,7 +511,13 @@ impl dyn GfxFramebuffer {
transform, transform,
None, 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( pub fn render_hardware_cursor(
@ -512,7 +540,13 @@ impl dyn GfxFramebuffer {
}, },
}; };
cursor.render_hardware_cursor(&mut renderer); 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)) Rc::new(Dummy(size))
} }
#[expect(dead_code)]
fn acquire_blend_buffer(
&self,
width: i32,
height: i32,
) -> Result<Rc<dyn GfxBlendBuffer>, GfxError>;
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

View file

@ -197,6 +197,8 @@ enum RenderError {
UnsupportedShmFormat(&'static str), UnsupportedShmFormat(&'static str),
#[error("Could not access the client memory")] #[error("Could not access the client memory")]
AccessFailed(#[source] Box<dyn Error + Sync + Send>), AccessFailed(#[source] Box<dyn Error + Sync + Send>),
#[error("OpenGL does not support blend buffers")]
NoBlendBuffer,
} }
#[derive(Default)] #[derive(Default)]

View file

@ -4,8 +4,8 @@ use {
cpu_worker::CpuWorker, cpu_worker::CpuWorker,
format::{Format, XRGB8888}, format::{Format, XRGB8888},
gfx_api::{ gfx_api::{
AsyncShmGfxTexture, BufferResvUser, GfxContext, GfxError, GfxFormat, GfxFramebuffer, AsyncShmGfxTexture, BufferResvUser, GfxBlendBuffer, GfxContext, GfxError, GfxFormat,
GfxImage, GfxInternalFramebuffer, ResetStatus, ShmGfxTexture, GfxFramebuffer, GfxImage, GfxInternalFramebuffer, ResetStatus, ShmGfxTexture,
}, },
gfx_apis::gl::{ gfx_apis::gl::{
GfxGlState, RenderError, Texture, GfxGlState, RenderError, Texture,
@ -339,4 +339,12 @@ impl GfxContext for GlRenderContext {
fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>> { fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>> {
Some(&self.sync_ctx) Some(&self.sync_ctx)
} }
fn acquire_blend_buffer(
&self,
_width: i32,
_height: i32,
) -> Result<Rc<dyn GfxBlendBuffer>, GfxError> {
Err(GfxError(Box::new(RenderError::NoBlendBuffer)))
}
} }

View file

@ -2,9 +2,9 @@ use {
crate::{ crate::{
format::Format, format::Format,
gfx_api::{ gfx_api::{
AcquireSync, AsyncShmGfxTextureCallback, GfxApiOpt, GfxError, GfxFramebuffer, AcquireSync, AsyncShmGfxTextureCallback, GfxApiOpt, GfxBlendBuffer, GfxError,
GfxInternalFramebuffer, GfxStagingBuffer, PendingShmTransfer, ReleaseSync, ShmMemory, GfxFramebuffer, GfxInternalFramebuffer, GfxStagingBuffer, PendingShmTransfer,
SyncFile, ReleaseSync, ShmMemory, SyncFile,
}, },
gfx_apis::gl::{ gfx_apis::gl::{
RenderError, RenderError,
@ -106,6 +106,7 @@ impl GfxFramebuffer for Framebuffer {
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
_region: &Region, _region: &Region,
_blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
(*self) (*self)
.render(acquire_sync, ops, clear) .render(acquire_sync, ops, clear)

View file

@ -24,9 +24,9 @@ use {
cpu_worker::{CpuWorker, jobs::read_write::ReadWriteJobError}, cpu_worker::{CpuWorker, jobs::read_write::ReadWriteJobError},
format::Format, format::Format,
gfx_api::{ gfx_api::{
AsyncShmGfxTexture, GfxContext, GfxError, GfxFormat, GfxImage, GfxInternalFramebuffer, AsyncShmGfxTexture, GfxBlendBuffer, GfxContext, GfxError, GfxFormat, GfxImage,
GfxStagingBuffer, ResetStatus, STAGING_DOWNLOAD, STAGING_UPLOAD, ShmGfxTexture, GfxInternalFramebuffer, GfxStagingBuffer, ResetStatus, STAGING_DOWNLOAD,
StagingBufferUsecase, STAGING_UPLOAD, ShmGfxTexture, StagingBufferUsecase,
}, },
gfx_apis::vulkan::{ gfx_apis::vulkan::{
image::VulkanImageMemory, instance::VulkanInstance, renderer::VulkanRenderer, image::VulkanImageMemory, instance::VulkanInstance, renderer::VulkanRenderer,
@ -204,6 +204,8 @@ pub enum VulkanError {
UndefinedContents, UndefinedContents,
#[error("The framebuffer is being used by the transfer queue")] #[error("The framebuffer is being used by the transfer queue")]
BusyInTransfer, BusyInTransfer,
#[error("Vulkan does not support blend buffers")]
NoBlendBuffer,
} }
impl From<VulkanError> for GfxError { impl From<VulkanError> for GfxError {
@ -350,6 +352,14 @@ impl GfxContext for Context {
.device .device
.create_staging_shell(size as u64, upload, download) .create_staging_shell(size as u64, upload, download)
} }
fn acquire_blend_buffer(
&self,
_width: i32,
_height: i32,
) -> Result<Rc<dyn GfxBlendBuffer>, GfxError> {
Err(GfxError(Box::new(VulkanError::NoBlendBuffer)))
}
} }
impl Drop for Context { impl Drop for Context {

View file

@ -3,9 +3,9 @@ use {
format::Format, format::Format,
gfx_api::{ gfx_api::{
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback,
AsyncShmGfxTextureTransferCancellable, GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, AsyncShmGfxTextureTransferCancellable, GfxApiOpt, GfxBlendBuffer, GfxError,
GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture, PendingShmTransfer, ReleaseSync, GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture,
ShmGfxTexture, ShmMemory, SyncFile, PendingShmTransfer, ReleaseSync, ShmGfxTexture, ShmMemory, SyncFile,
}, },
gfx_apis::vulkan::{ gfx_apis::vulkan::{
VulkanError, allocator::VulkanAllocation, device::VulkanDevice, VulkanError, allocator::VulkanAllocation, device::VulkanDevice,
@ -539,6 +539,7 @@ impl GfxFramebuffer for VulkanImage {
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
region: &Region, region: &Region,
_blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
self.renderer self.renderer
.execute(&self, acquire_sync, release_sync, ops, clear, region) .execute(&self, acquire_sync, release_sync, ops, clear, region)

View file

@ -245,6 +245,7 @@ impl ExtImageCopyCaptureFrameV1 {
true, true,
false, false,
jay_config::video::Transform::None, jay_config::video::Transform::None,
None,
) )
}); });
} }

View file

@ -202,6 +202,7 @@ impl JayScreencast {
false, false,
false, false,
Transform::None, Transform::None,
None,
); );
match res { match res {
Ok(_) => { Ok(_) => {

View file

@ -5,9 +5,10 @@ use {
format::{ARGB8888, Format, XRGB8888}, format::{ARGB8888, Format, XRGB8888},
gfx_api::{ gfx_api::{
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FillRect, AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FillRect,
FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage, FramebufferRect, GfxApiOpt, GfxBlendBuffer, GfxContext, GfxError, GfxFormat,
GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture, GfxWriteModifier, GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture,
PendingShmTransfer, ReleaseSync, ResetStatus, ShmGfxTexture, ShmMemory, SyncFile, GfxWriteModifier, PendingShmTransfer, ReleaseSync, ResetStatus, ShmGfxTexture,
ShmMemory, SyncFile,
}, },
rect::{Rect, Region}, rect::{Rect, Region},
theme::Color, theme::Color,
@ -37,6 +38,8 @@ enum TestGfxError {
ImportDmaBuf(#[source] AllocatorError), ImportDmaBuf(#[source] AllocatorError),
#[error("Could not access the client memory")] #[error("Could not access the client memory")]
AccessFailed(#[source] Box<dyn Error + Sync + Send>), AccessFailed(#[source] Box<dyn Error + Sync + Send>),
#[error("Text API does not support blend buffers")]
NoBlendBuffer,
} }
impl From<TestGfxError> for GfxError { impl From<TestGfxError> for GfxError {
@ -189,6 +192,14 @@ impl GfxContext for TestGfxCtx {
fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>> { fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>> {
None None
} }
fn acquire_blend_buffer(
&self,
_width: i32,
_height: i32,
) -> Result<Rc<dyn GfxBlendBuffer>, GfxError> {
Err(GfxError(Box::new(TestGfxError::NoBlendBuffer)))
}
} }
enum TestGfxImage { enum TestGfxImage {
@ -383,6 +394,7 @@ impl GfxFramebuffer for TestGfxFb {
ops: &[GfxApiOpt], ops: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
_region: &Region, _region: &Region,
_blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
let fb_points = |width: i32, height: i32, rect: &FramebufferRect| { let fb_points = |width: i32, height: i32, rect: &FramebufferRect| {
let points = rect.to_points(); let points = rect.to_points();

View file

@ -636,6 +636,7 @@ impl WindowData {
ReleaseSync::Implicit, ReleaseSync::Implicit,
self.scale.get(), self.scale.get(),
Some(&Color::from_gray(0)), Some(&Color::from_gray(0)),
None,
&mut |r| { &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)

View file

@ -88,6 +88,7 @@ pub fn take_screenshot(
false, false,
false, false,
Transform::None, Transform::None,
None,
)?; )?;
let drm = match allocator.drm() { let drm = match allocator.drm() {
Some(drm) => Some(drm.dup_render()?.fd().clone()), Some(drm) => Some(drm.dup_render()?.fd().clone()),

View file

@ -27,8 +27,8 @@ use {
forker::ForkerProxy, forker::ForkerProxy,
format::Format, format::Format,
gfx_api::{ gfx_api::{
AcquireSync, BufferResv, GfxContext, GfxError, GfxFramebuffer, GfxTexture, AcquireSync, BufferResv, GfxBlendBuffer, GfxContext, GfxError, GfxFramebuffer,
PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD, SampleRect, SyncFile, GfxTexture, PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD, SampleRect, SyncFile,
}, },
gfx_apis::create_gfx_context, gfx_apis::create_gfx_context,
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal}, globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
@ -979,6 +979,7 @@ impl State {
release_sync: ReleaseSync, release_sync: ReleaseSync,
tex: &Rc<dyn GfxTexture>, tex: &Rc<dyn GfxTexture>,
render_hw_cursor: bool, render_hw_cursor: bool,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
let sync_file = fb.render_output( let sync_file = fb.render_output(
acquire_sync, acquire_sync,
@ -989,6 +990,7 @@ impl State {
output.global.persistent.scale.get(), output.global.persistent.scale.get(),
render_hw_cursor, render_hw_cursor,
true, true,
blend_buffer,
)?; )?;
output.latched(false); output.latched(false);
output.perform_screencopies( output.perform_screencopies(
@ -1065,6 +1067,7 @@ impl State {
target_release_sync, target_release_sync,
&ops, &ops,
Some(&Color::SOLID_BLACK), Some(&Color::SOLID_BLACK),
None,
) )
} }