state: split rendering helpers
This commit is contained in:
parent
19c2265400
commit
27750a31c4
2 changed files with 217 additions and 203 deletions
208
src/state.rs
208
src/state.rs
|
|
@ -1,5 +1,6 @@
|
|||
mod animations;
|
||||
mod connectors;
|
||||
mod rendering;
|
||||
|
||||
pub(crate) use animations::LayoutAnimationCandidate;
|
||||
pub use connectors::{ConnectorData, DrmDevData, OutputData};
|
||||
|
|
@ -19,11 +20,7 @@ use {
|
|||
backends::dummy::DummyBackend,
|
||||
cli::RunArgs,
|
||||
client::{Client, ClientId, Clients, NUM_CACHED_SERIAL_RANGES, SerialRange},
|
||||
clientmem::ClientMemOffset,
|
||||
cmm::{
|
||||
cmm_description::ColorDescription, cmm_manager::ColorManager,
|
||||
cmm_render_intent::RenderIntent,
|
||||
},
|
||||
cmm::cmm_manager::ColorManager,
|
||||
compositor::LIBEI_SOCKET,
|
||||
config::ConfigProxy,
|
||||
copy_device::CopyDeviceRegistry,
|
||||
|
|
@ -39,14 +36,8 @@ use {
|
|||
ei_client::{EiClient, EiClients},
|
||||
},
|
||||
eventfd_cache::EventfdCache,
|
||||
fixed::Fixed,
|
||||
forker::ForkerProxy,
|
||||
format::Format,
|
||||
gfx_api::{
|
||||
AcquireSync, AlphaMode, BufferResv, FdSync, GfxApi, GfxBlendBuffer, GfxContext,
|
||||
GfxError, GfxFramebuffer, GfxTexture, PendingShmTransfer, ReleaseSync,
|
||||
STAGING_DOWNLOAD, SampleRect,
|
||||
},
|
||||
gfx_api::{GfxApi, GfxContext, GfxError},
|
||||
gfx_apis::create_gfx_context,
|
||||
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
|
||||
icons::Icons,
|
||||
|
|
@ -83,7 +74,6 @@ use {
|
|||
workspace_manager::WorkspaceManagerState,
|
||||
xdg_activation_token_v1::ActivationToken,
|
||||
zwlr_foreign_toplevel_manager_v1::ZwlrForeignToplevelManagerV1,
|
||||
zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1,
|
||||
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1,
|
||||
},
|
||||
io_uring::IoUring,
|
||||
|
|
@ -93,8 +83,7 @@ use {
|
|||
leaks::Tracker,
|
||||
logger::Logger,
|
||||
pr_caps::PrCapsThread,
|
||||
rect::{Rect, Region},
|
||||
renderer::Renderer,
|
||||
rect::Rect,
|
||||
scale::Scale,
|
||||
theme::{BarPosition, Color, Theme, ThemeColor, ThemeSized},
|
||||
time::Time,
|
||||
|
|
@ -102,7 +91,7 @@ use {
|
|||
ContainerNode, ContainerSplit, Direction, DisplayNode, FindTreeUsecase, FloatNode,
|
||||
FoundNode, LatchListener, Node, NodeIds, NodeVisitorBase, OutputNode,
|
||||
PlaceholderNode, TearingMode, TileState, ToplevelData, ToplevelIdentifier,
|
||||
ToplevelNode, ToplevelNodeBase, Transform, VrrMode, WorkspaceDisplayOrder,
|
||||
ToplevelNode, ToplevelNodeBase, VrrMode, WorkspaceDisplayOrder,
|
||||
WorkspaceNode, WorkspaceNodeId, WsMoveConfig, generic_node_visitor, move_ws_to_output,
|
||||
},
|
||||
udmabuf::UdmabufHolder,
|
||||
|
|
@ -145,7 +134,6 @@ use {
|
|||
sync::Arc,
|
||||
time::{Duration, SystemTime},
|
||||
},
|
||||
thiserror::Error,
|
||||
uapi::{OwnedFd, c},
|
||||
};
|
||||
|
||||
|
|
@ -1102,180 +1090,6 @@ 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)
|
||||
}
|
||||
|
||||
pub fn create_seat(self: &Rc<Self>, name: &str) -> Rc<WlSeatGlobal> {
|
||||
let global_name = self.globals.name();
|
||||
let seat = WlSeatGlobal::new(global_name, name, self);
|
||||
|
|
@ -1881,15 +1695,3 @@ impl State {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[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),
|
||||
}
|
||||
|
|
|
|||
212
src/state/rendering.rs
Normal file
212
src/state/rendering.rs
Normal 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),
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue