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

Added AlignSysMemSurfaces setting

This commit is contained in:
narzoul 2022-05-30 00:54:39 +02:00
parent 641df63f14
commit fa99142587
12 changed files with 125 additions and 10 deletions

View File

@ -2,6 +2,7 @@
namespace Config
{
Settings::AlignSysMemSurfaces alignSysMemSurfaces;
Settings::AlternatePixelCenter alternatePixelCenter;
Settings::AltTabFix altTabFix;
Settings::Antialiasing antialiasing;

View File

@ -1,5 +1,6 @@
#pragma once
#include <Config/Settings/AlignSysMemSurfaces.h>
#include <Config/Settings/AlternatePixelCenter.h>
#include <Config/Settings/AltTabFix.h>
#include <Config/Settings/Antialiasing.h>
@ -27,6 +28,7 @@
namespace Config
{
extern Settings::AlignSysMemSurfaces alignSysMemSurfaces;
extern Settings::AlternatePixelCenter alternatePixelCenter;
extern Settings::AltTabFix altTabFix;
extern Settings::Antialiasing antialiasing;

View File

@ -0,0 +1,18 @@
#pragma once
#include <Config/MappedSetting.h>
namespace Config
{
namespace Settings
{
class AlignSysMemSurfaces : public MappedSetting<UINT>
{
public:
AlignSysMemSurfaces()
: MappedSetting("AlignSysMemSurfaces", "on", { {"off", 8}, {"on", 0} })
{
}
};
}
}

View File

@ -566,6 +566,7 @@ namespace D3dDdi
return;
}
const auto ALIGNMENT = DDraw::Surface::ALIGNMENT;
std::vector<D3DDDI_SURFACEINFO> surfaceInfo(m_fixedData.SurfCount);
for (UINT i = 0; i < m_fixedData.SurfCount; ++i)
{
@ -575,21 +576,16 @@ namespace D3dDdi
if (i != 0)
{
std::uintptr_t offset = reinterpret_cast<std::uintptr_t>(surfaceInfo[i - 1].pSysMem) +
((surfaceInfo[i - 1].SysMemPitch * surfaceInfo[i - 1].Height + 15) & ~15);
((surfaceInfo[i - 1].SysMemPitch * surfaceInfo[i - 1].Height + ALIGNMENT - 1) / ALIGNMENT * ALIGNMENT);
surfaceInfo[i].pSysMem = reinterpret_cast<void*>(offset);
}
}
std::uintptr_t bufferSize = reinterpret_cast<std::uintptr_t>(surfaceInfo.back().pSysMem) +
surfaceInfo.back().SysMemPitch * surfaceInfo.back().Height + 8;
surfaceInfo.back().SysMemPitch * surfaceInfo.back().Height + ALIGNMENT;
m_lockBuffer.reset(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufferSize));
BYTE* bufferStart = static_cast<BYTE*>(m_lockBuffer.get());
if (0 == reinterpret_cast<std::uintptr_t>(bufferStart) % 16)
{
bufferStart += 8;
}
BYTE* bufferStart = static_cast<BYTE*>(DDraw::Surface::alignBuffer(m_lockBuffer.get()));
for (UINT i = 0; i < m_fixedData.SurfCount; ++i)
{
surfaceInfo[i].pSysMem = bufferStart + reinterpret_cast<uintptr_t>(surfaceInfo[i].pSysMem);

View File

@ -1,3 +1,5 @@
#include <type_traits>
#include <Common/CompatVtable.h>
#include <DDraw/DirectDrawSurface.h>
#include <DDraw/ScopedThreadLock.h>
@ -69,6 +71,11 @@ namespace
SET_COMPAT_METHOD(SetClipper);
SET_COMPAT_METHOD(SetPalette);
SET_COMPAT_METHOD(Unlock);
if constexpr (!std::is_same_v<Vtable, IDirectDrawSurfaceVtbl> && !std::is_same_v<Vtable, IDirectDrawSurface2Vtbl>)
{
SET_COMPAT_METHOD(SetSurfaceDesc);
}
}
}

View File

