linux: work around the mutex locks for request_frame and resize

Dzmitry Malyshau created

Change summary

crates/gpui/src/platform/linux/blade_renderer.rs | 16 +++++--
crates/gpui/src/platform/linux/platform.rs       |  6 -
crates/gpui/src/platform/linux/text_system.rs    |  4 
crates/gpui/src/platform/linux/window.rs         | 39 +++++++++++------
4 files changed, 40 insertions(+), 25 deletions(-)

Detailed changes

crates/gpui/src/platform/linux/blade_renderer.rs 🔗

@@ -33,7 +33,16 @@ impl BladeRenderer {
         self.gpu.destroy_command_encoder(&mut self.command_encoder);
     }
 
+    fn wait_for_gpu(&mut self) {
+        if let Some(last_sp) = self.last_sync_point.take() {
+            if !self.gpu.wait_for(&last_sp, MAX_FRAME_TIME_MS) {
+                panic!("GPU hung");
+            }
+        }
+    }
+
     pub fn resize(&mut self, size: blade::Extent) {
+        self.wait_for_gpu();
         self.gpu.resize(blade::SurfaceConfig {
             size,
             usage: blade::TextureUsage::TARGET,
@@ -44,15 +53,12 @@ impl BladeRenderer {
     pub fn draw(&mut self, scene: &Scene) {
         let frame = self.gpu.acquire_frame();
         self.command_encoder.start();
+        self.command_encoder.init_texture(frame.texture());
 
         self.command_encoder.present(frame);
 
         let sync_point = self.gpu.submit(&mut self.command_encoder);
-        if let Some(ref last_sp) = self.last_sync_point {
-            if !self.gpu.wait_for(last_sp, MAX_FRAME_TIME_MS) {
-                panic!("GPU hung");
-            }
-        }
+        self.wait_for_gpu();
         self.last_sync_point = Some(sync_point);
     }
 }

crates/gpui/src/platform/linux/platform.rs 🔗

@@ -114,16 +114,14 @@ impl Platform for LinuxPlatform {
                 }
                 xcb::Event::X(x::Event::ResizeRequest(ev)) => {
                     let this = self.0.lock();
-                    let mut window = this.windows[&ev.window()].lock();
-                    window.resize(ev.width(), ev.height());
+                    LinuxWindowState::resize(&this.windows[&ev.window()], ev.width(), ev.height());
                 }
                 _ => {}
             }
 
             if let Some(x_window) = repaint_x_window {
                 let this = self.0.lock();
-                let mut window = this.windows[&x_window].lock();
-                window.request_frame();
+                LinuxWindowState::request_frame(&this.windows[&x_window]);
                 this.xcb_connection.flush();
             }
         }

crates/gpui/src/platform/linux/text_system.rs 🔗

@@ -64,7 +64,7 @@ impl PlatformTextSystem for LinuxTextSystem {
         Vec::new()
     }
     fn font_id(&self, descriptor: &Font) -> Result<FontId> {
-        unimplemented!()
+        Ok(FontId(0)) //TODO
     }
     fn font_metrics(&self, font_id: FontId) -> FontMetrics {
         unimplemented!()
@@ -89,7 +89,7 @@ impl PlatformTextSystem for LinuxTextSystem {
         unimplemented!()
     }
     fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout {
-        unimplemented!()
+        LineLayout::default() //TODO
     }
     fn wrap_line(
         &self,

crates/gpui/src/platform/linux/window.rs 🔗

@@ -166,30 +166,41 @@ impl LinuxWindowState {
         }))
     }
 
-    pub fn resize(&mut self, width: u16, height: u16) {
-        self.content_size = Size {
+    pub fn destroy(&mut self) {
+        self.sprite_atlas.destroy();
+        self.renderer.destroy();
+    }
+
+    pub fn resize(self_ptr: &LinuxWindowStatePtr, width: u16, height: u16) {
+        let content_size = Size {
             width: Pixels(width as f32),
             height: Pixels(height as f32),
         };
-        self.renderer.resize(blade::Extent {
+
+        let mut fun = match self_ptr.lock().callbacks.resize.take() {
+            Some(fun) => fun,
+            None => return,
+        };
+        fun(content_size, 1.0);
+
+        let mut this = self_ptr.lock();
+        this.callbacks.resize = Some(fun);
+        this.content_size = content_size;
+        this.renderer.resize(blade::Extent {
             width: width as u32,
             height: height as u32,
             depth: 1,
         });
-        if let Some(ref mut fun) = self.callbacks.resize {
-            fun(self.content_size, 1.0);
-        }
     }
 
-    pub fn request_frame(&mut self) {
-        if let Some(ref mut fun) = self.callbacks.request_frame {
-            fun();
-        }
-    }
+    pub fn request_frame(self_ptr: &LinuxWindowStatePtr) {
+        let mut fun = match self_ptr.lock().callbacks.request_frame.take() {
+            Some(fun) => fun,
+            None => return,
+        };
+        fun();
 
-    pub fn destroy(&mut self) {
-        self.sprite_atlas.destroy();
-        self.renderer.destroy();
+        self_ptr.lock().callbacks.request_frame = Some(fun);
     }
 }