1
0
Fork 0
forked from wry/wry

state: split rendering helpers

This commit is contained in:
kossLAN 2026-05-29 19:41:55 -04:00
parent 19c2265400
commit 27750a31c4
No known key found for this signature in database
2 changed files with 217 additions and 203 deletions

212
src/state/rendering.rs Normal file
View file

@ -0,0 +1,212 @@
use {
crate::{
clientmem::ClientMemOffset,
cmm::{cmm_description::ColorDescription, cmm_render_intent::RenderIntent},
fixed::Fixed,
format::Format,
gfx_api::{
AcquireSync, AlphaMode, BufferResv, FdSync, GfxBlendBuffer, GfxError,
GfxFramebuffer, GfxTexture, PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD,
SampleRect,
},
ifs::zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1,
rect::{Rect, Region},
renderer::Renderer,
scale::Scale,
theme::Color,
tree::{OutputNode, Transform},
},
std::rc::Rc,
thiserror::Error,
};
use super::State;
impl State {
pub fn present_output(
&self,
output: &OutputNode,
fb: &Rc<dyn GfxFramebuffer>,
cd: &Rc<ColorDescription>,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
tex: &Rc<dyn GfxTexture>,
render_hw_cursor: bool,
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
blend_cd: &Rc<ColorDescription>,
) -> Result<Option<FdSync>, GfxError> {
let sync = fb.render_output(
acquire_sync,
release_sync,
cd,
output,
self,
Some(output.global.pos.get()),
output.global.persistent.scale.get(),
render_hw_cursor,
true,
blend_buffer,
blend_cd,
)?;
output.latched(false);
output.perform_screencopies(
tex,
cd,
None,
&AcquireSync::Unnecessary,
ReleaseSync::None,
!render_hw_cursor,
0,
0,
None,
);
Ok(sync)
}
pub fn perform_screencopy(
&self,
src: &Rc<dyn GfxTexture>,
resv: Option<&Rc<dyn BufferResv>>,
acquire_sync: &AcquireSync,
release_sync: ReleaseSync,
src_cd: &Rc<ColorDescription>,
target: &Rc<dyn GfxFramebuffer>,
target_acquire_sync: AcquireSync,
target_release_sync: ReleaseSync,
target_transform: Transform,
target_cd: &Rc<ColorDescription>,
position: Rect,
render_hardware_cursors: bool,
x_off: i32,
y_off: i32,
size: Option<(i32, i32)>,
transform: Transform,
scale: Scale,
) -> Result<Option<FdSync>, GfxError> {
let mut ops = vec![];
let mut renderer = Renderer {
base: target.renderer_base(&mut ops, scale, target_transform),
state: self,
logical_extents: position.at_point(0, 0),
pixel_extents: {
let (width, height) = target.logical_size(target_transform);
Rect::new_sized_saturating(0, 0, width, height)
},
stretch: None,
corner_radius: None,
};
let mut sample_rect = SampleRect::identity();
sample_rect.buffer_transform = transform;
renderer.base.render_texture(
src,
None,
x_off,
y_off,
Some(sample_rect),
size,
scale,
None,
resv.cloned(),
acquire_sync.clone(),
release_sync,
false,
src_cd,
RenderIntent::Perceptual,
AlphaMode::PremultipliedElectrical,
);
if render_hardware_cursors
&& let Some(cursor_user_group) = self.cursor_user_group_hardware_cursor.get()
&& let Some(cursor_user) = cursor_user_group.active()
&& let Some(cursor) = cursor_user.get()
{
let (mut x, mut y) = cursor_user.position();
x = x + x_off - Fixed::from_int(position.x1());
y = y + y_off - Fixed::from_int(position.y1());
cursor.render(&mut renderer, x, y);
}
target.render(
target_acquire_sync,
target_release_sync,
target_cd,
&ops,
Some(&Color::SOLID_BLACK),
&target_cd.linear,
None,
target_cd,
)
}
pub fn perform_shm_screencopy(
&self,
src: &Rc<dyn GfxTexture>,
src_cd: &Rc<ColorDescription>,
acquire_sync: &AcquireSync,
position: Rect,
x_off: i32,
y_off: i32,
size: Option<(i32, i32)>,
capture: &Rc<ZwlrScreencopyFrameV1>,
mem: &Rc<ClientMemOffset>,
stride: i32,
format: &'static Format,
transform: Transform,
scale: Scale,
) -> Result<Option<PendingShmTransfer>, ShmScreencopyError> {
let Some(ctx) = self.render_ctx.get() else {
return Err(ShmScreencopyError::NoRenderContext);
};
let fb = ctx
.clone()
.create_internal_fb(
&self.cpu_worker,
capture.rect.width(),
capture.rect.height(),
stride,
format,
)
.map_err(ShmScreencopyError::CreateTemporaryFb)?;
self.perform_screencopy(
src,
None,
acquire_sync,
ReleaseSync::None,
src_cd,
&(fb.clone() as Rc<dyn GfxFramebuffer>),
AcquireSync::Unnecessary,
ReleaseSync::None,
transform,
self.color_manager.srgb_gamma22(),
position,
true,
x_off - capture.rect.x1(),
y_off - capture.rect.y1(),
size,
transform,
scale,
)
.map_err(ShmScreencopyError::CopyToTemporary)?;
let staging = ctx.create_staging_buffer(fb.staging_size(), STAGING_DOWNLOAD);
let pending = fb
.download(
&staging,
capture.clone(),
mem.clone(),
Region::new(capture.rect.at_point(0, 0)),
)
.map_err(ShmScreencopyError::ReadPixels)?;
Ok(pending)
}
}
#[derive(Debug, Error)]
pub enum ShmScreencopyError {
#[error("There is no render context")]
NoRenderContext,
#[error("Could not create a bridge framebuffer")]
CreateTemporaryFb(#[source] GfxError),
#[error("Could not copy texture to bridge framebuffer")]
CopyToTemporary(#[source] GfxError),
#[error("Could not read pixels from texture")]
ReadPixels(#[source] GfxError),
}