Ver Fonte

app: use a Mutex<Vec> + thread to merge render_api incoming requests queue with the main render loop update(). Once update() is called, we take the stack from the Vec and process it.

darkfi há 11 meses atrás
pai
commit
ffd44686b9
3 ficheiros alterados com 46 adições e 20 exclusões
  1. 2 4
      bin/app/src/app/locale.rs
  2. 41 13
      bin/app/src/gfx/mod.rs
  3. 3 3
      bin/app/src/main.rs

+ 2 - 4
bin/app/src/app/locale.rs

@@ -32,9 +32,7 @@ mod ui_consts {
 
 pub use ui_consts::*;
 
-static ENTRIES: &[&'static str] = &[
-    "app.ftl"
-];
+static ENTRIES: &[&'static str] = &["app.ftl"];
 
 pub fn read_locale_ftl(locale: &str) -> String {
     let dir = LOCALE_PATH.replace("{locale}", locale);
@@ -45,7 +43,7 @@ pub fn read_locale_ftl(locale: &str) -> String {
         let (sender, recvr) = sync_channel(1);
         miniquad::fs::load_file(&path, move |res| match res {
             Ok(res) => sender.send(res).unwrap(),
-            Err(e) => panic!("FTL not found! {e}")
+            Err(e) => panic!("FTL not found! {e}"),
         });
         let res = recvr.recv().unwrap();
         let contents = std::str::from_utf8(&res).unwrap();

+ 41 - 13
bin/app/src/gfx/mod.rs

@@ -27,6 +27,7 @@ use miniquad::{
     MouseButton, PassAction, Pipeline, PipelineParams, RenderingBackend, ShaderMeta, ShaderSource,
     TouchPhase, UniformDesc, UniformType, VertexAttribute, VertexFormat,
 };
+use parking_lot::Mutex as SyncMutex;
 use std::{
     collections::HashMap,
     fs::File,
@@ -790,6 +791,7 @@ impl GraphicsEventPublisher {
 
 struct Stage {
     ctx: Box<dyn RenderingBackend>,
+    #[cfg(target_os = "android")]
     libegl: egl::LibEgl,
     pipeline: Pipeline,
     white_texture: miniquad::TextureId,
@@ -799,7 +801,7 @@ struct Stage {
     buffers: HashMap<GfxBufferId, miniquad::BufferId>,
 
     epoch: EpochIndex,
-    method_recv: async_channel::Receiver<(EpochIndex, GraphicsMethod)>,
+    method_queue: Arc<SyncMutex<Vec<(EpochIndex, GraphicsMethod)>>>,
     event_pub: GraphicsEventPublisherPtr,
 
     pruner: PruneMethodHeap,
@@ -822,6 +824,22 @@ impl Stage {
         let method_recv = god.method_recv.clone();
         let event_pub = god.event_pub.clone();
 
+        let method_queue = Arc::new(SyncMutex::new(vec![]));
+        let method_queue2 = method_queue.clone();
+        let sink_task = god.fg_ex.spawn(async move {
+            // Pull from render_api
+            while let Ok((epoch, method)) = method_recv.recv().await {
+                let is_replace_dc = matches!(method, GraphicsMethod::ReplaceDrawCalls { .. });
+                // Append to stage data
+                method_queue2.lock().push((epoch, method));
+                // If ReplaceDrawCall then wake up miniquad
+                if is_replace_dc {
+                    miniquad::window::schedule_update();
+                }
+            }
+        });
+        god.fg_runtime.push_task(sink_task);
+
         let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
 
         let mut shader_meta: ShaderMeta = shader::meta();
@@ -861,10 +879,12 @@ impl Stage {
             params,
         );
 
+        #[cfg(target_os = "android")]
         let libegl = egl::LibEgl::try_load().expect("Cant load LibEGL");
 
         Stage {
             ctx,
+            #[cfg(target_os = "android")]
             libegl,
             pipeline,
             white_texture,
@@ -877,7 +897,7 @@ impl Stage {
             buffers: HashMap::new(),
 
             epoch,
-            method_recv,
+            method_queue,
             event_pub,
 
             pruner: PruneMethodHeap::new(epoch),
@@ -901,7 +921,7 @@ impl Stage {
             GraphicsMethod::DeleteBuffer((gbuff_id, _, _)) => self.method_delete_buffer(*gbuff_id),
             GraphicsMethod::ReplaceDrawCalls { timest, dcs } => {
                 let dcs = std::mem::take(dcs);
-                self.method_recvlace_draw_calls(*timest, dcs)
+                self.method_replace_draw_calls(*timest, dcs)
             }
         };
         if let Err(err) = res {
@@ -1029,7 +1049,7 @@ impl Stage {
         }
         Ok(())
     }
-    fn method_recvlace_draw_calls(
+    fn method_replace_draw_calls(
         &mut self,
         timest: Timestamp,
         dcs: Vec<(DcId, GfxDrawCall)>,
@@ -1097,8 +1117,13 @@ impl Stage {
     }
 
     fn egl_ctx_is_disabled(&self) -> bool {
-        let egl_ctx = unsafe { (self.libegl.eglGetCurrentContext)() };
-        egl_ctx.is_null()
+        #[cfg(target_os = "android")]
+        {
+            let egl_ctx = unsafe { (self.libegl.eglGetCurrentContext)() };
+            egl_ctx.is_null()
+        }
+        #[cfg(not(target_os = "android"))]
+        false
     }
 }
 
@@ -1129,9 +1154,9 @@ impl PruneMethodHeap {
         }
     }
 
-    fn drain(&mut self, method_recv: &async_channel::Receiver<(EpochIndex, GraphicsMethod)>) {
+    fn drain(&mut self, methods: Vec<(EpochIndex, GraphicsMethod)>) {
         // Process as many methods as we can
-        while let Ok((epoch, method)) = method_recv.try_recv() {
+        for (epoch, method) in methods {
             if epoch < self.epoch {
                 // Discard old rubbish
                 trace!(target: "gfx::pruner", "Discard method with old epoch: {epoch} curr: {} [method={method:?}]", self.epoch);
@@ -1164,12 +1189,12 @@ impl PruneMethodHeap {
                 }
             }
             GraphicsMethod::ReplaceDrawCalls { timest, dcs } => {
-                self.method_recvlace_draw_calls(timest, dcs)
+                self.method_replace_draw_calls(timest, dcs)
             }
         }
     }
 
-    fn method_recvlace_draw_calls(&mut self, timest: Timestamp, dcs: Vec<(DcId, GfxDrawCall)>) {
+    fn method_replace_draw_calls(&mut self, timest: Timestamp, dcs: Vec<(DcId, GfxDrawCall)>) {
         for (key, val) in dcs {
             match self.dcs.get_mut(&key) {
                 Some(old_val) => {
@@ -1206,9 +1231,11 @@ impl PruneMethodHeap {
 
 impl EventHandler for Stage {
     fn update(&mut self) {
+        let methods = std::mem::take(&mut *self.method_queue.lock());
+
         if self.egl_ctx_is_disabled() {
             // Screen is off so collect all methods into the pruner
-            self.pruner.drain(&self.method_recv);
+            self.pruner.drain(methods);
             self.screen_was_off = true;
             return
         }
@@ -1234,7 +1261,7 @@ impl EventHandler for Stage {
         }
 
         // Process as many methods as we can
-        while let Ok((epoch, method)) = self.method_recv.try_recv() {
+        for (epoch, method) in methods {
             if DEBUG_TRAX {
                 self.trax_method(epoch, &method);
             }
@@ -1359,7 +1386,8 @@ pub fn run_gui() {
         window_resizable: true,
         platform: miniquad::conf::Platform {
             linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
-            //blocking_event_loop: true,
+            #[cfg(target_os = "android")]
+            blocking_event_loop: true,
             android_panic_hook: false,
             ..Default::default()
         },

+ 3 - 3
bin/app/src/main.rs

@@ -102,8 +102,8 @@ struct God {
     _bg_runtime: AsyncRuntime,
     _bg_ex: ExecutorPtr,
 
-    fg_runtime: AsyncRuntime,
-    _fg_ex: ExecutorPtr,
+    pub fg_runtime: AsyncRuntime,
+    pub fg_ex: ExecutorPtr,
 
     /// App must fully finish setup() before start() is allowed to begin.
     cv_app_is_setup: Arc<CondVar>,
@@ -200,7 +200,7 @@ impl God {
             _bg_ex: bg_ex,
 
             fg_runtime,
-            _fg_ex: fg_ex,
+            fg_ex,
             cv_app_is_setup,
             app,