@ -1,6 +1,7 @@
#include <initguid.h>
#include <Common/CompatPtr.h>
#include <Config/Config.h>
#include <DDraw/DirectDrawClipper.h>
#include <DDraw/DirectDrawSurface.h>
#include <DDraw/Surfaces/Surface.h>
@ -11,6 +12,14 @@
DEFINE_GUID(IID_CompatSurfacePrivateData,
0xc62d8849, 0xdfac, 0x4454, 0xa1, 0xe8, 0xda, 0x67, 0x44, 0x64, 0x26, 0xba);
namespace
{
void heapFree(void* p)
{
HeapFree(GetProcessHeap(), 0, p);
}
}
namespace DDraw
{
HRESULT STDMETHODCALLTYPE Surface::QueryInterface(REFIID, LPVOID*)
@ -37,6 +46,7 @@ namespace DDraw
: m_origCaps(origCaps)
, m_refCount(0)
, m_sizeOverride{}
, m_sysMemBuffer(nullptr, &heapFree)
{
}
@ -45,6 +55,19 @@ namespace DDraw
DirectDrawClipper::setClipper(*this, nullptr);
}
void* Surface::alignBuffer(void* buffer)
{
auto p = static_cast<BYTE*>(buffer);
const DWORD alignmentOffset = Config::alignSysMemSurfaces.get();
const DWORD mod = reinterpret_cast<DWORD>(p) % ALIGNMENT;
p = p - mod + alignmentOffset;
if (mod > alignmentOffset)
{
p += ALIGNMENT;
}
return p;
}
void Surface::attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface> privateData)
{
if (SUCCEEDED(dds->SetPrivateData(&dds, IID_CompatSurfacePrivateData,
@ -82,6 +105,10 @@ namespace DDraw
attach(*attachedSurfaces[i], std::make_unique<Surface>(privateData->m_origCaps));
}
}
else if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) && !(desc.dwFlags & DDSD_LPSURFACE))
{
privateData->fixAlignment(*surface7);
}
attach(*surface7, std::move(privateData));
@ -106,6 +133,39 @@ namespace DDraw
m_impl7.reset(new SurfaceImpl<IDirectDrawSurface7>(this));
}
void Surface::fixAlignment(CompatRef<IDirectDrawSurface7> surface)
{
DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc);
if (FAILED(surface->Lock(&surface, nullptr, &desc, DDLOCK_WAIT, nullptr)))
{
return;
}
surface->Unlock(&surface, nullptr);
const DWORD alignmentOffset = Config::alignSysMemSurfaces.get();
const DWORD size = desc.lPitch * desc.dwHeight;
if (0 == size || alignmentOffset == reinterpret_cast<DWORD>(desc.lpSurface) % ALIGNMENT)
{
return;
}
m_sysMemBuffer.reset(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + ALIGNMENT));
if (!m_sysMemBuffer)
{
return;
}
desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_LPSURFACE;
desc.lpSurface = alignBuffer(m_sysMemBuffer.get());
if (FAILED(surface->SetSurfaceDesc(&surface, &desc, 0)))
{
m_sysMemBuffer.reset();
}
}
template <>
SurfaceImpl<IDirectDrawSurface>* Surface::getImpl<IDirectDrawSurface>() const { return m_impl.get(); }
template <>

View File

@ -16,6 +16,8 @@ namespace DDraw
class Surface
{
public:
static const DWORD ALIGNMENT = 32;
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
@ -23,6 +25,8 @@ namespace DDraw
Surface(DWORD origCaps);
virtual ~Surface();
static void* alignBuffer(void* buffer);
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
static HRESULT create(
CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface, std::unique_ptr<Surface> privateData);
@ -44,6 +48,8 @@ namespace DDraw
virtual void createImpl();
void fixAlignment(CompatRef<IDirectDrawSurface7> surface);
std::unique_ptr<SurfaceImpl<IDirectDrawSurface>> m_impl;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface2>> m_impl2;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface3>> m_impl3;
@ -59,5 +65,6 @@ namespace DDraw
DWORD m_origCaps;
DWORD m_refCount;
SIZE m_sizeOverride;
std::unique_ptr<void, void(*)(void*)> m_sysMemBuffer;
};
}

View File

@ -1,4 +1,5 @@
#include <set>
#include <type_traits>
#include <d3d.h>
#include <d3dumddi.h>
@ -255,6 +256,24 @@ namespace DDraw
return getOrigVtable(This).SetPalette(This, lpDDPalette);
}
template <typename TSurface>
HRESULT SurfaceImpl<TSurface>::SetSurfaceDesc(TSurface* This, TSurfaceDesc* lpddsd, DWORD dwFlags)
{
if constexpr (!std::is_same_v<TSurface, IDirectDrawSurface> && !std::is_same_v<TSurface, IDirectDrawSurface2>)
{
HRESULT result = getOrigVtable(This).SetSurfaceDesc(This, lpddsd, dwFlags);
if (SUCCEEDED(result) && (lpddsd->dwFlags & DDSD_LPSURFACE))
{
m_data->m_sysMemBuffer.reset();
}
return result;
}
else
{
return DD_OK;
}
}
template <typename TSurface>
HRESULT SurfaceImpl<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
{

View File

@ -40,6 +40,7 @@ namespace DDraw
virtual HRESULT Restore(TSurface* This);
virtual HRESULT SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper);
virtual HRESULT SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette);
virtual HRESULT SetSurfaceDesc(TSurface* This, TSurfaceDesc* lpddsd, DWORD dwFlags);
virtual HRESULT Unlock(TSurface* This, TUnlockParam lpRect);
protected:

View File

@ -158,6 +158,7 @@
<ClInclude Include="Config\MappedSetting.h" />
<ClInclude Include="Config\Parser.h" />
<ClInclude Include="Config\Setting.h" />
<ClInclude Include="Config\Settings\AlignSysMemSurfaces.h" />
<ClInclude Include="Config\Settings\AlternatePixelCenter.h" />
<ClInclude Include="Config\Settings\AltTabFix.h" />
<ClInclude Include="Config\Settings\Antialiasing.h" />

View File

@ -570,6 +570,9 @@
<ClInclude Include="Overlay\ButtonControl.h">
<Filter>Header Files\Overlay</Filter>
</ClInclude>
<ClInclude Include="Config\Settings\AlignSysMemSurfaces.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">

View File

@ -90,7 +90,7 @@ namespace
}
void* bits = nullptr;
return CreateDIBSection(nullptr, &bmi, DIB_RGB_COLORS, &bits, section, 8);
return CreateDIBSection(nullptr, &bmi, DIB_RGB_COLORS, &bits, section, Config::alignSysMemSurfaces.get());
}
}
@ -206,7 +206,7 @@ namespace Gdi
desc.ddpfPixelFormat = DDraw::DirectDraw::getRgbPixelFormat(g_bpp);
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
desc.lPitch = g_pitch;
desc.lpSurface = static_cast<unsigned char*>(g_surfaceView) + 8 +
desc.lpSurface = static_cast<unsigned char*>(g_surfaceView) + Config::alignSysMemSurfaces.get() +
(rect.top - g_bounds.top) * g_pitch +
(rect.left - g_bounds.left) * g_bpp / 8;
return desc;