<NME> winit.rs
<BEF> use std::{
    sync::{atomic::Ordering, Mutex},
    time::Duration,
};

use slog::Logger;
#[cfg(feature = "debug")]
use smithay::backend::renderer::ImportMem;
#[cfg(feature = "egl")]
use smithay::{
    backend::{
        allocator::dmabuf::Dmabuf,
        renderer::{ImportDma, ImportEgl},
    },
    delegate_dmabuf,
    wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportError},
};
use smithay::{
    backend::{
        renderer::{
            damage::{DamageTrackedRenderer, DamageTrackedRendererError},
            element::AsRenderElements,
            gles2::{Gles2Renderer, Gles2Texture},
        },
        winit::{self, WinitEvent, WinitGraphicsBackend},
        SwapBuffersError,
    },
    input::pointer::{CursorImageAttributes, CursorImageStatus},
    output::{Mode, Output, PhysicalProperties, Subpixel},
    reexports::{
        calloop::EventLoop,
        wayland_server::{protocol::wl_surface, Display},
    },
    utils::{IsAlive, Point, Scale, Transform},
    wayland::{compositor, input_method::InputMethodSeat},
};

use crate::state::{AnvilState, Backend, CalloopData};
use crate::{drawing::*, render::*};

pub const OUTPUT_NAME: &str = "winit";

pub struct WinitData {
    backend: WinitGraphicsBackend,
    damage_tracked_renderer: DamageTrackedRenderer,
    #[cfg(feature = "egl")]
    dmabuf_state: Option<(DmabufState, DmabufGlobal)>,
    full_redraw: u8,
    #[cfg(feature = "debug")]
    pub fps: fps_ticker::Fps,
}

#[cfg(feature = "egl")]
impl DmabufHandler for AnvilState<WinitData> {
    fn dmabuf_state(&mut self) -> &mut DmabufState {
        &mut self.backend_data.dmabuf_state.as_mut().unwrap().0
    }

    fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf) -> Result<(), ImportError> {
        self.backend_data
            .backend
            .renderer()
            .import_dmabuf(&dmabuf, None)
            .map(|_| ())
            .map_err(|_| ImportError::Failed)
    }
}
#[cfg(feature = "egl")]
delegate_dmabuf!(AnvilState<WinitData>);

impl Backend for WinitData {
    fn seat_name(&self) -> String {
        String::from("winit")
    }
    fn reset_buffers(&mut self, _output: &Output) {
        self.full_redraw = 4;
    }
    fn early_import(&mut self, _surface: &wl_surface::WlSurface) {}
}

