Преглед на файлове

wallet/gfx: texture debug mode (optional)

darkfi преди 1 година
родител
ревизия
1a33cd7c02

+ 1 - 1
bin/darkwallet/src/app/schema/menu.rs

@@ -297,7 +297,7 @@ pub async fn make(app: &App, window: SceneNodePtr) {
 
         // Create shortcut
         let channel_id = i + 1;
-        let node = create_shortcut("channel_shortcut_{channel_id}");
+        let node = create_shortcut(&format!("channel_shortcut_{channel_id}"));
         let key = format!("alt+{channel_id}");
         node.set_property_str(Role::App, "key", key).unwrap();
         node.set_property_u32(Role::App, "priority", 1).unwrap();

+ 44 - 2
bin/darkwallet/src/gfx/mod.rs

@@ -49,6 +49,7 @@ pub type GfxBufferId = u32;
 // This is very noisy so suppress output by default
 const DEBUG_RENDER: bool = false;
 const DEBUG_GFXAPI: bool = false;
+const DEBUG_RESRC: bool = false;
 
 #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
 #[repr(C)]
@@ -74,10 +75,14 @@ pub type ManagedTexturePtr = Arc<ManagedTexture>;
 pub struct ManagedTexture {
     id: GfxTextureId,
     render_api: RenderApi,
+    debug: String,
 }
 
 impl Drop for ManagedTexture {
     fn drop(&mut self) {
+        if DEBUG_RESRC {
+            debug!(target: "gfx", "Dropping texture ID={}, debug={}", self.id, self.debug);
+        }
         self.render_api.delete_unmanaged_texture(self.id);
     }
 }
@@ -128,10 +133,21 @@ impl RenderApi {
         gfx_texture_id
     }
 
-    pub fn new_texture(&self, width: u16, height: u16, data: Vec<u8>) -> ManagedTexturePtr {
+    pub fn new_texture<F>(
+        &self,
+        width: u16,
+        height: u16,
+        data: Vec<u8>,
+        make_debug: F,
+    ) -> ManagedTexturePtr
+    where
+        F: Fn() -> String,
+    {
+        let debug = if DEBUG_RESRC { make_debug().into() } else { String::new() };
         Arc::new(ManagedTexture {
             id: self.new_unmanaged_texture(width, height, data),
             render_api: self.clone(),
+            debug,
         })
     }
 
@@ -197,14 +213,40 @@ impl GfxDrawMesh {
         buffers: &HashMap<GfxBufferId, miniquad::BufferId>,
     ) -> DrawMesh {
         let buffers_keep_alive = [self.vertex_buffer.clone(), self.index_buffer.clone()];
+        let texture = match self.texture {
+            Some(gfx_texture) => Self::try_get_texture(textures, gfx_texture),
+            None => None,
+        };
         DrawMesh {
             vertex_buffer: buffers[&self.vertex_buffer.id],
             index_buffer: buffers[&self.index_buffer.id],
             buffers_keep_alive,
-            texture: self.texture.map(|t| (t.clone(), textures[&t.id])),
+            texture,
             num_elements: self.num_elements,
         }
     }
+
+    fn try_get_texture(
+        textures: &HashMap<GfxTextureId, miniquad::TextureId>,
+        gfx_texture: ManagedTexturePtr,
+    ) -> Option<(ManagedTexturePtr, miniquad::TextureId)> {
+        let gfx_texture_id = gfx_texture.id;
+
+        let Some(mq_texture_id) = textures.get(&gfx_texture_id) else {
+            error!(target: "gfx", "Serious error: missing texture ID={gfx_texture_id}");
+            error!(target: "gfx", "Dumping textures:");
+            for (gfx_texture_id, texture_id) in textures {
+                error!(target: "gfx", "{gfx_texture_id} => {texture_id:?}");
+            }
+
+            if DEBUG_RESRC {
+                panic!("Missing texture ID={gfx_texture_id}, debug={}", gfx_texture.debug);
+            }
+            return None
+        };
+
+        Some((gfx_texture, textures[&gfx_texture_id]))
+    }
 }
 
 #[derive(Debug, Clone)]

+ 5 - 0
bin/darkwallet/src/logger.rs

@@ -6,7 +6,12 @@ use simplelog::{
 };
 use std::{path::PathBuf, thread::sleep, time::Duration};
 
+#[cfg(target_os = "android")]
 const LOGS_ENABLED: bool = false;
+
+#[cfg(not(target_os = "android"))]
+const LOGS_ENABLED: bool = true;
+
 // Measured in bytes
 const LOGFILE_MAXSIZE: usize = 5_000_000;
 

+ 14 - 4
bin/darkwallet/src/text/atlas.rs

@@ -4,16 +4,22 @@ use crate::{
     gfx::{GfxTextureId, ManagedTexturePtr, Rectangle, RenderApi},
 };
 
+use super::glyph_str;
+
 /// Prevents render artifacts from aliasing.
 /// Even with aliasing turned off, some bleed still appears possibly
 /// due to UV coord calcs. Adding a gap perfectly fixes this.
 const ATLAS_GAP: usize = 2;
 
 /// Convenience wrapper fn. Use if rendering a single line of glyphs.
-pub fn make_texture_atlas(render_api: &RenderApi, glyphs: &Vec<Glyph>) -> RenderedAtlas {
+pub fn make_texture_atlas(
+    render_api: &RenderApi,
+    glyphs: &Vec<Glyph>,
+    debug_context: &str,
+) -> RenderedAtlas {
     let mut atlas = Atlas::new(render_api);
     atlas.push(&glyphs);
-    atlas.make()
+    atlas.make(|| format!("{debug_context}: '{}'", glyph_str(glyphs)))
 }
 
 /// Responsible for aggregating glyphs, and then producing a single software
@@ -129,7 +135,10 @@ impl<'a> Atlas<'a> {
     /// Each glyph is given a sub-rect within the texture, accessible by calling
     /// `rendered_atlas.fetch_uv(my_glyph_id)`.
     /// The texture ID is a struct member: `rendered_atlas.texture_id`.
-    pub fn make(self) -> RenderedAtlas {
+    pub fn make<F>(self, debug_info: F) -> RenderedAtlas
+    where
+        F: Fn() -> String,
+    {
         //if self.glyph_ids.is_empty() {
         //    return Err(Error::AtlasIsEmpty);
         //}
@@ -138,7 +147,8 @@ impl<'a> Atlas<'a> {
         assert_eq!(self.glyph_ids.len(), self.x_pos.len());
 
         let atlas = self.render();
-        let texture = self.render_api.new_texture(self.width as u16, self.height as u16, atlas);
+        let texture =
+            self.render_api.new_texture(self.width as u16, self.height as u16, atlas, debug_info);
 
         let uv_rects = self.compute_uvs();
         let glyph_ids = self.glyph_ids;

+ 1 - 1
bin/darkwallet/src/ui/chatedit.rs

@@ -710,7 +710,7 @@ impl ChatEdit {
             let rendered = text_wrap.get_render();
             let under_start = rendered.under_start;
             let under_end = rendered.under_end;
-            let atlas = text::make_texture_atlas(&self.render_api, &rendered.glyphs);
+            let atlas = text::make_texture_atlas(&self.render_api, &rendered.glyphs, "chatedit");
             let wrapped_lines = text_wrap.wrap(width);
             let selections = text_wrap.select.clone();
             (atlas, wrapped_lines, selections, under_start, under_end)

+ 8 - 8
bin/darkwallet/src/ui/chatview/page.rs

@@ -98,12 +98,12 @@ impl PrivMessage {
         if nick == "NOTICE" {
             font_size *= 0.8;
         }
-        let unwrapped_glyphs = text_shaper.shape(linetext, font_size, window_scale);
+        let unwrapped_glyphs = text_shaper.shape(linetext.clone(), font_size, window_scale);
 
         let mut atlas = text::Atlas::new(render_api);
         atlas.push(&time_glyphs);
         atlas.push(&unwrapped_glyphs);
-        let atlas = atlas.make();
+        let atlas = atlas.make(|| format!("chatview '{linetext}'"));
 
         let mut self_ = Self {
             font_size,
@@ -328,12 +328,12 @@ impl PrivMessage {
         } else {
             format!("{} {}", self.nick, self.text)
         };
-        self.unwrapped_glyphs = text_shaper.shape(linetext, font_size, window_scale);
+        self.unwrapped_glyphs = text_shaper.shape(linetext.clone(), font_size, window_scale);
 
         let mut atlas = text::Atlas::new(render_api);
         atlas.push(&self.time_glyphs);
         atlas.push(&self.unwrapped_glyphs);
-        self.atlas = atlas.make();
+        self.atlas = atlas.make(|| format!("chatview '{linetext}'"));
 
         // We need to rewrap the glyphs since they've been reloaded
         self.adjust_width(line_width, timestamp_width);
@@ -393,11 +393,11 @@ impl DateMessage {
         let datestr = Self::datestr(timestamp);
         let timestamp = Self::timest_to_midnight(timestamp);
 
-        let glyphs = text_shaper.shape(datestr, font_size, window_scale);
+        let glyphs = text_shaper.shape(datestr.clone(), font_size, window_scale);
 
         let mut atlas = text::Atlas::new(render_api);
         atlas.push(&glyphs);
-        let atlas = atlas.make();
+        let atlas = atlas.make(|| format!("chatview '{datestr}'"));
 
         Message::Date(Self { font_size, window_scale, timestamp, glyphs, atlas, mesh_cache: None })
     }
@@ -428,11 +428,11 @@ impl DateMessage {
         self.window_scale = window_scale;
 
         let datestr = Self::datestr(self.timestamp);
-        self.glyphs = text_shaper.shape(datestr, font_size, window_scale);
+        self.glyphs = text_shaper.shape(datestr.clone(), font_size, window_scale);
 
         let mut atlas = text::Atlas::new(render_api);
         atlas.push(&self.glyphs);
-        self.atlas = atlas.make();
+        self.atlas = atlas.make(|| format!("chatview '{datestr}'"));
     }
 
     //fn adjust_width(&mut self, line_width: f32) { }

+ 1 - 1
bin/darkwallet/src/ui/editbox/mod.rs

@@ -332,7 +332,7 @@ impl EditBox {
         //debug!(target: "ui::editbox", "    cursor_pos={cursor_pos}, is_focused={is_focused}");
 
         let rendered = self.editable.lock().unwrap().render();
-        let atlas = text::make_texture_atlas(&self.render_api, &rendered.glyphs);
+        let atlas = text::make_texture_atlas(&self.render_api, &rendered.glyphs, "editbox");
 
         let mut mesh = MeshBuilder::with_clip(clip.clone());
 

+ 1 - 1
bin/darkwallet/src/ui/emoji_picker/mod.rs

@@ -77,7 +77,7 @@ impl EmojiMeshes {
         // The params here don't actually matter since we're talking about BMP fixed sizes
         let glyphs = self.text_shaper.shape(emoji.to_string(), 10., 1.);
         assert_eq!(glyphs.len(), 1);
-        let atlas = text::make_texture_atlas(&self.render_api, &glyphs);
+        let atlas = text::make_texture_atlas(&self.render_api, &glyphs, "emoji");
         let glyph = glyphs.into_iter().next().unwrap();
 
         // Emoji's vary in size. We make them all a consistent size.

+ 4 - 1
bin/darkwallet/src/ui/image.rs

@@ -124,7 +124,10 @@ impl Image {
         let height = img.height() as u16;
         let bmp = img.into_raw();
 
-        let texture = self.render_api.new_texture(width, height, bmp);
+        let texture = self.render_api.new_texture(width, height, bmp, || {
+            let node = &self.node.upgrade().unwrap();
+            format!("{node:?}")
+        });
         texture
     }
 

+ 20 - 1
bin/darkwallet/src/ui/layer.rs

@@ -35,6 +35,8 @@ use super::{
     get_children_ordered, get_ui_object3, get_ui_object_ptr, DrawUpdate, OnModify, UIObject,
 };
 
+pub const DEBUG_LAYER: bool = false;
+
 pub type LayerPtr = Arc<Layer>;
 
 pub struct Layer {
@@ -186,6 +188,9 @@ impl UIObject for Layer {
         for child in self.get_children() {
             let obj = get_ui_object3(&child);
             if obj.handle_char(key, mods, repeat).await {
+                if DEBUG_LAYER {
+                    debug!(target: "layer", "handle_char({key:?}, {mods:?}, {repeat}) swallowed by {child:?}");
+                }
                 return true
             }
         }
@@ -199,7 +204,9 @@ impl UIObject for Layer {
         for child in self.get_children() {
             let obj = get_ui_object3(&child);
             if obj.handle_key_down(key, mods, repeat).await {
-                //debug!(target: "layer", "handle_key_down({key:?}, {mods:?}, {repeat}) swallowed by {child:?}");
+                if DEBUG_LAYER {
+                    debug!(target: "layer", "handle_key_down({key:?}, {mods:?}, {repeat}) swallowed by {child:?}");
+                }
                 return true
             }
         }
@@ -213,6 +220,9 @@ impl UIObject for Layer {
         for child in self.get_children() {
             let obj = get_ui_object3(&child);
             if obj.handle_key_up(key, mods).await {
+                if DEBUG_LAYER {
+                    debug!(target: "layer", "handle_key_up({key:?}, {mods:?}) swallowed by {child:?}");
+                }
                 return true
             }
         }
@@ -226,6 +236,9 @@ impl UIObject for Layer {
         for child in self.get_children() {
             let obj = get_ui_object3(&child);
             if obj.handle_mouse_btn_down(btn, mouse_pos).await {
+                if DEBUG_LAYER {
+                    debug!(target: "layer", "handle_mouse_btn_down({btn:?}, {mouse_pos:?}) swallowed by {child:?}");
+                }
                 return true
             }
         }
@@ -239,6 +252,9 @@ impl UIObject for Layer {
         for child in self.get_children() {
             let obj = get_ui_object3(&child);
             if obj.handle_mouse_btn_up(btn, mouse_pos).await {
+                if DEBUG_LAYER {
+                    debug!(target: "layer", "handle_mouse_btn_up({btn:?}, {mouse_pos:?}) swallowed by {child:?}");
+                }
                 return true
             }
         }
@@ -252,6 +268,9 @@ impl UIObject for Layer {
         for child in self.get_children() {
             let obj = get_ui_object3(&child);
             if obj.handle_mouse_move(mouse_pos).await {
+                if DEBUG_LAYER {
+                    debug!(target: "layer", "handle_mouse_move({mouse_pos:?}) swallowed by {child:?}");
+                }
                 return true
             }
         }

+ 1 - 1
bin/darkwallet/src/ui/text.rs

@@ -123,7 +123,7 @@ impl Text {
 
         debug!(target: "ui::text", "Rendering label '{}'", text);
         let glyphs = self.text_shaper.shape(text, font_size, window_scale);
-        let atlas = text::make_texture_atlas(&self.render_api, &glyphs);
+        let atlas = text::make_texture_atlas(&self.render_api, &glyphs, "text");
 
         let mut mesh = MeshBuilder::new();
         let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);