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

Avoid side effects when method implementations are delegated to higher versions

Some DirectDraw methods are implemented by delegating to the same method
in a higher interface version. In this case, the hooking logic could be
executed twice, leading to unwanted side effects. This is now avoided.
This commit is contained in:
narzoul 2016-05-02 23:53:36 +02:00
parent f7f5348a87
commit fe8abe9d5a
2 changed files with 62 additions and 54 deletions

View File

@ -17,14 +17,69 @@ namespace
return DDENUMRET_CANCEL;
}
DWORD getRefreshRate()
template <typename TDirectDraw>
HRESULT setDisplayMode(TDirectDraw* This, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP,
DWORD dwRefreshRate, DWORD dwFlags)
{
return 0;
typename Types<TDirectDraw>::TSurfaceDesc desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
desc.dwWidth = dwWidth;
desc.dwHeight = dwHeight;
desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
desc.ddpfPixelFormat.dwRGBBitCount = dwBPP;
switch (dwBPP)
{
case 1: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED1; break;
case 2: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED2; break;
case 4: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED4; break;
case 8: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8; break;
}
DDPIXELFORMAT pf = {};
if (dwBPP > 8)
{
if (FAILED(CompatDirectDraw<TDirectDraw>::s_origVtable.EnumDisplayModes(
This, 0, &desc, &pf, &enumDisplayModesCallback)) || 0 == pf.dwSize)
{
Compat::Log() << "Failed to find the requested display mode: " <<
dwWidth << "x" << dwHeight << "x" << dwBPP;
return DDERR_INVALIDMODE;
}
}
else
{
pf = desc.ddpfPixelFormat;
}
HRESULT result = CompatDirectDraw<TDirectDraw>::s_origVtable.SetDisplayMode(
This, dwWidth, dwHeight, 32, dwRefreshRate, dwFlags);
if (SUCCEEDED(result))
{
CompatPrimarySurface::displayMode.width = dwWidth;
CompatPrimarySurface::displayMode.height = dwHeight;
CompatPrimarySurface::displayMode.pixelFormat = pf;
CompatPrimarySurface::displayMode.refreshRate = dwRefreshRate;
CompatPrimarySurface::isDisplayModeChanged = true;
}
else
{
Compat::Log() << "Failed to set the display mode to " << dwWidth << "x" << dwHeight << "x32";
}
return result;
}
DWORD getRefreshRate(DWORD dwRefreshRate, DWORD /*dwFlags*/)
HRESULT setDisplayMode(IDirectDraw* This, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
{
return dwRefreshRate;
IDirectDraw7* dd = nullptr;
CompatDirectDraw<IDirectDraw>::s_origVtable.QueryInterface(
This, IID_IDirectDraw7, reinterpret_cast<void**>(&dd));
HRESULT result = setDisplayMode(dd, dwWidth, dwHeight, dwBPP, 0, 0);
CompatDirectDraw<IDirectDraw7>::s_origVtable.Release(dd);
return result;
}
}
@ -116,54 +171,7 @@ HRESULT STDMETHODCALLTYPE CompatDirectDraw<TDirectDraw>::SetDisplayMode(
DWORD dwBPP,
Params... params)
{
TSurfaceDesc desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
desc.dwWidth = dwWidth;
desc.dwHeight = dwHeight;
desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
desc.ddpfPixelFormat.dwRGBBitCount = dwBPP;
switch (dwBPP)
{
case 1: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED1; break;
case 2: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED2; break;
case 4: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED4; break;
case 8: desc.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8; break;
}
DDPIXELFORMAT pf = {};
if (dwBPP > 8)
{
if (FAILED(s_origVtable.EnumDisplayModes(This, 0, &desc, &pf, &enumDisplayModesCallback)) ||
0 == pf.dwSize)
{
Compat::Log() << "Failed to find the requested display mode: " <<
dwWidth << "x" << dwHeight << "x" << dwBPP;
return DDERR_INVALIDMODE;
}
}
else
{
pf = desc.ddpfPixelFormat;
}
HRESULT result = s_origVtable.SetDisplayMode(This, dwWidth, dwHeight, 32, params...);
if (SUCCEEDED(result))
{
CompatPrimarySurface::displayMode.width = dwWidth;
CompatPrimarySurface::displayMode.height = dwHeight;
CompatPrimarySurface::displayMode.pixelFormat = pf;
CompatPrimarySurface::displayMode.refreshRate = getRefreshRate(params...);
CompatPrimarySurface::isDisplayModeChanged = true;
}
else
{
Compat::Log() << "Failed to set the display mode to " << dwWidth << "x" << dwHeight << "x32";
}
return result;
return setDisplayMode(This, dwWidth, dwHeight, dwBPP, params...);
}
template CompatDirectDraw<IDirectDraw>;

View File

@ -565,8 +565,8 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::Unlock(TSurface* Th
template <typename TSurface>
void CompatDirectDrawSurface<TSurface>::restorePrimaryCaps(TDdsCaps& caps)
{
caps.dwCaps ^= DDSCAPS_OFFSCREENPLAIN;
caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE;
caps.dwCaps &= ~(DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
}
template <> const IID& CompatDirectDrawSurface<IDirectDrawSurface>::s_iid = IID_IDirectDrawSurface;