1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Track palette realization state

This commit is contained in:
narzoul 2021-01-26 22:56:51 +01:00
parent 39bb699cf7
commit 922d17d283
2 changed files with 108 additions and 53 deletions

View File

@ -1,16 +1,28 @@
#include <set> #include <map>
#include "Common/Hook.h" #include <Common/Hook.h>
#include "Common/Log.h" #include <Common/Log.h>
#include "Common/ScopedCriticalSection.h" #include <Common/ScopedSrwLock.h>
#include "Gdi/Gdi.h" #include <Gdi/Gdi.h>
#include "Gdi/Palette.h" #include <Gdi/Palette.h>
#include "VirtualScreen.h" #include <Gdi/VirtualScreen.h>
#include "Win32/DisplayMode.h" #include <Win32/DisplayMode.h>
namespace namespace
{ {
Compat::CriticalSection g_cs; struct PaletteInfo
{
bool isForeground;
bool isRealized;
PaletteInfo()
: isForeground(false)
, isRealized(false)
{
}
};
Compat::SrwLock g_srwLock;
PALETTEENTRY g_defaultPalette[256] = {}; PALETTEENTRY g_defaultPalette[256] = {};
PALETTEENTRY g_hardwarePalette[256] = {}; PALETTEENTRY g_hardwarePalette[256] = {};
PALETTEENTRY g_systemPalette[256] = {}; PALETTEENTRY g_systemPalette[256] = {};
@ -19,7 +31,7 @@ namespace
UINT g_systemPaletteFirstNonReservedIndex = 10; UINT g_systemPaletteFirstNonReservedIndex = 10;
UINT g_systemPaletteLastNonReservedIndex = 245; UINT g_systemPaletteLastNonReservedIndex = 245;
std::set<HPALETTE> g_foregroundPalettes; std::map<HPALETTE, PaletteInfo> g_paletteInfo;
bool isSameColor(PALETTEENTRY entry1, PALETTEENTRY entry2) bool isSameColor(PALETTEENTRY entry1, PALETTEENTRY entry2)
{ {
@ -57,9 +69,9 @@ namespace
return; return;
} }
memcpy(g_systemPalette, g_defaultPalette, count * sizeof(g_systemPalette[0])); std::memcpy(g_systemPalette, g_defaultPalette, count * sizeof(g_systemPalette[0]));
memcpy(&g_systemPalette[256 - count], &g_defaultPalette[256 - count], count * sizeof(g_systemPalette[0])); std::memcpy(&g_systemPalette[256 - count], &g_defaultPalette[256 - count], count * sizeof(g_systemPalette[0]));
Gdi::Palette::setHardwarePalette(g_systemPalette); std::memcpy(g_hardwarePalette, g_systemPalette, sizeof(g_hardwarePalette));
Gdi::VirtualScreen::updatePalette(g_systemPalette); Gdi::VirtualScreen::updatePalette(g_systemPalette);
} }
@ -68,8 +80,8 @@ namespace
BOOL result = CALL_ORIG_FUNC(DeleteObject)(ho); BOOL result = CALL_ORIG_FUNC(DeleteObject)(ho);
if (result && OBJ_PAL == GetObjectType(ho)) if (result && OBJ_PAL == GetObjectType(ho))
{ {
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockExclusive lock(g_srwLock);
g_foregroundPalettes.erase(static_cast<HPALETTE>(ho)); g_paletteInfo.erase(static_cast<HPALETTE>(ho));
} }
return result; return result;
} }
@ -97,7 +109,7 @@ namespace
nEntries = 256 - iStartIndex; nEntries = 256 - iStartIndex;
} }
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockShared lock(g_srwLock);
std::memcpy(lppe, &g_systemPalette[iStartIndex], nEntries * sizeof(PALETTEENTRY)); std::memcpy(lppe, &g_systemPalette[iStartIndex], nEntries * sizeof(PALETTEENTRY));
return LOG_RESULT(nEntries); return LOG_RESULT(nEntries);
@ -110,7 +122,7 @@ namespace
{ {
return LOG_RESULT(SYSPAL_ERROR); return LOG_RESULT(SYSPAL_ERROR);
} }
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockShared lock(g_srwLock);
return LOG_RESULT(g_systemPaletteUse); return LOG_RESULT(g_systemPaletteUse);
} }
@ -126,15 +138,57 @@ namespace
} }
PALETTEENTRY entries[256] = {}; PALETTEENTRY entries[256] = {};
UINT count = GetPaletteEntries(palette, 0, 256, entries); const UINT count = GetPaletteEntries(palette, 0, 256, entries);
Compat::ScopedCriticalSection lock(g_cs);
Gdi::Palette::setSystemPalette(entries, count, Compat::ScopedSrwLockExclusive lock(g_srwLock);
g_foregroundPalettes.find(palette) == g_foregroundPalettes.end()); auto& paletteInfo = g_paletteInfo[palette];
if (paletteInfo.isRealized)
{
return LOG_RESULT(0);
}
if (paletteInfo.isForeground)
{
g_systemPaletteFirstUnusedIndex = g_systemPaletteFirstNonReservedIndex;
for (auto& pi : g_paletteInfo)
{
pi.second.isRealized = false;
}
}
for (UINT i = 0; i < count && g_systemPaletteFirstUnusedIndex <= g_systemPaletteLastNonReservedIndex; ++i)
{
if ((entries[i].peFlags & PC_EXPLICIT) ||
0 == (entries[i].peFlags & (PC_NOCOLLAPSE | PC_RESERVED)) && exactMatch(entries[i]))
{
continue;
}
g_systemPalette[g_systemPaletteFirstUnusedIndex] = entries[i];
g_systemPalette[g_systemPaletteFirstUnusedIndex].peFlags = 0;
++g_systemPaletteFirstUnusedIndex;
}
paletteInfo.isRealized = true;
std::memcpy(g_hardwarePalette, g_systemPalette, sizeof(g_hardwarePalette));
Gdi::VirtualScreen::updatePalette(g_systemPalette);
return LOG_RESULT(count); return LOG_RESULT(count);
} }
return LOG_RESULT(CALL_ORIG_FUNC(RealizePalette)(hdc)); return LOG_RESULT(CALL_ORIG_FUNC(RealizePalette)(hdc));
} }
BOOL WINAPI resizePalette(HPALETTE hpal, UINT n)
{
LOG_FUNC("ResizePalette", hpal, n);
BOOL result = CALL_ORIG_FUNC(ResizePalette)(hpal, n);
if (result)
{
Compat::ScopedSrwLockExclusive lock(g_srwLock);
g_paletteInfo[hpal].isRealized = false;
}
return LOG_RESULT(result);
}
HPALETTE WINAPI selectPalette(HDC hdc, HPALETTE hpal, BOOL bForceBackground) HPALETTE WINAPI selectPalette(HDC hdc, HPALETTE hpal, BOOL bForceBackground)
{ {
LOG_FUNC("SelectPalette", hdc, hpal, bForceBackground); LOG_FUNC("SelectPalette", hdc, hpal, bForceBackground);
@ -147,14 +201,26 @@ namespace
HWND activeWindow = GetActiveWindow(); HWND activeWindow = GetActiveWindow();
if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow)) if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow))
{ {
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockExclusive lock(g_srwLock);
g_foregroundPalettes.insert(hpal); g_paletteInfo[hpal].isForeground = true;
} }
} }
} }
return LOG_RESULT(result); return LOG_RESULT(result);
} }
UINT WINAPI setPaletteEntries(HPALETTE hpal, UINT iStart, UINT cEntries, const PALETTEENTRY* pPalEntries)
{
LOG_FUNC("SetPaletteEntries", hpal, iStart, cEntries, pPalEntries);
UINT result = CALL_ORIG_FUNC(SetPaletteEntries)(hpal, iStart, cEntries, pPalEntries);
if (result)
{
Compat::ScopedSrwLockExclusive lock(g_srwLock);
g_paletteInfo[hpal].isRealized = false;
}
return LOG_RESULT(result);
}
UINT WINAPI setSystemPaletteUse(HDC hdc, UINT uUsage) UINT WINAPI setSystemPaletteUse(HDC hdc, UINT uUsage)
{ {
LOG_FUNC("SetSystemPaletteUse", hdc, uUsage); LOG_FUNC("SetSystemPaletteUse", hdc, uUsage);
@ -163,7 +229,7 @@ namespace
return LOG_RESULT(SYSPAL_ERROR); return LOG_RESULT(SYSPAL_ERROR);
} }
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockExclusive lock(g_srwLock);
if (uUsage == g_systemPaletteUse) if (uUsage == g_systemPaletteUse)
{ {
return LOG_RESULT(g_systemPaletteUse); return LOG_RESULT(g_systemPaletteUse);
@ -195,6 +261,18 @@ namespace
updateStaticSysPalEntries(); updateStaticSysPalEntries();
return LOG_RESULT(prevUsage); return LOG_RESULT(prevUsage);
} }
BOOL WINAPI unrealizeObject(HGDIOBJ h)
{
LOG_FUNC("UnrealizeObject", h);
BOOL result = CALL_ORIG_FUNC(UnrealizeObject)(h);
if (result && OBJ_PAL == GetObjectType(h))
{
Compat::ScopedSrwLockExclusive lock(g_srwLock);
g_paletteInfo[static_cast<HPALETTE>(h)].isRealized = false;
}
return LOG_RESULT(result);
}
} }
namespace Gdi namespace Gdi
@ -208,13 +286,13 @@ namespace Gdi
std::vector<PALETTEENTRY> getHardwarePalette() std::vector<PALETTEENTRY> getHardwarePalette()
{ {
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockShared lock(g_srwLock);
return std::vector<PALETTEENTRY>(g_hardwarePalette, g_hardwarePalette + 256); return std::vector<PALETTEENTRY>(g_hardwarePalette, g_hardwarePalette + 256);
} }
std::vector<PALETTEENTRY> getSystemPalette() std::vector<PALETTEENTRY> getSystemPalette()
{ {
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockShared lock(g_srwLock);
return std::vector<PALETTEENTRY>(g_systemPalette, g_systemPalette + 256); return std::vector<PALETTEENTRY>(g_systemPalette, g_systemPalette + 256);
} }
@ -230,39 +308,17 @@ namespace Gdi
HOOK_FUNCTION(gdi32, GetSystemPaletteEntries, getSystemPaletteEntries); HOOK_FUNCTION(gdi32, GetSystemPaletteEntries, getSystemPaletteEntries);
HOOK_FUNCTION(gdi32, GetSystemPaletteUse, getSystemPaletteUse); HOOK_FUNCTION(gdi32, GetSystemPaletteUse, getSystemPaletteUse);
HOOK_FUNCTION(gdi32, RealizePalette, realizePalette); HOOK_FUNCTION(gdi32, RealizePalette, realizePalette);
HOOK_FUNCTION(gdi32, ResizePalette, resizePalette);
HOOK_FUNCTION(gdi32, SelectPalette, selectPalette); HOOK_FUNCTION(gdi32, SelectPalette, selectPalette);
HOOK_FUNCTION(gdi32, SetPaletteEntries, setPaletteEntries);
HOOK_FUNCTION(gdi32, SetSystemPaletteUse, setSystemPaletteUse); HOOK_FUNCTION(gdi32, SetSystemPaletteUse, setSystemPaletteUse);
HOOK_FUNCTION(gdi32, UnrealizeObject, unrealizeObject);
} }
void setHardwarePalette(PALETTEENTRY* entries) void setHardwarePalette(PALETTEENTRY* entries)
{ {
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedSrwLockExclusive lock(g_srwLock);
std::memcpy(g_hardwarePalette, entries, sizeof(g_hardwarePalette)); std::memcpy(g_hardwarePalette, entries, sizeof(g_hardwarePalette));
} }
void setSystemPalette(PALETTEENTRY* entries, DWORD count, bool forceBackground)
{
Compat::ScopedCriticalSection lock(g_cs);
if (!forceBackground)
{
g_systemPaletteFirstUnusedIndex = g_systemPaletteFirstNonReservedIndex;
}
for (UINT i = 0; i < count && g_systemPaletteFirstUnusedIndex <= g_systemPaletteLastNonReservedIndex; ++i)
{
if ((entries[i].peFlags & PC_EXPLICIT) ||
0 == (entries[i].peFlags & (PC_NOCOLLAPSE | PC_RESERVED)) && exactMatch(entries[i]))
{
continue;
}
g_systemPalette[g_systemPaletteFirstUnusedIndex] = entries[i];
g_systemPalette[g_systemPaletteFirstUnusedIndex].peFlags = 0;
++g_systemPaletteFirstUnusedIndex;
}
Gdi::Palette::setHardwarePalette(g_systemPalette);
Gdi::VirtualScreen::updatePalette(g_systemPalette);
}
} }
} }

View File

@ -13,6 +13,5 @@ namespace Gdi
std::vector<PALETTEENTRY> getSystemPalette(); std::vector<PALETTEENTRY> getSystemPalette();
void installHooks(); void installHooks();
void setHardwarePalette(PALETTEENTRY* entries); void setHardwarePalette(PALETTEENTRY* entries);
void setSystemPalette(PALETTEENTRY* entries, DWORD count, bool forceBackground);
} }
} }