Hide menu pictures only inside the menu frames

The hidden-texture list stayed active in a game; a game texture made at the
address of a freed menu picture was skipped (rendering glitches in-game).
Hiding now applies only while the main menu's frame or the in-game options
draw over the menu background.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-21 00:10:30 +02:00
1 parent db87e276bf
commit c4aacbcdd2
2 files changed
+20 -4

No files matched your search

+17 -2
View File
@@ -409,10 +409,22 @@ DrawPrimitiveFn g_drawPrimitive = nullptr;
DrawIndexedPrimitiveFn g_drawIndexedPrimitive = nullptr;
// Textures not drawn (SetHiddenTextures): the surface bound to stage 0 is
// tracked per thread (each thread draws with its own device calls).
// tracked per thread (each thread draws with its own device calls). Only
// inside a frame drawn over the menu background (g_hidingPictures: the main
// menu's, the options' in a game): the list keeps surfaces the cache may
// have freed since, and a game texture made at the same address was skipped
// in the world view (user, 2026-10-21: "rendering glitches ingame").
constexpr int kHiddenTextureMax = 64;
std::atomic<void*> g_hiddenTextures[kHiddenTextureMax] = {};
thread_local void* g_boundTexture = nullptr;
thread_local int g_hidingPictures = 0;
struct HidingPictures {
HidingPictures() { ++g_hidingPictures; }
~HidingPictures() { --g_hidingPictures; }
HidingPictures(const HidingPictures&) = delete;
HidingPictures& operator=(const HidingPictures&) = delete;
};
using SetTextureFn = HRESULT(__stdcall*)(void* device, DWORD stage, void* surface);
SetTextureFn g_setTexture = nullptr;
@@ -425,7 +437,7 @@ HRESULT __stdcall SetTextureTracked(void* device, DWORD stage, void* surface) {
}
bool BoundTextureHidden() {
if (!g_boundTexture) {
if (!g_boundTexture || g_hidingPictures == 0) {
return false;
}
for (const auto& hidden : g_hiddenTextures) {
@@ -521,9 +533,11 @@ public:
Viewport7 frame = {static_cast<DWORD>(dx), 0, kLayoutWidth, 768, previous_.minZ, previous_.maxZ};
device_ = device;
g_setViewport(device, &frame);
++g_hidingPictures;
}
~FrameScope() {
if (device_) {
--g_hidingPictures;
g_setViewport(device_, &previous_);
}
}
@@ -872,6 +886,7 @@ int RenderMenuFrame(void* device, bool framed, int (*body)(void* context), void*
const int width = mods::widescreen::RenderWidth();
const int dx = framed && width > kLayoutWidth ? (width - kLayoutWidth) / 2 : 0;
g_menuFrameDx = dx;
HidingPictures hiding;
Viewport7 previous;
auto getViewport =
device ? reinterpret_cast<GetViewportFn>((*static_cast<void***>(device))[kVtableGetViewport]) : nullptr;