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

Implement GDI system palette emulation

This commit is contained in:
narzoul 2018-11-25 16:15:53 +01:00
parent 12e78aab84
commit 727be63db1
26 changed files with 348 additions and 128 deletions

View File

@ -225,7 +225,7 @@ namespace
{
g_gdiAdapterInfo = getAdapterInfo(data);
}
ReleaseDC(nullptr, data.hDc);
CALL_ORIG_FUNC(ReleaseDC)(nullptr, data.hDc);
lastDisplaySettingsUniqueness = currentDisplaySettingsUniqueness;
}

View File

@ -20,7 +20,7 @@ namespace
{
Win32::DisplayMode::setDDrawBpp(bpp);
HRESULT result = DDraw::DirectDraw<TDirectDraw>::s_origVtable.SetDisplayMode(
This, width, height, bpp, refreshRate, flags);
This, width, height, 32, refreshRate, flags);
Win32::DisplayMode::setDDrawBpp(0);
return result;
}
@ -59,7 +59,7 @@ namespace DDraw
{
DDSURFACEDESC2 dm = {};
dm.dwSize = sizeof(dm);
dd->GetDisplayMode(&dd, &dm);
dd.get().lpVtbl->GetDisplayMode(&dd, &dm);
return dm;
}
@ -114,6 +114,7 @@ namespace DDraw
{
vtable.CreateSurface = &CreateSurface;
vtable.FlipToGDISurface = &FlipToGDISurface;
vtable.GetDisplayMode = &GetDisplayMode;
vtable.GetGDISurface = &GetGDISurface;
vtable.SetCooperativeLevel = &SetCooperativeLevel;
vtable.SetDisplayMode = &SetDisplayMode;
@ -148,6 +149,18 @@ namespace DDraw
return PrimarySurface::flipToGdiSurface();
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::GetDisplayMode(
TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc)
{
HRESULT result = s_origVtable.GetDisplayMode(This, lpDDSurfaceDesc);
if (SUCCEEDED(result) && lpDDSurfaceDesc)
{
lpDDSurfaceDesc->ddpfPixelFormat = getRgbPixelFormat(Win32::DisplayMode::getBpp());
}
return result;
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::GetGDISurface(
TDirectDraw* /*This*/, TSurface** lplpGDIDDSSurface)

View File

@ -35,6 +35,7 @@ namespace DDraw
IUnknown* pUnkOuter);
static HRESULT STDMETHODCALLTYPE FlipToGDISurface(TDirectDraw* This);
static HRESULT STDMETHODCALLTYPE GetDisplayMode(TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc);
static HRESULT STDMETHODCALLTYPE GetGDISurface(TDirectDraw* This, TSurface** lplpGDIDDSSurface);
static HRESULT STDMETHODCALLTYPE Initialize(TDirectDraw* This, GUID* lpGUID);
static HRESULT STDMETHODCALLTYPE SetCooperativeLevel(TDirectDraw* This, HWND hWnd, DWORD dwFlags);

View File

@ -42,7 +42,7 @@ namespace
}
DeleteObject(rgn);
ReleaseDC(data.hwnd, dc);
CALL_ORIG_FUNC(ReleaseDC)(data.hwnd, dc);
}
HRESULT STDMETHODCALLTYPE GetHWnd(IDirectDrawClipper* This, HWND* lphWnd)

View File

@ -4,7 +4,6 @@
#include "Common/Time.h"
#include "Config/Config.h"
#include "DDraw/DirectDrawPalette.h"
#include "DDraw/RealPrimarySurface.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "Gdi/AccessGuard.h"
@ -36,9 +35,7 @@ namespace DDraw
HRESULT result = s_origVtable.SetEntries(This, dwFlags, dwStartingEntry, dwCount, lpEntries);
if (This == PrimarySurface::s_palette && SUCCEEDED(result))
{
std::memcpy(&PrimarySurface::s_paletteEntries[dwStartingEntry], lpEntries,
dwCount * sizeof(PALETTEENTRY));
RealPrimarySurface::updatePalette();
PrimarySurface::updatePalette();
}
return result;
}

View File

