cosmic-screencopy-v2
This commit is contained in:
parent
973cfed87b
commit
b40d153809
27 changed files with 3647 additions and 2743 deletions
|
|
@ -19,7 +19,9 @@ use smithay::{
|
|||
},
|
||||
reexports::wayland_server::protocol::wl_surface,
|
||||
render_elements,
|
||||
utils::{IsAlive, Logical, Monotonic, Point, Scale, Time, Transform},
|
||||
utils::{
|
||||
Buffer as BufferCoords, IsAlive, Logical, Monotonic, Point, Scale, Size, Time, Transform,
|
||||
},
|
||||
wayland::compositor::{get_role, with_states},
|
||||
};
|
||||
use std::{cell::RefCell, collections::HashMap, io::Read, sync::Mutex, time::Duration};
|
||||
|
|
@ -156,12 +158,12 @@ pub fn draw_surface_cursor<R>(
|
|||
surface: &wl_surface::WlSurface,
|
||||
location: impl Into<Point<i32, Logical>>,
|
||||
scale: impl Into<Scale<f64>>,
|
||||
) -> Vec<CursorRenderElement<R>>
|
||||
) -> Vec<(CursorRenderElement<R>, Point<i32, BufferCoords>)>
|
||||
where
|
||||
R: Renderer + ImportAll,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
{
|
||||
let mut position = location.into();
|
||||
let position = location.into();
|
||||
let scale = scale.into();
|
||||
let h = with_states(&surface, |states| {
|
||||
states
|
||||
|
|
@ -171,8 +173,12 @@ where
|
|||
.lock()
|
||||
.unwrap()
|
||||
.hotspot
|
||||
.to_buffer(
|
||||
1,
|
||||
Transform::Normal,
|
||||
&Size::from((1, 1)), /* Size doesn't matter for Transform::Normal */
|
||||
)
|
||||
});
|
||||
position -= h;
|
||||
|
||||
render_elements_from_surface_tree(
|
||||
renderer,
|
||||
|
|
@ -182,6 +188,9 @@ where
|
|||
1.0,
|
||||
Kind::Cursor,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|elem| (elem, h))
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[profiling::function]
|
||||
|
|
@ -190,7 +199,7 @@ pub fn draw_dnd_icon<R>(
|
|||
surface: &wl_surface::WlSurface,
|
||||
location: impl Into<Point<i32, Logical>>,
|
||||
scale: impl Into<Scale<f64>>,
|
||||
) -> Vec<CursorRenderElement<R>>
|
||||
) -> Vec<WaylandSurfaceRenderElement<R>>
|
||||
where
|
||||
R: Renderer + ImportAll,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
|
|
@ -307,7 +316,7 @@ pub fn draw_cursor<R>(
|
|||
scale: Scale<f64>,
|
||||
time: Time<Monotonic>,
|
||||
draw_default: bool,
|
||||
) -> Vec<CursorRenderElement<R>>
|
||||
) -> Vec<(CursorRenderElement<R>, Point<i32, BufferCoords>)>
|
||||
where
|
||||
R: Renderer + ImportMem + ImportAll,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
|
|
@ -367,20 +376,23 @@ where
|
|||
}
|
||||
};
|
||||
|
||||
let hotspot = Point::<i32, Logical>::from((frame.xhot as i32, frame.yhot as i32)).to_f64();
|
||||
let hotspot = Point::<i32, BufferCoords>::from((frame.xhot as i32, frame.yhot as i32));
|
||||
*state.current_image.borrow_mut() = Some(frame);
|
||||
|
||||
return vec![CursorRenderElement::Static(
|
||||
MemoryRenderBufferRenderElement::from_buffer(
|
||||
renderer,
|
||||
(location - hotspot).to_physical(scale),
|
||||
pointer_image,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Kind::Cursor,
|
||||
)
|
||||
.expect("Failed to import cursor bitmap"),
|
||||
return vec![(
|
||||
CursorRenderElement::Static(
|
||||
MemoryRenderBufferRenderElement::from_buffer(
|
||||
renderer,
|
||||
location.to_physical(scale),
|
||||
pointer_image,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Kind::Cursor,
|
||||
)
|
||||
.expect("Failed to import cursor bitmap"),
|
||||
),
|
||||
hotspot,
|
||||
)];
|
||||
} else {
|
||||
Vec::new()
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ use crate::shell::{CosmicMappedRenderElement, WorkspaceRenderElement};
|
|||
use smithay::{
|
||||
backend::renderer::{
|
||||
element::{
|
||||
surface::WaylandSurfaceRenderElement,
|
||||
utils::{Relocate, RelocateRenderElement},
|
||||
Element, RenderElement, UnderlyingStorage,
|
||||
Element, Id, RenderElement, UnderlyingStorage,
|
||||
},
|
||||
glow::{GlowFrame, GlowRenderer},
|
||||
utils::CommitCounter,
|
||||
Frame, ImportAll, ImportMem, Renderer,
|
||||
},
|
||||
utils::{Buffer as BufferCoords, Physical, Point, Rectangle, Scale},
|
||||
utils::{Buffer as BufferCoords, Logical, Physical, Point, Rectangle, Scale},
|
||||
};
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
|
|
@ -24,8 +26,10 @@ where
|
|||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
Workspace(RelocateRenderElement<WorkspaceRenderElement<R>>),
|
||||
Cursor(CursorRenderElement<R>),
|
||||
Cursor(RelocateRenderElement<CursorRenderElement<R>>),
|
||||
Dnd(WaylandSurfaceRenderElement<R>),
|
||||
MoveGrab(CosmicMappedRenderElement<R>),
|
||||
AdditionalDamage(DamageElement),
|
||||
#[cfg(feature = "debug")]
|
||||
Egui(TextureRenderElement<GlesTexture>),
|
||||
}
|
||||
|
|
@ -36,21 +40,25 @@ where
|
|||
<R as Renderer>::TextureId: 'static,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
fn id(&self) -> &smithay::backend::renderer::element::Id {
|
||||
fn id(&self) -> &Id {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.id(),
|
||||
CosmicElement::Cursor(elem) => elem.id(),
|
||||
CosmicElement::Dnd(elem) => elem.id(),
|
||||
CosmicElement::MoveGrab(elem) => elem.id(),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.id(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.id(),
|
||||
}
|
||||
}
|
||||
|
||||
fn current_commit(&self) -> smithay::backend::renderer::utils::CommitCounter {
|
||||
fn current_commit(&self) -> CommitCounter {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.current_commit(),
|
||||
CosmicElement::Cursor(elem) => elem.current_commit(),
|
||||
CosmicElement::Dnd(elem) => elem.current_commit(),
|
||||
CosmicElement::MoveGrab(elem) => elem.current_commit(),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.current_commit(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.current_commit(),
|
||||
}
|
||||
|
|
@ -60,7 +68,9 @@ where
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.src(),
|
||||
CosmicElement::Cursor(elem) => elem.src(),
|
||||
CosmicElement::Dnd(elem) => elem.src(),
|
||||
CosmicElement::MoveGrab(elem) => elem.src(),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.src(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.src(),
|
||||
}
|
||||
|
|
@ -70,7 +80,9 @@ where
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.geometry(scale),
|
||||
CosmicElement::Cursor(elem) => elem.geometry(scale),
|
||||
CosmicElement::Dnd(elem) => elem.geometry(scale),
|
||||
CosmicElement::MoveGrab(elem) => elem.geometry(scale),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.geometry(scale),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.geometry(scale),
|
||||
}
|
||||
|
|
@ -80,7 +92,9 @@ where
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.location(scale),
|
||||
CosmicElement::Cursor(elem) => elem.location(scale),
|
||||
CosmicElement::Dnd(elem) => elem.location(scale),
|
||||
CosmicElement::MoveGrab(elem) => elem.location(scale),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.location(scale),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.location(scale),
|
||||
}
|
||||
|
|
@ -90,7 +104,9 @@ where
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.transform(),
|
||||
CosmicElement::Cursor(elem) => elem.transform(),
|
||||
CosmicElement::Dnd(elem) => elem.transform(),
|
||||
CosmicElement::MoveGrab(elem) => elem.transform(),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.transform(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.transform(),
|
||||
}
|
||||
|
|
@ -99,12 +115,14 @@ where
|
|||
fn damage_since(
|
||||
&self,
|
||||
scale: Scale<f64>,
|
||||
commit: Option<smithay::backend::renderer::utils::CommitCounter>,
|
||||
commit: Option<CommitCounter>,
|
||||
) -> Vec<Rectangle<i32, Physical>> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.damage_since(scale, commit),
|
||||
CosmicElement::Cursor(elem) => elem.damage_since(scale, commit),
|
||||
CosmicElement::Dnd(elem) => elem.damage_since(scale, commit),
|
||||
CosmicElement::MoveGrab(elem) => elem.damage_since(scale, commit),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.damage_since(scale, commit),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.damage_since(scale, commit),
|
||||
}
|
||||
|
|
@ -114,7 +132,9 @@ where
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.opaque_regions(scale),
|
||||
CosmicElement::Cursor(elem) => elem.opaque_regions(scale),
|
||||
CosmicElement::Dnd(elem) => elem.opaque_regions(scale),
|
||||
CosmicElement::MoveGrab(elem) => elem.opaque_regions(scale),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.opaque_regions(scale),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.opaque_regions(scale),
|
||||
}
|
||||
|
|
@ -124,7 +144,9 @@ where
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.alpha(),
|
||||
CosmicElement::Cursor(elem) => elem.alpha(),
|
||||
CosmicElement::Dnd(elem) => elem.alpha(),
|
||||
CosmicElement::MoveGrab(elem) => elem.alpha(),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.alpha(),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.alpha(),
|
||||
}
|
||||
|
|
@ -142,7 +164,11 @@ impl RenderElement<GlowRenderer> for CosmicElement<GlowRenderer> {
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::AdditionalDamage(elem) => {
|
||||
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage)
|
||||
}
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => {
|
||||
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage)
|
||||
|
|
@ -154,7 +180,9 @@ impl RenderElement<GlowRenderer> for CosmicElement<GlowRenderer> {
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::Cursor(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::Dnd(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.underlying_storage(renderer),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => elem.underlying_storage(renderer),
|
||||
}
|
||||
|
|
@ -172,7 +200,11 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicElement<GlMultiRenderer<'a
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::AdditionalDamage(elem) => {
|
||||
RenderElement::<GlMultiRenderer<'a>>::draw(elem, frame, src, dst, damage)
|
||||
}
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => {
|
||||
let elem = {
|
||||
|
|
@ -189,7 +221,9 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicElement<GlMultiRenderer<'a
|
|||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::Cursor(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::Dnd(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer),
|
||||
CosmicElement::AdditionalDamage(elem) => elem.underlying_storage(renderer),
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicElement::Egui(elem) => {
|
||||
let glow_renderer = renderer.glow_renderer_mut();
|
||||
|
|
@ -219,17 +253,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<R> From<CursorRenderElement<R>> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
fn from(elem: CursorRenderElement<R>) -> Self {
|
||||
Self::Cursor(elem)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<CosmicMappedRenderElement<R>> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
|
|
@ -241,6 +264,17 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<R> From<DamageElement> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
fn from(elem: DamageElement) -> Self {
|
||||
Self::AdditionalDamage(elem)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
impl<R> From<TextureRenderElement<GlesTexture>> for CosmicElement<R>
|
||||
where
|
||||
|
|
@ -304,3 +338,58 @@ impl<'renderer, 'frame> AsGlowFrame<'frame> for GlMultiFrame<'renderer, 'frame>
|
|||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DamageElement {
|
||||
id: Id,
|
||||
geometry: Rectangle<i32, Logical>,
|
||||
}
|
||||
|
||||
impl DamageElement {
|
||||
pub fn new(geometry: Rectangle<i32, Logical>) -> DamageElement {
|
||||
DamageElement {
|
||||
id: Id::new(),
|
||||
geometry,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for DamageElement {
|
||||
fn id(&self) -> &Id {
|
||||
&self.id
|
||||
}
|
||||
|
||||
fn current_commit(&self) -> CommitCounter {
|
||||
CommitCounter::default()
|
||||
}
|
||||
|
||||
fn src(&self) -> Rectangle<f64, BufferCoords> {
|
||||
Rectangle::from_loc_and_size((0.0, 0.0), (1.0, 1.0))
|
||||
}
|
||||
|
||||
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
|
||||
self.geometry.to_f64().to_physical(scale).to_i32_round()
|
||||
}
|
||||
|
||||
fn damage_since(
|
||||
&self,
|
||||
scale: Scale<f64>,
|
||||
_commit: Option<CommitCounter>,
|
||||
) -> Vec<Rectangle<i32, Physical>> {
|
||||
vec![Rectangle::from_loc_and_size(
|
||||
(0, 0),
|
||||
self.geometry(scale).size,
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Renderer> RenderElement<R> for DamageElement {
|
||||
fn draw(
|
||||
&self,
|
||||
_frame: &mut <R as Renderer>::Frame<'_>,
|
||||
_src: Rectangle<f64, BufferCoords>,
|
||||
_dst: Rectangle<i32, Physical>,
|
||||
_damage: &[Rectangle<i32, Physical>],
|
||||
) -> Result<(), <R as Renderer>::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use std::{
|
|||
#[cfg(feature = "debug")]
|
||||
use crate::debug::fps_ui;
|
||||
use crate::{
|
||||
backend::render::element::DamageElement,
|
||||
shell::{
|
||||
focus::target::WindowGroup,
|
||||
grabs::{SeatMenuGrabState, SeatMoveGrabState},
|
||||
|
|
@ -23,19 +24,13 @@ use crate::{
|
|||
wayland::{
|
||||
handlers::{
|
||||
data_device::get_dnd_icon,
|
||||
screencopy::{render_session, WORKSPACE_OVERVIEW_NAMESPACE},
|
||||
},
|
||||
protocols::{
|
||||
screencopy::{
|
||||
BufferParams, CursorMode as ScreencopyCursorMode, Session as ScreencopySession,
|
||||
},
|
||||
workspace::WorkspaceHandle,
|
||||
screencopy::{render_session, FrameHolder, SessionData, WORKSPACE_OVERVIEW_NAMESPACE},
|
||||
},
|
||||
protocols::workspace::WorkspaceHandle,
|
||||
},
|
||||
};
|
||||
|
||||
use cosmic_comp_config::workspace::WorkspaceLayout;
|
||||
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::FailureReason;
|
||||
use keyframe::{ease, functions::EaseInOutCubic};
|
||||
use smithay::{
|
||||
backend::{
|
||||
|
|
@ -61,19 +56,17 @@ use smithay::{
|
|||
},
|
||||
desktop::{layer_map_for_output, PopupManager},
|
||||
output::{Output, OutputNoMode},
|
||||
utils::{IsAlive, Logical, Point, Rectangle, Scale},
|
||||
utils::{IsAlive, Logical, Point, Rectangle, Scale, Transform},
|
||||
wayland::{
|
||||
dmabuf::get_dmabuf,
|
||||
shell::wlr_layer::Layer,
|
||||
shm::{shm_format_to_fourcc, with_buffer_contents},
|
||||
},
|
||||
};
|
||||
use tracing::warn;
|
||||
|
||||
pub mod animations;
|
||||
|
||||
pub mod cursor;
|
||||
use self::cursor::CursorRenderElement;
|
||||
pub mod element;
|
||||
use self::element::{AsGlowRenderer, CosmicElement};
|
||||
|
||||
|
|
@ -392,17 +385,16 @@ pub enum CursorMode {
|
|||
}
|
||||
|
||||
#[profiling::function]
|
||||
pub fn cursor_elements<'frame, E, R>(
|
||||
pub fn cursor_elements<'frame, R>(
|
||||
renderer: &mut R,
|
||||
state: &Common,
|
||||
output: &Output,
|
||||
mode: CursorMode,
|
||||
) -> Vec<E>
|
||||
) -> Vec<CosmicElement<R>>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
E: From<CursorRenderElement<R>> + From<CosmicMappedRenderElement<R>>,
|
||||
{
|
||||
let scale = output.current_scale().fractional_scale();
|
||||
let mut elements = Vec::new();
|
||||
|
|
@ -425,7 +417,13 @@ where
|
|||
mode != CursorMode::NotDefault,
|
||||
)
|
||||
.into_iter()
|
||||
.map(E::from),
|
||||
.map(|(elem, hotspot)| {
|
||||
CosmicElement::Cursor(RelocateRenderElement::from_element(
|
||||
elem,
|
||||
Point::from((-hotspot.x, -hotspot.y)),
|
||||
Relocate::Relative,
|
||||
))
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -433,7 +431,7 @@ where
|
|||
elements.extend(
|
||||
cursor::draw_dnd_icon(renderer, &wl_surface, location.to_i32_round(), scale)
|
||||
.into_iter()
|
||||
.map(E::from),
|
||||
.map(CosmicElement::Dnd),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -444,7 +442,7 @@ where
|
|||
.unwrap()
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|state| state.render::<E, R>(renderer, seat, output, theme))
|
||||
.map(|state| state.render::<CosmicElement<R>, R>(renderer, seat, output, theme))
|
||||
{
|
||||
elements.extend(grab_elements);
|
||||
}
|
||||
|
|
@ -940,7 +938,7 @@ where
|
|||
}
|
||||
|
||||
#[profiling::function]
|
||||
pub fn render_output<R, Target, OffTarget, Source>(
|
||||
pub fn render_output<R, Target, OffTarget>(
|
||||
gpu: Option<&DrmNode>,
|
||||
renderer: &mut R,
|
||||
target: Target,
|
||||
|
|
@ -949,7 +947,6 @@ pub fn render_output<R, Target, OffTarget, Source>(
|
|||
state: &mut Common,
|
||||
output: &Output,
|
||||
cursor_mode: CursorMode,
|
||||
screencopy: Option<(Source, &[(ScreencopySession, BufferParams)])>,
|
||||
fps: Option<&mut Fps>,
|
||||
) -> Result<RenderOutputResult, RenderError<R>>
|
||||
where
|
||||
|
|
@ -960,14 +957,14 @@ where
|
|||
+ Bind<Dmabuf>
|
||||
+ Bind<Target>
|
||||
+ Offscreen<OffTarget>
|
||||
+ Blit<Source>
|
||||
+ Blit<Target>
|
||||
+ AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
<R as Renderer>::Error: From<GlesError>,
|
||||
CosmicElement<R>: RenderElement<R>,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
Source: Clone,
|
||||
Target: Clone,
|
||||
{
|
||||
let (previous_workspace, workspace) = state.shell.workspaces.active(output);
|
||||
let (previous_idx, idx) = state.shell.workspaces.active_num(output);
|
||||
|
|
@ -979,38 +976,128 @@ where
|
|||
let result = render_workspace(
|
||||
gpu,
|
||||
renderer,
|
||||
target,
|
||||
target.clone(),
|
||||
damage_tracker,
|
||||
age,
|
||||
None,
|
||||
state,
|
||||
output,
|
||||
previous_workspace,
|
||||
workspace,
|
||||
cursor_mode,
|
||||
screencopy,
|
||||
fps,
|
||||
false,
|
||||
);
|
||||
|
||||
result
|
||||
match result {
|
||||
Ok((res, mut elements)) => {
|
||||
for (session, frame) in output.take_pending_frames() {
|
||||
if let Some((frame, damage)) = render_session(
|
||||
renderer,
|
||||
&session.user_data().get::<SessionData>().unwrap(),
|
||||
frame,
|
||||
output.current_transform(),
|
||||
|buffer, renderer, dt, age, additional_damage| {
|
||||
let old_len = if !additional_damage.is_empty() {
|
||||
let area = output
|
||||
.current_mode()
|
||||
.ok_or(RenderError::OutputNoMode(OutputNoMode))
|
||||
.map(
|
||||
|mode| {
|
||||
mode.size
|
||||
.to_logical(1)
|
||||
.to_buffer(1, Transform::Normal)
|
||||
.to_f64()
|
||||
}, /* TODO: Mode is Buffer..., why is this Physical in the first place */
|
||||
)?;
|
||||
|
||||
let old_len = elements.len();
|
||||
elements.extend(
|
||||
additional_damage
|
||||
.into_iter()
|
||||
.map(|rect| {
|
||||
rect.to_f64()
|
||||
.to_logical(
|
||||
output.current_scale().fractional_scale(),
|
||||
output.current_transform(),
|
||||
&area,
|
||||
)
|
||||
.to_i32_round()
|
||||
})
|
||||
.map(DamageElement::new)
|
||||
.map(Into::into),
|
||||
);
|
||||
|
||||
Some(old_len)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let res = dt.damage_output(age, &elements)?;
|
||||
|
||||
if let Some(old_len) = old_len {
|
||||
elements.truncate(old_len);
|
||||
}
|
||||
|
||||
if let (Some(ref damage), _) = &res {
|
||||
if let Ok(dmabuf) = get_dmabuf(buffer) {
|
||||
renderer.bind(dmabuf).map_err(RenderError::Rendering)?;
|
||||
} else {
|
||||
let size = buffer_dimensions(buffer).unwrap();
|
||||
let format = with_buffer_contents(buffer, |_, _, data| {
|
||||
shm_format_to_fourcc(data.format)
|
||||
})
|
||||
.map_err(|_| OutputNoMode)? // eh, we have to do some error
|
||||
.expect(
|
||||
"We should be able to convert all hardcoded shm screencopy formats",
|
||||
);
|
||||
let render_buffer = renderer
|
||||
.create_buffer(format, size)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
renderer
|
||||
.bind(render_buffer)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
}
|
||||
for rect in damage {
|
||||
renderer
|
||||
.blit_from(target.clone(), *rect, *rect, TextureFilter::Nearest)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(RenderOutputResult {
|
||||
damage: res.0,
|
||||
sync: SyncPoint::default(),
|
||||
states: res.1,
|
||||
})
|
||||
},
|
||||
)? {
|
||||
frame.success(output.current_transform(), damage, state.clock.now());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
#[profiling::function]
|
||||
pub fn render_workspace<R, Target, OffTarget, Source>(
|
||||
pub fn render_workspace<R, Target, OffTarget>(
|
||||
gpu: Option<&DrmNode>,
|
||||
renderer: &mut R,
|
||||
target: Target,
|
||||
damage_tracker: &mut OutputDamageTracker,
|
||||
age: usize,
|
||||
additional_damage: Option<Vec<Rectangle<i32, Logical>>>,
|
||||
state: &mut Common,
|
||||
output: &Output,
|
||||
previous: Option<(WorkspaceHandle, usize, WorkspaceDelta)>,
|
||||
current: (WorkspaceHandle, usize),
|
||||
mut cursor_mode: CursorMode,
|
||||
screencopy: Option<(Source, &[(ScreencopySession, BufferParams)])>,
|
||||
cursor_mode: CursorMode,
|
||||
mut fps: Option<&mut Fps>,
|
||||
exclude_workspace_overview: bool,
|
||||
) -> Result<RenderOutputResult, RenderError<R>>
|
||||
) -> Result<(RenderOutputResult, Vec<CosmicElement<R>>), RenderError<R>>
|
||||
where
|
||||
R: Renderer
|
||||
+ ImportAll
|
||||
|
|
@ -1019,14 +1106,12 @@ where
|
|||
+ Bind<Dmabuf>
|
||||
+ Bind<Target>
|
||||
+ Offscreen<OffTarget>
|
||||
+ Blit<Source>
|
||||
+ AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: Clone + 'static,
|
||||
<R as Renderer>::Error: From<GlesError>,
|
||||
CosmicElement<R>: RenderElement<R>,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
Source: Clone,
|
||||
{
|
||||
if let Some(ref mut fps) = fps {
|
||||
fps.start();
|
||||
|
|
@ -1039,22 +1124,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
let screencopy_contains_embedded = screencopy.as_ref().map_or(false, |(_, sessions)| {
|
||||
sessions
|
||||
.iter()
|
||||
.any(|(s, _)| s.cursor_mode() == ScreencopyCursorMode::Embedded)
|
||||
});
|
||||
// cursor handling without a cursor_plane in this case is horrible.
|
||||
// because what if some session disagree and/or the backend wants to render with a different mode?
|
||||
// It seems we would need to render to an offscreen buffer in those cases (and do multiple renders, which messes with damage tracking).
|
||||
// So for now, we just pick the worst mode (embedded), if any requires it.
|
||||
//
|
||||
// Once we move to a cursor_plane, the default framebuffer will never contain a cursor and we can just composite the cursor for each session separately on top (or not).
|
||||
if screencopy_contains_embedded {
|
||||
cursor_mode = CursorMode::All;
|
||||
};
|
||||
|
||||
let elements: Vec<CosmicElement<R>> = workspace_elements(
|
||||
let mut elements: Vec<CosmicElement<R>> = workspace_elements(
|
||||
gpu,
|
||||
renderer,
|
||||
state,
|
||||
|
|
@ -1065,6 +1135,18 @@ where
|
|||
&mut fps,
|
||||
exclude_workspace_overview,
|
||||
)?;
|
||||
|
||||
if let Some(additional_damage) = additional_damage {
|
||||
let output_geo = output.geometry().to_local(&output).as_logical();
|
||||
elements.extend(
|
||||
additional_damage
|
||||
.into_iter()
|
||||
.filter_map(|rect| rect.intersection(output_geo))
|
||||
.map(DamageElement::new)
|
||||
.map(Into::<CosmicElement<R>>::into),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(fps) = fps.as_mut() {
|
||||
fps.elements();
|
||||
}
|
||||
|
|
@ -1081,62 +1163,6 @@ where
|
|||
fps.render();
|
||||
}
|
||||
|
||||
if let Some((source, buffers)) = screencopy {
|
||||
if res.is_ok() {
|
||||
for (session, params) in buffers {
|
||||
match render_session(
|
||||
gpu.cloned(),
|
||||
renderer,
|
||||
&session,
|
||||
params,
|
||||
output.current_transform(),
|
||||
|_node, buffer, renderer, dt, age| {
|
||||
let res = dt.damage_output(age, &elements)?;
|
||||
|
||||
if let (Some(ref damage), _) = &res {
|
||||
if let Ok(dmabuf) = get_dmabuf(buffer) {
|
||||
renderer.bind(dmabuf).map_err(RenderError::Rendering)?;
|
||||
} else {
|
||||
let size = buffer_dimensions(buffer).unwrap();
|
||||
let format =
|
||||
with_buffer_contents(buffer, |_, _, data| shm_format_to_fourcc(data.format))
|
||||
.map_err(|_| OutputNoMode)? // eh, we have to do some error
|
||||
.expect("We should be able to convert all hardcoded shm screencopy formats");
|
||||
let render_buffer = renderer
|
||||
.create_buffer(format, size)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
renderer
|
||||
.bind(render_buffer)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
}
|
||||
for rect in damage {
|
||||
renderer
|
||||
.blit_from(source.clone(), *rect, *rect, TextureFilter::Nearest)
|
||||
.map_err(RenderError::Rendering)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(RenderOutputResult {
|
||||
damage: res.0,
|
||||
sync: SyncPoint::default(),
|
||||
states: res.1,
|
||||
})
|
||||
},
|
||||
) {
|
||||
Ok(true) => {} // success
|
||||
Ok(false) => state.still_pending(session.clone(), params.clone()),
|
||||
Err(err) => {
|
||||
warn!(?err, "Error rendering to screencopy session.");
|
||||
session.failed(FailureReason::Unspec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(fps) = fps.as_mut() {
|
||||
fps.screencopy();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
if let Some(ref mut fps) = fps {
|
||||
if let Some(rd) = fps.rd.as_mut() {
|
||||
|
|
@ -1147,5 +1173,5 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
res
|
||||
res.map(|res| (res, elements))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue