Skip to content
Open
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 | |
26 changes: 22 additions & 4 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use smithay::{
input::InputEvent,
libinput::{LibinputInputBackend, LibinputSessionInterface},
renderer::{
DebugFlags, ImportDma, ImportMemWl,
DebugFlags, ImportDma, ImportMemWl, PresentationMode,
damage::Error as OutputDamageTrackerError,
element::{AsRenderElements, RenderElementStates, memory::MemoryRenderBuffer},
gles::{Capability, GlesRenderer},
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 @@ -1046,6 +1047,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 +1063,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 @@ -1253,7 +1256,13 @@ impl AnvilState<UdevData> {
});

if let Some(vblank_remaining_time) = vblank_remaining_time {
if vblank_remaining_time > frame_duration / 2 {
let presentation_mode = surface
.drm_output
.with_pending_frame(|frame| frame.map(|frame| frame.presentation_mode));

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 +1294,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 @@ -1638,19 +1647,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
Loading
Loading