From 39bb699cf70b6ddeea99375408707d6c280c9177 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 24 Jan 2021 21:49:16 +0100 Subject: [PATCH] Use RealizePalette for windowed mode palette changes --- DDrawCompat/DDraw/DirectDraw.h | 6 ++ DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp | 65 ++++++++++++------- DDrawCompat/DDraw/Surfaces/Surface.h | 1 - DDrawCompat/Gdi/DcFunctions.cpp | 2 - DDrawCompat/Gdi/Palette.cpp | 45 +++++++------ 5 files changed, 71 insertions(+), 48 deletions(-) diff --git a/DDrawCompat/DDraw/DirectDraw.h b/DDrawCompat/DDraw/DirectDraw.h index c7d80e1..1f33f61 100644 --- a/DDrawCompat/DDraw/DirectDraw.h +++ b/DDrawCompat/DDraw/DirectDraw.h @@ -13,6 +13,12 @@ namespace DDraw DDPIXELFORMAT getRgbPixelFormat(DWORD bpp); void suppressEmulatedDirectDraw(GUID*& guid); + template + HWND getDeviceWindow(TDirectDraw& dd) + { + return reinterpret_cast(&dd)[1][8]; + } + template class DirectDraw: public CompatVtable> { diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp index b8ab9af..bdf55f0 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp @@ -1,15 +1,15 @@ -#include "Common/CompatPtr.h" -#include "Common/CompatRef.h" -#include "Config/Config.h" -#include "D3dDdi/Device.h" -#include "D3dDdi/KernelModeThunks.h" -#include "DDraw/DirectDraw.h" -#include "DDraw/DirectDrawSurface.h" -#include "DDraw/RealPrimarySurface.h" -#include "DDraw/Surfaces/PrimarySurface.h" -#include "DDraw/Surfaces/PrimarySurfaceImpl.h" -#include "Gdi/Palette.h" -#include "Gdi/VirtualScreen.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace { @@ -17,6 +17,8 @@ namespace HANDLE g_gdiResourceHandle = nullptr; HANDLE g_frontResource = nullptr; DWORD g_origCaps = 0; + HWND g_deviceWindow = nullptr; + HPALETTE g_palette = nullptr; } namespace DDraw @@ -29,6 +31,12 @@ namespace DDraw g_frontResource = nullptr; g_primarySurface = nullptr; g_origCaps = 0; + g_deviceWindow = nullptr; + if (g_palette) + { + DeleteObject(g_palette); + g_palette = nullptr; + } s_palette = nullptr; DDraw::RealPrimarySurface::release(); @@ -70,6 +78,17 @@ namespace DDraw } 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(); return DD_OK; } @@ -215,24 +234,26 @@ namespace DDraw 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 (!s_palette) - { - auto sysPalEntries(Gdi::Palette::getSystemPalette()); - std::memcpy(entries, sysPalEntries.data(), sizeof(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(); diff --git a/DDrawCompat/DDraw/Surfaces/Surface.h b/DDrawCompat/DDraw/Surfaces/Surface.h index cf47f0f..2c155c7 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.h +++ b/DDrawCompat/DDraw/Surfaces/Surface.h @@ -42,7 +42,6 @@ namespace DDraw virtual void createImpl(); - void* m_ddObject; std::unique_ptr> m_impl; std::unique_ptr> m_impl2; std::unique_ptr> m_impl3; diff --git a/DDrawCompat/Gdi/DcFunctions.cpp b/DDrawCompat/Gdi/DcFunctions.cpp index 1cdad50..b974e45 100644 --- a/DDrawCompat/Gdi/DcFunctions.cpp +++ b/DDrawCompat/Gdi/DcFunctions.cpp @@ -429,12 +429,10 @@ namespace Gdi HOOK_GDI_DC_FUNCTION(gdi32, GdiAlphaBlend); HOOK_GDI_DC_FUNCTION(gdi32, GdiGradientFill); HOOK_GDI_DC_FUNCTION(gdi32, GdiTransparentBlt); - HOOK_GDI_DC_FUNCTION(gdi32, GetDIBits); HOOK_GDI_DC_FUNCTION(gdi32, GetPixel); HOOK_GDI_DC_FUNCTION(msimg32, GradientFill); HOOK_GDI_DC_FUNCTION(gdi32, MaskBlt); HOOK_GDI_DC_FUNCTION(gdi32, PlgBlt); - HOOK_GDI_DC_FUNCTION(gdi32, SetDIBits); HOOK_GDI_DC_FUNCTION(gdi32, SetDIBitsToDevice); HOOK_GDI_DC_FUNCTION(gdi32, SetPixel); HOOK_GDI_DC_FUNCTION(gdi32, SetPixelV); diff --git a/DDrawCompat/Gdi/Palette.cpp b/DDrawCompat/Gdi/Palette.cpp index b0d0cc4..3bf4b24 100644 --- a/DDrawCompat/Gdi/Palette.cpp +++ b/DDrawCompat/Gdi/Palette.cpp @@ -19,7 +19,7 @@ namespace UINT g_systemPaletteFirstNonReservedIndex = 10; UINT g_systemPaletteLastNonReservedIndex = 245; - std::set g_foregroundPaletteDcs; + std::set g_foregroundPalettes; bool isSameColor(PALETTEENTRY entry1, PALETTEENTRY entry2) { @@ -63,6 +63,17 @@ namespace 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(ho)); + } + return result; + } + UINT WINAPI getSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries, LPPALETTEENTRY lppe) { LOG_FUNC("GetSystemPaletteEntries", hdc, iStartIndex, nEntries, lppe); @@ -108,8 +119,6 @@ namespace LOG_FUNC("RealizePalette", hdc); if (Gdi::isDisplayDc(hdc)) { - Compat::ScopedCriticalSection lock(g_cs); - HPALETTE palette = reinterpret_cast(GetCurrentObject(hdc, OBJ_PAL)); if (!palette || GetStockObject(DEFAULT_PALETTE) == palette) { @@ -118,38 +127,28 @@ namespace PALETTEENTRY entries[256] = {}; UINT count = GetPaletteEntries(palette, 0, 256, entries); + Compat::ScopedCriticalSection lock(g_cs); 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(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) { LOG_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); - if (wnd && GetDesktopWindow() != wnd) + HWND dcWindow = CALL_ORIG_FUNC(WindowFromDC)(hdc); + if (dcWindow && !(GetWindowLong(dcWindow, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) { - Compat::ScopedCriticalSection lock(g_cs); - if (bForceBackground || GetStockObject(DEFAULT_PALETTE) == hpal) + HWND activeWindow = GetActiveWindow(); + if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow)) { - g_foregroundPaletteDcs.erase(hdc); - } - else - { - g_foregroundPaletteDcs.insert(hdc); + Compat::ScopedCriticalSection lock(g_cs); + g_foregroundPalettes.insert(hpal); } } } @@ -227,10 +226,10 @@ namespace Gdi updateStaticSysPalEntries(); + HOOK_FUNCTION(gdi32, DeleteObject, deleteObject); HOOK_FUNCTION(gdi32, GetSystemPaletteEntries, getSystemPaletteEntries); HOOK_FUNCTION(gdi32, GetSystemPaletteUse, getSystemPaletteUse); HOOK_FUNCTION(gdi32, RealizePalette, realizePalette); - HOOK_FUNCTION(user32, ReleaseDC, releaseDc); HOOK_FUNCTION(gdi32, SelectPalette, selectPalette); HOOK_FUNCTION(gdi32, SetSystemPaletteUse, setSystemPaletteUse); }