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

Fixed depth buffer issues with D3D9On12

This commit is contained in:
narzoul 2022-12-30 18:12:35 +01:00
parent 12c4f87cb6
commit defdfafe20
8 changed files with 166 additions and 70 deletions

View File

@ -58,6 +58,7 @@ namespace D3dDdi
, m_luid(KernelModeThunks::getLastOpenAdapterInfo().luid)
, m_deviceName(KernelModeThunks::getLastOpenAdapterInfo().deviceName)
, m_repository{}
, m_info(findInfo())
{
}
@ -80,7 +81,7 @@ namespace D3dDdi
return getAspectRatio({});
}
const Adapter::AdapterInfo& Adapter::getInfo() const
const Adapter::AdapterInfo& Adapter::findInfo() const
{
auto it = s_adapterInfos.find(m_luid);
if (it != s_adapterInfos.end())
@ -91,12 +92,16 @@ namespace D3dDdi
AdapterInfo& info = s_adapterInfos.insert({ m_luid, {} }).first->second;
getCaps(D3DDDICAPS_GETD3D7CAPS, info.d3dExtendedCaps);
info.formatOps = getFormatOps();
info.supportedZBufferBitDepths = getSupportedZBufferBitDepths(info.formatOps);
auto d3d9on12 = GetModuleHandle("d3d9on12");
info.isD3D9On12 = d3d9on12 && d3d9on12 == Compat::getModuleHandleFromAddress(m_origVtable.pfnGetCaps);
info.isMsaaDepthResolveSupported =
!info.isD3D9On12 &&
info.formatOps.find(FOURCC_RESZ) != info.formatOps.end() &&
info.formatOps.find(FOURCC_INTZ) != info.formatOps.end() &&
info.formatOps.find(FOURCC_NULL) != info.formatOps.end();
info.fixedFormatOps = getFixedFormatOps(info);
info.supportedZBufferBitDepths = getSupportedZBufferBitDepths(info.fixedFormatOps);
LOG_INFO << "Supported z-buffer bit depths: " << bitDepthsToString(info.supportedZBufferBitDepths);
LOG_INFO << "Supported MSAA modes: " << getSupportedMsaaModes(info.formatOps);
@ -117,6 +122,47 @@ namespace D3dDdi
return info;
}
std::map<D3DDDIFORMAT, FORMATOP> Adapter::getFixedFormatOps(const AdapterInfo& info) const
{
std::map<D3DDDIFORMAT, FORMATOP> fixedFormatOps;
for (auto& formatOp : info.formatOps)
{
auto fixedFormatOp = formatOp.second;
if (isEmulatedRenderTargetFormat(formatOp.first, info.formatOps))
{
fixedFormatOp.Operations |= FORMATOP_OFFSCREEN_RENDERTARGET;
}
if (D3DDDIFMT_P8 == formatOp.first && Config::palettizedTextures.get())
{
fixedFormatOp.Operations |= FORMATOP_TEXTURE | FORMATOP_CUBETEXTURE;
}
if (D3DDDIFMT_D24X4S4 == formatOp.first || D3DDDIFMT_X4S4D24 == formatOp.first)
{
// If these formats are reported as depth buffers, then EnumZBufferFormats returns only D16
fixedFormatOp.Operations &= ~(FORMATOP_ZSTENCIL | FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH);
}
if (info.isD3D9On12)
{
if (D3DDDIFMT_D24X8 == formatOp.first)
{
fixedFormatOp.Format = D3DDDIFMT_X8D24;
}
else if (D3DDDIFMT_D24S8 == formatOp.first)
{
fixedFormatOp.Format = D3DDDIFMT_S8D24;
}
}
fixedFormatOps[fixedFormatOp.Format] = fixedFormatOp;
}
return fixedFormatOps;
}
template <typename Data>
HRESULT Adapter::getCaps(D3DDDICAPS_TYPE type, Data& data, UINT size) const
{
@ -266,7 +312,12 @@ namespace D3dDdi
return supportedZBufferBitDepths;
}
bool Adapter::isEmulatedRenderTargetFormat(D3DDDIFORMAT format)
bool Adapter::isEmulatedRenderTargetFormat(D3DDDIFORMAT format) const
{
return isEmulatedRenderTargetFormat(format, m_info.formatOps);
}
bool Adapter::isEmulatedRenderTargetFormat(D3DDDIFORMAT format, const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const
{
const auto& fi = getFormatInfo(format);
if (0 == fi.red.bitCount)
@ -274,7 +325,6 @@ namespace D3dDdi
return false;
}
const auto& formatOps = getInfo().formatOps;
auto it = formatOps.find(format);
if (it == formatOps.end() || (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET))
{
@ -339,27 +389,24 @@ namespace D3dDdi
break;
}
case D3DDDICAPS_GETFORMATCOUNT:
*static_cast<UINT*>(pData->pData) = m_info.fixedFormatOps.size();
break;
case D3DDDICAPS_GETFORMATDATA:
{
UINT count = pData->DataSize / sizeof(FORMATOP);
if (count > m_info.fixedFormatOps.size())
{
count = m_info.fixedFormatOps.size();
}
auto formatOp = static_cast<FORMATOP*>(pData->pData);
auto it = m_info.fixedFormatOps.begin();
for (UINT i = 0; i < count; ++i)
{
if (isEmulatedRenderTargetFormat(formatOp[i].Format))
{
formatOp[i].Operations |= FORMATOP_OFFSCREEN_RENDERTARGET;
}
if (D3DDDIFMT_P8 == formatOp[i].Format && Config::palettizedTextures.get())
{
formatOp[i].Operations |= FORMATOP_TEXTURE | FORMATOP_CUBETEXTURE;
}
if (D3DDDIFMT_D24X4S4 == formatOp[i].Format || D3DDDIFMT_X4S4D24 == formatOp[i].Format)
{
// If these formats are reported as depth buffers, then EnumZBufferFormats returns only D16
formatOp[i].Operations &= ~(FORMATOP_ZSTENCIL | FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH);
}
formatOp[i] = it->second;
++it;
}
break;
}

View File

@ -21,8 +21,10 @@ namespace D3dDdi
{
D3DNTHAL_D3DEXTENDEDCAPS d3dExtendedCaps;
std::map<D3DDDIFORMAT, FORMATOP> formatOps;
std::map<D3DDDIFORMAT, FORMATOP> fixedFormatOps;
DWORD supportedZBufferBitDepths;
bool isMsaaDepthResolveSupported;
bool isD3D9On12;
};
Adapter(const D3DDDIARG_OPENADAPTER& data);
@ -34,13 +36,13 @@ namespace D3dDdi
operator HANDLE() const { return m_adapter; }
Int2 getAspectRatio() const;
const AdapterInfo& getInfo() const;
const AdapterInfo& getInfo() const { return m_info; }
LUID getLuid() const { return m_luid; }
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
SIZE getScaledSize(Int2 size) const;
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format);
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format) const;
HRESULT pfnCloseAdapter();
HRESULT pfnCreateDevice(D3DDDIARG_CREATEDEVICE* pCreateData);
@ -51,14 +53,18 @@ namespace D3dDdi
static void setRepository(LUID luid, CompatWeakPtr<IDirectDraw7> repository);
private:
const AdapterInfo& findInfo() const;
template <typename Data>
HRESULT getCaps(D3DDDICAPS_TYPE type, Data& data, UINT size = sizeof(Data)) const;
Int2 getAspectRatio(Win32::DisplayMode::Resolution res) const;
std::map<D3DDDIFORMAT, FORMATOP> getFixedFormatOps(const AdapterInfo& info) const;
std::map<D3DDDIFORMAT, FORMATOP> getFormatOps() const;
Float2 getScaleFactor() const;
std::string getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
DWORD getSupportedZBufferBitDepths(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format, const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
HANDLE m_adapter;
D3DDDI_ADAPTERFUNCS m_origVtable;
@ -67,6 +73,7 @@ namespace D3dDdi
LUID m_luid;
std::wstring m_deviceName;
CompatWeakPtr<IDirectDraw7> m_repository;
const AdapterInfo& m_info;
static std::map<HANDLE, Adapter> s_adapters;
static std::map<LUID, AdapterInfo> s_adapterInfos;

View File

@ -73,25 +73,45 @@ namespace D3dDdi
HRESULT Device::createPrivateResource(D3DDDIARG_CREATERESOURCE2& data)
{
const bool isPalettized = D3DDDIFMT_P8 == data.Format;
const bool isTexture = data.Flags.Texture;
if (isPalettized)
LOG_FUNC("Device::createPrivateResource", data);
const auto origFormat = data.Format;
const auto origMipLevels = data.MipLevels;
const auto origFlags = data.Flags.Value;
auto& adapterInfo = m_adapter.getInfo();
if (D3DDDIFMT_P8 == data.Format)
{
data.Format = D3DDDIFMT_L8;
data.Flags.Texture = 1;
if (!data.Flags.Texture)
{
data.Flags.Texture = 1;
data.MipLevels = 1;
}
}
else if (adapterInfo.isD3D9On12)
{
if (D3DDDIFMT_D16 == data.Format)
{
data.Format = FOURCC_DF16;
}
else if (D3DDDIFMT_X8D24 == data.Format)
{
data.Format = FOURCC_DF24;
}
else if (D3DDDIFMT_S8D24 == data.Format)
{
data.Format = FOURCC_INTZ;
}
}
HRESULT result = m_origVtable.pfnCreateResource2
? m_origVtable.pfnCreateResource2(m_device, &data)
: m_origVtable.pfnCreateResource(m_device, reinterpret_cast<D3DDDIARG_CREATERESOURCE*>(&data));
if (isPalettized)
{
data.Format = D3DDDIFMT_P8;
data.Flags.Texture = isTexture;
}
return result;
data.Format = origFormat;
data.MipLevels = origMipLevels;
data.Flags.Value = origFlags;
return LOG_RESULT(result);
}
Device* Device::findDeviceByResource(HANDLE resource)

View File

@ -7,9 +7,11 @@
namespace D3dDdi
{
static const auto FOURCC_RESZ = static_cast<D3DDDIFORMAT>(MAKEFOURCC('R', 'E', 'S', 'Z'));
static const auto FOURCC_DF16 = static_cast<D3DDDIFORMAT>(MAKEFOURCC('D', 'F', '1', '6'));
static const auto FOURCC_DF24 = static_cast<D3DDDIFORMAT>(MAKEFOURCC('D', 'F', '2', '4'));
static const auto FOURCC_INTZ = static_cast<D3DDDIFORMAT>(MAKEFOURCC('I', 'N', 'T', 'Z'));
static const auto FOURCC_NULL = static_cast<D3DDDIFORMAT>(MAKEFOURCC('N', 'U', 'L', 'L'));
static const auto FOURCC_RESZ = static_cast<D3DDDIFORMAT>(MAKEFOURCC('R', 'E', 'S', 'Z'));
struct FormatInfo
{

View File

@ -97,7 +97,7 @@ namespace
void logUnsupportedMsaaDepthBufferResolve()
{
LOG_ONCE("Warning: Resolving multisampled depth buffers is not supported by the GPU. "
LOG_ONCE("Warning: Resolving multisampled depth buffers is not supported by the GPU driver. "
"Disable antialiasing if experiencing visual glitches.");
}
}
@ -158,7 +158,8 @@ namespace D3dDdi
}
m_handle = m_fixedData.hResource;
if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool && m_origData.Flags.ZBuffer)
if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool && m_origData.Flags.ZBuffer &&
!m_device.getAdapter().getInfo().isD3D9On12)
{
m_lockData.resize(m_origData.SurfCount);
for (UINT i = 0; i < m_origData.SurfCount; ++i)
@ -207,13 +208,6 @@ namespace D3dDdi
HRESULT Resource::blt(D3DDDIARG_BLT data)
{
if (m_fixedData.Flags.ZBuffer && m_msaaSurface.resource &&
!m_device.getAdapter().getInfo().isMsaaDepthResolveSupported)
{
logUnsupportedMsaaDepthBufferResolve();
return S_OK;
}
if (!m_fixedData.Flags.MatchGdiPrimary && !isValidRect(data.DstSubResourceIndex, data.DstRect))
{
return S_OK;
@ -243,6 +237,13 @@ namespace D3dDdi
return m_device.getOrigVtable().pfnBlt(m_device, &data);
}
if (srcResource->m_fixedData.Flags.ZBuffer && srcResource->m_msaaSurface.resource &&
!m_device.getAdapter().getInfo().isMsaaDepthResolveSupported)
{
logUnsupportedMsaaDepthBufferResolve();
return S_OK;
}
if (shouldBltViaCpu(data, *srcResource))
{
return bltViaCpu(data, *srcResource);
@ -404,7 +405,8 @@ namespace D3dDdi
}
if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
(m_fixedData.Flags.ZBuffer && &dstRes == m_msaaSurface.resource && m_nullSurface.resource ||
(m_fixedData.Flags.ZBuffer &&
(m_nullSurface.resource && &dstRes == m_msaaSurface.resource || m_device.getAdapter().getInfo().isD3D9On12) ||
dstRes.m_fixedData.Flags.RenderTarget ||
!m_fixedData.Flags.ZBuffer && (
data.Flags.SrcColorKey ||
@ -585,11 +587,15 @@ namespace D3dDdi
flags.Value = g_resourceTypeFlags;
flags.RenderTarget = 0;
flags.Texture = 0;
if (m_device.getAdapter().getInfo().isD3D9On12)
{
flags.ZBuffer = 0;
}
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool ||
m_isSurfaceRepoResource ||
0 == m_formatInfo.bytesPerPixel ||
0 != (m_fixedData.Flags.Value & flags.Value) ||
m_fixedData.Flags.Texture && !m_origData.Flags.RenderTarget)
m_fixedData.Flags.Texture && !m_origData.Flags.RenderTarget && !m_origData.Flags.ZBuffer)
{
return;
}
@ -709,10 +715,6 @@ namespace D3dDdi
else if (D3DDDIFMT_UNKNOWN != g_formatOverride)
{
m_fixedData.Format = g_formatOverride;
if (FOURCC_INTZ == g_formatOverride)
{
m_fixedData.Flags.Texture = 1;
}
}
else if (m_fixedData.Flags.RenderTarget && m_device.getAdapter().isEmulatedRenderTargetFormat(m_fixedData.Format))
{
@ -724,6 +726,19 @@ namespace D3dDdi
m_fixedData.MultisampleType = g_msaaOverride.first;
m_fixedData.MultisampleQuality = g_msaaOverride.second;
}
else if (!m_fixedData.Flags.Texture &&
!m_fixedData.Flags.MatchGdiPrimary &&
D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
(m_origData.Flags.RenderTarget || m_fixedData.Flags.ZBuffer))
{
const auto& formatOps = m_device.getAdapter().getInfo().fixedFormatOps;
auto it = formatOps.find(m_fixedData.Format);
if (it != formatOps.end() && (it->second.Operations & FORMATOP_TEXTURE))
{
m_fixedData.Flags.Texture = 1;
m_fixedData.MipLevels = 1;
}
}
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool &&
1 == m_fixedData.SurfCount &&
@ -763,7 +778,7 @@ namespace D3dDdi
else if (m_fixedData.Flags.ZBuffer && Config::Settings::DepthFormat::APP != Config::depthFormat.get() &&
getFormatInfo(m_fixedData.Format).depth.bitCount != Config::depthFormat.get())
{
auto& formatOps = m_device.getAdapter().getInfo().formatOps;
auto& formatOps = m_device.getAdapter().getInfo().fixedFormatOps;
switch (Config::depthFormat.get())
{
#define USE_FORMAT(format) if (formatOps.find(format) != formatOps.end()) return format
@ -873,11 +888,13 @@ namespace D3dDdi
loadMsaaResolvedResource(subResourceIndex);
if (m_fixedData.Flags.ZBuffer)
{
if (m_nullSurface.resource)
bool isD3D9On12 = m_device.getAdapter().getInfo().isD3D9On12;
if (m_nullSurface.resource || isD3D9On12)
{
RECT r = m_msaaResolvedSurface.resource->getRect(0);
m_device.getShaderBlitter().depthBlt(
*m_msaaSurface.resource, r, *m_msaaResolvedSurface.resource, r, *m_nullSurface.resource);
*m_msaaSurface.resource, r, *m_msaaResolvedSurface.resource, r,
isD3D9On12 ? nullptr : static_cast<HANDLE>(*m_nullSurface.resource));
}
}
else
@ -925,7 +942,7 @@ namespace D3dDdi
loadVidMemResource(subResourceIndex);
const bool isScaled = static_cast<LONG>(m_fixedData.pSurfList[0].Width) != m_scaledSize.cx ||
static_cast<LONG>(m_fixedData.pSurfList[0].Height) != m_scaledSize.cy;
if (m_fixedData.Flags.ZBuffer || !isScaled)
if ((m_fixedData.Flags.ZBuffer || !isScaled) && !m_device.getAdapter().getInfo().isD3D9On12)
{
copySubResource(*m_msaaResolvedSurface.resource, *this, subResourceIndex);
}
@ -971,7 +988,7 @@ namespace D3dDdi
{
const bool isScaled = static_cast<LONG>(m_fixedData.pSurfList[0].Width) != m_scaledSize.cx ||
static_cast<LONG>(m_fixedData.pSurfList[0].Height) != m_scaledSize.cy;
if (m_fixedData.Flags.ZBuffer || !isScaled)
if ((m_fixedData.Flags.ZBuffer || !isScaled) && !m_device.getAdapter().getInfo().isD3D9On12)
{
copySubResource(*this, *m_msaaResolvedSurface.resource, subResourceIndex);
}
@ -1570,7 +1587,8 @@ namespace D3dDdi
: DeviceState::ShaderConstF{};
if (m_fixedData.Flags.ZBuffer)
{
m_device.getShaderBlitter().depthBlt(*dstRes, dstRect, *srcRes, srcRect, *m_nullSurface.resource);
m_device.getShaderBlitter().depthBlt(*dstRes, dstRect, *srcRes, srcRect,
m_device.getAdapter().getInfo().isD3D9On12 ? nullptr : static_cast<HANDLE>(*m_nullSurface.resource));
}
else
{
@ -1682,8 +1700,8 @@ namespace D3dDdi
g_msaaOverride = {};
}
if (m_fixedData.Flags.ZBuffer && m_msaaSurface.resource &&
m_device.getAdapter().getInfo().isMsaaDepthResolveSupported)
auto& adapterInfo = m_device.getAdapter().getInfo();
if (m_fixedData.Flags.ZBuffer && m_msaaSurface.resource && adapterInfo.isMsaaDepthResolveSupported)
{
g_msaaOverride = msaa;
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_nullSurface,
@ -1691,16 +1709,15 @@ namespace D3dDdi
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
g_msaaOverride = {};
}
auto msaaResolvedSurfaceCaps = caps | ((m_fixedData.Flags.ZBuffer || !isScaled) ? 0 : DDSCAPS_TEXTURE);
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
scaledSize.cx, scaledSize.cy, m_nullSurface.resource ? FOURCC_INTZ : formatConfig,
msaaResolvedSurfaceCaps, m_fixedData.SurfCount);
caps, m_fixedData.SurfCount);
if (!m_msaaResolvedSurface.resource && m_msaaSurface.resource)
{
m_msaaSurface = {};
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
scaledSize.cx, scaledSize.cy, formatConfig, msaaResolvedSurfaceCaps, m_fixedData.SurfCount);
scaledSize.cx, scaledSize.cy, formatConfig, caps, m_fixedData.SurfCount);
}
if (!m_fixedData.Flags.ZBuffer && m_msaaResolvedSurface.resource)

View File

@ -264,10 +264,10 @@ namespace D3dDdi
}
void ShaderBlitter::depthBlt(const Resource& dstResource, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, const Resource& nullResource)
const Resource& srcResource, const RECT& srcRect, HANDLE nullResource)
{
LOG_FUNC("ShaderBlitter::depthBlt", static_cast<HANDLE>(dstResource), dstRect,
static_cast<HANDLE>(srcResource), srcRect, static_cast<HANDLE>(nullResource));
static_cast<HANDLE>(srcResource), srcRect, nullResource);
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[0];
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[0];
@ -289,7 +289,7 @@ namespace D3dDdi
state.setTempRenderState({ D3DDDIRS_ALPHATESTENABLE, FALSE });
state.setTempRenderState({ D3DDDIRS_CULLMODE, D3DCULL_NONE });
state.setTempRenderState({ D3DDDIRS_DITHERENABLE, FALSE });
state.setTempRenderState({ D3DDDIRS_ALPHABLENDENABLE, TRUE });
state.setTempRenderState({ D3DDDIRS_ALPHABLENDENABLE, FALSE });
state.setTempRenderState({ D3DDDIRS_FOGENABLE, FALSE });
state.setTempRenderState({ D3DDDIRS_COLORKEYENABLE, FALSE });
state.setTempRenderState({ D3DDDIRS_STENCILENABLE, FALSE });
@ -298,11 +298,6 @@ namespace D3dDdi
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0 });
const UINT D3DBLEND_ZERO = 1;
const UINT D3DBLEND_ONE = 2;
state.setTempRenderState({ D3DDDIRS_SRCBLEND, D3DBLEND_ZERO });
state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_ONE });
setTempTextureStage(0, srcResource, srcRect, D3DTEXF_POINT);
state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, FALSE });

