perf: @setRuntimeSafety(false) + burst detection infrastructure
- fillRect: disable runtime safety for hot path (bounds pre-validated) - drawGlyphBitmap: disable runtime safety for hot path - Context: add burst detection (isSelectionBurstActive, markNavigationEvent) - PanelFrameConfig: add burst_sensitive field - PanelFrameResult: new struct for frame drawing results Note: burst_sensitive mechanism available but not actively used (causes visual flickering when suppressing panel content) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
84bf37cd89
commit
4ce39c4fc8
3 changed files with 45 additions and 3 deletions
|
|
@ -102,6 +102,10 @@ pub const Context = struct {
|
||||||
/// Set by application for non-dirty panels to save CPU while keeping input working.
|
/// Set by application for non-dirty panels to save CPU while keeping input working.
|
||||||
suppress_commands: bool = false,
|
suppress_commands: bool = false,
|
||||||
|
|
||||||
|
/// Burst detection: timestamp of last navigation event (selection change)
|
||||||
|
/// Used by drawPanelFrame to auto-suppress burst_sensitive panels during rapid navigation
|
||||||
|
last_navigation_time: i64 = 0,
|
||||||
|
|
||||||
/// Frame statistics
|
/// Frame statistics
|
||||||
stats: FrameStats,
|
stats: FrameStats,
|
||||||
|
|
||||||
|
|
@ -665,10 +669,24 @@ pub const Context = struct {
|
||||||
draw_shadow: bool = true,
|
draw_shadow: bool = true,
|
||||||
/// Draw bevel effect (default true)
|
/// Draw bevel effect (default true)
|
||||||
draw_bevel: bool = true,
|
draw_bevel: bool = true,
|
||||||
|
|
||||||
|
// === Performance ===
|
||||||
|
/// Si true, el panel se auto-suprime durante ráfagas de navegación.
|
||||||
|
/// Paneles principales (listas, fichas) deben ser false.
|
||||||
|
/// Paneles secundarios (documentos) pueden ser true para mejor rendimiento.
|
||||||
|
burst_sensitive: bool = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Result of drawPanelFrame for LEGO-style control flow
|
||||||
|
pub const PanelFrameResult = struct {
|
||||||
|
/// True if color transition is still animating
|
||||||
|
animating: bool,
|
||||||
|
/// False if panel was suppressed - caller should return immediately
|
||||||
|
should_draw: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Draw a complete panel frame with focus transition and 3D effects.
|
/// Draw a complete panel frame with focus transition and 3D effects.
|
||||||
/// Returns true if the transition is still animating (need more frames).
|
/// Returns PanelFrameResult: check should_draw to know if panel content should be rendered.
|
||||||
///
|
///
|
||||||
/// Supports two modes:
|
/// Supports two modes:
|
||||||
/// - **Explicit**: Provide focus_bg, unfocus_bg, border_color directly
|
/// - **Explicit**: Provide focus_bg, unfocus_bg, border_color directly
|
||||||
|
|
@ -678,7 +696,11 @@ pub const Context = struct {
|
||||||
rect: Layout.Rect,
|
rect: Layout.Rect,
|
||||||
transition: *ColorTransition,
|
transition: *ColorTransition,
|
||||||
config: PanelFrameConfig,
|
config: PanelFrameConfig,
|
||||||
) bool {
|
) PanelFrameResult {
|
||||||
|
// Auto-supresión LEGO: detectar si el panel debe suprimir operaciones costosas
|
||||||
|
// El frame SIEMPRE se dibuja, pero should_draw indica si continuar con widgets/BD
|
||||||
|
const burst_suppressed = config.burst_sensitive and self.isSelectionBurstActive();
|
||||||
|
|
||||||
// Determine colors: Z-Design derivation or explicit
|
// Determine colors: Z-Design derivation or explicit
|
||||||
const focus_bg: Style.Color = blk: {
|
const focus_bg: Style.Color = blk: {
|
||||||
if (config.base_color) |base| {
|
if (config.base_color) |base| {
|
||||||
|
|
@ -764,7 +786,8 @@ pub const Context = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return animating;
|
// should_draw = false indica que el panel debe saltar operaciones costosas (BD, widgets)
|
||||||
|
return .{ .animating = animating, .should_draw = !burst_suppressed };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resize the context
|
/// Resize the context
|
||||||
|
|
@ -837,6 +860,23 @@ pub const Context = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// BURST DETECTION: Para auto-supresión de paneles durante navegación rápida
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
/// Marca que ocurrió un evento de navegación (cambio de selección).
|
||||||
|
/// Llamar desde DataManager cuando notifica cambios de selección.
|
||||||
|
pub fn markNavigationEvent(self: *Self) void {
|
||||||
|
self.last_navigation_time = std.time.milliTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve true si estamos en medio de una ráfaga de navegación.
|
||||||
|
/// Se considera ráfaga si pasaron menos de 100ms desde el último evento.
|
||||||
|
pub fn isSelectionBurstActive(self: *Self) bool {
|
||||||
|
const now = std.time.milliTimestamp();
|
||||||
|
return (now - self.last_navigation_time) < 100;
|
||||||
|
}
|
||||||
|
|
||||||
/// Get rectangles of all dirty panels (for renderer).
|
/// Get rectangles of all dirty panels (for renderer).
|
||||||
/// Returns slice allocated from frame arena (valid until next beginFrame).
|
/// Returns slice allocated from frame arena (valid until next beginFrame).
|
||||||
pub fn getDirtyPanelRects(self: *Self) []const Layout.Rect {
|
pub fn getDirtyPanelRects(self: *Self) []const Layout.Rect {
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ pub const Framebuffer = struct {
|
||||||
/// Draw a filled rectangle
|
/// Draw a filled rectangle
|
||||||
/// Optimized with SIMD-friendly @memset for solid colors (alpha=255)
|
/// Optimized with SIMD-friendly @memset for solid colors (alpha=255)
|
||||||
pub fn fillRect(self: *Self, x: i32, y: i32, w: u32, h: u32, color: Color) void {
|
pub fn fillRect(self: *Self, x: i32, y: i32, w: u32, h: u32, color: Color) void {
|
||||||
|
@setRuntimeSafety(false); // Hot path: bounds already validated below
|
||||||
const x_start = @max(0, x);
|
const x_start = @max(0, x);
|
||||||
const y_start = @max(0, y);
|
const y_start = @max(0, y);
|
||||||
const x_end = @min(@as(i32, @intCast(self.width)), x + @as(i32, @intCast(w)));
|
const x_end = @min(@as(i32, @intCast(self.width)), x + @as(i32, @intCast(w)));
|
||||||
|
|
|
||||||
|
|
@ -320,6 +320,7 @@ pub const TtfFont = struct {
|
||||||
color: Color,
|
color: Color,
|
||||||
clip: Rect,
|
clip: Rect,
|
||||||
) void {
|
) void {
|
||||||
|
@setRuntimeSafety(false); // Hot path: bounds validated in visible region calculation
|
||||||
_ = self;
|
_ = self;
|
||||||
|
|
||||||
const width: u32 = glyph.metrics.width;
|
const width: u32 = glyph.metrics.width;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue