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
|
||||
{
|
||||
CompatPtr<IDirectDraw7> getDirectDraw(CompatRef<IDirectDrawSurface7> surface)
|
||||
{
|
||||
CompatPtr<IUnknown> dd;
|
||||
surface.get().lpVtbl->GetDDInterface(&surface, reinterpret_cast<void**>(&dd.getRef()));
|
||||
return dd;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
void DirectDrawSurface<TSurface>::setCompatVtable(Vtable<TSurface>& vtable)
|
||||
{
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
CompatPtr<IDirectDraw7> getDirectDraw(CompatRef<IDirectDrawSurface7> surface);
|
||||
|
||||
template <typename TSurface>
|
||||
class DirectDrawSurface : public CompatVtable<Vtable<TSurface>>
|
||||
{
|
||||
|
@ -8,9 +8,14 @@
|
||||
namespace
|
||||
{
|
||||
DDSURFACEDESC2 g_primarySurfaceDesc = {};
|
||||
CompatWeakPtr<IDirectDrawSurface> g_gdiSurface = nullptr;
|
||||
CompatWeakPtr<IDirectDrawSurface> g_primarySurface = nullptr;
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_primarySurface = nullptr;
|
||||
HANDLE g_gdiResourceHandle = nullptr;
|
||||
DWORD g_origCaps = 0;
|
||||
|
||||
HANDLE getResourceHandle(IDirectDrawSurface7& surface)
|
||||
{
|
||||
return reinterpret_cast<HANDLE**>(&surface)[1][2];
|
||||
}
|
||||
}
|
||||
|
||||
namespace DDraw
|
||||
@ -24,7 +29,7 @@ namespace DDraw
|
||||
{
|
||||
Compat::LogEnter("PrimarySurface::~PrimarySurface");
|
||||
|
||||
g_gdiSurface = nullptr;
|
||||
g_gdiResourceHandle = nullptr;
|
||||
g_primarySurface = nullptr;
|
||||
g_origCaps = 0;
|
||||
s_palette = nullptr;
|
||||
@ -68,9 +73,8 @@ namespace DDraw
|
||||
std::unique_ptr<Surface> privateData(new PrimarySurface(Surface::getSurface(*surface)));
|
||||
attach(*surface7, privateData);
|
||||
|
||||
CompatPtr<IDirectDrawSurface> surface1(Compat::queryInterface<IDirectDrawSurface>(surface));
|
||||
g_gdiSurface = surface1;
|
||||
g_primarySurface = surface1;
|
||||
g_gdiResourceHandle = getResourceHandle(*surface7);
|
||||
g_primarySurface = surface7;
|
||||
g_origCaps = origCaps;
|
||||
|
||||
ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc));
|
||||
@ -105,11 +109,12 @@ namespace DDraw
|
||||
|
||||
HRESULT PrimarySurface::flipToGdiSurface()
|
||||
{
|
||||
if (!g_primarySurface)
|
||||
CompatPtr<IDirectDrawSurface7> gdiSurface;
|
||||
if (!g_primarySurface || !(gdiSurface = getGdiSurface()))
|
||||
{
|
||||
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()
|
||||
@ -118,18 +123,36 @@ namespace DDraw
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> PrimarySurface::getGdiSurface()
|
||||
{
|
||||
return CompatPtr<IDirectDrawSurface7>::from(g_gdiSurface.get());
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> PrimarySurface::getPrimary()
|
||||
{
|
||||
if (!g_primarySurface)
|
||||
{
|
||||
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()
|
||||
@ -162,37 +185,6 @@ namespace DDraw
|
||||
} 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;
|
||||
PALETTEENTRY PrimarySurface::s_paletteEntries[256] = {};
|
||||
std::vector<std::vector<unsigned char>> PrimarySurface::s_surfaceBuffers;
|
||||
|
@ -19,7 +19,7 @@ namespace DDraw
|
||||
static HRESULT flipToGdiSurface();
|
||||
static const DDSURFACEDESC2& getDesc();
|
||||
static CompatPtr<IDirectDrawSurface7> getGdiSurface();
|
||||
static CompatPtr<IDirectDrawSurface7> getPrimary();
|
||||
static CompatWeakPtr<IDirectDrawSurface7> getPrimary();
|
||||
static DWORD getOrigCaps();
|
||||
|
||||
void updateGdiSurfacePtr(IDirectDrawSurface* flipTargetOverride);
|
||||
|
@ -96,8 +96,6 @@ namespace DDraw
|
||||
result = RealPrimarySurface::flip(dwFlags);
|
||||
if (SUCCEEDED(result) && !isFlipEmulated)
|
||||
{
|
||||
static_cast<PrimarySurface*>(m_data)->updateGdiSurfacePtr(
|
||||
CompatPtr<IDirectDrawSurface>::from(lpDDSurfaceTargetOverride));
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,6 @@ namespace DDraw
|
||||
|
||||
Surface::Surface()
|
||||
: m_ddObject(nullptr)
|
||||
, m_dds(nullptr)
|
||||
, m_ddId()
|
||||
, m_refCount(0)
|
||||
{
|
||||
@ -133,8 +132,6 @@ namespace DDraw
|
||||
privateData->m_impl4->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_ddObject = DDraw::getDdObject(*CompatPtr<IDirectDraw>(dd));
|
||||
|
||||
@ -207,16 +204,6 @@ namespace DDraw
|
||||
template <>
|
||||
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>
|
||||
Surface* Surface::getSurface(TSurface& dds)
|
||||
{
|
||||
|
@ -29,9 +29,6 @@ namespace DDraw
|
||||
template <typename TSurface>
|
||||
static Surface* getSurface(TSurface& dds);
|
||||
|
||||
CompatPtr<IDirectDraw7> getDirectDraw() const;
|
||||
CompatPtr<IDirectDrawSurface7> getDirectDrawSurface() const;
|
||||
|
||||
template <typename TSurface>
|
||||
SurfaceImpl<TSurface>* getImpl() const;
|
||||
|
||||
@ -55,7 +52,6 @@ namespace DDraw
|
||||
IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface);
|
||||
virtual void createImpl();
|
||||
|
||||
IDirectDrawSurface* m_dds;
|
||||
IID m_ddId;
|
||||
DWORD m_refCount;
|
||||
};
|
||||
|
@ -121,7 +121,12 @@ namespace DDraw
|
||||
replDesc.ddpfPixelFormat = desc.ddpfPixelFormat;
|
||||
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)
|
||||
{
|
||||
surface = CompatPtr<TSurface>::from(replacementSurface.surface.get());
|
||||
|
Loading…
x
Reference in New Issue
Block a user