mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Fixed a performance issue caused by unnecessary visible region updates
See issue #288.
This commit is contained in:
parent
2e48469ae4
commit
edcd3b1aca
@ -494,7 +494,7 @@ namespace
|
|||||||
{
|
{
|
||||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||||
{
|
{
|
||||||
Gdi::Window::updateAll();
|
Gdi::Window::destroyWindow(hwnd);
|
||||||
Gdi::GuiThread::deleteTaskbarTab(hwnd);
|
Gdi::GuiThread::deleteTaskbarTab(hwnd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -561,7 +561,7 @@ namespace
|
|||||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||||
{
|
{
|
||||||
DDraw::RealPrimarySurface::setPresentationWindowTopmost();
|
DDraw::RealPrimarySurface::setPresentationWindowTopmost();
|
||||||
Gdi::Window::updateAll();
|
Gdi::Window::updateWindowPos(hwnd);
|
||||||
|
|
||||||
if (g_dwmSetIconicThumbnail)
|
if (g_dwmSetIconicThumbnail)
|
||||||
{
|
{
|
||||||
@ -964,7 +964,19 @@ namespace Gdi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gdi::Window::updateAll();
|
DWMNCRENDERINGPOLICY ncRenderingPolicy = DWMNCRP_DISABLED;
|
||||||
|
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncRenderingPolicy, sizeof(ncRenderingPolicy));
|
||||||
|
|
||||||
|
BOOL disableTransitions = TRUE;
|
||||||
|
DwmSetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, &disableTransitions, sizeof(disableTransitions));
|
||||||
|
|
||||||
|
const auto style = GetClassLong(hwnd, GCL_STYLE);
|
||||||
|
if (style & CS_DROPSHADOW)
|
||||||
|
{
|
||||||
|
CALL_ORIG_FUNC(SetClassLongA)(hwnd, GCL_STYLE, style & ~CS_DROPSHADOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdi::Window::updateWindowPos(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startFrame()
|
void startFrame()
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <dwmapi.h>
|
|
||||||
|
|
||||||
#include <Common/Log.h>
|
#include <Common/Log.h>
|
||||||
#include <Common/Rect.h>
|
#include <Common/Rect.h>
|
||||||
#include <D3dDdi/KernelModeThunks.h>
|
#include <D3dDdi/KernelModeThunks.h>
|
||||||
@ -128,23 +126,6 @@ namespace
|
|||||||
std::map<HWND, Window> g_windows;
|
std::map<HWND, Window> g_windows;
|
||||||
std::vector<Window*> g_windowZOrder;
|
std::vector<Window*> g_windowZOrder;
|
||||||
|
|
||||||
std::map<HWND, Window>::iterator addWindow(HWND hwnd)
|
|
||||||
{
|
|
||||||
DWMNCRENDERINGPOLICY ncRenderingPolicy = DWMNCRP_DISABLED;
|
|
||||||
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncRenderingPolicy, sizeof(ncRenderingPolicy));
|
|
||||||
|
|
||||||
BOOL disableTransitions = TRUE;
|
|
||||||
DwmSetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, &disableTransitions, sizeof(disableTransitions));
|
|
||||||
|
|
||||||
const auto style = GetClassLong(hwnd, GCL_STYLE);
|
|
||||||
if (style & CS_DROPSHADOW)
|
|
||||||
{
|
|
||||||
CALL_ORIG_FUNC(SetClassLongA)(hwnd, GCL_STYLE, style & ~CS_DROPSHADOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_windows.emplace(hwnd, Window(hwnd)).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bltWindow(const RECT& dst, const RECT& src, const Gdi::Region& clipRegion)
|
bool bltWindow(const RECT& dst, const RECT& src, const Gdi::Region& clipRegion)
|
||||||
{
|
{
|
||||||
if (dst.left == src.left && dst.top == src.top || clipRegion.isEmpty())
|
if (dst.left == src.left && dst.top == src.top || clipRegion.isEmpty())
|
||||||
@ -160,6 +141,16 @@ namespace
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto removeWindow(std::map<HWND, Window>::iterator it)
|
||||||
|
{
|
||||||
|
if (it->second.presentationWindow)
|
||||||
|
{
|
||||||
|
Gdi::GuiThread::destroyWindow(it->second.presentationWindow);
|
||||||
|
it->second.presentationWindow = nullptr;
|
||||||
|
}
|
||||||
|
return g_windows.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
void updatePosition(Window& window, const RECT& oldWindowRect, const RECT& oldClientRect,
|
void updatePosition(Window& window, const RECT& oldWindowRect, const RECT& oldClientRect,
|
||||||
const Gdi::Region& oldVisibleRegion, Gdi::Region& invalidatedRegion)
|
const Gdi::Region& oldVisibleRegion, Gdi::Region& invalidatedRegion)
|
||||||
{
|
{
|
||||||
@ -258,16 +249,20 @@ namespace
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool isWindowVisible = IsWindowVisible(hwnd);
|
||||||
|
const bool isVisible = isWindowVisible && !IsIconic(hwnd);
|
||||||
auto it = g_windows.find(hwnd);
|
auto it = g_windows.find(hwnd);
|
||||||
if (it == g_windows.end())
|
if (it == g_windows.end())
|
||||||
{
|
{
|
||||||
it = addWindow(hwnd);
|
if (!isWindowVisible)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
it = g_windows.emplace(hwnd, Window(hwnd)).first;
|
||||||
}
|
}
|
||||||
g_windowZOrder.push_back(&it->second);
|
|
||||||
|
|
||||||
const LONG exStyle = CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_EXSTYLE);
|
const LONG exStyle = CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_EXSTYLE);
|
||||||
const bool isLayered = it->second.isMenu || (exStyle & WS_EX_LAYERED);
|
const bool isLayered = it->second.isMenu || (exStyle & WS_EX_LAYERED);
|
||||||
const bool isVisible = IsWindowVisible(hwnd) && !IsIconic(hwnd);
|
|
||||||
|
|
||||||
if (isLayered != it->second.isLayered)
|
if (isLayered != it->second.isLayered)
|
||||||
{
|
{
|
||||||
@ -340,13 +335,22 @@ namespace
|
|||||||
context.invalidatedRegion |= visibleRegion - it->second.visibleRegion;
|
context.invalidatedRegion |= visibleRegion - it->second.visibleRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->second.presentationWindow &&
|
if (it->second.presentationWindow && isVisible &&
|
||||||
(!isVisible || it->second.presentationWindow != DDraw::RealPrimarySurface::getPresentationWindow()))
|
it->second.presentationWindow != DDraw::RealPrimarySurface::getPresentationWindow())
|
||||||
{
|
{
|
||||||
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, Gdi::Window::getWindowRgn(hwnd));
|
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, Gdi::Window::getWindowRgn(hwnd));
|
||||||
Gdi::Window::updatePresentationWindowPos(it->second.presentationWindow, hwnd);
|
Gdi::Window::updatePresentationWindowPos(it->second.presentationWindow, hwnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isWindowVisible)
|
||||||
|
{
|
||||||
|
g_windowZOrder.push_back(&it->second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removeWindow(it);
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,6 +359,25 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
namespace Window
|
namespace Window
|
||||||
{
|
{
|
||||||
|
void destroyWindow(HWND hwnd)
|
||||||
|
{
|
||||||
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
|
auto it = g_windows.find(hwnd);
|
||||||
|
if (it == g_windows.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->second.visibleRegion.isEmpty())
|
||||||
|
{
|
||||||
|
removeWindow(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HWND getPresentationWindow(HWND hwnd)
|
HWND getPresentationWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
D3dDdi::ScopedCriticalSection lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
@ -613,11 +636,7 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
if (g_windowZOrder.end() == std::find(g_windowZOrder.begin(), g_windowZOrder.end(), &it->second))
|
if (g_windowZOrder.end() == std::find(g_windowZOrder.begin(), g_windowZOrder.end(), &it->second))
|
||||||
{
|
{
|
||||||
if (it->second.presentationWindow)
|
it = removeWindow(it);
|
||||||
{
|
|
||||||
GuiThread::destroyWindow(it->second.presentationWindow);
|
|
||||||
}
|
|
||||||
it = g_windows.erase(it);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -724,5 +743,21 @@ namespace Gdi
|
|||||||
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_NOSIZE);
|
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_NOSIZE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateWindowPos(HWND hwnd)
|
||||||
|
{
|
||||||
|
if (IsWindowVisible(hwnd) && !IsIconic(hwnd))
|
||||||
|
{
|
||||||
|
updateAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
|
auto it = g_windows.find(hwnd);
|
||||||
|
if (it != g_windows.end() && !it->second.visibleRegion.isEmpty())
|
||||||
|
{
|
||||||
|
updateAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ namespace Gdi
|
|||||||
BYTE alphaFormat;
|
BYTE alphaFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void destroyWindow(HWND hwnd);
|
||||||
HWND getPresentationWindow(HWND hwnd);
|
HWND getPresentationWindow(HWND hwnd);
|
||||||
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
||||||
std::vector<LayeredWindow> getVisibleOverlayWindows();
|
std::vector<LayeredWindow> getVisibleOverlayWindows();
|
||||||
@ -38,5 +39,6 @@ namespace Gdi
|
|||||||
void updateLayeredWindowInfo(HWND hwnd, HDC hdcSrc, const POINT* pptSrc,
|
void updateLayeredWindowInfo(HWND hwnd, HDC hdcSrc, const POINT* pptSrc,
|
||||||
COLORREF colorKey, BYTE alpha, BYTE alphaFormat);
|
COLORREF colorKey, BYTE alpha, BYTE alphaFormat);
|
||||||
void updatePresentationWindowPos(HWND presentationWindow, HWND owner);
|
void updatePresentationWindowPos(HWND presentationWindow, HWND owner);
|
||||||
|
void updateWindowPos(HWND hwnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user