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

Use RealizePalette for windowed mode palette changes

This commit is contained in:
narzoul 2021-01-24 21:49:16 +01:00
parent 950bde4161
commit 39bb699cf7
5 changed files with 71 additions and 48 deletions

View File

@ -13,6 +13,12 @@ namespace DDraw
DDPIXELFORMAT getRgbPixelFormat(DWORD bpp); DDPIXELFORMAT getRgbPixelFormat(DWORD bpp);
void suppressEmulatedDirectDraw(GUID*& guid); void suppressEmulatedDirectDraw(GUID*& guid);
template <typename TDirectDraw>
HWND getDeviceWindow(TDirectDraw& dd)
{
return reinterpret_cast<HWND**>(&dd)[1][8];
}
template <typename TDirectDraw> template <typename TDirectDraw>
class DirectDraw: public CompatVtable<Vtable<TDirectDraw>> class DirectDraw: public CompatVtable<Vtable<TDirectDraw>>
{ {

View File

@ -1,15 +1,15 @@
#include "Common/CompatPtr.h" #include <Common/CompatPtr.h>
#include "Common/CompatRef.h" #include <Common/CompatRef.h>
#include "Config/Config.h" #include <Config/Config.h>
#include "D3dDdi/Device.h" #include <D3dDdi/Device.h>
#include "D3dDdi/KernelModeThunks.h" #include <D3dDdi/KernelModeThunks.h>
#include "DDraw/DirectDraw.h" #include <DDraw/DirectDraw.h>
#include "DDraw/DirectDrawSurface.h" #include <DDraw/DirectDrawSurface.h>
#include "DDraw/RealPrimarySurface.h" #include <DDraw/RealPrimarySurface.h>
#include "DDraw/Surfaces/PrimarySurface.h" #include <DDraw/Surfaces/PrimarySurface.h>
#include "DDraw/Surfaces/PrimarySurfaceImpl.h" #include <DDraw/Surfaces/PrimarySurfaceImpl.h>
#include "Gdi/Palette.h" #include <Gdi/Palette.h>
#include "Gdi/VirtualScreen.h" #include <Gdi/VirtualScreen.h>
namespace namespace
{ {
@ -17,6 +17,8 @@ namespace
HANDLE g_gdiResourceHandle = nullptr; HANDLE g_gdiResourceHandle = nullptr;
HANDLE g_frontResource = nullptr; HANDLE g_frontResource = nullptr;
DWORD g_origCaps = 0; DWORD g_origCaps = 0;
HWND g_deviceWindow = nullptr;
HPALETTE g_palette = nullptr;
} }
namespace DDraw namespace DDraw
@ -29,6 +31,12 @@ namespace DDraw
g_frontResource = nullptr; g_frontResource = nullptr;
g_primarySurface = nullptr; g_primarySurface = nullptr;
g_origCaps = 0; g_origCaps = 0;
g_deviceWindow = nullptr;
if (g_palette)
{
DeleteObject(g_palette);
g_palette = nullptr;
}
s_palette = nullptr; s_palette = nullptr;
DDraw::RealPrimarySurface::release(); DDraw::RealPrimarySurface::release();
@ -70,6 +78,17 @@ namespace DDraw
} }
g_origCaps = origCaps; g_origCaps = origCaps;
g_deviceWindow = DDraw::getDeviceWindow(dd.get());
if (desc.ddpfPixelFormat.dwRGBBitCount <= 8)
{
LOGPALETTE lp = {};
lp.palVersion = 0x300;
lp.palNumEntries = 1;
g_palette = CreatePalette(&lp);
ResizePalette(g_palette, 256);
}
data->restore(); data->restore();
return DD_OK; return DD_OK;
} }
@ -215,24 +234,26 @@ namespace DDraw
void PrimarySurface::updatePalette() void PrimarySurface::updatePalette()
{ {
PALETTEENTRY entries[256] = {}; if (!s_palette)
if (s_palette)
{ {
PrimarySurface::s_palette->GetEntries(s_palette, 0, 0, 256, entries); return;
} }
PALETTEENTRY entries[256] = {};
PrimarySurface::s_palette->GetEntries(s_palette, 0, 0, 256, entries);
if (RealPrimarySurface::isFullScreen()) if (RealPrimarySurface::isFullScreen())
{ {
if (!s_palette)
{
auto sysPalEntries(Gdi::Palette::getSystemPalette());
std::memcpy(entries, sysPalEntries.data(), sizeof(entries));
}
Gdi::Palette::setHardwarePalette(entries); Gdi::Palette::setHardwarePalette(entries);
} }
else if (s_palette) else
{ {
Gdi::Palette::setSystemPalette(entries, 256, false); SetPaletteEntries(g_palette, 0, 256, entries);
HDC dc = GetDC(g_deviceWindow);
HPALETTE oldPal = SelectPalette(dc, g_palette, FALSE);
RealizePalette(dc);
SelectPalette(dc, oldPal, FALSE);
ReleaseDC(g_deviceWindow, dc);
} }
RealPrimarySurface::update(); RealPrimarySurface::update();

View File

@ -42,7 +42,6 @@ namespace DDraw
virtual void createImpl(); virtual void createImpl();
void* m_ddObject;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface>> m_impl; std::unique_ptr<SurfaceImpl<IDirectDrawSurface>> m_impl;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface2>> m_impl2; std::unique_ptr<SurfaceImpl<IDirectDrawSurface2>> m_impl2;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface3>> m_impl3; std::unique_ptr<SurfaceImpl<IDirectDrawSurface3>> m_impl3;

View File

@ -429,12 +429,10 @@ namespace Gdi
HOOK_GDI_DC_FUNCTION(gdi32, GdiAlphaBlend); HOOK_GDI_DC_FUNCTION(gdi32, GdiAlphaBlend);
HOOK_GDI_DC_FUNCTION(gdi32, GdiGradientFill); HOOK_GDI_DC_FUNCTION(gdi32, GdiGradientFill);
HOOK_GDI_DC_FUNCTION(gdi32, GdiTransparentBlt); HOOK_GDI_DC_FUNCTION(gdi32, GdiTransparentBlt);
HOOK_GDI_DC_FUNCTION(gdi32, GetDIBits);
HOOK_GDI_DC_FUNCTION(gdi32, GetPixel); HOOK_GDI_DC_FUNCTION(gdi32, GetPixel);
HOOK_GDI_DC_FUNCTION(msimg32, GradientFill); HOOK_GDI_DC_FUNCTION(msimg32, GradientFill);
HOOK_GDI_DC_FUNCTION(gdi32, MaskBlt); HOOK_GDI_DC_FUNCTION(gdi32, MaskBlt);
HOOK_GDI_DC_FUNCTION(gdi32, PlgBlt); HOOK_GDI_DC_FUNCTION(gdi32, PlgBlt);
HOOK_GDI_DC_FUNCTION(gdi32, SetDIBits);
HOOK_GDI_DC_FUNCTION(gdi32, SetDIBitsToDevice); HOOK_GDI_DC_FUNCTION(gdi32, SetDIBitsToDevice);
HOOK_GDI_DC_FUNCTION(gdi32, SetPixel); HOOK_GDI_DC_FUNCTION(gdi32, SetPixel);
HOOK_GDI_DC_FUNCTION(gdi32, SetPixelV); HOOK_GDI_DC_FUNCTION(gdi32, SetPixelV);

View File

@ -19,7 +19,7 @@ namespace
UINT g_systemPaletteFirstNonReservedIndex = 10; UINT g_systemPaletteFirstNonReservedIndex = 10;
UINT g_systemPaletteLastNonReservedIndex = 245; UINT g_systemPaletteLastNonReservedIndex = 245;
std::set<HDC> g_foregroundPaletteDcs; std::set<HPALETTE> g_foregroundPalettes;
bool isSameColor(PALETTEENTRY entry1, PALETTEENTRY entry2) bool isSameColor(PALETTEENTRY entry1, PALETTEENTRY entry2)
{ {
@ -63,6 +63,17 @@ namespace
Gdi::VirtualScreen::updatePalette(g_systemPalette); Gdi::VirtualScreen::updatePalette(g_systemPalette);
} }
BOOL WINAPI deleteObject(HGDIOBJ ho)
{
BOOL result = CALL_ORIG_FUNC(DeleteObject)(ho);
if (result && OBJ_PAL == GetObjectType(ho))
{
Compat::ScopedCriticalSection lock(g_cs);
g_foregroundPalettes.erase(static_cast<HPALETTE>(ho));
}
return result;
}
UINT WINAPI getSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries, LPPALETTEENTRY lppe) UINT WINAPI getSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries, LPPALETTEENTRY lppe)
{ {
LOG_FUNC("GetSystemPaletteEntries", hdc, iStartIndex, nEntries, lppe); LOG_FUNC("GetSystemPaletteEntries", hdc, iStartIndex, nEntries, lppe);
@ -108,8 +119,6 @@ namespace
LOG_FUNC("RealizePalette", hdc); LOG_FUNC("RealizePalette", hdc);
if (Gdi::isDisplayDc(hdc)) if (Gdi::isDisplayDc(hdc))
{ {
Compat::ScopedCriticalSection lock(g_cs);
HPALETTE palette = reinterpret_cast<HPALETTE>(GetCurrentObject(hdc, OBJ_PAL)); HPALETTE palette = reinterpret_cast<HPALETTE>(GetCurrentObject(hdc, OBJ_PAL));
if (!palette || GetStockObject(DEFAULT_PALETTE) == palette) if (!palette || GetStockObject(DEFAULT_PALETTE) == palette)
{ {
@ -118,38 +127,28 @@ namespace
PALETTEENTRY entries[256] = {}; PALETTEENTRY entries[256] = {};
UINT count = GetPaletteEntries(palette, 0, 256, entries); UINT count = GetPaletteEntries(palette, 0, 256, entries);
Compat::ScopedCriticalSection lock(g_cs);
Gdi::Palette::setSystemPalette(entries, count, Gdi::Palette::setSystemPalette(entries, count,
g_foregroundPaletteDcs.find(hdc) == g_foregroundPaletteDcs.end()); g_foregroundPalettes.find(palette) == g_foregroundPalettes.end());
return LOG_RESULT(count); return LOG_RESULT(count);
} }
return LOG_RESULT(CALL_ORIG_FUNC(RealizePalette)(hdc)); return LOG_RESULT(CALL_ORIG_FUNC(RealizePalette)(hdc));
} }
int WINAPI releaseDc(HWND hWnd, HDC hDC)
{
LOG_FUNC("ReleaseDC", hWnd, hDC);
Compat::ScopedCriticalSection lock(g_cs);
g_foregroundPaletteDcs.erase(hDC);
return LOG_RESULT(CALL_ORIG_FUNC(ReleaseDC)(hWnd, hDC));
}
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);
HPALETTE result = CALL_ORIG_FUNC(SelectPalette)(hdc, hpal, bForceBackground); HPALETTE result = CALL_ORIG_FUNC(SelectPalette)(hdc, hpal, bForceBackground);
if (result && Gdi::isDisplayDc(hdc)) if (result && !bForceBackground)
{ {
HWND wnd = CALL_ORIG_FUNC(WindowFromDC)(hdc); HWND dcWindow = CALL_ORIG_FUNC(WindowFromDC)(hdc);
if (wnd && GetDesktopWindow() != wnd) if (dcWindow && !(GetWindowLong(dcWindow, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
{ {
Compat::ScopedCriticalSection lock(g_cs); HWND activeWindow = GetActiveWindow();
if (bForceBackground || GetStockObject(DEFAULT_PALETTE) == hpal) if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow))
{ {
g_foregroundPaletteDcs.erase(hdc); Compat::ScopedCriticalSection lock(g_cs);
} g_foregroundPalettes.insert(hpal);
else
{
g_foregroundPaletteDcs.insert(hdc);
} }
} }
} }
@ -227,10 +226,10 @@ namespace Gdi
updateStaticSysPalEntries(); updateStaticSysPalEntries();
HOOK_FUNCTION(gdi32, DeleteObject, deleteObject);
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(user32, ReleaseDC, releaseDc);
HOOK_FUNCTION(gdi32, SelectPalette, selectPalette); HOOK_FUNCTION(gdi32, SelectPalette, selectPalette);
HOOK_FUNCTION(gdi32, SetSystemPaletteUse, setSystemPaletteUse); HOOK_FUNCTION(gdi32, SetSystemPaletteUse, setSystemPaletteUse);
} }