Преглед изворни кода

wallet: fix android crash(es)

darkfi пре 2 година
родитељ
комит
09decc20a3

+ 2 - 0
bin/darkwallet/README.android.md

@@ -16,6 +16,8 @@ Enable USB debugging in developer options and run the following commands:
 
 ```
 adb install -r target/android-artifacts/debug/apk/darkwallet.apk
+# Clear the log
+adb logcat -c
 adb logcat -s darkfi
 ```
 

+ 48 - 10
bin/darkwallet/src/chatview.rs

@@ -1,5 +1,5 @@
 use atomic_float::AtomicF32;
-use miniquad::{KeyMods, UniformType, MouseButton, window};
+use miniquad::{KeyMods, UniformType, MouseButton, window, TextureId};
 use log::debug;
 use std::{
     collections::HashMap,
@@ -34,6 +34,7 @@ pub struct ChatView {
     scroll: AtomicF32,
     lines: Vec<String>,
     glyph_lines: Mutex<Vec<Vec<Glyph>>>,
+    atlas: Mutex<HashMap<(u32, [u8; 4]), TextureId>>,
 }
 
 impl ChatView {
@@ -59,6 +60,7 @@ impl ChatView {
             scroll: AtomicF32::new(0.),
             lines,
             glyph_lines: Mutex::new(glyph_lines),
+            atlas: Mutex::new(HashMap::new()),
         });
 
         let weak_self = Arc::downgrade(&self_);
@@ -151,6 +153,7 @@ impl ChatView {
         };
 
         let glyph_lines = &mut self.glyph_lines.lock().unwrap();
+        let atlas = &mut self.atlas.lock().unwrap();
 
         let scroll = self.scroll.load(Ordering::Relaxed);
         for (i, (line, glyph_line)) in self.lines.iter().zip(glyph_lines.iter_mut()).enumerate() {
@@ -171,16 +174,18 @@ impl ChatView {
                 continue
             };
 
-            if glyph_line.is_empty() {
-                *glyph_line = self.text_shaper.shape(line.to_string(), font_size, COLOR_WHITE);
-            }
             let linespacing = window_scale*30.;
             let off_y = linespacing * i as f32 + scroll;
             if off_y + linespacing < 0. || off_y - linespacing > rect.h {
                 continue;
             }
 
+            if glyph_line.is_empty() {
+                *glyph_line = self.text_shaper.shape(line.to_string(), font_size, COLOR_WHITE);
+            }
+
             let times_color = [0.4, 0.4, 0.4, 1.];
+            let times_color_u8 = [(255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 1.) as u8];
             let glyphs_time = self.text_shaper.shape(time.to_string(), font_size, times_color);
             let mut rhs = 0.;
             for glyph in glyphs_time {
@@ -190,9 +195,15 @@ impl ChatView {
 
                 assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width*glyph.bmp_height*4);
                 //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
-                let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                let texture = if atlas.contains_key(&(glyph.id, times_color_u8.clone())) {
+                    *atlas.get(&(glyph.id, times_color_u8.clone())).unwrap()
+                } else {
+                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                    atlas.insert((glyph.id, times_color_u8.clone()), texture);
+                    texture
+                };
                 render.render_clipped_box_with_texture2(&bound, &pos, COLOR_WHITE, texture);
-                render.ctx.delete_texture(texture);
+                //render.ctx.delete_texture(texture);
             }
 
             let nick_colors = [
@@ -207,8 +218,21 @@ impl ChatView {
                 [1.00, 0.36, 0.48, 1.],
                 [1.00, 0.30, 0.00, 1.]
             ];
+            let nick_colors_u8 = [
+                [(255. * 0.00) as u8, (255. * 0.94) as u8, (255. * 1.00) as u8, (255. * 1.) as u8],
+                [(255. * 0.36) as u8, (255. * 1.00) as u8, (255. * 0.69) as u8, (255. * 1.) as u8],
+                [(255. * 0.29) as u8, (255. * 1.00) as u8, (255. * 0.45) as u8, (255. * 1. ) as u8],
+                [(255. * 0.00) as u8, (255. * 0.73) as u8, (255. * 0.38) as u8, (255. * 1. ) as u8],
+                [(255. * 0.21) as u8, (255. * 0.67) as u8, (255. * 0.67) as u8, (255. * 1. ) as u8],
+                [(255. * 0.56) as u8, (255. * 0.61) as u8, (255. * 1.00) as u8, (255. * 1. ) as u8],
+                [(255. * 0.84) as u8, (255. * 0.48) as u8, (255. * 1.00) as u8, (255. * 1. ) as u8],
+                [(255. * 1.00) as u8, (255. * 0.61) as u8, (255. * 0.94) as u8, (255. * 1. ) as u8],
+                [(255. * 1.00) as u8, (255. * 0.36) as u8, (255. * 0.48) as u8, (255. * 1. ) as u8],
+                [(255. * 1.00) as u8, (255. * 0.30) as u8, (255. * 0.00) as u8, (255. * 1. ) as u8]
+            ];
 
             let nick_color = nick_colors[nick.len() % nick_colors.len()];
+            let nick_color_u8 = nick_colors_u8[nick.len() % nick_colors.len()];
             let glyphs_nick = self.text_shaper.shape(nick.to_string(), font_size, nick_color);
             let off_x = rhs + window_scale*20.;
             for glyph in glyphs_nick {
@@ -219,9 +243,16 @@ impl ChatView {
 
                 assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width*glyph.bmp_height*4);
                 //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
-                let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                let texture = if atlas.contains_key(&(glyph.id, nick_color_u8.clone())) {
+                    *atlas.get(&(glyph.id, nick_color_u8.clone())).unwrap()
+                } else {
+                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                    atlas.insert((glyph.id, nick_color_u8.clone()), texture);
+                    texture
+                };
                 render.render_clipped_box_with_texture2(&bound, &pos, COLOR_WHITE, texture);
-                render.ctx.delete_texture(texture);
+                //render.ctx.delete_texture(texture);
             }
 
             let off_x = rhs + window_scale*20.;
@@ -232,9 +263,16 @@ impl ChatView {
 
                 assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width*glyph.bmp_height*4);
                 //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
-                let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                let texture = if atlas.contains_key(&(glyph.id, [255, 255, 255, 255])) {
+                    *atlas.get(&(glyph.id, [255, 255, 255, 255])).unwrap()
+                } else {
+                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                    atlas.insert((glyph.id, [255, 255, 255, 255]), texture);
+                    texture
+                };
                 render.render_clipped_box_with_texture2(&bound, &pos, COLOR_WHITE, texture);
-                render.ctx.delete_texture(texture);
+                //render.ctx.delete_texture(texture);
             }
         }
 

+ 13 - 3
bin/darkwallet/src/editbox.rs

@@ -1,4 +1,4 @@
-use miniquad::{KeyMods, UniformType, MouseButton, window};
+use miniquad::{KeyMods, UniformType, MouseButton, window, TextureId};
 use log::{debug, info};
 use std::{
     collections::HashMap,
@@ -98,6 +98,7 @@ pub struct EditBox {
     mouse_btn_held: AtomicBool,
     window_scale: f32,
     screen_size: Arc<Property>,
+    atlas: Mutex<HashMap<u32, TextureId>>,
 }
 
 impl EditBox {
@@ -149,6 +150,7 @@ impl EditBox {
             mouse_btn_held: AtomicBool::new(false),
             window_scale,
             screen_size,
+            atlas: Mutex::new(HashMap::new()),
         });
         self_.regen_glyphs().unwrap();
 
@@ -325,6 +327,7 @@ impl EditBox {
         let text_color = self.text_color.get();
 
         let glyphs = &*self.glyphs.lock().unwrap();
+        let atlas = &mut self.atlas.lock().unwrap();
 
         if !self.selected.is_null(0)? && !self.selected.is_null(1)? {
             self.render_selected(render, &rect, glyphs)?;
@@ -344,10 +347,17 @@ impl EditBox {
             let x2 = x1 + glyph.pos.w;
             let y2 = y1 + glyph.pos.h;
 
-            let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                let texture = if atlas.contains_key(&glyph.id) {
+                    *atlas.get(&glyph.id).unwrap()
+                } else {
+                    let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
+                    atlas.insert(glyph.id, texture);
+                    texture
+                };
+            //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
             render.render_clipped_box_with_texture(&bound, x1, y1, x2, y2, COLOR_WHITE, texture);
             //render.render_box_with_texture(x1, y1, x2, y2, COLOR_WHITE, texture);
-            render.ctx.delete_texture(texture);
+            //render.ctx.delete_texture(texture);
 
             // Glyph outlines
             //if debug {

+ 29 - 3
bin/darkwallet/src/gfx.rs

@@ -9,9 +9,10 @@ use miniquad::{
 };
 use std::{
     array::IntoIter,
+    collections::HashMap,
     fmt,
     io::Cursor,
-    sync::{mpsc, Arc, MutexGuard},
+    sync::{mpsc, Arc, Mutex, MutexGuard},
     time::{Duration, Instant},
 };
 
@@ -145,6 +146,7 @@ struct Stage {
     method_sender: mpsc::SyncSender<(GraphicsMethodEvent, SceneNodeId, Vec<u8>, MethodResponseFn)>,
 
     last_draw_time: Option<Instant>,
+    atlas: Mutex<HashMap<(u32, [u8; 4]), TextureId>>,
 }
 
 impl Stage {
@@ -217,6 +219,7 @@ impl Stage {
             method_recvr,
             method_sender,
             last_draw_time: None,
+            atlas: Mutex::new(HashMap::new())
         };
         stage.setup_scene_graph_window();
 
@@ -469,6 +472,7 @@ pub struct RenderContext<'a> {
     pub proj: glam::Mat4,
     pub textures: &'a ResourceManager<TextureId>,
     pub font_faces: &'a Vec<FreetypeFace>,
+    pub atlas: &'a mut HashMap<(u32, [u8; 4]), TextureId>,
 }
 
 impl<'a> RenderContext<'a> {
@@ -772,6 +776,8 @@ impl<'a> RenderContext<'a> {
 
         self.ctx.apply_bindings(&bindings);
         self.ctx.draw(0, 6, 1);
+        self.ctx.delete_buffer(vertex_buffer);
+        self.ctx.delete_buffer(index_buffer);
     }
 
     pub fn render_clipped_box_with_texture(
@@ -836,6 +842,8 @@ impl<'a> RenderContext<'a> {
 
         self.ctx.apply_bindings(&bindings);
         self.ctx.draw(0, 6, 1);
+        self.ctx.delete_buffer(vertex_buffer);
+        self.ctx.delete_buffer(index_buffer);
     }
 
     pub fn render_box_with_texture(
@@ -876,6 +884,8 @@ impl<'a> RenderContext<'a> {
 
         self.ctx.apply_bindings(&bindings);
         self.ctx.draw(0, 6, 1);
+        self.ctx.delete_buffer(vertex_buffer);
+        self.ctx.delete_buffer(index_buffer);
     }
 
     pub fn render_box(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {
@@ -1102,9 +1112,23 @@ impl<'a> RenderContext<'a> {
                     (x1, y1, x2, y2)
                 };
 
-                let texture = self.ctx.new_texture_from_rgba8(bmp_width as u16, bmp_height as u16, &tdata);
+                let key = (gid, [
+                    (255. * color_r) as u8,
+                    (255. * color_g) as u8,
+                    (255. * color_b) as u8,
+                    (255. * color_a) as u8,
+                ]);
+                let texture = if self.atlas.contains_key(&key) {
+                    *self.atlas.get(&key).unwrap()
+                } else {
+                    let texture = self.ctx.new_texture_from_rgba8(bmp_width as u16, bmp_height as u16, &tdata);
+                    self.atlas.insert(key, texture);
+                    texture
+                };
+
+                //let texture = self.ctx.new_texture_from_rgba8(bmp_width as u16, bmp_height as u16, &tdata);
                 self.render_box_with_texture(x1, y1, x2, y2, COLOR_WHITE, texture);
-                self.ctx.delete_texture(texture);
+                //self.ctx.delete_texture(texture);
 
                 if debug {
                     self.outline(x1, y1, x2, y2, COLOR_BLUE, 1.);
@@ -1167,6 +1191,7 @@ impl EventHandler for Stage {
         //let proj = glam::Mat4::IDENTITY;
 
         let scene_graph = self.scene_graph.lock().unwrap();
+        let atlas = &mut self.atlas.lock().unwrap();
 
         // We need this because scene_graph must remain locked for the duration of the rendering
         let mut render_context = RenderContext {
@@ -1176,6 +1201,7 @@ impl EventHandler for Stage {
             proj,
             textures: &self.textures,
             font_faces: &self.font_faces,
+            atlas
         };
 
         render_context.render_window();

+ 2 - 0
bin/darkwallet/src/text.rs

@@ -5,6 +5,7 @@ use crate::gfx::{Rectangle, FreetypeFace};
 
 #[derive(Clone)]
 pub struct Glyph {
+    pub id: u32,
     // Substring this glyph corresponds to
     pub substr: String,
 
@@ -191,6 +192,7 @@ impl TextShaper {
                 };
 
                 let glyph = Glyph {
+                    id: gid,
                     substr: String::new(),
                     bmp,
                     bmp_width: bmp_width as u16,