mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Improved GDI performance
This commit is contained in:
parent
c53ffab664
commit
7785133d02
@ -8,6 +8,7 @@
|
||||
#include "Gdi/Dc.h"
|
||||
#include "Gdi/DcCache.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Gdi/Region.h"
|
||||
#include "Gdi/VirtualScreen.h"
|
||||
#include "Gdi/Window.h"
|
||||
|
||||
@ -20,6 +21,9 @@ namespace
|
||||
HDC origDc;
|
||||
DWORD threadId;
|
||||
int savedState;
|
||||
HGDIOBJ savedFont;
|
||||
HGDIOBJ savedBrush;
|
||||
HGDIOBJ savedPen;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
|
||||
@ -28,35 +32,41 @@ namespace
|
||||
|
||||
void restoreDc(const CompatDc& compatDc);
|
||||
|
||||
void copyDcAttributes(const CompatDc& compatDc, HDC origDc, const POINT& origin)
|
||||
void copyDcAttributes(CompatDc& compatDc, HDC origDc, const POINT& origin)
|
||||
{
|
||||
SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_FONT));
|
||||
SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_BRUSH));
|
||||
SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_PEN));
|
||||
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));
|
||||
|
||||
if (GM_ADVANCED == GetGraphicsMode(origDc))
|
||||
const int graphicsMode = GetGraphicsMode(origDc);
|
||||
SetGraphicsMode(compatDc.dc, graphicsMode);
|
||||
if (GM_ADVANCED == graphicsMode)
|
||||
{
|
||||
SetGraphicsMode(compatDc.dc, GM_ADVANCED);
|
||||
XFORM transform = {};
|
||||
GetWorldTransform(origDc, &transform);
|
||||
SetWorldTransform(compatDc.dc, &transform);
|
||||
}
|
||||
|
||||
SetMapMode(compatDc.dc, GetMapMode(origDc));
|
||||
const int mapMode = GetMapMode(origDc);
|
||||
SetMapMode(compatDc.dc, mapMode);
|
||||
if (MM_TEXT != mapMode)
|
||||
{
|
||||
SIZE windowExt = {};
|
||||
GetWindowExtEx(origDc, &windowExt);
|
||||
SetWindowExtEx(compatDc.dc, windowExt.cx, windowExt.cy, nullptr);
|
||||
|
||||
POINT viewportOrg = {};
|
||||
GetViewportOrgEx(origDc, &viewportOrg);
|
||||
SetViewportOrgEx(compatDc.dc, viewportOrg.x + origin.x, viewportOrg.y + origin.y, nullptr);
|
||||
SIZE viewportExt = {};
|
||||
GetViewportExtEx(origDc, &viewportExt);
|
||||
SetViewportExtEx(compatDc.dc, viewportExt.cx, viewportExt.cy, nullptr);
|
||||
SIZE viewportExt = {};
|
||||
GetViewportExtEx(origDc, &viewportExt);
|
||||
SetViewportExtEx(compatDc.dc, viewportExt.cx, viewportExt.cy, nullptr);
|
||||
}
|
||||
|
||||
POINT windowOrg = {};
|
||||
GetWindowOrgEx(origDc, &windowOrg);
|
||||
SetWindowOrgEx(compatDc.dc, windowOrg.x, windowOrg.y, nullptr);
|
||||
SIZE windowExt = {};
|
||||
GetWindowExtEx(origDc, &windowExt);
|
||||
SetWindowExtEx(compatDc.dc, windowExt.cx, windowExt.cy, nullptr);
|
||||
|
||||
POINT viewportOrg = {};
|
||||
GetViewportOrgEx(origDc, &viewportOrg);
|
||||
SetViewportOrgEx(compatDc.dc, viewportOrg.x + origin.x, viewportOrg.y + origin.y, nullptr);
|
||||
|
||||
SetArcDirection(compatDc.dc, GetArcDirection(origDc));
|
||||
SetBkColor(compatDc.dc, GetBkColor(origDc));
|
||||
@ -82,32 +92,46 @@ namespace
|
||||
|
||||
void restoreDc(const CompatDc& compatDc)
|
||||
{
|
||||
// Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one
|
||||
HGDIOBJ bitmap = GetCurrentObject(compatDc.dc, OBJ_BITMAP);
|
||||
RestoreDC(compatDc.dc, compatDc.savedState);
|
||||
SelectObject(compatDc.dc, bitmap);
|
||||
if (0 != compatDc.savedState)
|
||||
{
|
||||
// Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one
|
||||
HGDIOBJ bitmap = GetCurrentObject(compatDc.dc, OBJ_BITMAP);
|
||||
RestoreDC(compatDc.dc, compatDc.savedState);
|
||||
SelectObject(compatDc.dc, bitmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectObject(compatDc.dc, compatDc.savedFont);
|
||||
SelectObject(compatDc.dc, compatDc.savedBrush);
|
||||
SelectObject(compatDc.dc, compatDc.savedPen);
|
||||
}
|
||||
}
|
||||
|
||||
void setClippingRegion(HDC compatDc, HDC origDc, HWND hwnd, const POINT& origin)
|
||||
void setClippingRegion(const CompatDc& compatDc, std::shared_ptr<Gdi::Window> rootWindow, const POINT& origin)
|
||||
{
|
||||
if (hwnd)
|
||||
if (rootWindow)
|
||||
{
|
||||
HRGN sysRgn = CreateRectRgn(0, 0, 0, 0);
|
||||
if (1 == GetRandomRgn(origDc, sysRgn, SYSRGN))
|
||||
{
|
||||
SelectClipRgn(compatDc, sysRgn);
|
||||
SetMetaRgn(compatDc);
|
||||
}
|
||||
DeleteObject(sysRgn);
|
||||
Gdi::Region sysRgn;
|
||||
CALL_ORIG_FUNC(GetRandomRgn)(compatDc.origDc, sysRgn, SYSRGN);
|
||||
sysRgn &= rootWindow->getVisibleRegion();
|
||||
SelectClipRgn(compatDc.dc, sysRgn);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectClipRgn(compatDc.dc, nullptr);
|
||||
}
|
||||
|
||||
HRGN clipRgn = CreateRectRgn(0, 0, 0, 0);
|
||||
if (1 == GetClipRgn(origDc, clipRgn))
|
||||
Gdi::Region clipRgn;
|
||||
if (1 == GetClipRgn(compatDc.origDc, clipRgn))
|
||||
{
|
||||
OffsetRgn(clipRgn, origin.x, origin.y);
|
||||
SelectClipRgn(compatDc, clipRgn);
|
||||
ExtSelectClipRgn(compatDc.dc, clipRgn, RGN_AND);
|
||||
}
|
||||
|
||||
if (0 != compatDc.savedState)
|
||||
{
|
||||
SetMetaRgn(compatDc.dc);
|
||||
}
|
||||
DeleteObject(clipRgn);
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +170,7 @@ namespace Gdi
|
||||
}
|
||||
}
|
||||
|
||||
HDC getDc(HDC origDc)
|
||||
HDC getDc(HDC origDc, bool useMetaRgn)
|
||||
{
|
||||
if (!origDc || OBJ_DC != GetObjectType(origDc) || DT_RASDISPLAY != GetDeviceCaps(origDc, TECHNOLOGY))
|
||||
{
|
||||
@ -162,14 +186,9 @@ namespace Gdi
|
||||
}
|
||||
|
||||
const HWND wnd = CALL_ORIG_FUNC(WindowFromDC)(origDc);
|
||||
auto rootWnd = wnd ? GetAncestor(wnd, GA_ROOT) : nullptr;
|
||||
if (rootWnd && GetDesktopWindow() != rootWnd)
|
||||
auto rootWindow(wnd ? Gdi::Window::get(GetAncestor(wnd, GA_ROOT)) : nullptr);
|
||||
if (rootWindow)
|
||||
{
|
||||
auto rootWindow(Window::get(rootWnd));
|
||||
if (!rootWindow)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
rootWindow->updateWindow();
|
||||
}
|
||||
|
||||
@ -186,13 +205,13 @@ namespace Gdi
|
||||
origin.x -= virtualScreenBounds.left;
|
||||
origin.y -= virtualScreenBounds.top;
|
||||
|
||||
compatDc.savedState = SaveDC(compatDc.dc);
|
||||
copyDcAttributes(compatDc, origDc, origin);
|
||||
setClippingRegion(compatDc.dc, origDc, wnd, origin);
|
||||
|
||||
compatDc.refCount = 1;
|
||||
compatDc.origDc = origDc;
|
||||
compatDc.threadId = GetCurrentThreadId();
|
||||
compatDc.savedState = useMetaRgn ? SaveDC(compatDc.dc) : 0;
|
||||
copyDcAttributes(compatDc, origDc, origin);
|
||||
setClippingRegion(compatDc, rootWindow, origin);
|
||||
|
||||
g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc));
|
||||
|
||||
return compatDc.dc;
|
||||
|
@ -10,7 +10,7 @@ namespace Gdi
|
||||
{
|
||||
void dllProcessDetach();
|
||||
void dllThreadDetach();
|
||||
HDC getDc(HDC origDc);
|
||||
HDC getDc(HDC origDc, bool useMetaRgn = true);
|
||||
HDC getOrigDc(HDC dc);
|
||||
void releaseDc(HDC origDc);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace
|
||||
class CompatDc
|
||||
{
|
||||
public:
|
||||
CompatDc(HDC dc) : m_origDc(dc), m_compatDc(Gdi::Dc::getDc(dc))
|
||||
CompatDc(HDC dc) : m_origDc(dc), m_compatDc(Gdi::Dc::getDc(dc, false))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "Common/Hook.h"
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Gdi/VirtualScreen.h"
|
||||
#include "Gdi/Window.h"
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
@ -175,7 +175,6 @@ namespace Gdi
|
||||
HDC windowDc = GetWindowDC(m_hwnd);
|
||||
GetRandomRgn(windowDc, newVisibleRegion, SYSRGN);
|
||||
ReleaseDC(m_hwnd, windowDc);
|
||||
newVisibleRegion &= VirtualScreen::getRegion();
|
||||
}
|
||||
|
||||
if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr))
|
||||
|
Loading…
x
Reference in New Issue
Block a user