From 29a2b9246bcf912b494126b00666fab41eaacfde Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 16 Jun 2024 14:35:06 +0200 Subject: [PATCH] Extend lock surfaces to non-managed textures Fixes issues with locked texture pitch. See issue #320. --- DDrawCompat/D3dDdi/Device.cpp | 28 ++++++++++++++++++++++++++ DDrawCompat/D3dDdi/Device.h | 3 +++ DDrawCompat/D3dDdi/DeviceFuncs.cpp | 4 ++-- DDrawCompat/D3dDdi/Resource.cpp | 25 ++++++++++++++++++++++- DDrawCompat/D3dDdi/Resource.h | 2 ++ DDrawCompat/DDraw/Surfaces/Surface.cpp | 8 ++++++++ DDrawCompat/DDraw/Surfaces/Surface.h | 1 + 7 files changed, 68 insertions(+), 3 deletions(-) diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index 0b9b6a4..7ec10f5 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -486,6 +486,18 @@ namespace D3dDdi return S_OK; } + HRESULT Device::pfnTexBlt(const D3DDDIARG_TEXBLT* data) + { + prepareForTextureBlt(data->hDstResource, data->hSrcResource); + return m_origVtable.pfnTexBlt(m_device, data); + } + + HRESULT Device::pfnTexBlt1(const D3DDDIARG_TEXBLT1* data) + { + prepareForTextureBlt(data->hDstResource, data->hSrcResource); + return m_origVtable.pfnTexBlt1(m_device, data); + } + HRESULT Device::pfnUnlock(const D3DDDIARG_UNLOCK* data) { flushPrimitives(); @@ -532,6 +544,22 @@ namespace D3dDdi return m_origVtable.pfnValidateDevice(m_device, data); } + void Device::prepareForTextureBlt(HANDLE dstResource, HANDLE srcResource) + { + flushPrimitives(); + auto it = m_resources.find(dstResource); + if (it != m_resources.end()) + { + it->second->prepareForGpuWriteAll(); + } + + it = m_resources.find(srcResource); + if (it != m_resources.end()) + { + it->second->prepareForGpuReadAll(); + } + } + void Device::updateAllConfig() { g_isConfigUpdatePending = true; diff --git a/DDrawCompat/D3dDdi/Device.h b/DDrawCompat/D3dDdi/Device.h index 7c598ec..4ddf9f9 100644 --- a/DDrawCompat/D3dDdi/Device.h +++ b/DDrawCompat/D3dDdi/Device.h @@ -50,6 +50,8 @@ namespace D3dDdi HRESULT pfnPresent(const D3DDDIARG_PRESENT* data); HRESULT pfnPresent1(D3DDDIARG_PRESENT1* data); HRESULT pfnSetPalette(const D3DDDIARG_SETPALETTE* data); + HRESULT pfnTexBlt(const D3DDDIARG_TEXBLT* data); + HRESULT pfnTexBlt1(const D3DDDIARG_TEXBLT1* data); HRESULT pfnUnlock(const D3DDDIARG_UNLOCK* data); HRESULT pfnUpdatePalette(const D3DDDIARG_UPDATEPALETTE* data, const PALETTEENTRY* paletteData); HRESULT pfnValidateDevice(D3DDDIARG_VALIDATETEXTURESTAGESTATE* data); @@ -85,6 +87,7 @@ namespace D3dDdi private: HRESULT clear(D3DDDIARG_CLEAR data, UINT numRect, const RECT* rect, Resource* resource, DWORD flags); UINT detectColorKeyMethod(); + void prepareForTextureBlt(HANDLE dstResource, HANDLE srcResource); static void updateAllConfigNow(); D3DDDI_DEVICEFUNCS m_origVtable; diff --git a/DDrawCompat/D3dDdi/DeviceFuncs.cpp b/DDrawCompat/D3dDdi/DeviceFuncs.cpp index 5bf21fd..fd36548 100644 --- a/DDrawCompat/D3dDdi/DeviceFuncs.cpp +++ b/DDrawCompat/D3dDdi/DeviceFuncs.cpp @@ -67,6 +67,8 @@ namespace SET_DEVICE_FUNC(pfnPresent); SET_DEVICE_FUNC(pfnPresent1); SET_DEVICE_FUNC(pfnSetPalette); + SET_DEVICE_FUNC(pfnTexBlt); + SET_DEVICE_FUNC(pfnTexBlt1); SET_DEVICE_FUNC(pfnUnlock); SET_DEVICE_FUNC(pfnUpdatePalette); SET_DEVICE_FUNC(pfnValidateDevice); @@ -103,8 +105,6 @@ namespace SET_FLUSH_PRIMITIVES_FUNC(pfnSetClipPlane); SET_FLUSH_PRIMITIVES_FUNC(pfnSetScissorRect); SET_FLUSH_PRIMITIVES_FUNC(pfnStateSet); - SET_FLUSH_PRIMITIVES_FUNC(pfnTexBlt); - SET_FLUSH_PRIMITIVES_FUNC(pfnTexBlt1); } } diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 4823935..d182517 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -601,7 +601,7 @@ namespace D3dDdi m_isSurfaceRepoResource || 0 == m_formatInfo.bytesPerPixel || 0 != (m_fixedData.Flags.Value & flags.Value) || - m_fixedData.Flags.Texture && !m_origData.Flags.RenderTarget && !m_origData.Flags.ZBuffer) + m_fixedData.Flags.Texture && (DDraw::Surface::getCurrentSurfaceCaps().dwCaps2 & 0x100000)) // managed texture { return; } @@ -1190,6 +1190,17 @@ namespace D3dDdi return *this; } + void Resource::prepareForGpuReadAll() + { + if (m_lockResource) + { + for (UINT i = 0; i < m_lockData.size(); ++i) + { + prepareForGpuRead(i); + } + } + } + Resource& Resource::prepareForGpuWrite(UINT subResourceIndex) { m_isColorKeyedSurfaceUpToDate = false; @@ -1219,6 +1230,17 @@ namespace D3dDdi return *this; } + void Resource::prepareForGpuWriteAll() + { + if (m_lockResource) + { + for (UINT i = 0; i < m_lockData.size(); ++i) + { + prepareForGpuWrite(i); + } + } + } + Resource& Resource::prepareForTextureRead(UINT stage) { if (m_lockResource) @@ -1817,6 +1839,7 @@ namespace D3dDdi } auto rect = getRect(0); + m_palettizedTexture->prepareForGpuReadAll(); m_device.getShaderBlitter().palettizedBlt(*this, 0, rect, *m_palettizedTexture, 0, rect, palettePtr); m_palettizedTexture->m_isPalettizedTextureUpToDate = true; diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index 269cf95..0379d30 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -53,7 +53,9 @@ namespace D3dDdi void prepareForCpuRead(UINT subResourceIndex); void prepareForCpuWrite(UINT subResourceIndex); Resource& prepareForGpuRead(UINT subResourceIndex); + void prepareForGpuReadAll(); Resource& prepareForGpuWrite(UINT subResourceIndex); + void prepareForGpuWriteAll(); Resource& prepareForTextureRead(UINT stage); HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource); void scaleRect(RECT& rect); diff --git a/DDrawCompat/DDraw/Surfaces/Surface.cpp b/DDrawCompat/DDraw/Surfaces/Surface.cpp index 7408869..96ed912 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.cpp +++ b/DDrawCompat/DDraw/Surfaces/Surface.cpp @@ -16,6 +16,7 @@ DEFINE_GUID(IID_CompatSurfacePrivateData, namespace { + DDSCAPS2 g_currentSurfaceCaps = {}; std::set g_surfaces; void heapFree(void* p) @@ -105,7 +106,9 @@ namespace DDraw desc.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX | DDSCAPS_MIPMAP); } + memcpy(&g_currentSurfaceCaps, &desc.ddsCaps, sizeof(desc.ddsCaps)); HRESULT result = dd->CreateSurface(&dd, &desc, &surface, nullptr); + g_currentSurfaceCaps = {}; if (FAILED(result)) { return result; @@ -189,6 +192,11 @@ namespace DDraw } } + DDSCAPS2 Surface::getCurrentSurfaceCaps() + { + return g_currentSurfaceCaps; + } + template <> SurfaceImpl* Surface::getImpl() const { return m_impl.get(); } template <> diff --git a/DDrawCompat/DDraw/Surfaces/Surface.h b/DDrawCompat/DDraw/Surfaces/Surface.h index 8476c89..c52a268 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.h +++ b/DDrawCompat/DDraw/Surfaces/Surface.h @@ -33,6 +33,7 @@ namespace DDraw CompatRef dd, TSurfaceDesc desc, TSurface*& surface, std::unique_ptr privateData); static void enumSurfaces(const std::function& callback); + static DDSCAPS2 getCurrentSurfaceCaps(); template static Surface* getSurface(TSurface& dds);