Commit Graph
5 Commits
Author SHA1 Message Date
DanSandClaude Opus 4.8 968d6d3875 fix(effects): capture the acrylic backdrop at framebuffer size on HiDPI
The acrylic effect blits its backdrop from the default framebuffer using
the logical viewport size as the source rectangle. On a HiDPI display
the framebuffer is larger than the logical size, so the blur sampled
only the lower-left corner of the screen and the glass showed the wrong
region stretched across each panel.

- The capture blit source now uses the real framebuffer pixel size
  (logical size times ImGui's DisplayFramebufferScale, truncated the
  same way the GL backend does), while the capture and blur targets stay
  at logical size. The framebuffer size is tracked separately from the
  viewport size so quality or buffer-lifetime resets cannot lose it, and
  moving the window between a Retina and a non-Retina display redoes the
  capture. DX11 is unaffected; its scale is one.
- The debug screenshot sweep captures at framebuffer size too, so HiDPI
  captures are no longer cropped.

Tests: the framebuffer-extent helper matches the GL backend's
truncation and falls back to the logical size when the scale is unknown.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-13 13:30:20 -05:00
DanSandClaude Opus 5.5 261883ca21 perf(acrylic): release blur render targets while the effect is skipped
Turning blur off (blur 0), switching to low-spec mode or enabling
reduced transparency after the acrylic targets existed left the capture
FBO and both blur ping-pong targets allocated for the rest of the
session, although nothing draws with them while the effect is skipped.

They are now released at a frame boundary and rebuilt on demand:
- ImGuiAcrylic::ReleaseIdleBuffers() runs right after app.preFrame(),
  before NewFrame(), when the previous frame's draw data has been
  rendered, and once in the resize-watcher frame (GL and DX11). While
  the effect is skipped it frees the targets; when the effect is wanted
  again it reallocates them once, with no per-frame retry if that fails;
- resize() while skipped only records that a reallocation is needed;
- the release checks the GL names (and each DX11 texture) directly, so a
  half-allocated ping-pong pair is freed too; DX11 also resets the
  ping-pong index;
- the capture paths and applyBlur() return early without a capture
  buffer, which would otherwise blit the default framebuffer onto
  itself;
- each release logs "released targets (effect skipped)".

With blur on, the path and the output are unchanged (screenshot sweeps
within noise). After re-enabling, the first frame draws the tinted
fallback until a fresh capture exists.

Measured with software GL, toggling every 30 frames for 1200 frames: the
targets were released exactly one frame after each switch-off (22 of 22)
and rebuilt on each switch-on (21 of 21), with no GL or framebuffer
errors. While off at 1280x720, with a fixed malloc mmap threshold, the
process holds 4.62 MB less (the 1280x720 RGBA8 capture plus two 320x180
RGBA16F blur targets) and RssAnon is about 3.1-3.5 MB lower. With
glibc's default threshold the freed memory stays in the heap and RssAnon
does not visibly drop.

Known issue: every off/on pair now frees and reallocates those targets.
Under software GL (llvmpipe) with the default glibc allocator the freed
texture memory is not reused: toggling every 2 frames grew RssAnon from
49 to 906 MB over 240 pairs, every 8 frames from 56 to 179 MB, and every
30 frames it levels off near 120 MB. It is not a GL object leak (with a
fixed mmap threshold the mapped bytes stay flat), and on a hardware
driver (WSLg d3d12) RssAnon stayed between 67.5 and 74.9 MB under the
2-frame churn (94.3 MB without the release). Users reach fast toggling
by holding Ctrl+Shift+Down (key repeat, about 20 Hz) or by dragging the
blur slider back and forth across 0. A short delay before releasing
would avoid it if software-rendered users matter.

Not verifiable here: the DX11 release and reallocation at runtime, and
macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 06:05:07 -05:00
DanSandClaude Opus 4.8 0e8816e220 feat(effects): overlay-time live-framebuffer blur behind the portfolio modal
The acrylic system only blurred a frozen snapshot of the static app background. Add
an overlay-time re-capture so the Manage-portfolio modal blurs the LIVE tab content
behind it.

- AcrylicMaterial::captureLiveFramebuffer() (GL blit of FB 0 / DX11 CopyResource of the
  backbuffer + no-backend stub) mirrors captureBackgroundDirect but bypasses the
  dirtyFrames_ gate so it refreshes every frame the overlay is open, forcing a re-blur.
- ImGuiAcrylic::GetLiveCaptureCallback() returns a draw callback for it.
- market_tab: the modal inserts that callback (+ ImDrawCallback_ResetRenderState) at the
  START of its overlay draw list, before the backdrop, so the capture holds the app UI
  drawn below and the backdrop blurs it. On close, InvalidateCapture() re-captures the
  background so other glass panels don't keep blurring the stale live capture.
- Panel theme-effects are suppressed during the market render while the modal is open
  (their foreground-draw-list borders draw above all windows and would otherwise bleed
  over the overlay). Market tab body is rendered again (no longer skipped).
- Backdrop draws the acrylic at full strength (fallbackColor.w=1) over an opaque base so
  the blurred content reads clearly; lighter dim.

Design mapped via an Explore investigation of the capture/blur pipeline; compiles on
both OpenGL (Linux) and DX11 (Windows cross-build). Needs on-device visual verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 20:26:11 -05:00
DanSandClaude Opus 4.8 280a71e973 refactor(audit): batch 3 — decompose App::update() + collapse acrylic fork
Three P1 structural refactors from the audit; no behavior change.

1. Extract the ~180-line daemon-stdout rescan/witness parser out of the
   ~790-line App::update() into a pure, static, unit-testable
   NetworkRefreshService::parseDaemonRescanOutput() returning a
   DaemonRescanScan result struct (sits next to the existing static parse*
   siblings). The scanning half moved verbatim; App::update() keeps the
   state-application half, now reading scan.* fields. Adds
   testParseDaemonRescanOutput() covering all six daemon signals + edge
   cases against fixture log snippets — previously untestable without a
   live daemon.

2. Extract the ~95-line global keyboard-shortcut block (Ctrl+, / theme
   cycle / F5 / low-spec / effects / gradient / wizard) out of
   App::update() into App::handleGlobalShortcuts().

3. Collapse the ImGuiAcrylic frontend fork: the GLAD and DX11 namespaces
   were ~375 lines of semantically-identical code (the frontend makes zero
   direct GL/DX calls — all backend work delegates to AcrylicMaterial, which
   has a backend per API). Extended the single frontend's guard to
   #if defined(DRAGONX_HAS_GLAD) || defined(DRAGONX_USE_DX11) and deleted the
   DX11 duplicate, leaving the no-backend stub. Kills the Windows/DX11 drift
   hazard (acrylic frontend changes now made once).

Verified: full-node + Lite build clean; ctest 1/1 (incl. the new parser
tests); source-hygiene clean; and the collapsed acrylic path was
compile-verified under DX11 via the mingw-w64 Windows cross-build
(ObsidianDragon.exe links).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 16:40:40 -05:00
DanS 3aee55b49c ObsidianDragon - DragonX ImGui Wallet
Full-node GUI wallet for DragonX cryptocurrency.
Built with Dear ImGui, SDL3, and OpenGL3/DX11.

Features:
- Send/receive shielded and transparent transactions
- Autoshield with merged transaction display
- Built-in CPU mining (xmrig)
- Peer management and network monitoring
- Wallet encryption with PIN lock
- QR code generation for receive addresses
- Transaction history with pagination
- Console for direct RPC commands
- Cross-platform (Linux, Windows)
2026-02-27 00:26:01 -06:00