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/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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user