@ -116,7 +116,7 @@ namespace
RECT rect = windowPair.second->getWindowRect();
CALL_ORIG_FUNC(BitBlt)(dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
virtualScreenDc.get(), rect.left, rect.top, SRCCOPY);
ReleaseDC(presentationWindow, dc);
CALL_ORIG_FUNC(ReleaseDC)(presentationWindow, dc);
}
}
@ -152,7 +152,7 @@ namespace
SelectClipRgn(backBufferDc, nullptr);
DeleteObject(rgn);
ReleaseDC(*it, windowDc);
CALL_ORIG_FUNC(ReleaseDC)(*it, windowDc);
}
backBuffer->ReleaseDC(backBuffer, backBufferDc);
@ -667,17 +667,6 @@ namespace DDraw
return gammaControl->SetGammaRamp(gammaControl, 0, rampData);
}
void RealPrimarySurface::setPalette()
{
DDraw::ScopedThreadLock lock;
if (g_surfaceDesc.ddpfPixelFormat.dwRGBBitCount <= 8)
{
g_frontBuffer->SetPalette(g_frontBuffer, PrimarySurface::s_palette);
}
updatePalette();
}
void RealPrimarySurface::update()
{
DDraw::ScopedThreadLock lock;
@ -689,15 +678,6 @@ namespace DDraw
}
}
void RealPrimarySurface::updatePalette()
{
DDraw::ScopedThreadLock lock;
if (PrimarySurface::s_palette)
{
update();
}
}
bool RealPrimarySurface::waitForFlip(Surface* surface, bool wait)
{
auto primary(DDraw::PrimarySurface::getPrimary());

View File

@ -27,9 +27,7 @@ namespace DDraw
static void removeUpdateThread();
static HRESULT restore();
static HRESULT setGammaRamp(DDGAMMARAMP* rampData);
static void setPalette();
static void update();
static void updatePalette();
static bool waitForFlip(Surface* surface, bool wait = true);
};
}

View File

@ -231,6 +231,15 @@ namespace DDraw
} while (surfacePtr && surfacePtr != g_primarySurface.get());
}
void PrimarySurface::updatePalette()
{
if (s_palette)
{
PrimarySurface::s_palette->GetEntries(s_palette, 0, 0, 256, s_paletteEntries);
RealPrimarySurface::update();
}
}
CompatWeakPtr<IDirectDrawPalette> PrimarySurface::s_palette;
PALETTEENTRY PrimarySurface::s_paletteEntries[256] = {};
std::vector<std::vector<unsigned char>> PrimarySurface::s_surfaceBuffers;

View File

@ -26,6 +26,7 @@ namespace DDraw
static CompatWeakPtr<IDirectDrawSurface7> getPrimary();
static DWORD getOrigCaps();
static void onRestore();
static void updatePalette();
template <typename TSurface>
static bool isGdiSurface(TSurface* surface);

View File

@ -173,7 +173,7 @@ namespace DDraw
if (SUCCEEDED(result))
{
PrimarySurface::s_palette = lpDDPalette;
RealPrimarySurface::setPalette();
PrimarySurface::updatePalette();
}
return result;
}

View File

