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

Fixed occasional crash with resolution scaling when alt-tabbing in NFS3

This commit is contained in:
narzoul 2023-11-11 11:04:52 +01:00
parent e43485f66b
commit a4256483de
6 changed files with 34 additions and 41 deletions

View File

@ -918,12 +918,6 @@ namespace D3dDdi
m_changedStates |= CS_RENDER_TARGET; m_changedStates |= CS_RENDER_TARGET;
} }
void DeviceState::setTempStreamSource(const D3DDDIARG_SETSTREAMSOURCE& streamSource)
{
setStreamSource(streamSource);
m_changedStates |= CS_STREAM_SOURCE;
}
void DeviceState::setTempStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& streamSourceUm, const void* umBuffer) void DeviceState::setTempStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& streamSourceUm, const void* umBuffer)
{ {
setStreamSourceUm(streamSourceUm, umBuffer); setStreamSourceUm(streamSourceUm, umBuffer);

View File

@ -141,7 +141,6 @@ namespace D3dDdi
void setTempPixelShader(HANDLE shader); void setTempPixelShader(HANDLE shader);
void setTempRenderState(const D3DDDIARG_RENDERSTATE& renderState); void setTempRenderState(const D3DDDIARG_RENDERSTATE& renderState);
void setTempRenderTarget(const D3DDDIARG_SETRENDERTARGET& renderTarget); void setTempRenderTarget(const D3DDDIARG_SETRENDERTARGET& renderTarget);
void setTempStreamSource(const D3DDDIARG_SETSTREAMSOURCE& streamSource);
void setTempStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& streamSourceUm, const void* umBuffer); void setTempStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& streamSourceUm, const void* umBuffer);
void setTempTexture(UINT stage, HANDLE texture); void setTempTexture(UINT stage, HANDLE texture);
void setTempTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE& tss); void setTempTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE& tss);
@ -164,8 +163,6 @@ namespace D3dDdi
void updateStreamSource(); void updateStreamSource();
private: private:
friend class ScopedDeviceState;
enum ChangedState enum ChangedState
{ {
CS_RENDER_STATE = 1 << 0, CS_RENDER_STATE = 1 << 0,

View File

@ -458,6 +458,10 @@ namespace D3dDdi
auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount); auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
if (!state.isLocked()) if (!state.isLocked())
{ {
if (0 == m_batched.primitiveCount)
{
m_device.prepareForGpuWrite();
}
state.updateStreamSource(); state.updateStreamSource();
if (m_streamSource.vertices && data.PrimitiveType >= D3DPT_TRIANGLELIST) if (m_streamSource.vertices && data.PrimitiveType >= D3DPT_TRIANGLELIST)
{ {
@ -472,7 +476,6 @@ namespace D3dDdi
{ {
state.setSpriteMode(false); state.setSpriteMode(false);
} }
m_device.prepareForGpuWrite();
state.flush(); state.flush();
} }
@ -509,6 +512,10 @@ namespace D3dDdi
auto& state = m_device.getState(); auto& state = m_device.getState();
if (!state.isLocked()) if (!state.isLocked())
{ {
if (0 == m_batched.primitiveCount)
{
m_device.prepareForGpuWrite();
}
state.updateStreamSource(); state.updateStreamSource();
} }
@ -529,7 +536,6 @@ namespace D3dDdi
{ {
state.setSpriteMode(false); state.setSpriteMode(false);
} }
m_device.prepareForGpuWrite();
state.flush(); state.flush();
} }
@ -639,10 +645,6 @@ namespace D3dDdi
} }
LOG_DEBUG << "Flushing " << m_batched.primitiveCount << " primitives of type " << m_batched.primitiveType; LOG_DEBUG << "Flushing " << m_batched.primitiveCount << " primitives of type " << m_batched.primitiveType;
if (!m_device.getState().isLocked())
{
m_device.prepareForGpuWrite();
}
return m_batched.indices.empty() ? flush(flagBuffer) : flushIndexed(flagBuffer); return m_batched.indices.empty() ? flush(flagBuffer) : flushIndexed(flagBuffer);
} }

View File

