Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions anvil/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ The currently available backends are:
| ANVIL_DISABLE_DIRECT_SCANOUT | any | tty-udev |
| ANVIL_GLES_DISABLE_INSTANCING | any | tty-udev |
| ANVIL_NO_VULKAN | 1,true,yes,y | x11 |
| ANVIL_FORCE_TEARING | any | tty-udev |
| SMITHAY_USE_LEGACY | 1,true,yes,y | tty-udev |
| SMITHAY_VK_VERSION | 1.3 | |
3 changes: 3 additions & 0 deletions anvil/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
render_element_states,
&dmabuf_feedback.render_feedback,
&dmabuf_feedback.scanout_feedback,
&dmabuf_feedback.async_feedback,
)
});
}
Expand Down Expand Up @@ -1041,6 +1042,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
render_element_states,
&dmabuf_feedback.render_feedback,
&dmabuf_feedback.scanout_feedback,
&dmabuf_feedback.async_feedback,
)
});
}
Expand Down Expand Up @@ -1178,6 +1180,7 @@ pub fn update_primary_scanout_output(
pub struct SurfaceDmabufFeedback {
pub render_feedback: DmabufFeedback,
pub scanout_feedback: DmabufFeedback,
pub async_feedback: DmabufFeedback,
}

#[profiling::function]
Expand Down
61 changes: 56 additions & 5 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use smithay::{
element::{memory::MemoryRenderBuffer, AsRenderElements, RenderElementStates},
gles::{Capability, GlesRenderer},
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer},
DebugFlags, ImportDma, ImportMemWl,
DebugFlags, ImportDma, ImportMemWl, PresentationMode,
},
session::{
libseat::{self, LibSeatSession},
Expand Down Expand Up @@ -651,6 +651,7 @@ struct SurfaceData {
dmabuf_feedback: Option<SurfaceDmabufFeedback>,
last_presentation_time: Option<Time<Monotonic>>,
vblank_throttle_timer: Option<RegistrationToken>,
force_tearing: bool,
}

impl Drop for SurfaceData {
Expand Down Expand Up @@ -726,7 +727,28 @@ fn get_surface_dmabuf_feedback(
.formats
.iter()
.copied()
.chain(planes.overlay.into_iter().flat_map(|p| p.formats))
.chain(planes.overlay.iter().flat_map(|p| p.formats.iter().copied()))
.collect::<FormatSet>()
.intersection(&all_render_formats)
.copied()
.collect::<FormatSet>();

// We limit the scan-out tranche to formats we can also render from
// so that there is always a fallback render path available in case
// the supplied buffer can not be scanned out directly
let async_planes_formats = surface
.plane_info()
.formats_async
.as_ref()
.unwrap_or(&surface.plane_info().formats)
.iter()
.copied()
.chain(
planes
.overlay
.into_iter()
.flat_map(|p| p.formats_async.unwrap_or(FormatSet::default())),
)
.collect::<FormatSet>()
.intersection(&all_render_formats)
.copied()
Expand All @@ -744,18 +766,30 @@ fn get_surface_dmabuf_feedback(
};

let scanout_feedback = builder
.clone()
.add_preference_tranche(
surface.device_fd().dev_id().unwrap(),
Some(zwp_linux_dmabuf_feedback_v1::TrancheFlags::Scanout),
planes_formats,
)
.add_preference_tranche(scanout_node.dev_id(), None, render_formats.clone())
.build()
.unwrap();

let async_feedback = builder
.add_preference_tranche(
surface.device_fd().dev_id().unwrap(),
Some(zwp_linux_dmabuf_feedback_v1::TrancheFlags::Scanout),
async_planes_formats,
)
.add_preference_tranche(scanout_node.dev_id(), None, render_formats)
.build()
.unwrap();

Some(SurfaceDmabufFeedback {
render_feedback,
scanout_feedback,
async_feedback,
})
}

Expand Down Expand Up @@ -1046,6 +1080,7 @@ impl AnvilState<UdevData> {
)
});

let force_tearing = std::env::var("ANVIL_FORCE_TEARING").is_ok();
let surface = SurfaceData {
dh: self.display_handle.clone(),
device_id: node,
Expand All @@ -1061,6 +1096,7 @@ impl AnvilState<UdevData> {
dmabuf_feedback,
last_presentation_time: None,
vblank_throttle_timer: None,
force_tearing,
};

device.surfaces.insert(crtc, surface);
Expand Down Expand Up @@ -1252,8 +1288,14 @@ impl AnvilState<UdevData> {
frame_duration.saturating_sub(Time::elapsed(&last_presentation_time, clock))
});

let presentation_mode = surface
.drm_output
.with_pending_frame(|frame| frame.map(|frame| frame.presentation_mode));

if let Some(vblank_remaining_time) = vblank_remaining_time {
if vblank_remaining_time > frame_duration / 2 {
if presentation_mode != Some(PresentationMode::Async)
&& vblank_remaining_time > frame_duration / 2
{
static WARN_ONCE: Once = Once::new();
WARN_ONCE.call_once(|| {
warn!("display running faster than expected, throttling vblanks and disabling HwClock")
Expand Down Expand Up @@ -1285,7 +1327,7 @@ impl AnvilState<UdevData> {

let schedule_render = match submit_result {
Ok(user_data) => {
if let Some(mut feedback) = user_data.flatten() {
if let Some(mut feedback) = user_data {
feedback.presented(clock, Refresh::fixed(frame_duration), seq as u64, flags);
}

Expand Down Expand Up @@ -1640,19 +1682,28 @@ fn render_surface<'a>(
let (elements, clear_color) =
output_elements(output, space, custom_elements, renderer, show_window_preview);

let presentation_mode = if surface.force_tearing {
PresentationMode::Async
} else {
PresentationMode::VSync
};

let frame_mode = if surface.disable_direct_scanout {
FrameFlags::empty()
} else if presentation_mode == PresentationMode::Async {
FrameFlags::DEFAULT | FrameFlags::ALLOW_PRIMARY_PLANE_SCANOUT_ANY
} else {
FrameFlags::DEFAULT
};
let (rendered, states) = surface
.drm_output
.render_frame(renderer, &elements, clear_color, frame_mode)
.render_frame(renderer, &elements, clear_color, frame_mode, presentation_mode)
.map(|render_frame_result| {
#[cfg(feature = "renderer_sync")]
if let PrimaryPlaneElement::Swapchain(element) = render_frame_result.primary_element {
element.sync.wait();
}

(!render_frame_result.is_empty, render_frame_result.states)
})
.map_err(|err| match err {
Expand Down
2 changes: 1 addition & 1 deletion src/backend/drm/compositor/frame_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct RenderFrameResult<'a, B: Buffer, F: Framebuffer, E> {
pub(super) supports_fencing: bool,
}

impl<B: Buffer, F: Framebuffer, E> RenderFrameResult<'_, B, F, E> {
impl<B: Buffer, F: Framebuffer, E: Element> RenderFrameResult<'_, B, F, E> {
/// Returns if synchronization with kms submission can't be guaranteed through the available apis.
pub fn needs_sync(&self) -> bool {
if let PrimaryPlaneElement::Swapchain(ref element) = self.primary_element {
Expand Down
Loading
Loading