@ -5,6 +5,7 @@
#include "DDraw/DirectDrawSurface.h"
#include "DDraw/Surfaces/Surface.h"
#include "DDraw/Surfaces/SurfaceImpl.h"
#include "Win32/DisplayMode.h"
// {C62D8849-DFAC-4454-A1E8-DA67446426BA}
DEFINE_GUID(IID_CompatSurfacePrivateData,
@ -15,8 +16,7 @@ namespace
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
HRESULT createSurface(CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface)
{
auto dd7(CompatPtr<IDirectDraw7>::from(&dd));
fixSurfaceDesc(*dd7, desc.dwFlags, desc.ddsCaps.dwCaps, desc.ddpfPixelFormat);
fixSurfaceDesc(desc.dwFlags, desc.ddsCaps.dwCaps, desc.ddpfPixelFormat);
if ((desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) &&
!(desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE)))
@ -35,7 +35,7 @@ namespace
return dd->CreateSurface(&dd, &desc, &surface, nullptr);
}
void fixSurfaceDesc(CompatRef<IDirectDraw7> dd, DWORD& flags, DWORD& caps, DDPIXELFORMAT& pf)
void fixSurfaceDesc(DWORD& flags, DWORD& caps, DDPIXELFORMAT& pf)
{
if ((flags & DDSD_WIDTH) &&
(flags & DDSD_HEIGHT) &&
@ -43,9 +43,8 @@ namespace
{
if (!(flags & DDSD_PIXELFORMAT))
{
auto dm = DDraw::getDisplayMode(dd);
flags |= DDSD_PIXELFORMAT;
pf = dm.ddpfPixelFormat;
pf = DDraw::getRgbPixelFormat(Win32::DisplayMode::getBpp());
}
if ((pf.dwFlags & DDPF_RGB) && pf.dwRGBBitCount <= 8)

View File

@ -290,6 +290,7 @@
<ClInclude Include="Gdi\DcCache.h" />
<ClInclude Include="Gdi\DcFunctions.h" />
<ClInclude Include="Gdi\PaintHandlers.h" />
<ClInclude Include="Gdi\Palette.h" />
<ClInclude Include="Gdi\Region.h" />
<ClInclude Include="Gdi\ScrollBar.h" />
<ClInclude Include="Gdi\ScrollFunctions.h" />
@ -350,6 +351,7 @@
<ClCompile Include="Gdi\DcCache.cpp" />
<ClCompile Include="Gdi\DcFunctions.cpp" />
<ClCompile Include="Gdi\PaintHandlers.cpp" />
<ClCompile Include="Gdi\Palette.cpp" />
<ClCompile Include="Gdi\Region.cpp" />
<ClCompile Include="Gdi\ScrollBar.cpp" />
<ClCompile Include="Gdi\ScrollFunctions.cpp" />

View File

@ -324,6 +324,9 @@
<ClInclude Include="Gdi\AccessGuard.h">
<Filter>Header Files\Gdi</Filter>
</ClInclude>
<ClInclude Include="Gdi\Palette.h">
<Filter>Header Files\Gdi</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -500,6 +503,9 @@
<ClCompile Include="Gdi\AccessGuard.cpp">
<Filter>Source Files\Gdi</Filter>
</ClCompile>
<ClCompile Include="Gdi\Palette.cpp">
<Filter>Source Files\Gdi</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Dll\DDrawCompat.def">

View File

@ -43,7 +43,7 @@ namespace
{
HDC dc = GetDC(g_caret.hwnd);
PatBlt(dc, g_caret.left, g_caret.top, g_caret.width, g_caret.height, PATINVERT);
ReleaseDC(g_caret.hwnd, dc);
CALL_ORIG_FUNC(ReleaseDC)(g_caret.hwnd, dc);
}
CaretData getCaretData(DWORD threadId)

View File

@ -24,6 +24,7 @@ namespace
HGDIOBJ savedFont;
HGDIOBJ savedBrush;
HGDIOBJ savedPen;
HPALETTE savedPalette;
};
typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
@ -37,6 +38,8 @@ namespace
SelectObject(compatDc.dc, compatDc.savedFont = GetCurrentObject(origDc, OBJ_FONT));
SelectObject(compatDc.dc, compatDc.savedBrush = GetCurrentObject(origDc, OBJ_BRUSH));
SelectObject(compatDc.dc, compatDc.savedPen = GetCurrentObject(origDc, OBJ_PEN));
CALL_ORIG_FUNC(SelectPalette)(
compatDc.dc, compatDc.savedPalette = static_cast<HPALETTE>(GetCurrentObject(origDc, OBJ_PAL)), FALSE);
const int graphicsMode = GetGraphicsMode(origDc);
SetGraphicsMode(compatDc.dc, graphicsMode);
@ -104,6 +107,7 @@ namespace
SelectObject(compatDc.dc, compatDc.savedFont);
SelectObject(compatDc.dc, compatDc.savedBrush);
SelectObject(compatDc.dc, compatDc.savedPen);
CALL_ORIG_FUNC(SelectPalette)(compatDc.dc, compatDc.savedPalette, FALSE);
}
}

View File

