mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Emulate unsupported render target formats
Fixes Midtown Madness 2 rendering on NVIDIA. See issue #159.
This commit is contained in:
parent
b53678bfd4
commit
12c4f87cb6
@ -266,6 +266,26 @@ namespace D3dDdi
|
|||||||
return supportedZBufferBitDepths;
|
return supportedZBufferBitDepths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Adapter::isEmulatedRenderTargetFormat(D3DDDIFORMAT format)
|
||||||
|
{
|
||||||
|
const auto& fi = getFormatInfo(format);
|
||||||
|
if (0 == fi.red.bitCount)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& formatOps = getInfo().formatOps;
|
||||||
|
auto it = formatOps.find(format);
|
||||||
|
if (it == formatOps.end() || (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto replacementFormat = 0 != fi.alpha.bitCount ? D3DDDIFMT_A8R8G8B8 : D3DDDIFMT_X8R8G8B8;
|
||||||
|
it = formatOps.find(replacementFormat);
|
||||||
|
return it != formatOps.end() && (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET);
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT Adapter::pfnCloseAdapter()
|
HRESULT Adapter::pfnCloseAdapter()
|
||||||
{
|
{
|
||||||
auto adapter = m_adapter;
|
auto adapter = m_adapter;
|
||||||
@ -325,10 +345,16 @@ namespace D3dDdi
|
|||||||
auto formatOp = static_cast<FORMATOP*>(pData->pData);
|
auto formatOp = static_cast<FORMATOP*>(pData->pData);
|
||||||
for (UINT i = 0; i < count; ++i)
|
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())
|
if (D3DDDIFMT_P8 == formatOp[i].Format && Config::palettizedTextures.get())
|
||||||
{
|
{
|
||||||
formatOp[i].Operations |= FORMATOP_TEXTURE | FORMATOP_CUBETEXTURE;
|
formatOp[i].Operations |= FORMATOP_TEXTURE | FORMATOP_CUBETEXTURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (D3DDDIFMT_D24X4S4 == formatOp[i].Format || D3DDDIFMT_X4S4D24 == formatOp[i].Format)
|
if (D3DDDIFMT_D24X4S4 == formatOp[i].Format || D3DDDIFMT_X4S4D24 == formatOp[i].Format)
|
||||||
{
|
{
|
||||||
// If these formats are reported as depth buffers, then EnumZBufferFormats returns only D16
|
// If these formats are reported as depth buffers, then EnumZBufferFormats returns only D16
|
||||||
|
@ -40,6 +40,7 @@ namespace D3dDdi
|
|||||||
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
|
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
|
||||||
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
|
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
|
||||||
SIZE getScaledSize(Int2 size) const;
|
SIZE getScaledSize(Int2 size) const;
|
||||||
|
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format);
|
||||||
|
|
||||||
HRESULT pfnCloseAdapter();
|
HRESULT pfnCloseAdapter();
|
||||||
HRESULT pfnCreateDevice(D3DDDIARG_CREATEDEVICE* pCreateData);
|
HRESULT pfnCreateDevice(D3DDDIARG_CREATEDEVICE* pCreateData);
|
||||||
|
@ -587,7 +587,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
void DeviceState::prepareTextures()
|
void DeviceState::prepareTextures()
|
||||||
{
|
{
|
||||||
for (UINT stage = 0; stage < m_app.textures.size(); ++stage)
|
for (UINT stage = 0; stage < getVertexDecl().textureStageCount; ++stage)
|
||||||
{
|
{
|
||||||
auto resource = getTextureResource(stage);
|
auto resource = getTextureResource(stage);
|
||||||
if (resource)
|
if (resource)
|
||||||
@ -1045,7 +1045,13 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
for (UINT stage = 0; stage <= m_maxChangedTextureStage; ++stage)
|
for (UINT stage = 0; stage <= m_maxChangedTextureStage; ++stage)
|
||||||
{
|
{
|
||||||
if (setTexture(stage, m_app.textures[stage]) ||
|
auto resource = getTextureResource(stage);
|
||||||
|
if (resource)
|
||||||
|
{
|
||||||
|
resource = &resource->prepareForGpuRead(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setTexture(stage, resource ? *resource : m_app.textures[stage]) ||
|
||||||
m_changedTextureStageStates[stage].test(D3DDDITSS_DISABLETEXTURECOLORKEY) ||
|
m_changedTextureStageStates[stage].test(D3DDDITSS_DISABLETEXTURECOLORKEY) ||
|
||||||
m_changedTextureStageStates[stage].test(D3DDDITSS_TEXTURECOLORKEYVAL))
|
m_changedTextureStageStates[stage].test(D3DDDITSS_TEXTURECOLORKEYVAL))
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,7 @@ namespace
|
|||||||
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
|
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
|
||||||
RECT g_presentationRect = {};
|
RECT g_presentationRect = {};
|
||||||
|
|
||||||
|
bool g_enableConfig = true;
|
||||||
D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN;
|
D3DDDIFORMAT g_formatOverride = D3DDDIFMT_UNKNOWN;
|
||||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> g_msaaOverride = {};
|
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> g_msaaOverride = {};
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ namespace D3dDdi
|
|||||||
, m_paletteHandle(0)
|
, m_paletteHandle(0)
|
||||||
, m_paletteColorKeyIndex(-1)
|
, m_paletteColorKeyIndex(-1)
|
||||||
, m_isOversized(false)
|
, m_isOversized(false)
|
||||||
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface())
|
, m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface() || !g_enableConfig)
|
||||||
, m_isClampable(true)
|
, m_isClampable(true)
|
||||||
, m_isPrimary(false)
|
, m_isPrimary(false)
|
||||||
, m_isPalettizedTextureUpToDate(false)
|
, m_isPalettizedTextureUpToDate(false)
|
||||||
@ -404,7 +405,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
|
if (D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
|
||||||
(m_fixedData.Flags.ZBuffer && &dstRes == m_msaaSurface.resource && m_nullSurface.resource ||
|
(m_fixedData.Flags.ZBuffer && &dstRes == m_msaaSurface.resource && m_nullSurface.resource ||
|
||||||
m_fixedData.Flags.RenderTarget ||
|
dstRes.m_fixedData.Flags.RenderTarget ||
|
||||||
!m_fixedData.Flags.ZBuffer && (
|
!m_fixedData.Flags.ZBuffer && (
|
||||||
data.Flags.SrcColorKey ||
|
data.Flags.SrcColorKey ||
|
||||||
data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown ||
|
data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown ||
|
||||||
@ -583,10 +584,12 @@ namespace D3dDdi
|
|||||||
D3DDDI_RESOURCEFLAGS flags = {};
|
D3DDDI_RESOURCEFLAGS flags = {};
|
||||||
flags.Value = g_resourceTypeFlags;
|
flags.Value = g_resourceTypeFlags;
|
||||||
flags.RenderTarget = 0;
|
flags.RenderTarget = 0;
|
||||||
|
flags.Texture = 0;
|
||||||
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool ||
|
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool ||
|
||||||
m_isSurfaceRepoResource ||
|
m_isSurfaceRepoResource ||
|
||||||
0 == m_formatInfo.bytesPerPixel ||
|
0 == m_formatInfo.bytesPerPixel ||
|
||||||
0 != (m_fixedData.Flags.Value & flags.Value))
|
0 != (m_fixedData.Flags.Value & flags.Value) ||
|
||||||
|
m_fixedData.Flags.Texture && !m_origData.Flags.RenderTarget)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -683,6 +686,11 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Resource::enableConfig(bool enable)
|
||||||
|
{
|
||||||
|
g_enableConfig = enable;
|
||||||
|
}
|
||||||
|
|
||||||
void Resource::fixResourceData()
|
void Resource::fixResourceData()
|
||||||
{
|
{
|
||||||
if (m_fixedData.Flags.MatchGdiPrimary)
|
if (m_fixedData.Flags.MatchGdiPrimary)
|
||||||
@ -698,8 +706,7 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
m_fixedData.Format = D3DDDIFMT_X8R8G8B8;
|
m_fixedData.Format = D3DDDIFMT_X8R8G8B8;
|
||||||
}
|
}
|
||||||
|
else if (D3DDDIFMT_UNKNOWN != g_formatOverride)
|
||||||
if (D3DDDIFMT_UNKNOWN != g_formatOverride)
|
|
||||||
{
|
{
|
||||||
m_fixedData.Format = g_formatOverride;
|
m_fixedData.Format = g_formatOverride;
|
||||||
if (FOURCC_INTZ == g_formatOverride)
|
if (FOURCC_INTZ == g_formatOverride)
|
||||||
@ -707,6 +714,10 @@ namespace D3dDdi
|
|||||||
m_fixedData.Flags.Texture = 1;
|
m_fixedData.Flags.Texture = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (m_fixedData.Flags.RenderTarget && m_device.getAdapter().isEmulatedRenderTargetFormat(m_fixedData.Format))
|
||||||
|
{
|
||||||
|
m_fixedData.Flags.RenderTarget = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (D3DDDIMULTISAMPLE_NONE != g_msaaOverride.first)
|
if (D3DDDIMULTISAMPLE_NONE != g_msaaOverride.first)
|
||||||
{
|
{
|
||||||
@ -736,6 +747,11 @@ namespace D3dDdi
|
|||||||
|
|
||||||
D3DDDIFORMAT Resource::getFormatConfig()
|
D3DDDIFORMAT Resource::getFormatConfig()
|
||||||
{
|
{
|
||||||
|
if (m_origData.Flags.RenderTarget && !m_fixedData.Flags.RenderTarget)
|
||||||
|
{
|
||||||
|
return 0 != m_formatInfo.alpha.bitCount ? D3DDDIFMT_A8R8G8B8 : D3DDDIFMT_X8R8G8B8;
|
||||||
|
}
|
||||||
|
|
||||||
if (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)
|
if (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)
|
||||||
{
|
{
|
||||||
switch (Config::renderColorDepth.get())
|
switch (Config::renderColorDepth.get())
|
||||||
@ -775,8 +791,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Resource::getMultisampleConfig()
|
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Resource::getMultisampleConfig()
|
||||||
{
|
{
|
||||||
if (!m_fixedData.Flags.Texture &&
|
if (!m_isPrimary || m_origData.Flags.RenderTarget)
|
||||||
(!m_isPrimary || m_fixedData.Flags.RenderTarget))
|
|
||||||
{
|
{
|
||||||
return m_device.getAdapter().getMultisampleConfig(m_fixedData.Format);
|
return m_device.getAdapter().getMultisampleConfig(m_fixedData.Format);
|
||||||
}
|
}
|
||||||
@ -803,7 +818,7 @@ namespace D3dDdi
|
|||||||
SIZE Resource::getScaledSize()
|
SIZE Resource::getScaledSize()
|
||||||
{
|
{
|
||||||
SIZE size = { static_cast<LONG>(m_fixedData.pSurfList[0].Width), static_cast<LONG>(m_fixedData.pSurfList[0].Height) };
|
SIZE size = { static_cast<LONG>(m_fixedData.pSurfList[0].Width), static_cast<LONG>(m_fixedData.pSurfList[0].Height) };
|
||||||
if (!m_fixedData.Flags.Texture)
|
if (m_origData.Flags.RenderTarget || m_fixedData.Flags.ZBuffer)
|
||||||
{
|
{
|
||||||
return m_device.getAdapter().getScaledSize(size);
|
return m_device.getAdapter().getScaledSize(size);
|
||||||
}
|
}
|
||||||
@ -951,7 +966,7 @@ namespace D3dDdi
|
|||||||
if (m_lockData[subResourceIndex].isMsaaUpToDate || m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
|
if (m_lockData[subResourceIndex].isMsaaUpToDate || m_lockData[subResourceIndex].isMsaaResolvedUpToDate)
|
||||||
{
|
{
|
||||||
loadMsaaResolvedResource(subResourceIndex);
|
loadMsaaResolvedResource(subResourceIndex);
|
||||||
if (!m_fixedData.Flags.RenderTarget ||
|
if (!m_origData.Flags.RenderTarget ||
|
||||||
Config::Settings::ResolutionScaleFilter::POINT == Config::resolutionScaleFilter.get())
|
Config::Settings::ResolutionScaleFilter::POINT == Config::resolutionScaleFilter.get())
|
||||||
{
|
{
|
||||||
const bool isScaled = static_cast<LONG>(m_fixedData.pSurfList[0].Width) != m_scaledSize.cx ||
|
const bool isScaled = static_cast<LONG>(m_fixedData.pSurfList[0].Width) != m_scaledSize.cx ||
|
||||||
@ -1199,7 +1214,7 @@ namespace D3dDdi
|
|||||||
if (srcResource->m_lockResource)
|
if (srcResource->m_lockResource)
|
||||||
{
|
{
|
||||||
if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
|
if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
|
||||||
!srcResource->m_fixedData.Flags.RenderTarget)
|
!srcResource->m_origData.Flags.RenderTarget)
|
||||||
{
|
{
|
||||||
srcResource->m_lockData[data.SrcSubResourceIndex].isVidMemUpToDate = false;
|
srcResource->m_lockData[data.SrcSubResourceIndex].isVidMemUpToDate = false;
|
||||||
srcResource->m_lockData[data.SrcSubResourceIndex].isMsaaResolvedUpToDate = false;
|
srcResource->m_lockData[data.SrcSubResourceIndex].isMsaaResolvedUpToDate = false;
|
||||||
@ -1515,7 +1530,7 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer)
|
if (!dstResource.m_fixedData.Flags.RenderTarget && !dstResource.m_fixedData.Flags.ZBuffer)
|
||||||
{
|
{
|
||||||
LONG width = data.DstRect.right - data.DstRect.left;
|
LONG width = data.DstRect.right - data.DstRect.left;
|
||||||
LONG height = data.DstRect.bottom - data.DstRect.top;
|
LONG height = data.DstRect.bottom - data.DstRect.top;
|
||||||
@ -1563,7 +1578,7 @@ namespace D3dDdi
|
|||||||
data.Flags.Linear ? D3DTEXF_LINEAR : D3DTEXF_POINT, data.Flags.SrcColorKey ? &ck : nullptr);
|
data.Flags.Linear ? D3DTEXF_LINEAR : D3DTEXF_POINT, data.Flags.SrcColorKey ? &ck : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer)
|
if (!dstResource.m_fixedData.Flags.RenderTarget && !dstResource.m_fixedData.Flags.ZBuffer)
|
||||||
{
|
{
|
||||||
HRESULT result = copySubResourceRegion(data.hDstResource, data.DstSubResourceIndex, data.DstRect,
|
HRESULT result = copySubResourceRegion(data.hDstResource, data.DstSubResourceIndex, data.DstRect,
|
||||||
*dstRes, dstIndex, dstRect);
|
*dstRes, dstIndex, dstRect);
|
||||||
@ -1617,7 +1632,7 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
if (m_isSurfaceRepoResource || D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool || D3DDDIFMT_P8 == m_fixedData.Format ||
|
if (m_isSurfaceRepoResource || D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool || D3DDDIFMT_P8 == m_fixedData.Format ||
|
||||||
m_fixedData.Flags.MatchGdiPrimary ||
|
m_fixedData.Flags.MatchGdiPrimary ||
|
||||||
!m_isPrimary && !m_fixedData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer ||
|
!m_isPrimary && !m_origData.Flags.RenderTarget && !m_fixedData.Flags.ZBuffer ||
|
||||||
!m_fixedData.Flags.ZBuffer && !m_lockResource)
|
!m_fixedData.Flags.ZBuffer && !m_lockResource)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -60,6 +60,7 @@ namespace D3dDdi
|
|||||||
void updateConfig();
|
void updateConfig();
|
||||||
void updatePalettizedTexture(UINT stage);
|
void updatePalettizedTexture(UINT stage);
|
||||||
|
|
||||||
|
static void enableConfig(bool enable);
|
||||||
static void setFormatOverride(D3DDDIFORMAT format);
|
static void setFormatOverride(D3DDDIFORMAT format);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -38,7 +38,9 @@ namespace DDraw
|
|||||||
auto data = privateData.get();
|
auto data = privateData.get();
|
||||||
data->m_palettizedSurface = palettizedSurface;
|
data->m_palettizedSurface = palettizedSurface;
|
||||||
|
|
||||||
|
D3dDdi::Resource::enableConfig(false);
|
||||||
result = Surface::create(dd, desc, surface, std::move(privateData));
|
result = Surface::create(dd, desc, surface, std::move(privateData));
|
||||||
|
D3dDdi::Resource::enableConfig(true);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
return LOG_RESULT(result);
|
return LOG_RESULT(result);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user