diff --git a/DDrawCompat/Config/Config.h b/DDrawCompat/Config/Config.h index 861269a..2720b36 100644 --- a/DDrawCompat/Config/Config.h +++ b/DDrawCompat/Config/Config.h @@ -5,6 +5,7 @@ typedef unsigned long DWORD; namespace Config { const int delayedFlipModeTimeout = 200; + const int evictionTimeout = 200; const int maxPaletteUpdatesPerMs = 5; const int maxUserModeDisplayDrivers = 3; } diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index d10be69..5f7aba2 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -63,7 +63,7 @@ namespace D3dDdi { try { - Resource resource(Resource::create(*this, data)); + Resource resource(*this, data); m_resources.emplace(resource, std::move(resource)); return S_OK; } diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 7d61819..9f69f78 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -132,53 +134,57 @@ namespace D3dDdi pSurfList = surfaceData.data(); } - Resource::Data::Data(const Data& other) - : D3DDDIARG_CREATERESOURCE2(other) - , surfaceData(other.surfaceData) - { - pSurfList = surfaceData.data(); - } - - Resource::Data& Resource::Data::operator=(const Data& other) - { - static_cast(*this) = other; - surfaceData = other.surfaceData; - pSurfList = surfaceData.data(); - return *this; - } - - Resource::SysMemBltGuard::SysMemBltGuard(Resource& resource, UINT subResourceIndex, bool isReadOnly) - : data(nullptr) - , pitch(0) - { - if (D3DDDIPOOL_SYSTEMMEM == resource.m_fixedData.Pool) - { - data = const_cast(resource.m_fixedData.pSurfList[subResourceIndex].pSysMem); - pitch = resource.m_fixedData.pSurfList[subResourceIndex].SysMemPitch; - } - else if (resource.m_lockResource) - { - if (!resource.m_lockData[subResourceIndex].isSysMemUpToDate) - { - resource.copyToSysMem(subResourceIndex); - } - resource.m_lockData[subResourceIndex].isVidMemUpToDate &= isReadOnly; - data = resource.m_lockData[subResourceIndex].data; - pitch = resource.m_lockData[subResourceIndex].pitch; - } - } - - Resource::Resource(Device& device, const D3DDDIARG_CREATERESOURCE& data) - : Resource(device, upgradeResourceData(data)) - { - } - - Resource::Resource(Device& device, const D3DDDIARG_CREATERESOURCE2& data) + template + Resource::Resource(Device& device, Arg& data, HRESULT(APIENTRY* createResourceFunc)(HANDLE, Arg*)) : m_device(device) , m_handle(nullptr) , m_origData(data) + , m_fixedData(data) , m_lockBuffer(nullptr, &heapFree) , m_lockResource(nullptr, ResourceDeleter(device)) + { + if (D3DDDIFMT_VERTEXDATA == data.Format && + data.Flags.VertexBuffer && + data.Flags.MightDrawFromLocked && + D3DDDIPOOL_SYSTEMMEM != data.Pool) + { + const HRESULT D3DERR_NOTAVAILABLE = 0x8876086A; + throw HResultException(D3DERR_NOTAVAILABLE); + } + + fixResourceData(device, reinterpret_cast(m_fixedData)); + m_formatInfo = getFormatInfo(m_fixedData.Format); + + HRESULT result = createResourceFunc(device, reinterpret_cast(&m_fixedData)); + if (FAILED(result)) + { + throw HResultException(result); + } + m_handle = m_fixedData.hResource; + + if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool && + 0 != m_formatInfo.bytesPerPixel) + { + m_lockData.resize(m_fixedData.SurfCount); + for (UINT i = 0; i < m_fixedData.SurfCount; ++i) + { + m_lockData[i].data = const_cast(m_fixedData.pSurfList[i].pSysMem); + m_lockData[i].pitch = m_fixedData.pSurfList[i].SysMemPitch; + m_lockData[i].isSysMemUpToDate = true; + } + } + + createLockResource(); + data.hResource = m_fixedData.hResource; + } + + Resource::Resource(Device& device, D3DDDIARG_CREATERESOURCE& data) + : Resource(device, data, device.getOrigVtable().pfnCreateResource) + { + } + + Resource::Resource(Device& device, D3DDDIARG_CREATERESOURCE2& data) + : Resource(device, data, device.getOrigVtable().pfnCreateResource2) { } @@ -227,6 +233,7 @@ namespace D3dDdi copyToSysMem(data.SubResourceIndex); } lockData.isVidMemUpToDate &= data.Flags.ReadOnly; + lockData.qpcLastForcedLock = Time::queryPerformanceCounter(); unsigned char* ptr = static_cast(lockData.data); if (data.Flags.AreaValid) @@ -408,10 +415,12 @@ namespace D3dDdi { m_lockResource.reset(data.hResource); m_lockData.resize(surfaceInfo.size()); + auto qpcLastForcedLock = Time::queryPerformanceCounter() - Time::msToQpc(Config::evictionTimeout); for (std::size_t i = 0; i < surfaceInfo.size(); ++i) { m_lockData[i].data = const_cast(surfaceInfo[i].pSysMem); m_lockData[i].pitch = surfaceInfo[i].SysMemPitch; + m_lockData[i].qpcLastForcedLock = qpcLastForcedLock; m_lockData[i].isSysMemUpToDate = true; m_lockData[i].isVidMemUpToDate = true; } @@ -420,48 +429,6 @@ namespace D3dDdi LOG_RESULT(m_lockResource.get()); } - template - Resource Resource::create(Device& device, Arg& data, HRESULT(APIENTRY *createResourceFunc)(HANDLE, Arg*)) - { - if (D3DDDIFMT_VERTEXDATA == data.Format && - data.Flags.VertexBuffer && - data.Flags.MightDrawFromLocked && - D3DDDIPOOL_SYSTEMMEM != data.Pool) - { - const HRESULT D3DERR_NOTAVAILABLE = 0x8876086A; - throw HResultException(D3DERR_NOTAVAILABLE); - } - - Resource resource(device, data); - Arg origData = data; - fixResourceData(device, reinterpret_cast(data)); - resource.m_fixedData = data; - resource.m_formatInfo = getFormatInfo(data.Format); - - HRESULT result = createResourceFunc(device, &data); - if (FAILED(result)) - { - data = origData; - throw HResultException(result); - } - - resource.m_handle = data.hResource; - resource.createLockResource(); - data = origData; - data.hResource = resource.m_handle; - return resource; - } - - Resource Resource::create(Device& device, D3DDDIARG_CREATERESOURCE& data) - { - return create(device, data, device.getOrigVtable().pfnCreateResource); - } - - Resource Resource::create(Device& device, D3DDDIARG_CREATERESOURCE2& data) - { - return create(device, data, device.getOrigVtable().pfnCreateResource2); - } - void Resource::fixVertexData(UINT offset, UINT count, UINT stride) { if (!m_fixedData.Flags.MightDrawFromLocked || @@ -489,14 +456,7 @@ namespace D3dDdi void* Resource::getLockPtr(UINT subResourceIndex) { - return m_lockResource ? m_lockData[subResourceIndex].data - : const_cast(m_fixedData.pSurfList[subResourceIndex].pSysMem); - } - - bool Resource::isInSysMem(UINT subResourceIndex) const - { - return D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool || - (m_lockResource && m_lockData[subResourceIndex].isSysMemUpToDate); + return m_lockData.empty() ? nullptr : m_lockData[subResourceIndex].data; } bool Resource::isOversized() const @@ -622,37 +582,52 @@ namespace D3dDdi HRESULT Resource::sysMemPreferredBlt(const D3DDDIARG_BLT& data, Resource& srcResource) { if (m_fixedData.Format == srcResource.m_fixedData.Format && - 0 != m_formatInfo.bytesPerPixel && - (data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown || - (isInSysMem(data.DstSubResourceIndex) && - (!srcResource.m_fixedData.Flags.RenderTarget || srcResource.isInSysMem(data.SrcSubResourceIndex))))) + !m_lockData.empty() && + !srcResource.m_lockData.empty()) { - SysMemBltGuard srcGuard(srcResource, data.SrcSubResourceIndex, true); - if (srcGuard.data) + auto& dstLockData = m_lockData[data.DstSubResourceIndex]; + auto& srcLockData = srcResource.m_lockData[data.SrcSubResourceIndex]; + + bool isSysMemBltPreferred = true; + auto now = Time::queryPerformanceCounter(); + if (data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown) { - SysMemBltGuard dstGuard(*this, data.DstSubResourceIndex, false); - if (dstGuard.data) + dstLockData.qpcLastForcedLock = now; + srcLockData.qpcLastForcedLock = now; + } + else if (m_lockResource) + { + isSysMemBltPreferred = dstLockData.isSysMemUpToDate && + Time::qpcToMs(now - dstLockData.qpcLastForcedLock) <= Config::evictionTimeout; + } + + if (isSysMemBltPreferred) + { + dstLockData.isVidMemUpToDate = false; + if (!srcLockData.isSysMemUpToDate) { - auto dstBuf = static_cast(dstGuard.data) + - data.DstRect.top * dstGuard.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel; - auto srcBuf = static_cast(srcGuard.data) + - data.SrcRect.top * srcGuard.pitch + data.SrcRect.left * m_formatInfo.bytesPerPixel; - - DDraw::Blitter::blt( - dstBuf, - dstGuard.pitch, - data.DstRect.right - data.DstRect.left, - data.DstRect.bottom - data.DstRect.top, - srcBuf, - srcGuard.pitch, - (1 - 2 * data.Flags.MirrorLeftRight) * (data.SrcRect.right - data.SrcRect.left), - (1 - 2 * data.Flags.MirrorUpDown) * (data.SrcRect.bottom - data.SrcRect.top), - m_formatInfo.bytesPerPixel, - data.Flags.DstColorKey ? reinterpret_cast(&data.ColorKey) : nullptr, - data.Flags.SrcColorKey ? reinterpret_cast(&data.ColorKey) : nullptr); - - return S_OK; + srcResource.copyToSysMem(data.SrcSubResourceIndex); } + + auto dstBuf = static_cast(dstLockData.data) + + data.DstRect.top * dstLockData.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel; + auto srcBuf = static_cast(srcLockData.data) + + data.SrcRect.top * srcLockData.pitch + data.SrcRect.left * m_formatInfo.bytesPerPixel; + + DDraw::Blitter::blt( + dstBuf, + dstLockData.pitch, + data.DstRect.right - data.DstRect.left, + data.DstRect.bottom - data.DstRect.top, + srcBuf, + srcLockData.pitch, + (1 - 2 * data.Flags.MirrorLeftRight) * (data.SrcRect.right - data.SrcRect.left), + (1 - 2 * data.Flags.MirrorUpDown) * (data.SrcRect.bottom - data.SrcRect.top), + m_formatInfo.bytesPerPixel, + data.Flags.DstColorKey ? reinterpret_cast(&data.ColorKey) : nullptr, + data.Flags.SrcColorKey ? reinterpret_cast(&data.ColorKey) : nullptr); + + return S_OK; } } diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index c81d09f..990f412 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -15,8 +15,8 @@ namespace D3dDdi class Resource { public: - static Resource create(Device& device, D3DDDIARG_CREATERESOURCE& data); - static Resource create(Device& device, D3DDDIARG_CREATERESOURCE2& data); + Resource(Device& device, D3DDDIARG_CREATERESOURCE& data); + Resource(Device& device, D3DDDIARG_CREATERESOURCE2& data); Resource(const Resource&) = delete; Resource& operator=(const Resource&) = delete; @@ -42,8 +42,10 @@ namespace D3dDdi Data(); Data(const D3DDDIARG_CREATERESOURCE& data); Data(const D3DDDIARG_CREATERESOURCE2& data); - Data(const Data& other); - Data& operator=(const Data& other); + + Data(const Data&) = delete; + Data& operator=(const Data&) = delete; + Data(Data&&) = default; Data& operator=(Data&&) = default; @@ -55,6 +57,7 @@ namespace D3dDdi void* data; UINT pitch; UINT lockCount; + long long qpcLastForcedLock; bool isSysMemUpToDate; bool isVidMemUpToDate; }; @@ -69,19 +72,8 @@ namespace D3dDdi Device& m_device; }; - struct SysMemBltGuard - { - void* data; - UINT pitch; - - SysMemBltGuard(Resource& resource, UINT subResourceIndex, bool isReadOnly); - }; - - Resource(Device& device, const D3DDDIARG_CREATERESOURCE& data); - Resource(Device& device, const D3DDDIARG_CREATERESOURCE2& data); - template - static Resource create(Device& device, Arg& data, HRESULT(APIENTRY *createResourceFunc)(HANDLE, Arg*)); + Resource(Device& device, Arg& data, HRESULT(APIENTRY *createResourceFunc)(HANDLE, Arg*)); HRESULT bltLock(D3DDDIARG_LOCK& data); HRESULT bltUnlock(const D3DDDIARG_UNLOCK& data); @@ -92,7 +84,6 @@ namespace D3dDdi void createLockResource(); void createSysMemResource(const std::vector& surfaceInfo); bool isOversized() const; - bool isInSysMem(UINT subResourceIndex) const; HRESULT presentationBlt(const D3DDDIARG_BLT& data, Resource& srcResource); HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect); diff --git a/DDrawCompat/DDraw/Surfaces/Surface.cpp b/DDrawCompat/DDraw/Surfaces/Surface.cpp index d9c83b0..f666388 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.cpp +++ b/DDrawCompat/DDraw/Surfaces/Surface.cpp @@ -64,14 +64,6 @@ namespace DDraw } auto surface7(CompatPtr::from(surface)); - if (!(desc.dwFlags & DDSD_PIXELFORMAT)) - { - desc.dwFlags |= DDSD_PIXELFORMAT; - desc.ddpfPixelFormat = {}; - desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); - surface7->GetPixelFormat(surface7, &desc.ddpfPixelFormat); - } - if (desc.ddsCaps.dwCaps & DDSCAPS_COMPLEX) { auto attachedSurfaces(getAllAttachedSurfaces(*surface7));