@ -67,8 +67,7 @@ namespace
bool hasDisplayDcArg(HDC dc)
{
return dc && OBJ_DC == GetObjectType(dc) && DT_RASDISPLAY == GetDeviceCaps(dc, TECHNOLOGY) &&
!(GetWindowLongPtr(CALL_ORIG_FUNC(WindowFromDC)(dc), GWL_EXSTYLE) & WS_EX_LAYERED);
return Gdi::isDisplayDc(dc);
}
template <typename T>
@ -153,6 +152,42 @@ namespace
return LOG_RESULT(TRUE);
}
HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy)
{
LOG_FUNC("CreateCompatibleBitmap", hdc, cx, cy);
if (Gdi::isDisplayDc(hdc))
{
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(cx, cy));
}
return LOG_RESULT(CALL_ORIG_FUNC(CreateCompatibleBitmap)(hdc, cx, cy));
}
HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit,
const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage)
{
LOG_FUNC("CreateDIBitmap", hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage);
if (lpbmih && (!(fdwInit & CBM_INIT) || lpbInit && lpbmi))
{
HBITMAP bitmap = Gdi::VirtualScreen::createOffScreenDib(lpbmih->biWidth, std::abs(lpbmih->biHeight));
if (bitmap && (fdwInit & CBM_INIT))
{
SetDIBits(hdc, bitmap, 0, std::abs(lpbmih->biHeight), lpbInit, lpbmi, fuUsage);
}
return LOG_RESULT(bitmap);
}
return LOG_RESULT(CALL_ORIG_FUNC(CreateDIBitmap)(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage));
}
HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight)
{
LOG_FUNC("CreateDiscardableBitmap", hdc, nWidth, nHeight);
if (Gdi::isDisplayDc(hdc))
{
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(nWidth, nHeight));
}
return LOG_RESULT(CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight));
}
BOOL CALLBACK excludeRgnForOverlappingWindow(HWND hwnd, LPARAM lParam)
{
auto& args = *reinterpret_cast<ExcludeRgnForOverlappingWindowArgs*>(lParam);
@ -262,13 +297,6 @@ namespace
return 1;
}
UINT WINAPI realizePalette(HDC hdc)
{
UINT result = CALL_ORIG_FUNC(RealizePalette)(hdc);
Gdi::VirtualScreen::updatePalette();
return result;
}
HWND WINAPI windowFromDc(HDC dc)
{
return CALL_ORIG_FUNC(WindowFromDC)(Gdi::Dc::getOrigDc(dc));
@ -299,9 +327,9 @@ namespace Gdi
// Bitmap functions
HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend);
HOOK_GDI_DC_FUNCTION(gdi32, BitBlt);
HOOK_FUNCTION(gdi32, CreateCompatibleBitmap, Win32::DisplayMode::createCompatibleBitmap);
HOOK_FUNCTION(gdi32, CreateDIBitmap, Win32::DisplayMode::createDIBitmap);
HOOK_FUNCTION(gdi32, CreateDiscardableBitmap, Win32::DisplayMode::createDiscardableBitmap);
HOOK_FUNCTION(gdi32, CreateCompatibleBitmap, createCompatibleBitmap);
HOOK_FUNCTION(gdi32, CreateDIBitmap, createDIBitmap);
HOOK_FUNCTION(gdi32, CreateDiscardableBitmap, createDiscardableBitmap);
HOOK_GDI_DC_FUNCTION(gdi32, ExtFloodFill);
HOOK_GDI_DC_FUNCTION(gdi32, GdiAlphaBlend);
HOOK_GDI_DC_FUNCTION(gdi32, GdiGradientFill);
@ -325,9 +353,6 @@ namespace Gdi
// Clipping functions
HOOK_FUNCTION(gdi32, GetRandomRgn, getRandomRgn);
// Color functions
HOOK_SHIM_FUNCTION(RealizePalette, realizePalette);
// Device context functions
HOOK_GDI_DC_FUNCTION(gdi32, DrawEscape);
HOOK_FUNCTION(user32, WindowFromDC, windowFromDc);

View File

@ -5,6 +5,7 @@
#include "Gdi/DcFunctions.h"
#include "Gdi/Gdi.h"
#include "Gdi/PaintHandlers.h"
#include "Gdi/Palette.h"
#include "Gdi/ScrollFunctions.h"
#include "Gdi/Window.h"
#include "Gdi/WinProc.h"
@ -50,12 +51,19 @@ namespace Gdi
DcFunctions::installHooks();
PaintHandlers::installHooks();
Palette::installHooks();
ScrollFunctions::installHooks();
Window::installHooks();
WinProc::installHooks();
Caret::installHooks();
}
bool isDisplayDc(HDC dc)
{
return dc && OBJ_DC == GetObjectType(dc) && DT_RASDISPLAY == GetDeviceCaps(dc, TECHNOLOGY) &&
!(GetWindowLongPtr(CALL_ORIG_FUNC(WindowFromDC)(dc), GWL_EXSTYLE) & WS_EX_LAYERED);
}
void redraw(HRGN rgn)
{
EnumWindows(&redrawWindowCallback, reinterpret_cast<LPARAM>(rgn));
@ -97,7 +105,7 @@ namespace Gdi
Window::uninstallHooks();
Dc::dllProcessDetach();
DcCache::dllProcessDetach();
ReleaseDC(nullptr, g_screenDc);
CALL_ORIG_FUNC(ReleaseDC)(nullptr, g_screenDc);
}
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc)

