mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Mitigate performance issues caused by slow surface interface release
Releasing the last reference to a surface interface has a significant performance impact. Mitigating the issue by eliminating some frequent but unnecessary QueryInterface calls. Fixes most of the performance drop reported in issue #24.
This commit is contained in:
parent
3f1fa0fae1
commit
60c3c4f153
@ -26,13 +26,6 @@ namespace
|
|||||||
|
|
||||||
namespace DDraw
|
namespace DDraw
|
||||||
{
|
{
|
||||||
CompatPtr<IDirectDraw7> getDirectDraw(CompatRef<IDirectDrawSurface7> surface)
|
|
||||||
{
|
|
||||||
CompatPtr<IUnknown> dd;
|
|
||||||
surface.get().lpVtbl->GetDDInterface(&surface, reinterpret_cast<void**>(&dd.getRef()));
|
|
||||||
return dd;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
void DirectDrawSurface<TSurface>::setCompatVtable(Vtable<TSurface>& vtable)
|
void DirectDrawSurface<TSurface>::setCompatVtable(Vtable<TSurface>& vtable)
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
namespace DDraw
|
namespace DDraw
|
||||||
{
|
{
|
||||||
CompatPtr<IDirectDraw7> getDirectDraw(CompatRef<IDirectDrawSurface7> surface);
|
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
class DirectDrawSurface : public CompatVtable<Vtable<TSurface>>
|
class DirectDrawSurface : public CompatVtable<Vtable<TSurface>>
|
||||||
{
|
{
|
||||||
|
@ -8,9 +8,14 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
DDSURFACEDESC2 g_primarySurfaceDesc = {};
|
DDSURFACEDESC2 g_primarySurfaceDesc = {};
|
||||||
CompatWeakPtr<IDirectDrawSurface> g_gdiSurface = nullptr;
|
CompatWeakPtr<IDirectDrawSurface7> g_primarySurface = nullptr;
|
||||||
CompatWeakPtr<IDirectDrawSurface> g_primarySurface = nullptr;
|
HANDLE g_gdiResourceHandle = nullptr;
|
||||||
DWORD g_origCaps = 0;
|
DWORD g_origCaps = 0;
|
||||||
|
|
||||||
|
HANDLE getResourceHandle(IDirectDrawSurface7& surface)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<HANDLE**>(&surface)[1][2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace DDraw
|
namespace DDraw
|
||||||
@ -24,7 +29,7 @@ namespace DDraw
|
|||||||
{
|
{
|
||||||
Compat::LogEnter("PrimarySurface::~PrimarySurface");
|
Compat::LogEnter("PrimarySurface::~PrimarySurface");
|
||||||
|
|
||||||
g_gdiSurface = nullptr;
|
g_gdiResourceHandle = nullptr;
|
||||||
g_primarySurface = nullptr;
|
g_primarySurface = nullptr;
|
||||||
g_origCaps = 0;
|
g_origCaps = 0;
|
||||||
s_palette = nullptr;
|
s_palette = nullptr;
|
||||||
@ -68,9 +73,8 @@ namespace DDraw
|
|||||||
std::unique_ptr<Surface> privateData(new PrimarySurface(Surface::getSurface(*surface)));
|
std::unique_ptr<Surface> privateData(new PrimarySurface(Surface::getSurface(*surface)));
|
||||||
attach(*surface7, privateData);
|
attach(*surface7, privateData);
|
||||||
|
|
||||||
CompatPtr<IDirectDrawSurface> surface1(Compat::queryInterface<IDirectDrawSurface>(surface));
|
g_gdiResourceHandle = getResourceHandle(*surface7);
|
||||||
g_gdiSurface = surface1;
|
g_primarySurface = surface7;
|
||||||
g_primarySurface = surface1;
|
|
||||||
g_origCaps = origCaps;
|
g_origCaps = origCaps;
|
||||||
|
|
||||||
ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc));
|
ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc));
|
||||||
@ -105,11 +109,12 @@ namespace DDraw
|
|||||||
|
|
||||||
HRESULT PrimarySurface::flipToGdiSurface()
|
HRESULT PrimarySurface::flipToGdiSurface()
|
||||||
{
|
{
|
||||||
if (!g_primarySurface)
|
CompatPtr<IDirectDrawSurface7> gdiSurface;
|
||||||
|
if (!g_primarySurface || !(gdiSurface = getGdiSurface()))
|
||||||
{
|
{
|
||||||
return DDERR_NOTFOUND;
|
return DDERR_NOTFOUND;
|
||||||
}
|
}
|
||||||
return g_primarySurface.get()->lpVtbl->Flip(g_primarySurface, g_gdiSurface, DDFLIP_WAIT);
|
return g_primarySurface.get()->lpVtbl->Flip(g_primarySurface, gdiSurface, DDFLIP_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
const DDSURFACEDESC2& PrimarySurface::getDesc()
|
const DDSURFACEDESC2& PrimarySurface::getDesc()
|
||||||
@ -118,18 +123,36 @@ namespace DDraw
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompatPtr<IDirectDrawSurface7> PrimarySurface::getGdiSurface()
|
CompatPtr<IDirectDrawSurface7> PrimarySurface::getGdiSurface()
|
||||||
{
|
|
||||||
return CompatPtr<IDirectDrawSurface7>::from(g_gdiSurface.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
CompatPtr<IDirectDrawSurface7> PrimarySurface::getPrimary()
|
|
||||||
{
|
{
|
||||||
if (!g_primarySurface)
|
if (!g_primarySurface)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return CompatPtr<IDirectDrawSurface7>(
|
|
||||||
Compat::queryInterface<IDirectDrawSurface7>(g_primarySurface.get()));
|
DDSCAPS2 caps = {};
|
||||||
|
caps.dwCaps = DDSCAPS_FLIP;
|
||||||
|
CompatWeakPtr<IDirectDrawSurface7> surface(g_primarySurface);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (getResourceHandle(*surface) == g_gdiResourceHandle)
|
||||||
|
{
|
||||||
|
return CompatPtr<IDirectDrawSurface7>::from(surface.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(surface->GetAttachedSurface(surface, &caps, &surface.getRef())))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
surface->Release(surface);
|
||||||
|
} while (surface != g_primarySurface);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompatWeakPtr<IDirectDrawSurface7> PrimarySurface::getPrimary()
|
||||||
|
{
|
||||||
|
return g_primarySurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD PrimarySurface::getOrigCaps()
|
DWORD PrimarySurface::getOrigCaps()
|
||||||
@ -162,37 +185,6 @@ namespace DDraw
|
|||||||
} while (surfacePtr && surfacePtr != &surface);
|
} while (surfacePtr && surfacePtr != &surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimarySurface::updateGdiSurfacePtr(IDirectDrawSurface* flipTargetOverride)
|
|
||||||
{
|
|
||||||
auto primary(CompatPtr<IDirectDrawSurface>::from(m_surface->getDirectDrawSurface().get()));
|
|
||||||
if (flipTargetOverride)
|
|
||||||
{
|
|
||||||
if (g_gdiSurface.get() == flipTargetOverride)
|
|
||||||
{
|
|
||||||
g_gdiSurface = primary;
|
|
||||||
}
|
|
||||||
else if (g_gdiSurface.get() == primary)
|
|
||||||
{
|
|
||||||
g_gdiSurface = flipTargetOverride;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DDSCAPS caps = {};
|
|
||||||
caps.dwCaps = DDSCAPS_FLIP;
|
|
||||||
CompatPtr<IDirectDrawSurface> current(primary);
|
|
||||||
CompatPtr<IDirectDrawSurface> next;
|
|
||||||
HRESULT result = current->GetAttachedSurface(current, &caps, &next.getRef());
|
|
||||||
while (SUCCEEDED(result) && next.get() != g_gdiSurface.get() && next.get() != primary)
|
|
||||||
{
|
|
||||||
current = next;
|
|
||||||
next.reset();
|
|
||||||
result = current->GetAttachedSurface(current, &caps, &next.getRef());
|
|
||||||
}
|
|
||||||
|
|
||||||
g_gdiSurface = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompatWeakPtr<IDirectDrawPalette> PrimarySurface::s_palette;
|
CompatWeakPtr<IDirectDrawPalette> PrimarySurface::s_palette;
|
||||||
PALETTEENTRY PrimarySurface::s_paletteEntries[256] = {};
|
PALETTEENTRY PrimarySurface::s_paletteEntries[256] = {};
|
||||||
std::vector<std::vector<unsigned char>> PrimarySurface::s_surfaceBuffers;
|
std::vector<std::vector<unsigned char>> PrimarySurface::s_surfaceBuffers;
|
||||||
|
@ -19,7 +19,7 @@ namespace DDraw
|
|||||||
static HRESULT flipToGdiSurface();
|
static HRESULT flipToGdiSurface();
|
||||||
static const DDSURFACEDESC2& getDesc();
|
static const DDSURFACEDESC2& getDesc();
|
||||||
static CompatPtr<IDirectDrawSurface7> getGdiSurface();
|
static CompatPtr<IDirectDrawSurface7> getGdiSurface();
|
||||||
static CompatPtr<IDirectDrawSurface7> getPrimary();
|
static CompatWeakPtr<IDirectDrawSurface7> getPrimary();
|
||||||
static DWORD getOrigCaps();
|
static DWORD getOrigCaps();
|
||||||
|
|
||||||
void updateGdiSurfacePtr(IDirectDrawSurface* flipTargetOverride);
|
void updateGdiSurfacePtr(IDirectDrawSurface* flipTargetOverride);
|
||||||
|
@ -96,8 +96,6 @@ namespace DDraw
|
|||||||
result = RealPrimarySurface::flip(dwFlags);
|
result = RealPrimarySurface::flip(dwFlags);
|
||||||
if (SUCCEEDED(result) && !isFlipEmulated)
|
if (SUCCEEDED(result) && !isFlipEmulated)
|
||||||
{
|
{
|
||||||
static_cast<PrimarySurface*>(m_data)->updateGdiSurfacePtr(
|
|
||||||
CompatPtr<IDirectDrawSurface>::from(lpDDSurfaceTargetOverride));
|
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,6 @@ namespace DDraw
|
|||||||
|
|
||||||
Surface::Surface()
|
Surface::Surface()
|
||||||
: m_ddObject(nullptr)
|
: m_ddObject(nullptr)
|
||||||
, m_dds(nullptr)
|
|
||||||
, m_ddId()
|
, m_ddId()
|
||||||
, m_refCount(0)
|
, m_refCount(0)
|
||||||
{
|
{
|
||||||
@ -133,8 +132,6 @@ namespace DDraw
|
|||||||
privateData->m_impl4->m_data = privateData.get();
|
privateData->m_impl4->m_data = privateData.get();
|
||||||
privateData->m_impl7->m_data = privateData.get();
|
privateData->m_impl7->m_data = privateData.get();
|
||||||
|
|
||||||
privateData->m_dds = CompatPtr<IDirectDrawSurface>(
|
|
||||||
Compat::queryInterface<IDirectDrawSurface>(&dds));
|
|
||||||
privateData->m_ddId = getDdIidFromVtablePtr(reinterpret_cast<void**>(dd.get())[0]);
|
privateData->m_ddId = getDdIidFromVtablePtr(reinterpret_cast<void**>(dd.get())[0]);
|
||||||
privateData->m_ddObject = DDraw::getDdObject(*CompatPtr<IDirectDraw>(dd));
|
privateData->m_ddObject = DDraw::getDdObject(*CompatPtr<IDirectDraw>(dd));
|
||||||
|
|
||||||
@ -207,16 +204,6 @@ namespace DDraw
|
|||||||
template <>
|
template <>
|
||||||
SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl<IDirectDrawSurface7>() const { return m_impl7.get(); }
|
SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl<IDirectDrawSurface7>() const { return m_impl7.get(); }
|
||||||
|
|
||||||
CompatPtr<IDirectDraw7> Surface::getDirectDraw() const
|
|
||||||
{
|
|
||||||
return DDraw::getDirectDraw(*getDirectDrawSurface());
|
|
||||||
}
|
|
||||||
|
|
||||||
CompatPtr<IDirectDrawSurface7> Surface::getDirectDrawSurface() const
|
|
||||||
{
|
|
||||||
return CompatPtr<IDirectDrawSurface7>(Compat::queryInterface<IDirectDrawSurface7>(m_dds));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
Surface* Surface::getSurface(TSurface& dds)
|
Surface* Surface::getSurface(TSurface& dds)
|
||||||
{
|
{
|
||||||
|
@ -29,9 +29,6 @@ namespace DDraw
|
|||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
static Surface* getSurface(TSurface& dds);
|
static Surface* getSurface(TSurface& dds);
|
||||||
|
|
||||||
CompatPtr<IDirectDraw7> getDirectDraw() const;
|
|
||||||
CompatPtr<IDirectDrawSurface7> getDirectDrawSurface() const;
|
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
SurfaceImpl<TSurface>* getImpl() const;
|
SurfaceImpl<TSurface>* getImpl() const;
|
||||||
|
|
||||||
@ -55,7 +52,6 @@ namespace DDraw
|
|||||||
IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface);
|
IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface);
|
||||||
virtual void createImpl();
|
virtual void createImpl();
|
||||||
|
|
||||||
IDirectDrawSurface* m_dds;
|
|
||||||
IID m_ddId;
|
IID m_ddId;
|
||||||
DWORD m_refCount;
|
DWORD m_refCount;
|
||||||
};
|
};
|
||||||
|
@ -121,7 +121,12 @@ namespace DDraw
|
|||||||
replDesc.ddpfPixelFormat = desc.ddpfPixelFormat;
|
replDesc.ddpfPixelFormat = desc.ddpfPixelFormat;
|
||||||
replDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
replDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||||
|
|
||||||
DDraw::Repository::ScopedSurface replacementSurface(*m_data->getDirectDraw(), replDesc);
|
CompatPtr<IUnknown> ddUnk;
|
||||||
|
GetDDInterface(surface, reinterpret_cast<void**>(&ddUnk.getRef()));
|
||||||
|
CompatPtr<IDirectDraw7> dd;
|
||||||
|
ddUnk->QueryInterface(ddUnk, IID_IDirectDraw7, reinterpret_cast<void**>(&dd.getRef()));
|
||||||
|
|
||||||
|
DDraw::Repository::ScopedSurface replacementSurface(*dd, replDesc);
|
||||||
if (replacementSurface.surface)
|
if (replacementSurface.surface)
|
||||||
{
|
{
|
||||||
surface = CompatPtr<TSurface>::from(replacementSurface.surface.get());
|
surface = CompatPtr<TSurface>::from(replacementSurface.surface.get());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user