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>
This commit is contained in:
2026-10-13 13:30:20 -05:00
co-authored by Claude Opus 4.8
parent fdd95aa457
commit 968d6d3875
9 changed files with 72 additions and 10 deletions
+13
View File
@@ -71,6 +71,7 @@
#include "ui/staleness_badge.h"
#include "ui/effects/effect_clock.h"
#include "ui/effects/border_sampling.h"
#include "ui/effects/capture_extent.h"
#include "ui/material/rect_cull.h"
#include "ui/notifications.h"
#include "data/seed_migration_resume.h"
@@ -17931,6 +17932,17 @@ void testLoadLanguageFromLooseFiles()
EXPECT_EQ(std::string(i18n.translate("overview")), std::string("Overview"));
}
void testCaptureExtent()
{
using namespace dragonx::ui::effects;
EXPECT_EQ(framebufferExtent(1280.0f, 1.0f), 1280);
EXPECT_EQ(framebufferExtent(1280.0f, 2.0f), 2560);
EXPECT_EQ(framebufferExtent(1001.0f, 1.5f), 1501); // truncation, same as imgui_impl_opengl3.cpp
EXPECT_EQ(framebufferExtent(800.0f, 0.0f), 800); // unknown/zero scale -> logical
EXPECT_EQ(captureSourceExtent(0, 1280), 1280);
EXPECT_EQ(captureSourceExtent(2560, 1280), 2560);
}
// resources::writeFileIfDifferent (bundled-theme extraction): rewrite a file only when its bytes differ.
void testWriteFileIfDifferent()
{
@@ -18312,6 +18324,7 @@ int main()
testTextFitBanner();
testLoadLanguageFromLooseFiles();
testWriteFileIfDifferent();
testCaptureExtent();
if (g_failures != 0) {
std::cerr << g_failures << " test assertion(s) failed\n";