View File

@ -27,7 +27,7 @@ namespace D3dDdi
void cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
HCURSOR cursor, POINT pt);
void depthBlt(const Resource& dstResource, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, const Resource& nullResource);
const Resource& srcResource, const RECT& srcRect, HANDLE nullResource);
void gammaBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect);
void genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,

View File

@ -25,6 +25,14 @@ namespace
UINT g_bltSrcSubResourceIndex = 0;
RECT g_bltSrcRect = {};
template <typename TSurface>
typename DDraw::Types<TSurface>::TDdsCaps getCaps(TSurface* This)
{
DDraw::Types<TSurface>::TDdsCaps caps = {};
getOrigVtable(This).GetCaps(This, &caps);
return caps;
}
template <typename TSurface>
typename DDraw::Types<TSurface>::TSurfaceDesc getDesc(TSurface* This)
{
@ -54,8 +62,8 @@ namespace
lpDDSrcSurface = srcSurface->getImpl<TSurface>()->getBltSrc(lpDDSrcSurface);
}
auto dstDesc = getDesc(This);
if (!(dstDesc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) || !(dstDesc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
auto dstCaps = getCaps(This);
if (!(dstCaps.dwCaps & DDSCAPS_3DDEVICE) || !(dstCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
return bltFunc(This, lpDDSrcSurface, lpSrcRect);
}