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

Avoid initial lock surface copy for unmodified surfaces

This commit is contained in:
narzoul 2019-08-19 22:42:48 +02:00
parent d0289de9a2
commit 55e08f62d4
5 changed files with 113 additions and 98 deletions

View File

@ -59,7 +59,7 @@ namespace D3dDdi
try try
{ {
Resource resource(Resource::create(*this, data)); Resource resource(Resource::create(*this, data));
m_resources.emplace(resource, std::move(resource)); m_resources.emplace(resource, std::move(resource)).first->second.initialize();
return S_OK; return S_OK;
} }
catch (const HResultException& e) catch (const HResultException& e)
@ -336,15 +336,19 @@ namespace D3dDdi
} }
Resource* Device::getResource(HANDLE resource) Resource* Device::getResource(HANDLE resource)
{
auto it = m_resources.find(resource);
return it != m_resources.end() ? &it->second : nullptr;
}
Resource* Device::findResource(HANDLE resource)
{ {
for (auto& device : s_devices) for (auto& device : s_devices)
{ {
for (auto& res : device.second.getResources()) auto res = device.second.getResource(resource);
if (res)
{ {
if (resource == res.second) return res;
{
return &res.second;
}
} }
} }
return nullptr; return nullptr;
@ -364,7 +368,7 @@ namespace D3dDdi
} }
g_gdiResourceHandle = resource; g_gdiResourceHandle = resource;
g_gdiResource = getResource(resource); g_gdiResource = findResource(resource);
if (g_gdiResource) if (g_gdiResource)
{ {

View File

@ -45,7 +45,7 @@ namespace D3dDdi
Adapter& getAdapter() const { return m_adapter; } Adapter& getAdapter() const { return m_adapter; }
const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; } const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; }
std::unordered_map<HANDLE, Resource>& getResources() { return m_resources; } Resource* getResource(HANDLE resource);
void addDirtyRenderTarget(Resource& resource, UINT subResourceIndex); void addDirtyRenderTarget(Resource& resource, UINT subResourceIndex);
void addDirtyTexture(Resource& resource, UINT subResourceIndex); void addDirtyTexture(Resource& resource, UINT subResourceIndex);
@ -58,8 +58,8 @@ namespace D3dDdi
static Device& get(HANDLE device); static Device& get(HANDLE device);
static void remove(HANDLE device); static void remove(HANDLE device);
static Resource* findResource(HANDLE resource);
static Resource* getGdiResource(); static Resource* getGdiResource();
static Resource* getResource(HANDLE resource);
static void setGdiResourceHandle(HANDLE resource); static void setGdiResourceHandle(HANDLE resource);
static void setReadOnlyGdiLock(bool enable); static void setReadOnlyGdiLock(bool enable);

View File

