perf(win): skip DWM blur/acrylic when the window starts opaque

The window always asked DWM for a full-window blur region and, on
Windows 11, an acrylic backdrop. When the user runs with an opaque
window (low-spec mode or full opacity) that desktop blur is never seen
but DWM still composites it every frame.

- An early read of the saved settings decides whether the window starts
  opaque before the backdrop is configured.
- When it does, the full-window blur region is left as SDL's zero-area
  default and the backdrop type is set to none instead of acrylic.

Windows-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 18:16:50 -05:00
co-authored by Claude Opus 4.8
parent 53da160546
commit fa1ba97286
+6 -1
View File
@@ -986,11 +986,13 @@ int main(int argc, char* argv[])
int savedWinW = 1200, savedWinH = 720; int savedWinW = 1200, savedWinH = 720;
float earlyFontScale = 1.0f; // consumed below, before the first (and only) font-atlas build float earlyFontScale = 1.0f; // consumed below, before the first (and only) font-atlas build
bool earlyEmojiColor = false; bool earlyEmojiColor = false;
bool earlyOpaque = false; // opaque start: skip DWM blur/acrylic backdrop (Windows)
{ {
dragonx::config::Settings earlySettings; dragonx::config::Settings earlySettings;
const bool earlyLoaded = earlySettings.load(); const bool earlyLoaded = earlySettings.load();
earlyFontScale = earlySettings.getFontScale(); // defaults when load failed, same as App::init sees earlyFontScale = earlySettings.getFontScale(); // defaults when load failed, same as App::init sees
earlyEmojiColor = earlySettings.getChatEmojiColor(); earlyEmojiColor = earlySettings.getChatEmojiColor();
earlyOpaque = earlySettings.getLowSpecMode() || earlySettings.getWindowOpacity() >= 0.99f;
if (earlyLoaded) { if (earlyLoaded) {
int sw = earlySettings.getWindowWidth(); int sw = earlySettings.getWindowWidth();
int sh = earlySettings.getWindowHeight(); int sh = earlySettings.getWindowHeight();
@@ -1163,6 +1165,8 @@ int main(int argc, char* argv[])
if (hwnd_blur) { if (hwnd_blur) {
// Override SDL's zero-area blur region with a full-window blur. // Override SDL's zero-area blur region with a full-window blur.
// This gives DWM the signal to blur everything behind our window. // This gives DWM the signal to blur everything behind our window.
// Skipped when the window starts opaque (SDL's zero-area region stays).
if (!earlyOpaque) {
HRGN blurRgn = CreateRectRgn(0, 0, -1, -1); // full window HRGN blurRgn = CreateRectRgn(0, 0, -1, -1); // full window
DWM_BLURBEHIND bb = {}; DWM_BLURBEHIND bb = {};
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
@@ -1171,6 +1175,7 @@ int main(int argc, char* argv[])
HRESULT hr_blur = DwmEnableBlurBehindWindow(hwnd_blur, &bb); HRESULT hr_blur = DwmEnableBlurBehindWindow(hwnd_blur, &bb);
DeleteObject(blurRgn); DeleteObject(blurRgn);
DEBUG_LOGF("DwmEnableBlurBehindWindow (full region): 0x%08lx\n", hr_blur); DEBUG_LOGF("DwmEnableBlurBehindWindow (full region): 0x%08lx\n", hr_blur);
}
// On Windows 11 22H2+, also enable Acrylic for nicer modern blur // On Windows 11 22H2+, also enable Acrylic for nicer modern blur
auto ver = dragonx::platform::getWindowsVersion(); auto ver = dragonx::platform::getWindowsVersion();
@@ -1188,7 +1193,7 @@ int main(int argc, char* argv[])
// Acrylic = blurred, semi-transparent desktop view // Acrylic = blurred, semi-transparent desktop view
// (NOT Mica which is opaque) // (NOT Mica which is opaque)
DWORD backdrop = 3; // DWMSBT_TRANSIENTWINDOW = Acrylic DWORD backdrop = earlyOpaque ? 1 /*DWMSBT_NONE*/ : 3 /*DWMSBT_TRANSIENTWINDOW = Acrylic*/;
HRESULT hr_acr = DwmSetWindowAttribute(hwnd_blur, 38, HRESULT hr_acr = DwmSetWindowAttribute(hwnd_blur, 38,
&backdrop, sizeof(backdrop)); &backdrop, sizeof(backdrop));
DEBUG_LOGF("DWM Acrylic (DWMSBT_TRANSIENTWINDOW): 0x%08lx\n", hr_acr); DEBUG_LOGF("DWM Acrylic (DWMSBT_TRANSIENTWINDOW): 0x%08lx\n", hr_acr);