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

Remove deleted textures from device state

Fixes flickering black box during SimCity 4 videos (issue #85).
This commit is contained in:
narzoul 2021-01-09 12:13:57 +01:00
parent 7b660e1396
commit e9a2bdc83f
3 changed files with 39 additions and 27 deletions

View File

@ -258,6 +258,7 @@ namespace D3dDdi
g_gdiResource = nullptr; g_gdiResource = nullptr;
} }
m_drawPrimitive.removeSysMemVertexBuffer(resource); m_drawPrimitive.removeSysMemVertexBuffer(resource);
m_state.removeTexture(resource);
} }
return result; return result;

View File

@ -3,6 +3,9 @@
namespace namespace
{ {
const UINT UNINITIALIZED_STATE = 0xBAADBAAD;
const HANDLE UNINITIALIZED_HANDLE = reinterpret_cast<HANDLE>(0xBAADBAAD);
bool operator==(const D3DDDIARG_ZRANGE& lhs, const D3DDDIARG_ZRANGE& rhs) bool operator==(const D3DDDIARG_ZRANGE& lhs, const D3DDDIARG_ZRANGE& rhs)
{ {
return lhs.MinZ == rhs.MinZ && lhs.MaxZ == rhs.MaxZ; return lhs.MinZ == rhs.MinZ && lhs.MaxZ == rhs.MaxZ;
@ -18,17 +21,17 @@ namespace D3dDdi
{ {
DeviceState::DeviceState(Device& device) DeviceState::DeviceState(Device& device)
: m_device(device) : m_device(device)
, m_pixelShader(nullptr) , m_pixelShader(UNINITIALIZED_HANDLE)
, m_textures{} , m_vertexShaderDecl(UNINITIALIZED_HANDLE)
, m_vertexShaderDecl(nullptr) , m_vertexShaderFunc(UNINITIALIZED_HANDLE)
, m_vertexShaderFunc(nullptr)
, m_wInfo{ NAN, NAN } , m_wInfo{ NAN, NAN }
, m_zRange{ NAN, NAN } , m_zRange{ NAN, NAN }
{ {
m_renderState.fill(0xBAADBAAD); m_renderState.fill(UNINITIALIZED_STATE);
m_textures.fill(UNINITIALIZED_HANDLE);
for (UINT i = 0; i < m_textureStageState.size(); ++i) for (UINT i = 0; i < m_textureStageState.size(); ++i)
{ {
m_textureStageState[i].fill(0xBAADBAAD); m_textureStageState[i].fill(UNINITIALIZED_STATE);
} }
} }
@ -80,7 +83,8 @@ namespace D3dDdi
return m_device.getOrigVtable().pfnSetTexture(m_device, stage, texture); return m_device.getOrigVtable().pfnSetTexture(m_device, stage, texture);
} }
if (texture == m_textures[stage]) if (texture == m_textures[stage] &&
texture != UNINITIALIZED_HANDLE)
{ {
return S_OK; return S_OK;
} }
@ -90,31 +94,23 @@ namespace D3dDdi
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
m_textures[stage] = texture; m_textures[stage] = texture;
m_textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = 0xBAADBAAD; m_textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = UNINITIALIZED_STATE;
m_textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL] = UNINITIALIZED_STATE;
} }
return result; return result;
} }
HRESULT DeviceState::pfnSetTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE* data) HRESULT DeviceState::pfnSetTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE* data)
{ {
if (D3DDDITSS_TEXTURECOLORKEYVAL == data->State) switch (data->State)
{ {
if (0 != m_textureStageState[data->Stage][D3DDDITSS_DISABLETEXTURECOLORKEY]) case D3DDDITSS_DISABLETEXTURECOLORKEY:
{ m_textureStageState[data->Stage][D3DDDITSS_TEXTURECOLORKEYVAL] = UNINITIALIZED_STATE;
m_textureStageState[data->Stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = 0; break;
}
else if (data->Value == m_textureStageState[data->Stage][D3DDDITSS_TEXTURECOLORKEYVAL])
{
return S_OK;
}
m_device.flushPrimitives(); case D3DDDITSS_TEXTURECOLORKEYVAL:
HRESULT result = m_device.getOrigVtable().pfnSetTextureStageState(m_device, data); m_textureStageState[data->Stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = UNINITIALIZED_STATE;
if (SUCCEEDED(result)) break;
{
m_textureStageState[data->Stage][D3DDDITSS_TEXTURECOLORKEYVAL] = data->Value;
}
return result;
} }
return setStateArray(data, m_textureStageState[data->Stage], m_device.getOrigVtable().pfnSetTextureStageState); return setStateArray(data, m_textureStageState[data->Stage], m_device.getOrigVtable().pfnSetTextureStageState);
} }
@ -170,15 +166,27 @@ namespace D3dDdi
HRESULT result = origDeleteShaderFunc(m_device, shader); HRESULT result = origDeleteShaderFunc(m_device, shader);
if (SUCCEEDED(result) && shader == currentShader) if (SUCCEEDED(result) && shader == currentShader)
{ {
currentShader = nullptr; currentShader = UNINITIALIZED_HANDLE;
} }
return result; return result;
} }
void DeviceState::removeTexture(HANDLE texture)
{
for (UINT i = 0; i < m_textures.size(); ++i)
{
if (m_textures[i] == texture)
{
m_textures[i] = UNINITIALIZED_HANDLE;
}
}
}
HRESULT DeviceState::setShader(HANDLE shader, HANDLE& currentShader, HRESULT DeviceState::setShader(HANDLE shader, HANDLE& currentShader,
HRESULT(APIENTRY* origSetShaderFunc)(HANDLE, HANDLE)) HRESULT(APIENTRY* origSetShaderFunc)(HANDLE, HANDLE))
{ {
if (shader == currentShader) if (shader == currentShader &&
shader != UNINITIALIZED_HANDLE)
{ {
return S_OK; return S_OK;
} }
@ -244,7 +252,8 @@ namespace D3dDdi
return origSetState(m_device, data); return origSetState(m_device, data);
} }
if (data->Value == currentState[data->State]) if (data->Value == currentState[data->State] &&
data->Value != UNINITIALIZED_STATE)
{ {
return S_OK; return S_OK;
} }

View File

@ -30,6 +30,8 @@ namespace D3dDdi
HRESULT pfnSetZRange(const D3DDDIARG_ZRANGE* data); HRESULT pfnSetZRange(const D3DDDIARG_ZRANGE* data);
HRESULT pfnUpdateWInfo(const D3DDDIARG_WINFO* data); HRESULT pfnUpdateWInfo(const D3DDDIARG_WINFO* data);
void removeTexture(HANDLE texture);
private: private:
typedef std::tuple<FLOAT, FLOAT, FLOAT, FLOAT> ShaderConstF; typedef std::tuple<FLOAT, FLOAT, FLOAT, FLOAT> ShaderConstF;
typedef std::tuple<INT, INT, INT, INT> ShaderConstI; typedef std::tuple<INT, INT, INT, INT> ShaderConstI;