@ -108,7 +108,7 @@ namespace
{ {
DDraw::ScopedThreadLock ddLock; DDraw::ScopedThreadLock ddLock;
D3dDdi::ScopedCriticalSection driverLock; D3dDdi::ScopedCriticalSection driverLock;
auto primaryResource = D3dDdi::Device::getResource(DDraw::PrimarySurface::getFrontResource()); auto primaryResource = D3dDdi::Device::findResource(DDraw::PrimarySurface::getFrontResource());
if (primaryResource && pData->pMemory == primaryResource->getLockPtr(0) && if (primaryResource && pData->pMemory == primaryResource->getLockPtr(0) &&
(DDraw::PrimarySurface::getOrigCaps() & DDSCAPS_COMPLEX)) (DDraw::PrimarySurface::getOrigCaps() & DDSCAPS_COMPLEX))
{ {

View File

@ -151,7 +151,7 @@ namespace D3dDdi
data = const_cast<void*>(resource.m_fixedData.pSurfList[subResourceIndex].pSysMem); data = const_cast<void*>(resource.m_fixedData.pSurfList[subResourceIndex].pSysMem);
pitch = resource.m_fixedData.pSurfList[subResourceIndex].SysMemPitch; pitch = resource.m_fixedData.pSurfList[subResourceIndex].SysMemPitch;
} }
else if (subResourceIndex < resource.m_lockData.size()) else if (resource.m_lockResource)
{ {
if (!resource.m_lockData[subResourceIndex].isSysMemUpToDate) if (!resource.m_lockData[subResourceIndex].isSysMemUpToDate)
{ {
@ -189,30 +189,33 @@ namespace D3dDdi
HRESULT Resource::blt(D3DDDIARG_BLT data) HRESULT Resource::blt(D3DDDIARG_BLT data)
{ {
auto srcResource = m_device.getResource(data.hSrcResource);
if (srcResource &&
D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool &&
D3DDDIPOOL_SYSTEMMEM == srcResource->m_fixedData.Pool)
{
return m_device.getOrigVtable().pfnBlt(m_device, &data);
}
if (isOversized()) if (isOversized())
{ {
m_device.prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex, true); m_device.prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex, true);
return splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect); return splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect);
} }
else else if (srcResource)
{ {
auto& resources = m_device.getResources(); if (srcResource->isOversized())
auto it = resources.find(data.hSrcResource);
if (it != resources.end())
{
if (it->second.isOversized())
{ {
prepareForRendering(data.DstSubResourceIndex, false); prepareForRendering(data.DstSubResourceIndex, false);
return it->second.splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect); return srcResource->splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect);
} }
else if (m_fixedData.Flags.Primary) else if (m_fixedData.Flags.Primary)
{ {
return presentationBlt(data, it->second); return presentationBlt(data, *srcResource);
} }
else else
{ {
return sysMemPreferredBlt(data, it->second); return sysMemPreferredBlt(data, *srcResource);
}
} }
} }
prepareForRendering(data.DstSubResourceIndex, false); prepareForRendering(data.DstSubResourceIndex, false);
@ -222,13 +225,8 @@ namespace D3dDdi
HRESULT Resource::bltLock(D3DDDIARG_LOCK& data) HRESULT Resource::bltLock(D3DDDIARG_LOCK& data)
{ {
LOG_FUNC("Resource::bltLock", data); LOG_FUNC("Resource::bltLock", data);
if (data.SubResourceIndex >= m_lockData.size())
{
return LOG_RESULT(m_device.getOrigVtable().pfnLock(m_device, &data));
}
auto& lockData = m_lockData[data.SubResourceIndex]; auto& lockData = m_lockData[data.SubResourceIndex];
if (!lockData.isSysMemUpToDate) if (!lockData.isSysMemUpToDate)
{ {
if (data.Flags.ReadOnly) if (data.Flags.ReadOnly)
@ -260,11 +258,6 @@ namespace D3dDdi
HRESULT Resource::bltUnlock(const D3DDDIARG_UNLOCK& data) HRESULT Resource::bltUnlock(const D3DDDIARG_UNLOCK& data)
{ {
LOG_FUNC("Resource::bltUnlock", data); LOG_FUNC("Resource::bltUnlock", data);
if (data.SubResourceIndex >= m_lockData.size())
{
return LOG_RESULT(m_device.getOrigVtable().pfnUnlock(m_device, &data));
}
if (0 != m_lockData[data.SubResourceIndex].lockCount) if (0 != m_lockData[data.SubResourceIndex].lockCount)
{ {
--m_lockData[data.SubResourceIndex].lockCount; --m_lockData[data.SubResourceIndex].lockCount;
@ -275,7 +268,7 @@ namespace D3dDdi
HRESULT Resource::colorFill(const D3DDDIARG_COLORFILL& data) HRESULT Resource::colorFill(const D3DDDIARG_COLORFILL& data)
{ {
LOG_FUNC("Resource::colorFill", data); LOG_FUNC("Resource::colorFill", data);
if (data.SubResourceIndex < m_lockData.size() && 0 != m_formatInfo.bytesPerPixel) if (m_lockResource && 0 != m_formatInfo.bytesPerPixel)
{ {
auto& lockData = m_lockData[data.SubResourceIndex]; auto& lockData = m_lockData[data.SubResourceIndex];
if (lockData.isSysMemUpToDate) if (lockData.isSysMemUpToDate)
@ -341,11 +334,16 @@ namespace D3dDdi
surfaceInfo.pSysMem = gdiSurfaceDesc.lpSurface; surfaceInfo.pSysMem = gdiSurfaceDesc.lpSurface;
surfaceInfo.SysMemPitch = gdiSurfaceDesc.lPitch; surfaceInfo.SysMemPitch = gdiSurfaceDesc.lPitch;
m_lockData.resize(m_fixedData.SurfCount);
createSysMemResource({ surfaceInfo }); createSysMemResource({ surfaceInfo });
if (m_lockResource) if (m_lockResource)
{ {
copySubResource(m_handle, m_lockResource, 0); setSysMemUpToDate(0, true);
m_canCreateLockResource = false; setVidMemUpToDate(0, false);
}
else
{
m_lockData.clear();
} }
} }
@ -378,6 +376,7 @@ namespace D3dDdi
if (!m_lockResource) if (!m_lockResource)
{ {
m_lockBuffers.clear(); m_lockBuffers.clear();
m_lockData.clear();
} }
} }
@ -403,21 +402,17 @@ namespace D3dDdi
reinterpret_cast<D3DDDIARG_CREATERESOURCE*>(&data)); reinterpret_cast<D3DDDIARG_CREATERESOURCE*>(&data));
} }
if (FAILED(result)) if (SUCCEEDED(result))
{ {
LOG_RESULT(nullptr);
return;
}
m_lockResource = data.hResource; m_lockResource = data.hResource;
m_lockData.resize(surfaceInfo.size());
for (std::size_t i = 0; i < surfaceInfo.size(); ++i) for (std::size_t i = 0; i < surfaceInfo.size(); ++i)
{ {
m_lockData[i].data = const_cast<void*>(surfaceInfo[i].pSysMem); m_lockData[i].data = const_cast<void*>(surfaceInfo[i].pSysMem);
m_lockData[i].pitch = surfaceInfo[i].SysMemPitch; m_lockData[i].pitch = surfaceInfo[i].SysMemPitch;
m_lockData[i].isSysMemUpToDate = false;
m_lockData[i].isVidMemUpToDate = true;
} }
}
m_canCreateLockResource = false;
LOG_RESULT(m_lockResource); LOG_RESULT(m_lockResource);
} }
@ -453,9 +448,6 @@ namespace D3dDdi
} }
resource.m_handle = data.hResource; resource.m_handle = data.hResource;
resource.m_canCreateLockResource = D3DDDIPOOL_SYSTEMMEM != data.Pool &&
0 != resource.m_formatInfo.bytesPerPixel &&
!data.Flags.Primary;
data = origData; data = origData;
data.hResource = resource.m_handle; data.hResource = resource.m_handle;
return resource; return resource;
@ -482,7 +474,6 @@ namespace D3dDdi
} }
m_device.getOrigVtable().pfnDestroyResource(m_device, m_lockResource); m_device.getOrigVtable().pfnDestroyResource(m_device, m_lockResource);
m_lockResource = nullptr; m_lockResource = nullptr;
m_lockData.clear();
m_lockBuffers.clear(); m_lockBuffers.clear();
} }
} }
@ -514,15 +505,25 @@ namespace D3dDdi
void* Resource::getLockPtr(UINT subResourceIndex) void* Resource::getLockPtr(UINT subResourceIndex)
{ {
if (subResourceIndex < m_lockData.size()) return m_lockResource ? m_lockData[subResourceIndex].data
{ : const_cast<void*>(m_fixedData.pSurfList[subResourceIndex].pSysMem);
return m_lockData[subResourceIndex].data;
} }
else if (subResourceIndex < m_fixedData.SurfCount)
void Resource::initialize()
{ {
return const_cast<void*>(m_fixedData.pSurfList[subResourceIndex].pSysMem); m_canCreateLockResource = D3DDDIPOOL_SYSTEMMEM != m_fixedData.Pool &&
0 != m_formatInfo.bytesPerPixel &&
!m_fixedData.Flags.Primary;
if (m_canCreateLockResource)
{
m_lockData.resize(m_fixedData.SurfCount);
for (std::size_t i = 0; i < m_fixedData.SurfCount; ++i)
{
setSysMemUpToDate(i, true);
setVidMemUpToDate(i, true);
}
} }
return nullptr;
} }
bool Resource::isOversized() const bool Resource::isOversized() const
@ -546,7 +547,6 @@ namespace D3dDdi
if (m_canCreateLockResource) if (m_canCreateLockResource)
{ {
createLockResource(); createLockResource();
m_canCreateLockResource = false;
} }
if (m_lockResource) if (m_lockResource)
@ -611,18 +611,13 @@ namespace D3dDdi
HRESULT Resource::presentationBlt(const D3DDDIARG_BLT& data, Resource& srcResource) HRESULT Resource::presentationBlt(const D3DDDIARG_BLT& data, Resource& srcResource)
{ {
if (data.SrcSubResourceIndex < srcResource.m_lockData.size()) if (srcResource.m_lockResource &&
{ srcResource.m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate)
if (srcResource.m_lockData[data.SrcSubResourceIndex].isVidMemUpToDate)
{
if (srcResource.m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate)
{ {
copySubResource(srcResource.m_handle, srcResource.m_lockResource, data.SrcSubResourceIndex); copySubResource(srcResource.m_handle, srcResource.m_lockResource, data.SrcSubResourceIndex);
} if (!srcResource.m_lockData[data.SrcSubResourceIndex].isVidMemUpToDate)
}
else
{ {
srcResource.copyToVidMem(data.SrcSubResourceIndex); srcResource.setVidMemUpToDate(data.SrcSubResourceIndex, true);
} }
} }
return m_device.getOrigVtable().pfnBlt(m_device, &data); return m_device.getOrigVtable().pfnBlt(m_device, &data);
@ -733,8 +728,22 @@ namespace D3dDdi
HRESULT Resource::sysMemPreferredBlt(const D3DDDIARG_BLT& data, Resource& srcResource) HRESULT Resource::sysMemPreferredBlt(const D3DDDIARG_BLT& data, Resource& srcResource)
{ {
if (m_fixedData.Format == srcResource.m_fixedData.Format && if (m_fixedData.Format == srcResource.m_fixedData.Format &&
(D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool || data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown || 0 != m_formatInfo.bytesPerPixel)
(data.DstSubResourceIndex < m_lockData.size() && m_lockData[data.DstSubResourceIndex].isSysMemUpToDate))) {
if (data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown)
{
if (m_canCreateLockResource)
{
createLockResource();
}
if (srcResource.m_canCreateLockResource)
{
srcResource.createLockResource();
}
}
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool ||
(m_lockResource && m_lockData[data.DstSubResourceIndex].isSysMemUpToDate))
{ {
SysMemBltGuard srcGuard(srcResource, data.SrcSubResourceIndex, true); SysMemBltGuard srcGuard(srcResource, data.SrcSubResourceIndex, true);
if (srcGuard.data) if (srcGuard.data)
@ -764,6 +773,7 @@ namespace D3dDdi
} }
} }
} }
}
prepareForRendering(data.DstSubResourceIndex, false); prepareForRendering(data.DstSubResourceIndex, false);
srcResource.prepareForRendering(data.SrcSubResourceIndex, true); srcResource.prepareForRendering(data.SrcSubResourceIndex, true);

View File

@ -24,6 +24,7 @@ namespace D3dDdi
void destroyLockResource(); void destroyLockResource();
void fixVertexData(UINT offset, UINT count, UINT stride); void fixVertexData(UINT offset, UINT count, UINT stride);
void* getLockPtr(UINT subResourceIndex); void* getLockPtr(UINT subResourceIndex);
void initialize();
HRESULT lock(D3DDDIARG_LOCK& data); HRESULT lock(D3DDDIARG_LOCK& data);
void prepareForRendering(UINT subResourceIndex, bool isReadOnly); void prepareForRendering(UINT subResourceIndex, bool isReadOnly);
void setAsGdiResource(bool isGdiResource); void setAsGdiResource(bool isGdiResource);