View File

@ -14,6 +14,7 @@ namespace Gdi
HDC getScreenDc();
HRGN getVisibleWindowRgn(HWND hwnd);
void installHooks();
bool isDisplayDc(HDC dc);
void redraw(HRGN rgn);
void redrawWindow(HWND hwnd, HRGN rgn);
void unhookWndProc(LPCSTR className, WNDPROC oldWndProc);

View File

@ -299,7 +299,7 @@ namespace
Gdi::Dc::releaseDc(windowDc);
}
ReleaseDC(hwnd, windowDc);
CALL_ORIG_FUNC(ReleaseDC)(hwnd, windowDc);
return 0;
}

224
DDrawCompat/Gdi/Palette.cpp Normal file
View File

@ -0,0 +1,224 @@
#define WIN32_LEAN_AND_MEAN
#include <set>
#include <Windows.h>
#include "Common/Hook.h"
#include "Common/Log.h"
#include "DDraw/ScopedThreadLock.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "Gdi/Gdi.h"
#include "Gdi/Palette.h"
#include "VirtualScreen.h"
#include "Win32/DisplayMode.h"
namespace
{
PALETTEENTRY g_systemPalette[256] = {};
UINT g_systemPaletteUse = SYSPAL_STATIC;
UINT g_systemPaletteFirstUnusedIndex = 10;
UINT g_systemPaletteFirstNonReservedIndex = 10;
UINT g_systemPaletteLastNonReservedIndex = 245;
std::set<HDC> g_foregroundPaletteDcs;
bool isSameColor(PALETTEENTRY entry1, PALETTEENTRY entry2)
{
return entry1.peRed == entry2.peRed &&
entry1.peGreen == entry2.peGreen &&
entry1.peBlue == entry2.peBlue;
}
bool exactMatch(PALETTEENTRY entry)
{
for (UINT i = 0; i < g_systemPaletteFirstUnusedIndex; ++i)
{
if (isSameColor(entry, g_systemPalette[i]))
{
return true;
}
}
for (UINT i = g_systemPaletteLastNonReservedIndex + 1; i < 256; ++i)
{
if (isSameColor(entry, g_systemPalette[i]))
{
return true;
}
}
return false;
}
UINT fillSystemPalette(HDC dc)
{
HPALETTE palette = reinterpret_cast<HPALETTE>(GetCurrentObject(dc, OBJ_PAL));
if (!palette || GetStockObject(DEFAULT_PALETTE) == palette)
{
return 0;
}
PALETTEENTRY entries[256] = {};
UINT count = GetPaletteEntries(palette, 0, 256, entries);
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::VirtualScreen::updatePalette();
return count;
}
UINT WINAPI getSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries, LPPALETTEENTRY lppe)
{
LOG_FUNC("GetSystemPaletteEntries", hdc, iStartIndex, nEntries, lppe);
if (!Gdi::isDisplayDc(hdc))
{
return LOG_RESULT(0);
}
if (!lppe)
{
return LOG_RESULT(256);
}
if (iStartIndex >= 256)
{
return LOG_RESULT(0);
}
if (nEntries > 256 - iStartIndex)
{
nEntries = 256 - iStartIndex;
}
DDraw::ScopedThreadLock lock;
std::memcpy(lppe, &DDraw::PrimarySurface::s_paletteEntries[iStartIndex], nEntries * sizeof(PALETTEENTRY));
return LOG_RESULT(nEntries);
}
UINT WINAPI getSystemPaletteUse(HDC hdc)
{
LOG_FUNC("GetSystemPaletteUse", hdc);
if (!Gdi::isDisplayDc(hdc))
{
return LOG_RESULT(SYSPAL_ERROR);
}
DDraw::ScopedThreadLock lock;
return g_systemPaletteUse;
}
UINT WINAPI realizePalette(HDC hdc)
{
LOG_FUNC("RealizePalette", hdc);
if (Gdi::isDisplayDc(hdc))
{
DDraw::ScopedThreadLock lock;
if (g_foregroundPaletteDcs.find(hdc) != g_foregroundPaletteDcs.end())
{
g_systemPaletteFirstUnusedIndex = g_systemPaletteFirstNonReservedIndex;
}
return LOG_RESULT(fillSystemPalette(hdc));
}
return LOG_RESULT(CALL_ORIG_FUNC(RealizePalette)(hdc));
}
int WINAPI releaseDc(HWND hWnd, HDC hDC)
{
LOG_FUNC("ReleaseDC", hWnd, hDC);
DDraw::ScopedThreadLock lock;
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))
{
HWND wnd = CALL_ORIG_FUNC(WindowFromDC)(hdc);
if (wnd && GetDesktopWindow() != wnd)
{
DDraw::ScopedThreadLock lock;
if (bForceBackground || GetStockObject(DEFAULT_PALETTE) == hpal)
{
g_foregroundPaletteDcs.erase(hdc);
}
else
{
g_foregroundPaletteDcs.insert(hdc);
}
}
}
return LOG_RESULT(result);
}
UINT WINAPI setSystemPaletteUse(HDC hdc, UINT uUsage)
{
LOG_FUNC("SetSystemPaletteUse", hdc, uUsage);
if (!Gdi::isDisplayDc(hdc))
{
return LOG_RESULT(SYSPAL_ERROR);
}
DDraw::ScopedThreadLock lock;
const UINT prevUsage = g_systemPaletteUse;
switch (uUsage)
{
case SYSPAL_STATIC:
g_systemPaletteFirstNonReservedIndex = 10;
g_systemPaletteLastNonReservedIndex = 245;
break;
case SYSPAL_NOSTATIC:
g_systemPaletteFirstNonReservedIndex = 1;
g_systemPaletteLastNonReservedIndex = 254;
break;
case SYSPAL_NOSTATIC256:
g_systemPaletteFirstNonReservedIndex = 0;
g_systemPaletteLastNonReservedIndex = 255;
break;
default:
return LOG_RESULT(SYSPAL_ERROR);
}
g_systemPaletteUse = uUsage;
return LOG_RESULT(prevUsage);
}
}
namespace Gdi
{
namespace Palette
{
void installHooks()
{
HPALETTE defaultPalette = reinterpret_cast<HPALETTE>(GetStockObject(DEFAULT_PALETTE));
GetPaletteEntries(defaultPalette, 0, 10, g_systemPalette);
GetPaletteEntries(defaultPalette, 246, 10, &g_systemPalette[246]);
Gdi::VirtualScreen::updatePalette();
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);
}
}
}

