diff --git a/DDrawCompat/Config/Config.cpp b/DDrawCompat/Config/Config.cpp index c0ddc91..48bc7c4 100644 --- a/DDrawCompat/Config/Config.cpp +++ b/DDrawCompat/Config/Config.cpp @@ -5,6 +5,7 @@ namespace Config Settings::AlternatePixelCenter alternatePixelCenter; Settings::AltTabFix altTabFix; Settings::Antialiasing antialiasing; + Settings::BltFilter bltFilter; Settings::ConfigHotKey configHotKey; Settings::CpuAffinity cpuAffinity; Settings::DesktopColorDepth desktopColorDepth; diff --git a/DDrawCompat/Config/Config.h b/DDrawCompat/Config/Config.h index cd58a71..e26b72f 100644 --- a/DDrawCompat/Config/Config.h +++ b/DDrawCompat/Config/Config.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ namespace Config extern Settings::AlternatePixelCenter alternatePixelCenter; extern Settings::AltTabFix altTabFix; extern Settings::Antialiasing antialiasing; + extern Settings::BltFilter bltFilter; extern Settings::ConfigHotKey configHotKey; extern Settings::CpuAffinity cpuAffinity; extern Settings::DesktopColorDepth desktopColorDepth; diff --git a/DDrawCompat/Config/Settings/BltFilter.h b/DDrawCompat/Config/Settings/BltFilter.h new file mode 100644 index 0000000..6bb762a --- /dev/null +++ b/DDrawCompat/Config/Settings/BltFilter.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace Config +{ + namespace Settings + { + class BltFilter : public MappedSetting + { + public: + static const UINT NATIVE = 0; + static const UINT POINT = 1; + static const UINT BILINEAR = 2; + + BltFilter::BltFilter() + : MappedSetting("BltFilter", "point", { {"native", NATIVE}, {"point", POINT}, {"bilinear", BILINEAR}}) + { + } + }; + } +} diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index dac1ec7..84a8748 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -220,7 +220,13 @@ namespace D3dDdi return presentationBlt(data, srcResource); } - return sysMemPreferredBlt(data, *srcResource); + HRESULT result = bltViaCpu(data, *srcResource); + if (S_FALSE != result) + { + return result; + } + + return bltViaGpu(data, *srcResource); } prepareForBltDst(data); @@ -255,6 +261,138 @@ namespace D3dDdi return LOG_RESULT(S_OK); } + HRESULT Resource::bltViaCpu(D3DDDIARG_BLT data, Resource& srcResource) + { + if (m_fixedData.Format != srcResource.m_fixedData.Format || + 0 == m_formatInfo.bytesPerPixel || + D3DDDIFMT_P8 != m_fixedData.Format && !m_isOversized && !srcResource.m_isOversized) + { + return S_FALSE; + } + + D3DDDIARG_LOCK srcLock = {}; + srcLock.hResource = data.hSrcResource; + srcLock.SubResourceIndex = data.SrcSubResourceIndex; + if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool) + { + srcLock.Flags.NotifyOnly = 1; + } + else + { + srcLock.Area = data.SrcRect; + srcLock.Flags.AreaValid = 1; + srcLock.Flags.ReadOnly = 1; + } + + HRESULT result = srcResource.lock(srcLock); + if (FAILED(result)) + { + return result; + } + + D3DDDIARG_LOCK dstLock = {}; + dstLock.hResource = data.hDstResource; + dstLock.SubResourceIndex = data.DstSubResourceIndex; + if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) + { + dstLock.Flags.NotifyOnly = 1; + } + else + { + dstLock.Area = data.DstRect; + dstLock.Flags.AreaValid = 1; + } + + result = lock(dstLock); + if (SUCCEEDED(result)) + { + if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool) + { + auto& lockData = srcResource.m_lockData[data.SrcSubResourceIndex]; + srcLock.pSurfData = static_cast(lockData.data) + data.SrcRect.top * lockData.pitch + + data.SrcRect.left * m_formatInfo.bytesPerPixel; + srcLock.Pitch = lockData.pitch; + } + + if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) + { + auto& lockData = m_lockData[data.DstSubResourceIndex]; + dstLock.pSurfData = static_cast(lockData.data) + data.DstRect.top * lockData.pitch + + data.DstRect.left * m_formatInfo.bytesPerPixel; + dstLock.Pitch = lockData.pitch; + } + + DDraw::Blitter::blt( + dstLock.pSurfData, + dstLock.Pitch, + data.DstRect.right - data.DstRect.left, + data.DstRect.bottom - data.DstRect.top, + srcLock.pSurfData, + srcLock.Pitch, + (1 - 2 * data.Flags.MirrorLeftRight) * (data.SrcRect.right - data.SrcRect.left), + (1 - 2 * data.Flags.MirrorUpDown) * (data.SrcRect.bottom - data.SrcRect.top), + m_formatInfo.bytesPerPixel, + data.Flags.DstColorKey ? reinterpret_cast(&data.ColorKey) : nullptr, + data.Flags.SrcColorKey ? reinterpret_cast(&data.ColorKey) : nullptr); + + D3DDDIARG_UNLOCK dstUnlock = {}; + dstUnlock.hResource = dstLock.hResource; + dstUnlock.SubResourceIndex = dstLock.SubResourceIndex; + dstUnlock.Flags.NotifyOnly = dstLock.Flags.NotifyOnly; + unlock(dstUnlock); + } + + D3DDDIARG_UNLOCK srcUnlock = {}; + srcUnlock.hResource = srcLock.hResource; + srcUnlock.SubResourceIndex = srcLock.SubResourceIndex; + srcUnlock.Flags.NotifyOnly = srcLock.Flags.NotifyOnly; + srcResource.unlock(srcUnlock); + return result; + } + + HRESULT Resource::bltViaGpu(D3DDDIARG_BLT data, Resource& srcResource) + { + if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool && + (m_fixedData.Flags.RenderTarget || data.Flags.SrcColorKey || data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown)) + { + if (SUCCEEDED(shaderBlt(data, srcResource))) + { + return S_OK; + } + } + else + { + srcResource.prepareForBltSrc(data); + prepareForBltDst(data); + } + + auto bltFilter = Config::bltFilter.get(); + if (Config::Settings::BltFilter::NATIVE != bltFilter && + D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool && + D3DDDIPOOL_SYSTEMMEM != srcResource.m_fixedData.Pool) + { + if (Config::Settings::BltFilter::POINT == bltFilter) + { + data.Flags.Point = 1; + } + else + { + data.Flags.Linear = 1; + } + } + + HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data); + if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) + { + notifyLock(data.DstSubResourceIndex); + } + else if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool) + { + srcResource.notifyLock(data.SrcSubResourceIndex); + } + return result; + } + void Resource::clearUpToDateFlags(UINT subResourceIndex) { m_lockData[subResourceIndex].isMsaaUpToDate = false; @@ -1096,118 +1234,6 @@ namespace D3dDdi return LOG_RESULT(S_OK); } - HRESULT Resource::sysMemPreferredBlt(D3DDDIARG_BLT& data, Resource& srcResource) - { - if (m_fixedData.Format == srcResource.m_fixedData.Format && - 0 != m_formatInfo.bytesPerPixel && - (D3DDDIFMT_P8 == m_fixedData.Format || m_isOversized || srcResource.m_isOversized)) - { - D3DDDIARG_LOCK srcLock = {}; - srcLock.hResource = data.hSrcResource; - srcLock.SubResourceIndex = data.SrcSubResourceIndex; - if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool) - { - srcLock.Flags.NotifyOnly = 1; - } - else - { - srcLock.Area = data.SrcRect; - srcLock.Flags.AreaValid = 1; - srcLock.Flags.ReadOnly = 1; - } - - HRESULT result = srcResource.lock(srcLock); - if (FAILED(result)) - { - return result; - } - - D3DDDIARG_LOCK dstLock = {}; - dstLock.hResource = data.hDstResource; - dstLock.SubResourceIndex = data.DstSubResourceIndex; - if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) - { - dstLock.Flags.NotifyOnly = 1; - } - else - { - dstLock.Area = data.DstRect; - dstLock.Flags.AreaValid = 1; - } - - result = lock(dstLock); - if (SUCCEEDED(result)) - { - if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool) - { - auto& lockData = srcResource.m_lockData[data.SrcSubResourceIndex]; - srcLock.pSurfData = static_cast(lockData.data) + data.SrcRect.top * lockData.pitch + - data.SrcRect.left * m_formatInfo.bytesPerPixel; - srcLock.Pitch = lockData.pitch; - } - - if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) - { - auto& lockData = m_lockData[data.DstSubResourceIndex]; - dstLock.pSurfData = static_cast(lockData.data) + data.DstRect.top * lockData.pitch + - data.DstRect.left * m_formatInfo.bytesPerPixel; - dstLock.Pitch = lockData.pitch; - } - - DDraw::Blitter::blt( - dstLock.pSurfData, - dstLock.Pitch, - data.DstRect.right - data.DstRect.left, - data.DstRect.bottom - data.DstRect.top, - srcLock.pSurfData, - srcLock.Pitch, - (1 - 2 * data.Flags.MirrorLeftRight) * (data.SrcRect.right - data.SrcRect.left), - (1 - 2 * data.Flags.MirrorUpDown) * (data.SrcRect.bottom - data.SrcRect.top), - m_formatInfo.bytesPerPixel, - data.Flags.DstColorKey ? reinterpret_cast(&data.ColorKey) : nullptr, - data.Flags.SrcColorKey ? reinterpret_cast(&data.ColorKey) : nullptr); - - D3DDDIARG_UNLOCK dstUnlock = {}; - dstUnlock.hResource = dstLock.hResource; - dstUnlock.SubResourceIndex = dstLock.SubResourceIndex; - dstUnlock.Flags.NotifyOnly = dstLock.Flags.NotifyOnly; - unlock(dstUnlock); - } - - D3DDDIARG_UNLOCK srcUnlock = {}; - srcUnlock.hResource = srcLock.hResource; - srcUnlock.SubResourceIndex = srcLock.SubResourceIndex; - srcUnlock.Flags.NotifyOnly = srcLock.Flags.NotifyOnly; - srcResource.unlock(srcUnlock); - return result; - } - - if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool && - (m_fixedData.Flags.RenderTarget || data.Flags.SrcColorKey || data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown)) - { - if (SUCCEEDED(shaderBlt(data, srcResource))) - { - return S_OK; - } - } - else - { - srcResource.prepareForBltSrc(data); - prepareForBltDst(data); - } - - HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data); - if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool) - { - notifyLock(data.DstSubResourceIndex); - } - else if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool) - { - srcResource.notifyLock(data.SrcSubResourceIndex); - } - return result; - } - HRESULT Resource::unlock(const D3DDDIARG_UNLOCK& data) { return (m_lockResource || m_isOversized) ? S_OK : m_device.getOrigVtable().pfnUnlock(m_device, &data); diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index 928b9be..adb9dbf 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -77,6 +77,8 @@ namespace D3dDdi }; HRESULT bltLock(D3DDDIARG_LOCK& data); + HRESULT bltViaCpu(D3DDDIARG_BLT data, Resource& srcResource); + HRESULT bltViaGpu(D3DDDIARG_BLT data, Resource& srcResource); void clearUpToDateFlags(UINT subResourceIndex); void clipRect(UINT subResourceIndex, RECT& rect); HRESULT copySubResource(Resource& dstResource, Resource& srcResource, UINT subResourceIndex); @@ -102,7 +104,6 @@ namespace D3dDdi HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource); void presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect); HRESULT shaderBlt(D3DDDIARG_BLT& data, Resource& srcResource); - HRESULT sysMemPreferredBlt(D3DDDIARG_BLT& data, Resource& srcResource); Device& m_device; HANDLE m_handle; diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index de884f0..da5ca56 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -220,6 +220,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 1bc12cf..eeafb5e 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -561,6 +561,9 @@ Header Files\Win32 + + Header Files\Config\Settings + diff --git a/DDrawCompat/Overlay/ConfigWindow.cpp b/DDrawCompat/Overlay/ConfigWindow.cpp index 11ff470..71cf70f 100644 --- a/DDrawCompat/Overlay/ConfigWindow.cpp +++ b/DDrawCompat/Overlay/ConfigWindow.cpp @@ -12,6 +12,7 @@ namespace Overlay , m_focus(nullptr) { addControl(Config::alternatePixelCenter); + addControl(Config::bltFilter); addControl(Config::antialiasing); addControl(Config::displayFilter); addControl(Config::renderColorDepth);