pub fn run_winit(log: Logger) {
    let mut event_loop = EventLoop::try_new().unwrap();
    let mut display = Display::new().unwrap();

    #[cfg_attr(not(feature = "egl"), allow(unused_mut))]
    let (mut backend, mut winit) = match winit::init(log.clone()) {
        Ok(ret) => ret,
        Err(err) => {
            slog::crit!(log, "Failed to initialize Winit backend: {}", err);
            return;
        }
    };
    let size = backend.window_size().physical_size;

    let mode = Mode {
        size,
        refresh: 60_000,
    };
    let output = Output::new(
        OUTPUT_NAME.to_string(),
        PhysicalProperties {
            size: (0, 0).into(),
            subpixel: Subpixel::Unknown,
            make: "Smithay".into(),
            model: "Winit".into(),
        },
        log.clone(),
    );
    let _global = output.create_global::<AnvilState<WinitData>>(&display.handle());
    output.change_current_state(Some(mode), Some(Transform::Flipped180), None, Some((0, 0).into()));
    output.set_preferred(mode);

    #[cfg(feature = "debug")]
    let fps_image =
        image::io::Reader::with_format(std::io::Cursor::new(FPS_NUMBERS_PNG), image::ImageFormat::Png)
            .decode()
            .unwrap();
    #[cfg(feature = "debug")]
    let fps_texture = backend
        .renderer()
        .import_memory(
            &fps_image.to_rgba8(),
            (fps_image.width() as i32, fps_image.height() as i32).into(),
            false,
        )
        .expect("Unable to upload FPS texture");
    #[cfg(feature = "debug")]
    let mut fps_element = FpsElement::new(fps_texture);

    let data = {
        #[cfg(feature = "egl")]
        let dmabuf_state = if backend.renderer().bind_wl_display(&display.handle()).is_ok() {
            info!(log, "EGL hardware-acceleration enabled");
            let dmabuf_formats = backend.renderer().dmabuf_formats().cloned().collect::<Vec<_>>();
            let mut state = DmabufState::new();
            let global = state.create_global::<AnvilState<WinitData>, _>(
                &display.handle(),
                dmabuf_formats,
                log.clone(),
            );
            Some((state, global))
        } else {
            None
        };

        let damage_tracked_renderer = DamageTrackedRenderer::from_output(&output);

        WinitData {
            backend,
            damage_tracked_renderer,
            #[cfg(feature = "egl")]
            dmabuf_state,
            full_redraw: 0,
            #[cfg(feature = "debug")]
            fps: fps_ticker::Fps::default(),
        }
    };
    let mut state = AnvilState::init(&mut display, event_loop.handle(), data, log.clone(), true);
    state.space.map_output(&output, (0, 0));

    #[cfg(feature = "xwayland")]
    state.start_xwayland();

    info!(log, "Initialization completed, starting the main loop.");

    let mut pointer_element = PointerElement::<Gles2Texture>::default();

                .and_then(|_| {
                    backend
                        .renderer()
                        .render(size, Transform::Flipped180, |renderer, frame| {
                            render_layers_and_windows(
                                renderer,
                                frame,
                                &*state.window_map.borrow(),
                                output_geometry,
                                output_scale,
                                &log,
                            )?;

                            let (x, y) = state.pointer_location.into();

                            // draw the dnd icon if any
                            {
                                let guard = state.dnd_icon.lock().unwrap();
                                if let Some(ref surface) = *guard {
                                    if surface.as_ref().is_alive() {
                                        draw_dnd_icon(
                                            renderer,
                                            frame,
                                            surface,

                                            output_scale,
                                            &log,
                                        )?;
                                    }
                                }
                            }
                            // draw the cursor as relevant
                            {
                                let mut guard = state.cursor_status.lock().unwrap();
                                // reset the cursor if the surface is no longer alive
                                let mut reset = false;
                                if let CursorImageStatus::Image(ref surface) = *guard {
                                    reset = !surface.as_ref().is_alive();
                                }
                                if reset {
                                    *guard = CursorImageStatus::Default;
                                }

                                // draw as relevant
                                if let CursorImageStatus::Image(ref surface) = *guard {
                                    cursor_visible = false;
                                    draw_cursor(
                                        renderer,
                                        frame,
                                        surface,
                                        (x as i32, y as i32).into(),
                                        output_scale,
                                        &log,
                                    )?;
                                } else {
                                    cursor_visible = true;
                                }
                            }

                            #[cfg(feature = "debug")]
                            {
                                let fps = state.backend_data.fps.avg().round() as u32;

                                draw_fps(
                                    renderer,
                                    frame,
                                    &state.backend_data.fps_texture,
                                    output_scale as f64,
                                    fps,
                                )?;
                            }

                            Ok(())
                        })
                        .map_err(Into::<SwapBuffersError>::into)
                        .and_then(|x| x)
                })

                elements.extend(pointer_element.render_elements(cursor_pos_scaled, scale));

                // draw input method surface if any
                let rectangle = input_method.coordinates();
                let position = Point::from((
                    rectangle.loc.x + rectangle.size.w,
                    rectangle.loc.y + rectangle.size.h,
                ));
                input_method.with_surface(|surface| {
                    elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
                        &smithay::desktop::space::SurfaceTree::from_surface(surface),
                        position.to_physical_precise_round(scale),
                        scale,
                    ));
                });

                // draw the dnd icon if any
                if let Some(surface) = dnd_icon {
                    if surface.alive() {
                        elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
                            &smithay::desktop::space::SurfaceTree::from_surface(surface),
                            cursor_pos_scaled,
                            scale,
                        ));
                    }
                }

                #[cfg(feature = "debug")]
                elements.push(CustomRenderElements::Fps(fps_element.clone()));

                render_output(
                    &output,
                    space,
                    &elements,
                    renderer,
                    damage_tracked_renderer,
                    age,
                    &log,
                )
                .map_err(|err| match err {
                    DamageTrackedRendererError::Rendering(err) => err.into(),
                    _ => unreachable!(),
                })
            });

            match render_res {
                Ok((damage, states)) => {
                    if let Some(damage) = damage {
                        if let Err(err) = backend.submit(Some(&*damage)) {
                            warn!(log, "Failed to submit buffer: {}", err);
                        }
                    }
                    backend.window().set_cursor_visible(cursor_visible);

                    // Send frame events so that client start drawing their next frame
                    state.send_frames(&output, &states);
                }
                Err(SwapBuffersError::ContextLost(err)) => {
                    error!(log, "Critical Rendering Error: {}", err);
                    state.running.store(false, Ordering::SeqCst);
                }
                Err(err) => warn!(log, "Rendering error: {}", err),
            }
        }

        let mut calloop_data = CalloopData { state, display };
        let result = event_loop.dispatch(Some(Duration::from_millis(16)), &mut calloop_data);
        CalloopData { state, display } = calloop_data;

        if result.is_err() {
            state.running.store(false, Ordering::SeqCst);
        } else {
            state.space.refresh();
            state.popups.cleanup();
            display.flush_clients().unwrap();
        }

        #[cfg(feature = "debug")]
        state.backend_data.fps.tick();
    }
}