View File

@ -0,0 +1,9 @@
#pragma once
namespace Gdi
{
namespace Palette
{
void installHooks();
}
}

View File

@ -168,7 +168,6 @@ namespace Gdi
void init()
{
update();
updatePalette();
}
bool update()
@ -220,13 +219,9 @@ namespace Gdi
void updatePalette()
{
DDraw::ScopedThreadLock lock;
if (8 != g_bpp)
{
return;
}
PALETTEENTRY pal[256] = {};
GetSystemPaletteEntries(nullptr, 0, 256, pal);
GetSystemPaletteEntries(Gdi::getScreenDc(), 0, 256, pal);
RGBQUAD systemPalette[256] = {};
for (int i = 0; i < 256; ++i)

View File

@ -6,10 +6,12 @@
#include <dwmapi.h>
#include <Windows.h>
#include "Common/Hook.h"
#include "Common/Log.h"
#include "Common/ScopedCriticalSection.h"
#include "Gdi/AccessGuard.h"
#include "Gdi/Dc.h"
#include "Win32/DisplayMode.h"
#include "Gdi/PaintHandlers.h"
#include "Gdi/ScrollBar.h"
#include "Gdi/ScrollFunctions.h"
@ -94,6 +96,10 @@ namespace
if (GetCurrentProcessId() == windowPid)
{
onCreateWindow(hwnd);
if (8 == Win32::DisplayMode::getBpp())
{
PostMessage(hwnd, WM_PALETTECHANGED, reinterpret_cast<WPARAM>(GetDesktopWindow()), 0);
}
}
return TRUE;
}
@ -148,7 +154,7 @@ namespace
}
Gdi::Dc::releaseDc(windowDc);
}
ReleaseDC(hwnd, windowDc);
CALL_ORIG_FUNC(ReleaseDC)(hwnd, windowDc);
}
}

View File

