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

GDI performance enhancements

This commit is contained in:
narzoul 2016-05-22 13:45:38 +02:00
parent c4ea2541a9
commit c8ecb227a3
3 changed files with 152 additions and 6 deletions

View File

@ -1,9 +1,31 @@
#include "CompatDisplayMode.h"
#include "CompatPtr.h"
#include "DDrawProcs.h"
#include "DDrawRepository.h"
#include "Hook.h"
namespace
{
CompatWeakPtr<IDirectDrawSurface7> g_compatibleSurface = {};
HDC g_compatibleDc = nullptr;
CompatDisplayMode::DisplayMode g_emulatedDisplayMode = {};
CompatPtr<IDirectDrawSurface7> createCompatibleSurface()
{
DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
desc.dwWidth = 1;
desc.dwHeight = 1;
desc.ddpfPixelFormat = g_emulatedDisplayMode.pixelFormat;
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
auto dd = DDrawRepository::getDirectDraw();
CompatPtr<IDirectDrawSurface7> surface;
dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr);
return surface;
}
template <typename TSurfaceDesc>
HRESULT PASCAL enumDisplayModesCallback(
TSurfaceDesc* lpDDSurfaceDesc,
@ -49,13 +71,63 @@ namespace
Compat::Log() << "Failed to find the requested display mode: " <<
width << "x" << height << "x" << bpp;
}
return pf;
}
void releaseCompatibleDc()
{
if (g_compatibleDc)
{
Compat::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 = createCompatibleSurface().detach();
if (g_compatibleSurface &&
SUCCEEDED(g_compatibleSurface->GetDC(g_compatibleSurface, &g_compatibleDc)))
{
Compat::origProcs.ReleaseDDThreadLock();
}
}
}
namespace CompatDisplayMode
{
HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy)
{
replaceDc(hdc);
return 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)
{
replaceDc(hdc);
return CALL_ORIG_FUNC(CreateDIBitmap)(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage);
}
HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight)
{
replaceDc(hdc);
return CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight);
}
DisplayMode getDisplayMode(CompatRef<IDirectDraw7> dd)
{
if (0 == g_emulatedDisplayMode.width)
@ -85,6 +157,7 @@ namespace CompatDisplayMode
if (SUCCEEDED(result))
{
ZeroMemory(&g_emulatedDisplayMode, sizeof(g_emulatedDisplayMode));
releaseCompatibleDc();
}
return result;
}
@ -111,6 +184,7 @@ namespace CompatDisplayMode
g_emulatedDisplayMode.pixelFormat = pf;
g_emulatedDisplayMode.refreshRate = refreshRate;
g_emulatedDisplayMode.flags = flags;
updateCompatibleDc();
return DD_OK;
}

View File

@ -17,6 +17,11 @@ namespace CompatDisplayMode
DWORD flags;
};
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);
DisplayMode getDisplayMode(CompatRef<IDirectDraw7> dd);
DisplayMode getRealDisplayMode(CompatRef<IDirectDraw7> dd);
HRESULT restoreDisplayMode(CompatRef<IDirectDraw7> dd);

View File

@ -1,5 +1,6 @@
#include <unordered_map>
#include "CompatDisplayMode.h"
#include "CompatGdi.h"
#include "CompatGdiDc.h"
#include "CompatGdiDcFunctions.h"
@ -111,18 +112,86 @@ namespace
return &compatGdiDcFunc<OrigFuncPtr, origFunc, Result, Params...>;
}
DWORD getDdLockFlagsBlt(HDC hdcDest, HDC hdcSrc)
{
return hasDisplayDcArg(hdcSrc) && !hasDisplayDcArg(hdcDest) ? DDLOCK_READONLY : 0;
}
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename... Params>
DWORD getDdLockFlags(Params...)
{
return 0;
}
template <>
DWORD getDdLockFlags<decltype(&AlphaBlend), &AlphaBlend>(
HDC hdcDest, int, int, int, int, HDC hdcSrc, int, int, int, int, BLENDFUNCTION)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <>
DWORD getDdLockFlags<decltype(&BitBlt), &BitBlt>(
HDC hdcDest, int, int, int, int, HDC hdcSrc, int, int, DWORD)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <>
DWORD getDdLockFlags<decltype(&GdiAlphaBlend), &GdiAlphaBlend>(
HDC hdcDest, int, int, int, int, HDC hdcSrc, int, int, int, int, BLENDFUNCTION)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <>
DWORD getDdLockFlags<decltype(&GdiTransparentBlt), &GdiTransparentBlt >(
HDC hdcDest, int, int, int, int, HDC hdcSrc, int, int, int, int, UINT)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <>
DWORD getDdLockFlags<decltype(&GetDIBits), &GetDIBits>(
HDC, HBITMAP, UINT, UINT, LPVOID, LPBITMAPINFO, UINT)
{
return DDLOCK_READONLY;
}
template <>
DWORD getDdLockFlags<decltype(&GetPixel), &GetPixel>(HDC, int, int)
{
return DDLOCK_READONLY;
}
template <>
DWORD getDdLockFlags<decltype(&MaskBlt), &MaskBlt>(
HDC hdcDest, int, int, int, int, HDC hdcSrc, int, int, HBITMAP, int, int, DWORD)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <>
DWORD getDdLockFlags<decltype(&PlgBlt), &PlgBlt>(
HDC hdcDest, const POINT*, HDC hdcSrc, int, int, int, int, HBITMAP, int, int)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <>
DWORD getDdLockFlags<decltype(&StretchBlt), &StretchBlt>(
HDC hdcDest, int, int, int, int, HDC hdcSrc, int, int, int, int, DWORD)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <>
DWORD getDdLockFlags<decltype(&TransparentBlt), &TransparentBlt>(
HDC hdcDest, int, int, int, int, HDC hdcSrc, int, int, int, int, UINT)
{
return getDdLockFlagsBlt(hdcDest, hdcSrc);
}
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
void hookGdiDcFunction(const char* moduleName, const char* funcName)
{
@ -154,10 +223,9 @@ namespace CompatGdiDcFunctions
// Bitmap functions
HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend);
HOOK_GDI_DC_FUNCTION(gdi32, BitBlt);
HOOK_GDI_DC_FUNCTION(gdi32, CreateCompatibleBitmap);
HOOK_GDI_DC_FUNCTION(gdi32, CreateDIBitmap);
HOOK_GDI_DC_FUNCTION(gdi32, CreateDIBSection);
HOOK_GDI_DC_FUNCTION(gdi32, CreateDiscardableBitmap);
HOOK_FUNCTION(gdi32, CreateCompatibleBitmap, CompatDisplayMode::createCompatibleBitmap);
HOOK_FUNCTION(gdi32, CreateDIBitmap, CompatDisplayMode::createDIBitmap);
HOOK_FUNCTION(gdi32, CreateDiscardableBitmap, CompatDisplayMode::createDiscardableBitmap);
HOOK_GDI_DC_FUNCTION(gdi32, ExtFloodFill);
HOOK_GDI_DC_FUNCTION(gdi32, GdiAlphaBlend);
HOOK_GDI_DC_FUNCTION(gdi32, GdiGradientFill);
@ -179,7 +247,6 @@ namespace CompatGdiDcFunctions
HOOK_GDI_DC_FUNCTION(gdi32, PatBlt);
// Device context functions
HOOK_GDI_DC_FUNCTION(gdi32, CreateCompatibleDC);
HOOK_GDI_DC_FUNCTION(gdi32, DrawEscape);
HOOK_FUNCTION(user32, WindowFromDC, windowFromDc);