<MSG> anvil: Fix winit resizing

<DFF> @@ -168,24 +168,57 @@ pub fn run_winit(log: Logger) {
                 .and_then(|_| {
                     backend
                         .renderer()
-                        .render(size, Transform::Flipped180, |renderer, frame| {
-                            render_layers_and_windows(
-                                renderer,
-                                frame,
-                                &*state.window_map.borrow(),
-                                output_geometry,
-                                output_scale,
-                                &log,
-                            )?;
-
-                            let (x, y) = state.pointer_location.into();
-
-                            // draw the dnd icon if any
-                            {
-                                let guard = state.dnd_icon.lock().unwrap();
-                                if let Some(ref surface) = *guard {
-                                    if surface.as_ref().is_alive() {
-                                        draw_dnd_icon(
+                        .render(
+                            output_geometry
+                                .size
+                                .to_f64()
+                                .to_physical(output_scale as f64)
+                                .to_i32_round(),
+                            Transform::Flipped180,
+                            |renderer, frame| {
+                                render_layers_and_windows(
+                                    renderer,
+                                    frame,
+                                    &*state.window_map.borrow(),
+                                    output_geometry,
+                                    output_scale,
+                                    &log,
+                                )?;
+
+                                let (x, y) = state.pointer_location.into();
+
+                                // draw the dnd icon if any
+                                {
+                                    let guard = state.dnd_icon.lock().unwrap();
+                                    if let Some(ref surface) = *guard {
+                                        if surface.as_ref().is_alive() {
+                                            draw_dnd_icon(
+                                                renderer,
+                                                frame,
+                                                surface,
+                                                (x as i32, y as i32).into(),
+                                                output_scale,
+                                                &log,
+                                            )?;
+                                        }
+                                    }
+                                }
+                                // draw the cursor as relevant
+                                {
+                                    let mut guard = state.cursor_status.lock().unwrap();
+                                    // reset the cursor if the surface is no longer alive
+                                    let mut reset = false;
+                                    if let CursorImageStatus::Image(ref surface) = *guard {
+                                        reset = !surface.as_ref().is_alive();
+                                    }
+                                    if reset {
+                                        *guard = CursorImageStatus::Default;
+                                    }
+
+                                    // draw as relevant
+                                    if let CursorImageStatus::Image(ref surface) = *guard {
+                                        cursor_visible = false;
+                                        draw_cursor(
                                             renderer,
                                             frame,
                                             surface,
@@ -193,52 +226,27 @@ pub fn run_winit(log: Logger) {
                                             output_scale,
                                             &log,
                                         )?;
+                                    } else {
+                                        cursor_visible = true;
                                     }
                                 }
-                            }
-                            // draw the cursor as relevant
-                            {
-                                let mut guard = state.cursor_status.lock().unwrap();
-                                // reset the cursor if the surface is no longer alive
-                                let mut reset = false;
-                                if let CursorImageStatus::Image(ref surface) = *guard {
-                                    reset = !surface.as_ref().is_alive();
-                                }
-                                if reset {
-                                    *guard = CursorImageStatus::Default;
-                                }
 
-                                // draw as relevant
-                                if let CursorImageStatus::Image(ref surface) = *guard {
-                                    cursor_visible = false;
-                                    draw_cursor(
+                                #[cfg(feature = "debug")]
+                                {
+                                    let fps = state.backend_data.fps.avg().round() as u32;
+
+                                    draw_fps(
                                         renderer,
                                         frame,
-                                        surface,
-                                        (x as i32, y as i32).into(),
-                                        output_scale,
-                                        &log,
+                                        &state.backend_data.fps_texture,
+                                        output_scale as f64,
+                                        fps,
                                     )?;
-                                } else {
-                                    cursor_visible = true;
                                 }
-                            }
-
-                            #[cfg(feature = "debug")]
-                            {
-                                let fps = state.backend_data.fps.avg().round() as u32;
-
-                                draw_fps(
-                                    renderer,
-                                    frame,
-                                    &state.backend_data.fps_texture,
-                                    output_scale as f64,
-                                    fps,
-                                )?;
-                            }
 
-                            Ok(())
-                        })
+                                Ok(())
+                            },
+                        )
                         .map_err(Into::<SwapBuffersError>::into)
                         .and_then(|x| x)
                 })

anvil: Fix winit resizing