@ -1362,6 +1362,7 @@ namespace D3dDdi
void Resource::setAsGdiResource(bool isGdiResource) void Resource::setAsGdiResource(bool isGdiResource)
{ {
m_device.flushPrimitives();
m_lockResource.reset(); m_lockResource.reset();
m_lockData.clear(); m_lockData.clear();
m_lockBuffer.reset(); m_lockBuffer.reset();

View File

@ -220,7 +220,8 @@ namespace D3dDdi
state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_INVSRCALPHA }); state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_INVSRCALPHA });
} }
setTempTextureStage(0, srcResource, srcRect, LOWORD(filter) | (srgbRead ? D3DTEXF_SRGBREAD : 0)); setTempTextureStage(0, srcResource, srcSubResourceIndex, srcRect,
LOWORD(filter) | (srgbRead ? D3DTEXF_SRGBREAD : 0));
if (flags & BLT_COLORKEYTEST) if (flags & BLT_COLORKEYTEST)
{ {
state.setTempTextureStageState({ 0, D3DDDITSS_TEXTURECOLORKEYVAL, 0xFF }); state.setTempTextureStageState({ 0, D3DDDITSS_TEXTURECOLORKEYVAL, 0xFF });
@ -237,12 +238,13 @@ namespace D3dDdi
{ {
RectF dr = Rect::toRectF(sr); RectF dr = Rect::toRectF(sr);
Rect::transform(dr, srcRect, dstRect); Rect::transform(dr, srcRect, dstRect);
drawRect(sr, dr, srcSurface.Width, srcSurface.Height); setTextureCoords(0, sr, srcSurface.Width, srcSurface.Height);
drawRect(dr);
} }
} }
else else
{ {
drawRect(srcRect, Rect::toRectF(dstRect), srcSurface.Width, srcSurface.Height); drawRect(Rect::toRectF(dstRect));
} }
m_device.flushPrimitives(); m_device.flushPrimitives();
@ -411,12 +413,12 @@ namespace D3dDdi
if (flags & CF_GAMMARAMP) if (flags & CF_GAMMARAMP)
{ {
setTempTextureStage(1, *gammaRampTexture, srcRect, D3DTEXF_LINEAR); setTempTextureStage(1, *gammaRampTexture, 0, srcRect, D3DTEXF_LINEAR);
} }
if (flags & CF_DITHERING) if (flags & CF_DITHERING)
{ {
setTempTextureStage(2, *ditherTexture, dstRect, D3DTEXF_POINT, D3DTADDRESS_WRAP); setTempTextureStage(2, *ditherTexture, 0, dstRect, D3DTEXF_POINT, D3DTADDRESS_WRAP);
m_convolutionParams.maxRgb[0] = static_cast<float>(1 << dstFi.red.bitCount) - 1; m_convolutionParams.maxRgb[0] = static_cast<float>(1 << dstFi.red.bitCount) - 1;
m_convolutionParams.maxRgb[1] = static_cast<float>(1 << dstFi.green.bitCount) - 1; m_convolutionParams.maxRgb[1] = static_cast<float>(1 << dstFi.green.bitCount) - 1;
m_convolutionParams.maxRgb[2] = static_cast<float>(1 << dstFi.blue.bitCount) - 1; m_convolutionParams.maxRgb[2] = static_cast<float>(1 << dstFi.blue.bitCount) - 1;
@ -547,9 +549,9 @@ namespace D3dDdi
if (cur.maskTexture) if (cur.maskTexture)
{ {
cur.tempTexture->copySubResourceRegion(0, clippedSrcRect, dstResource, dstSubResourceIndex, clippedDstRect); cur.tempTexture->copySubResourceRegion(0, clippedSrcRect, dstResource, dstSubResourceIndex, clippedDstRect);
setTempTextureStage(1, *cur.maskTexture, clippedSrcRect, D3DTEXF_POINT); setTempTextureStage(1, *cur.maskTexture, 0, clippedSrcRect, D3DTEXF_POINT);
setTempTextureStage(2, *cur.colorTexture, clippedSrcRect, D3DTEXF_POINT); setTempTextureStage(2, *cur.colorTexture, 0, clippedSrcRect, D3DTEXF_POINT);
setTempTextureStage(3, *xorTexture, clippedSrcRect, D3DTEXF_POINT); setTempTextureStage(3, *xorTexture, 0, clippedSrcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, 0, clippedSrcRect, blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, 0, clippedSrcRect,
m_psDrawCursor.get(), D3DTEXF_POINT); m_psDrawCursor.get(), D3DTEXF_POINT);
} }
@ -566,7 +568,6 @@ namespace D3dDdi
LOG_FUNC("ShaderBlitter::depthBlt", static_cast<HANDLE>(dstResource), dstRect, LOG_FUNC("ShaderBlitter::depthBlt", static_cast<HANDLE>(dstResource), dstRect,
static_cast<HANDLE>(srcResource), srcRect, nullResource); static_cast<HANDLE>(srcResource), srcRect, nullResource);
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[0];
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[0]; const auto& dstSurface = dstResource.getFixedDesc().pSurfList[0];
auto& state = m_device.getState(); auto& state = m_device.getState();
@ -595,13 +596,13 @@ namespace D3dDdi
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE }); state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0 }); state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0 });
setTempTextureStage(0, srcResource, srcRect, D3DTEXF_POINT); setTempTextureStage(0, srcResource, 0, srcRect, D3DTEXF_POINT);
state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, FALSE }); state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, FALSE });
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, m_vertices.data()); state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, m_vertices.data());
DeviceState::TempStateLock lock(state); DeviceState::TempStateLock lock(state);
drawRect(srcRect, Rect::toRectF(dstRect), srcSurface.Width, srcSurface.Height); drawRect(Rect::toRectF(dstRect));
m_device.flushPrimitives(); m_device.flushPrimitives();
} }
@ -643,14 +644,12 @@ namespace D3dDdi
} }
} }
void ShaderBlitter::drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight) void ShaderBlitter::drawRect(const RectF& rect)
{ {
m_vertices[0].xy = { dstRect.left - 0.5f, dstRect.top - 0.5f }; m_vertices[0].xy = { rect.left - 0.5f, rect.top - 0.5f };
m_vertices[1].xy = { dstRect.right - 0.5f, dstRect.top - 0.5f }; m_vertices[1].xy = { rect.right - 0.5f, rect.top - 0.5f };
m_vertices[2].xy = { dstRect.left - 0.5f, dstRect.bottom - 0.5f }; m_vertices[2].xy = { rect.left - 0.5f, rect.bottom - 0.5f };
m_vertices[3].xy = { dstRect.right - 0.5f, dstRect.bottom - 0.5f }; m_vertices[3].xy = { rect.right - 0.5f, rect.bottom - 0.5f };
setTextureCoords(0, srcRect, srcWidth, srcHeight);
D3DDDIARG_DRAWPRIMITIVE dp = {}; D3DDDIARG_DRAWPRIMITIVE dp = {};
dp.PrimitiveType = D3DPT_TRIANGLESTRIP; dp.PrimitiveType = D3DPT_TRIANGLESTRIP;
@ -677,7 +676,7 @@ namespace D3dDdi
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect, static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
static_cast<HANDLE>(lockRefResource)); static_cast<HANDLE>(lockRefResource));
setTempTextureStage(1, lockRefResource, srcRect, D3DTEXF_POINT); setTempTextureStage(1, lockRefResource, dstSubResourceIndex, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect, blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
m_psLockRef.get(), D3DTEXF_POINT); m_psLockRef.get(), D3DTEXF_POINT);
} }
@ -710,7 +709,7 @@ namespace D3dDdi
unlock.hResource = *paletteTexture; unlock.hResource = *paletteTexture;
m_device.getOrigVtable().pfnUnlock(m_device, &unlock); m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
setTempTextureStage(1, *paletteTexture, srcRect, D3DTEXF_POINT); setTempTextureStage(1, *paletteTexture, 0, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect, blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
m_psPaletteLookup.get(), D3DTEXF_POINT); m_psPaletteLookup.get(), D3DTEXF_POINT);
} }
@ -752,8 +751,8 @@ namespace D3dDdi
g_isGammaRampInvalidated = !g_isGammaRampDefault; g_isGammaRampInvalidated = !g_isGammaRampDefault;
} }
void ShaderBlitter::setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter, void ShaderBlitter::setTempTextureStage(UINT stage, const Resource& texture, UINT subResourceIndex,
UINT textureAddress) const RECT& rect, UINT filter, UINT textureAddress)
{ {
auto& state = m_device.getState(); auto& state = m_device.getState();
state.setTempTexture(stage, texture); state.setTempTexture(stage, texture);
@ -766,7 +765,7 @@ namespace D3dDdi
state.setTempTextureStageState({ stage, D3DDDITSS_SRGBTEXTURE, 0 != (filter & D3DTEXF_SRGBREAD) }); state.setTempTextureStageState({ stage, D3DDDITSS_SRGBTEXTURE, 0 != (filter & D3DTEXF_SRGBREAD) });
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 }); state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
auto& si = texture.getFixedDesc().pSurfList[0]; auto& si = texture.getFixedDesc().pSurfList[subResourceIndex];
setTextureCoords(stage, rect, si.Width, si.Height); setTextureCoords(stage, rect, si.Width, si.Height);
} }

View File

@ -111,9 +111,9 @@ namespace D3dDdi
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size); std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl(); std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
void drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight); void drawRect(const RectF& rect);
void setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter, void setTempTextureStage(UINT stage, const Resource& texture, UINT subResourceIndex,
UINT textureAddress = D3DTADDRESS_CLAMP); const RECT& rect, UINT filter, UINT textureAddress = D3DTADDRESS_CLAMP);
void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height); void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height);
Device& m_device; Device& m_device;