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:
parent
12e78aab84
commit
727be63db1
@ -225,7 +225,7 @@ namespace
|
||||
{
|
||||
g_gdiAdapterInfo = getAdapterInfo(data);
|
||||
}
|
||||
ReleaseDC(nullptr, data.hDc);
|
||||
CALL_ORIG_FUNC(ReleaseDC)(nullptr, data.hDc);
|
||||
|
||||
lastDisplaySettingsUniqueness = currentDisplaySettingsUniqueness;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -173,7 +173,7 @@ namespace DDraw
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
PrimarySurface::s_palette = lpDDPalette;
|
||||
RealPrimarySurface::setPalette();
|
||||
PrimarySurface::updatePalette();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
224
DDrawCompat/Gdi/Palette.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
9
DDrawCompat/Gdi/Palette.h
Normal file
9
DDrawCompat/Gdi/Palette.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace Gdi
|
||||
{
|
||||
namespace Palette
|
||||
{
|
||||
void installHooks();
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user