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

Improved GDI performance

This commit is contained in:
narzoul 2018-11-10 11:58:20 +01:00
parent c53ffab664
commit 7785133d02
4 changed files with 67 additions and 49 deletions

View File

@ -8,6 +8,7 @@
#include "Gdi/Dc.h" #include "Gdi/Dc.h"
#include "Gdi/DcCache.h" #include "Gdi/DcCache.h"
#include "Gdi/Gdi.h" #include "Gdi/Gdi.h"
#include "Gdi/Region.h"
#include "Gdi/VirtualScreen.h" #include "Gdi/VirtualScreen.h"
#include "Gdi/Window.h" #include "Gdi/Window.h"
@ -20,6 +21,9 @@ namespace
HDC origDc; HDC origDc;
DWORD threadId; DWORD threadId;
int savedState; int savedState;
HGDIOBJ savedFont;
HGDIOBJ savedBrush;
HGDIOBJ savedPen;
}; };
typedef std::unordered_map<HDC, CompatDc> CompatDcMap; typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
@ -28,35 +32,41 @@ namespace
void restoreDc(const CompatDc& compatDc); 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, compatDc.savedFont = GetCurrentObject(origDc, OBJ_FONT));
SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_BRUSH)); SelectObject(compatDc.dc, compatDc.savedBrush = GetCurrentObject(origDc, OBJ_BRUSH));
SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_PEN)); 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 = {}; XFORM transform = {};
GetWorldTransform(origDc, &transform); GetWorldTransform(origDc, &transform);
SetWorldTransform(compatDc.dc, &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 = {}; SIZE viewportExt = {};
GetViewportOrgEx(origDc, &viewportOrg); GetViewportExtEx(origDc, &viewportExt);
SetViewportOrgEx(compatDc.dc, viewportOrg.x + origin.x, viewportOrg.y + origin.y, nullptr); SetViewportExtEx(compatDc.dc, viewportExt.cx, viewportExt.cy, nullptr);
SIZE viewportExt = {}; }
GetViewportExtEx(origDc, &viewportExt);
SetViewportExtEx(compatDc.dc, viewportExt.cx, viewportExt.cy, nullptr);
POINT windowOrg = {}; POINT windowOrg = {};
GetWindowOrgEx(origDc, &windowOrg); GetWindowOrgEx(origDc, &windowOrg);
SetWindowOrgEx(compatDc.dc, windowOrg.x, windowOrg.y, nullptr); SetWindowOrgEx(compatDc.dc, windowOrg.x, windowOrg.y, nullptr);
SIZE windowExt = {};
GetWindowExtEx(origDc, &windowExt); POINT viewportOrg = {};
SetWindowExtEx(compatDc.dc, windowExt.cx, windowExt.cy, nullptr); GetViewportOrgEx(origDc, &viewportOrg);
SetViewportOrgEx(compatDc.dc, viewportOrg.x + origin.x, viewportOrg.y + origin.y, nullptr);
SetArcDirection(compatDc.dc, GetArcDirection(origDc)); SetArcDirection(compatDc.dc, GetArcDirection(origDc));
SetBkColor(compatDc.dc, GetBkColor(origDc)); SetBkColor(compatDc.dc, GetBkColor(origDc));
@ -82,32 +92,46 @@ namespace
void restoreDc(const CompatDc& compatDc) void restoreDc(const CompatDc& compatDc)
{ {
// Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one if (0 != compatDc.savedState)
HGDIOBJ bitmap = GetCurrentObject(compatDc.dc, OBJ_BITMAP); {
RestoreDC(compatDc.dc, compatDc.savedState); // Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one
SelectObject(compatDc.dc, bitmap); 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); Gdi::Region sysRgn;
if (1 == GetRandomRgn(origDc, sysRgn, SYSRGN)) CALL_ORIG_FUNC(GetRandomRgn)(compatDc.origDc, sysRgn, SYSRGN);
{ sysRgn &= rootWindow->getVisibleRegion();
SelectClipRgn(compatDc, sysRgn); SelectClipRgn(compatDc.dc, sysRgn);
SetMetaRgn(compatDc); }
} else
DeleteObject(sysRgn); {
SelectClipRgn(compatDc.dc, nullptr);
} }
HRGN clipRgn = CreateRectRgn(0, 0, 0, 0); Gdi::Region clipRgn;
if (1 == GetClipRgn(origDc, clipRgn)) if (1 == GetClipRgn(compatDc.origDc, clipRgn))
{ {
OffsetRgn(clipRgn, origin.x, origin.y); 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)) 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); const HWND wnd = CALL_ORIG_FUNC(WindowFromDC)(origDc);
auto rootWnd = wnd ? GetAncestor(wnd, GA_ROOT) : nullptr; auto rootWindow(wnd ? Gdi::Window::get(GetAncestor(wnd, GA_ROOT)) : nullptr);
if (rootWnd && GetDesktopWindow() != rootWnd) if (rootWindow)
{ {
auto rootWindow(Window::get(rootWnd));
if (!rootWindow)
{
return nullptr;
}
rootWindow->updateWindow(); rootWindow->updateWindow();
} }
@ -186,13 +205,13 @@ namespace Gdi
origin.x -= virtualScreenBounds.left; origin.x -= virtualScreenBounds.left;
origin.y -= virtualScreenBounds.top; origin.y -= virtualScreenBounds.top;
compatDc.savedState = SaveDC(compatDc.dc);
copyDcAttributes(compatDc, origDc, origin);
setClippingRegion(compatDc.dc, origDc, wnd, origin);
compatDc.refCount = 1; compatDc.refCount = 1;
compatDc.origDc = origDc; compatDc.origDc = origDc;
compatDc.threadId = GetCurrentThreadId(); 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)); g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc));
return compatDc.dc; return compatDc.dc;

View File

@ -10,7 +10,7 @@ namespace Gdi
{ {
void dllProcessDetach(); void dllProcessDetach();
void dllThreadDetach(); void dllThreadDetach();
HDC getDc(HDC origDc); HDC getDc(HDC origDc, bool useMetaRgn = true);
HDC getOrigDc(HDC dc); HDC getOrigDc(HDC dc);
void releaseDc(HDC origDc); void releaseDc(HDC origDc);
} }

View File

@ -16,7 +16,7 @@ namespace
class CompatDc class CompatDc
{ {
public: 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))
{ {
} }

View File

@ -1,6 +1,6 @@
#include "Common/Hook.h"
#include "DDraw/ScopedThreadLock.h" #include "DDraw/ScopedThreadLock.h"
#include "Gdi/Gdi.h" #include "Gdi/Gdi.h"
#include "Gdi/VirtualScreen.h"
#include "Gdi/Window.h" #include "Gdi/Window.h"
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -175,7 +175,6 @@ namespace Gdi
HDC windowDc = GetWindowDC(m_hwnd); HDC windowDc = GetWindowDC(m_hwnd);
GetRandomRgn(windowDc, newVisibleRegion, SYSRGN); GetRandomRgn(windowDc, newVisibleRegion, SYSRGN);
ReleaseDC(m_hwnd, windowDc); ReleaseDC(m_hwnd, windowDc);
newVisibleRegion &= VirtualScreen::getRegion();
} }
if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr)) if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr))