<NME> winit.rs
<BEF> use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration};

#[cfg(feature = "debug")]
use image::GenericImageView;

use slog::Logger;
use smithay::backend::renderer::{gles2::Gles2Texture, ImportMem};
#[cfg(feature = "egl")]
use smithay::{
    backend::renderer::{ImportDma, ImportEgl},
    wayland::dmabuf::init_dmabuf_global,
};
use smithay::{
    backend::{
        renderer::gles2::Gles2Renderer,
        winit::{self, WinitEvent},
        SwapBuffersError,
    },
    desktop::space::RenderError,
        },
        winit::{self, WinitEvent, WinitGraphicsBackend},
        SwapBuffersError,
    },
    input::pointer::{CursorImageAttributes, CursorImageStatus},
    output::{Mode, Output, PhysicalProperties, Subpixel},
    reexports::{
        calloop::EventLoop,
        output::{Mode, Output, PhysicalProperties},
        seat::CursorImageStatus,
    },
};

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

pub const OUTPUT_NAME: &str = "winit";

pub struct WinitData {
    #[cfg(feature = "debug")]
    fps_texture: Gles2Texture,
    #[cfg(feature = "debug")]
    pub fps: fps_ticker::Fps,
    full_redraw: u8,
}

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 display = Rc::new(RefCell::new(Display::new()));

    let (backend, mut winit) = match winit::init(log.clone()) {
        Ok(ret) => ret,
        Err(err) => {
            slog::crit!(log, "Failed to initialize Winit backend: {}", err);
            return;
        }
    };
    let backend = Rc::new(RefCell::new(backend));

    #[cfg(feature = "egl")]
    if backend
        .borrow_mut()
        .renderer()
        .bind_wl_display(&display.borrow())
        .is_ok()
    {
        info!(log, "EGL hardware-acceleration enabled");
        let dmabuf_formats = backend
            .borrow_mut()
            .renderer()
            .dmabuf_formats()
            .cloned()
            .collect::<Vec<_>>();
        let backend = backend.clone();
        init_dmabuf_global(
            &mut display.borrow_mut(),
            dmabuf_formats,
            move |buffer, _| {
                backend
                    .borrow_mut()
                    .renderer()
                    .import_dmabuf(buffer, None)
                    .is_ok()
            },
            log.clone(),
        );
    };

    let size = backend.borrow().window_size().physical_size;

    /*
     * Initialize the globals
     */

    #[cfg(feature = "debug")]
    let fps_image =
        image::io::Reader::with_format(std::io::Cursor::new(FPS_NUMBERS_PNG), image::ImageFormat::Png)
            .decode()
            .unwrap();
    let data = WinitData {
        #[cfg(feature = "debug")]
        fps_texture: backend
            .borrow_mut()
            .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")]
        fps: fps_ticker::Fps::default(),
        full_redraw: 0,
    };
    let mut state = AnvilState::init(display.clone(), event_loop.handle(), data, log.clone(), true);

    let mode = Mode {
        size,
        refresh: 60_000,
    };

    let output = Output::new(
        OUTPUT_NAME.to_string(),
        PhysicalProperties {
            size: (0, 0).into(),
            full_redraw: 0,
            #[cfg(feature = "debug")]
            fps: fps_ticker::Fps::default(),
        },
        log.clone(),
    );
    let _global = output.create_global(&mut *display.borrow_mut());
    output.change_current_state(
        Some(mode),
        Some(wl_output::Transform::Flipped180),
        None,
        Some((0, 0).into()),
    );
    output.set_preferred(mode);
    state.space.borrow_mut().map_output(&output, (0, 0));

    let start_time = std::time::Instant::now();

                WinitEvent::Resized { size, .. } => {
                    // We only have one output
                    let output = state.space.outputs().next().unwrap().clone();
                    state.space.map_output(&output, (0, 0));
                    let mode = Mode {
                        size,
        if winit
            .dispatch_new_events(|event| match event {
                WinitEvent::Resized { size, .. } => {
                    let mut space = state.space.borrow_mut();
                    // We only have one output
                    let output = space.outputs().next().unwrap().clone();
                    space.map_output(&output, (0, 0));
                    state.process_input_event_windowed(&display.handle(), event, OUTPUT_NAME)
                        size,
                        refresh: 60_000,
                    };
                    output.change_current_state(Some(mode), None, None, None);
                    output.set_preferred(mode);
                    crate::shell::fixup_positions(&mut *space);
                }

                WinitEvent::Input(event) => state.process_input_event_windowed(event, OUTPUT_NAME),

                _ => (),
            })
            .is_err()
            let backend = &mut state.backend_data.backend;

            let mut cursor_guard = state.cursor_status.lock().unwrap();


        // drawing logic
        {
            let mut backend = backend.borrow_mut();
            let cursor_visible: bool;

            let mut elements = Vec::<CustomElem<Gles2Renderer>>::new();
            let dnd_guard = state.dnd_icon.lock().unwrap();
            let mut cursor_guard = state.cursor_status.lock().unwrap();

            // draw the dnd icon if any
            if let Some(ref surface) = *dnd_guard {
                if surface.as_ref().is_alive() {
                    elements.push(
                        draw_dnd_icon(surface.clone(), state.pointer_location.to_i32_round(), &log).into(),
                    );
            #[cfg(feature = "debug")]
            fps_element.update_fps(fps);

            let full_redraw = &mut state.backend_data.full_redraw;
            // reset the cursor if the surface is no longer alive
            let mut reset = false;
            if let CursorImageStatus::Image(ref surface) = *cursor_guard {
                reset = !surface.as_ref().is_alive();
            }
            if reset {
                *cursor_guard = CursorImageStatus::Default;
            let scale = Scale::from(output.current_scale().fractional_scale());
            let cursor_hotspot = if let CursorImageStatus::Surface(ref surface) = *cursor_guard {
                compositor::with_states(surface, |states| {
                    states
                        .data_map
                        .get::<Mutex<CursorImageAttributes>>()
                        .unwrap()
                        .lock()
                        .unwrap()
                        .hotspot
                })
            } else {
                (0, 0).into()
            };
            let cursor_pos = state.pointer_location - cursor_hotspot.to_f64();
            let cursor_pos_scaled = cursor_pos.to_physical(scale).to_i32_round();

            let render_res = backend.bind().and_then(|_| {
                let age = if *full_redraw > 0 {
                    0
                } else {
            } else {
                backend.buffer_age().unwrap_or(0)
            };
            let render_res = backend.bind().and_then(|_| {
                let renderer = backend.renderer();
                crate::render::render_output(
                    &output,
                    &mut *state.space.borrow_mut(),
                    renderer,
                    age,
                    &*elements,
                    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()));

        // Send frame events so that client start drawing their next frame
        state
            .space
            .borrow()
            .send_frames(start_time.elapsed().as_millis() as u32);

        if event_loop
            .dispatch(Some(Duration::from_millis(16)), &mut state)
            .is_err()
        {
            state.running.store(false, Ordering::SeqCst);
        } else {
            state.space.borrow_mut().refresh();
            state.popups.borrow_mut().cleanup();
            display.borrow_mut().flush_clients(&mut state);
        }

        #[cfg(feature = "debug")]

                    // 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: Begin porting to 0.30

<DFF> @@ -1,4 +1,4 @@
-use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration};
+use std::{sync::atomic::Ordering, time::Duration};
 
 #[cfg(feature = "debug")]
 use image::GenericImageView;
@@ -7,13 +7,17 @@ use slog::Logger;
 use smithay::backend::renderer::{gles2::Gles2Texture, ImportMem};
 #[cfg(feature = "egl")]
 use smithay::{
-    backend::renderer::{ImportDma, ImportEgl},
-    wayland::dmabuf::init_dmabuf_global,
+    backend::{
+        allocator::dmabuf::Dmabuf,
+        renderer::{ImportDma, ImportEgl},
+    },
+    wayland::dmabuf::{DmabufState, DmabufHandler, DmabufGlobal, ImportError},
+    delegate_dmabuf,
 };
 use smithay::{
     backend::{
         renderer::gles2::Gles2Renderer,
-        winit::{self, WinitEvent},
+        winit::{self, WinitGraphicsBackend, WinitEvent},
         SwapBuffersError,
     },
     desktop::space::RenderError,
@@ -28,23 +32,42 @@ use smithay::{
         output::{Mode, Output, PhysicalProperties},
         seat::CursorImageStatus,
     },
+    utils::IsAlive,
 };
 
 use crate::{
     drawing::*,
-    state::{AnvilState, Backend},
+    state::{AnvilState, Backend, CalloopData},
 };
 
 pub const OUTPUT_NAME: &str = "winit";
 
 pub struct WinitData {
+    backend: WinitGraphicsBackend,
+    #[cfg(feature = "egl")]
+    dmabuf_state: Option<(DmabufState, DmabufGlobal)>,
+    full_redraw: u8,
     #[cfg(feature = "debug")]
     fps_texture: Gles2Texture,
     #[cfg(feature = "debug")]
     pub fps: fps_ticker::Fps,
-    full_redraw: u8,
 }
 
+#[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")
@@ -57,80 +80,73 @@ impl Backend for WinitData {
 
 pub fn run_winit(log: Logger) {
     let mut event_loop = EventLoop::try_new().unwrap();
-    let display = Rc::new(RefCell::new(Display::new()));
+    let mut display = Display::new().unwrap();
 
-    let (backend, mut winit) = match winit::init(log.clone()) {
+    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 backend = Rc::new(RefCell::new(backend));
-
-    #[cfg(feature = "egl")]
-    if backend
-        .borrow_mut()
-        .renderer()
-        .bind_wl_display(&display.borrow())
-        .is_ok()
-    {
-        info!(log, "EGL hardware-acceleration enabled");
-        let dmabuf_formats = backend
-            .borrow_mut()
-            .renderer()
-            .dmabuf_formats()
-            .cloned()
-            .collect::<Vec<_>>();
-        let backend = backend.clone();
-        init_dmabuf_global(
-            &mut display.borrow_mut(),
-            dmabuf_formats,
-            move |buffer, _| {
-                backend
-                    .borrow_mut()
-                    .renderer()
-                    .import_dmabuf(buffer, None)
-                    .is_ok()
-            },
-            log.clone(),
-        );
-    };
+    let size = backend.window_size().physical_size;
 
-    let size = backend.borrow().window_size().physical_size;
-
-    /*
-     * Initialize the globals
-     */
-
-    #[cfg(feature = "debug")]
-    let fps_image =
-        image::io::Reader::with_format(std::io::Cursor::new(FPS_NUMBERS_PNG), image::ImageFormat::Png)
-            .decode()
-            .unwrap();
-    let data = WinitData {
-        #[cfg(feature = "debug")]
-        fps_texture: backend
-            .borrow_mut()
+    let data = {
+        #[cfg(feature = "egl")]
+        let dmabuf_state = if 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"),
+            .bind_wl_display(&display)
+            .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(
+                &mut display,
+                dmabuf_formats,
+                log.clone(),
+            );
+            Some((state, global))
+        } else {
+            None
+        };
         #[cfg(feature = "debug")]
-        fps: fps_ticker::Fps::default(),
-        full_redraw: 0,
+        let fps_image =
+            image::io::Reader::with_format(std::io::Cursor::new(FPS_NUMBERS_PNG), image::ImageFormat::Png)
+                .decode()
+                .unwrap();
+
+        WinitData {
+            backend,
+            #[cfg(feature = "egl")]
+            dmabuf_state,
+            full_redraw: 0,
+            #[cfg(feature = "debug")]
+            fps_texture: backend
+                .borrow_mut()
+                .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")]
+            fps: fps_ticker::Fps::default(),
+        }
     };
-    let mut state = AnvilState::init(display.clone(), event_loop.handle(), data, log.clone(), true);
+    let mut state = AnvilState::init(&mut display, event_loop.handle(), data, log.clone(), true);
 
     let mode = Mode {
         size,
         refresh: 60_000,
     };
-
-    let output = Output::new(
+    let (output, _global) = Output::new(
+        &mut display,
         OUTPUT_NAME.to_string(),
         PhysicalProperties {
             size: (0, 0).into(),
@@ -140,15 +156,15 @@ pub fn run_winit(log: Logger) {
         },
         log.clone(),
     );
-    let _global = output.create_global(&mut *display.borrow_mut());
     output.change_current_state(
+        &mut display.handle(),
         Some(mode),
         Some(wl_output::Transform::Flipped180),
         None,
         Some((0, 0).into()),
     );
     output.set_preferred(mode);
-    state.space.borrow_mut().map_output(&output, (0, 0));
+    state.space.map_output(&output, (0, 0));
 
     let start_time = std::time::Instant::now();
 
@@ -161,7 +177,7 @@ pub fn run_winit(log: Logger) {
         if winit
             .dispatch_new_events(|event| match event {
                 WinitEvent::Resized { size, .. } => {
-                    let mut space = state.space.borrow_mut();
+                    let mut dh = display.handle();
                     // We only have one output
                     let output = space.outputs().next().unwrap().clone();
                     space.map_output(&output, (0, 0));
@@ -169,13 +185,11 @@ pub fn run_winit(log: Logger) {
                         size,
                         refresh: 60_000,
                     };
-                    output.change_current_state(Some(mode), None, None, None);
+                    output.change_current_state(&mut dh, Some(mode), None, None, None);
                     output.set_preferred(mode);
-                    crate::shell::fixup_positions(&mut *space);
+                    crate::shell::fixup_positions(&mut dh, &mut state.space);
                 }
-
-                WinitEvent::Input(event) => state.process_input_event_windowed(event, OUTPUT_NAME),
-
+                WinitEvent::Input(event) => state.process_input_event_windowed(&mut display.handle(), event, OUTPUT_NAME),
                 _ => (),
             })
             .is_err()
@@ -186,16 +200,15 @@ pub fn run_winit(log: Logger) {
 
         // drawing logic
         {
-            let mut backend = backend.borrow_mut();
+            let mut backend = &mut state.backend_data.backend;
             let cursor_visible: bool;
 
             let mut elements = Vec::<CustomElem<Gles2Renderer>>::new();
-            let dnd_guard = state.dnd_icon.lock().unwrap();
             let mut cursor_guard = state.cursor_status.lock().unwrap();
 
             // draw the dnd icon if any
-            if let Some(ref surface) = *dnd_guard {
-                if surface.as_ref().is_alive() {
+            if let Some(surface) = state.dnd_icon.as_ref() {
+                if surface.alive() {
                     elements.push(
                         draw_dnd_icon(surface.clone(), state.pointer_location.to_i32_round(), &log).into(),
                     );
@@ -206,7 +219,7 @@ pub fn run_winit(log: Logger) {
             // reset the cursor if the surface is no longer alive
             let mut reset = false;
             if let CursorImageStatus::Image(ref surface) = *cursor_guard {
-                reset = !surface.as_ref().is_alive();
+                reset = !surface.alive();
             }
             if reset {
                 *cursor_guard = CursorImageStatus::Default;
@@ -234,11 +247,13 @@ pub fn run_winit(log: Logger) {
             } else {
                 backend.buffer_age().unwrap_or(0)
             };
+            let space = &mut state.space;
             let render_res = backend.bind().and_then(|_| {
                 let renderer = backend.renderer();
                 crate::render::render_output(
+                    &mut display.handle(),
                     &output,
-                    &mut *state.space.borrow_mut(),
+                    space,
                     renderer,
                     age,
                     &*elements,
@@ -269,18 +284,23 @@ pub fn run_winit(log: Logger) {
         // Send frame events so that client start drawing their next frame
         state
             .space
-            .borrow()
-            .send_frames(start_time.elapsed().as_millis() as u32);
+            .send_frames(&mut display.handle(),start_time.elapsed().as_millis() as u32);
 
-        if event_loop
-            .dispatch(Some(Duration::from_millis(16)), &mut state)
-            .is_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.borrow_mut().refresh();
-            state.popups.borrow_mut().cleanup();
-            display.borrow_mut().flush_clients(&mut state);
+            state.space.refresh(&mut display.handle());
+            state.popups.cleanup();
+            display.flush_clients().unwrap();
         }
 
         #[cfg(feature = "debug")]

anvil: Begin porting to 0.30