@ -248,7 +248,7 @@ namespace Gdi
{
HDC windowDc = GetWindowDC(m_hwnd);
GetRandomRgn(windowDc, newVisibleRegion, SYSRGN);
ReleaseDC(m_hwnd, windowDc);
CALL_ORIG_FUNC(ReleaseDC)(m_hwnd, windowDc);
}
if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr))

View File

@ -28,8 +28,6 @@ namespace
}
};
CompatWeakPtr<IDirectDrawSurface7> g_compatibleSurface = {};
HDC g_compatibleDc = nullptr;
DWORD g_origBpp = 0;
DWORD g_currentBpp = 0;
DWORD g_lastBpp = 0;
@ -39,7 +37,6 @@ namespace
LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA* lpDevMode, DWORD dwFlags);
BOOL WINAPI enumDisplaySettingsExW(
LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode, DWORD dwFlags);
void updateCompatibleDc();
template <typename CStr, typename DevMode, typename ChangeDisplaySettingsExFunc,
typename EnumDisplaySettingsExFunc>
@ -80,7 +77,6 @@ namespace
{
g_currentBpp = g_origBpp;
}
updateCompatibleDc();
DevMode currDevMode = {};
currDevMode.dmSize = sizeof(currDevMode);
@ -290,65 +286,12 @@ namespace
}
return LOG_RESULT(CALL_ORIG_FUNC(GetDeviceCaps)(hdc, nIndex));
}
void releaseCompatibleDc()
{
if (g_compatibleDc)
{
Dll::g_origProcs.AcquireDDThreadLock();
g_compatibleSurface->ReleaseDC(g_compatibleSurface, g_compatibleDc);
g_compatibleDc = nullptr;
g_compatibleSurface.release();
}
}
void replaceDc(HDC& hdc)
{
if (g_compatibleDc && hdc &&
OBJ_DC == GetObjectType(hdc) && DT_RASDISPLAY == GetDeviceCaps(hdc, TECHNOLOGY))
{
hdc = g_compatibleDc;
}
}
void updateCompatibleDc()
{
releaseCompatibleDc();
g_compatibleSurface = DDraw::createCompatibleSurface(g_currentBpp).detach();
if (g_compatibleSurface &&
SUCCEEDED(g_compatibleSurface->GetDC(g_compatibleSurface, &g_compatibleDc)))
{
Dll::g_origProcs.ReleaseDDThreadLock();
}
}
}
namespace Win32
{
namespace DisplayMode
{
HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy)
{
LOG_FUNC("CreateCompatibleBitmap", hdc, cx, cy);
replaceDc(hdc);
return LOG_RESULT(CALL_ORIG_FUNC(CreateCompatibleBitmap)(hdc, cx, cy));
}
HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit,
const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage)
{
LOG_FUNC("CreateDIBitmap", hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage);
replaceDc(hdc);
return LOG_RESULT(CALL_ORIG_FUNC(CreateDIBitmap)(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage));
}
HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight)
{
LOG_FUNC("CreateDiscardableBitmap", hdc, nWidth, nHeight);
replaceDc(hdc);
return LOG_RESULT(CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight));
}
DWORD getBpp()
{
return g_currentBpp;
@ -380,6 +323,12 @@ namespace Win32
g_currentBpp = g_origBpp;
g_lastBpp = g_origBpp;
if (32 != devMode.dmBitsPerPel)
{
devMode.dmBitsPerPel = 32;
ChangeDisplaySettings(&devMode, 0);
}
HOOK_FUNCTION(user32, ChangeDisplaySettingsExA, changeDisplaySettingsExA);
HOOK_FUNCTION(user32, ChangeDisplaySettingsExW, changeDisplaySettingsExW);
HOOK_FUNCTION(user32, EnumDisplaySettingsExA, enumDisplaySettingsExA);
@ -402,8 +351,6 @@ namespace Win32
&ddrawEnumDisplaySettingsExA);
Compat::hookIatFunction(origDDrawModule, "user32.dll", "EnumDisplaySettingsExW",
&ddrawEnumDisplaySettingsExW);
updateCompatibleDc();
}
}
}

View File

@ -8,11 +8,6 @@ namespace Win32
{
namespace DisplayMode
{
HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy);
HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit,
const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage);
HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight);
DWORD getBpp();
ULONG queryDisplaySettingsUniqueness();
void setDDrawBpp(DWORD bpp);