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

Allow PrimarySurface to wrap different surface implementations

This commit is contained in:
narzoul 2016-09-11 22:44:30 +02:00
parent 47f02667bf
commit d163787437
7 changed files with 77 additions and 49 deletions

View File

@ -11,13 +11,12 @@ namespace
typename TSurface, typename... Params>
HRESULT STDMETHODCALLTYPE callImpl(TSurface* This, Params... params)
{
DDraw::SurfaceImpl<TSurface>* surfaceImpl =
This ? DDraw::Surface::getImpl<TSurface>(*This) : nullptr;
if (!surfaceImpl)
DDraw::Surface* surface = This ? DDraw::Surface::getSurface(*This) : nullptr;
if (!surface)
{
return (CompatVtableBase<TSurface>::s_origVtable.*origMethod)(This, params...);
}
return (surfaceImpl->*compatMethod)(This, params...);
return (surface->getImpl<TSurface>()->*compatMethod)(This, params...);
}
}

View File

@ -12,6 +12,11 @@ namespace
namespace DDraw
{
PrimarySurface::PrimarySurface(Surface* surface) : m_surface(surface)
{
surface->AddRef();
}
PrimarySurface::~PrimarySurface()
{
Compat::LogEnter("PrimarySurface::~PrimarySurface");
@ -53,7 +58,7 @@ namespace DDraw
}
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(surface));
std::unique_ptr<Surface> privateData(new PrimarySurface());
std::unique_ptr<Surface> privateData(new PrimarySurface(Surface::getSurface(*surface)));
attach(*surface7, privateData);
CompatPtr<IDirectDrawSurface> surface1(Compat::queryInterface<IDirectDrawSurface>(surface));
@ -77,11 +82,11 @@ namespace DDraw
void PrimarySurface::createImpl()
{
m_impl.reset(new PrimarySurfaceImpl<IDirectDrawSurface>());
m_impl2.reset(new PrimarySurfaceImpl<IDirectDrawSurface2>());
m_impl3.reset(new PrimarySurfaceImpl<IDirectDrawSurface3>());
m_impl4.reset(new PrimarySurfaceImpl<IDirectDrawSurface4>());
m_impl7.reset(new PrimarySurfaceImpl<IDirectDrawSurface7>());
m_impl.reset(new PrimarySurfaceImpl<IDirectDrawSurface>(*m_surface->getImpl<IDirectDrawSurface>()));
m_impl2.reset(new PrimarySurfaceImpl<IDirectDrawSurface2>(*m_surface->getImpl<IDirectDrawSurface2>()));
m_impl3.reset(new PrimarySurfaceImpl<IDirectDrawSurface3>(*m_surface->getImpl<IDirectDrawSurface3>()));
m_impl4.reset(new PrimarySurfaceImpl<IDirectDrawSurface4>(*m_surface->getImpl<IDirectDrawSurface4>()));
m_impl7.reset(new PrimarySurfaceImpl<IDirectDrawSurface7>(*m_surface->getImpl<IDirectDrawSurface7>()));
}
const DDSURFACEDESC2& PrimarySurface::getDesc()

View File

@ -20,6 +20,10 @@ namespace DDraw
static PALETTEENTRY s_paletteEntries[256];
private:
PrimarySurface(Surface* surface);
virtual void createImpl() override;
std::unique_ptr<Surface> m_surface;
};
}

View File

@ -15,6 +15,11 @@ namespace
namespace DDraw
{
template <typename TSurface>
PrimarySurfaceImpl<TSurface>::PrimarySurfaceImpl(SurfaceImpl& impl) : m_impl(impl)
{
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Blt(
TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
@ -25,7 +30,7 @@ namespace DDraw
return DDERR_SURFACELOST;
}
HRESULT result = SurfaceImpl::Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
HRESULT result = m_impl.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
if (SUCCEEDED(result))
{
RealPrimarySurface::invalidate(lpDestRect);
@ -43,7 +48,7 @@ namespace DDraw
return DDERR_SURFACELOST;
}
HRESULT result = SurfaceImpl::BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
HRESULT result = m_impl.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
if (SUCCEEDED(result))
{
const LONG x = dwX;
@ -76,7 +81,7 @@ namespace DDraw
return DDERR_SURFACELOST;
}
HRESULT result = SurfaceImpl::Flip(This, lpDDSurfaceTargetOverride, dwFlags);
HRESULT result = m_impl.Flip(This, lpDDSurfaceTargetOverride, dwFlags);
if (SUCCEEDED(result))
{
result = RealPrimarySurface::flip(dwFlags);
@ -87,7 +92,7 @@ namespace DDraw
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::GetCaps(TSurface* This, TDdsCaps* lpDDSCaps)
{
HRESULT result = SurfaceImpl::GetCaps(This, lpDDSCaps);
HRESULT result = m_impl.GetCaps(This, lpDDSCaps);
if (SUCCEEDED(result))
{
restorePrimaryCaps(lpDDSCaps->dwCaps);
@ -98,7 +103,7 @@ namespace DDraw
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc)
{
HRESULT result = SurfaceImpl::GetSurfaceDesc(This, lpDDSurfaceDesc);
HRESULT result = m_impl.GetSurfaceDesc(This, lpDDSurfaceDesc);
if (SUCCEEDED(result))
{
restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps.dwCaps);
@ -109,7 +114,7 @@ namespace DDraw
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::IsLost(TSurface* This)
{
HRESULT result = SurfaceImpl::IsLost(This);
HRESULT result = m_impl.IsLost(This);
if (SUCCEEDED(result))
{
result = RealPrimarySurface::isLost() ? DDERR_SURFACELOST : DD_OK;
@ -127,7 +132,7 @@ namespace DDraw
return DDERR_SURFACELOST;
}
HRESULT result = SurfaceImpl::Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
HRESULT result = m_impl.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
if (SUCCEEDED(result))
{
RealPrimarySurface::invalidate(lpDestRect);
@ -144,13 +149,13 @@ namespace DDraw
auto realPrimary(RealPrimarySurface::getSurface());
return realPrimary->QueryInterface(realPrimary, riid, obp);
}
return SurfaceImpl::QueryInterface(This, riid, obp);
return m_impl.QueryInterface(This, riid, obp);
}
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::ReleaseDC(TSurface* This, HDC hDC)
{
HRESULT result = SurfaceImpl::ReleaseDC(This, hDC);
HRESULT result = m_impl.ReleaseDC(This, hDC);
if (SUCCEEDED(result))
{
RealPrimarySurface::invalidate(nullptr);
@ -168,7 +173,7 @@ namespace DDraw
result = RealPrimarySurface::restore();
if (SUCCEEDED(result))
{
result = SurfaceImpl::Restore(This);
result = m_impl.Restore(This);
if (SUCCEEDED(result))
{
fixSurfacePtrs(*This);
@ -182,7 +187,7 @@ namespace DDraw
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper)
{
HRESULT result = SurfaceImpl::SetClipper(This, lpDDClipper);
HRESULT result = m_impl.SetClipper(This, lpDDClipper);
if (SUCCEEDED(result))
{
RealPrimarySurface::setClipper(lpDDClipper);
@ -202,7 +207,7 @@ namespace DDraw
return DD_OK;
}
HRESULT result = SurfaceImpl::SetPalette(This, lpDDPalette);
HRESULT result = m_impl.SetPalette(This, lpDDPalette);
if (SUCCEEDED(result))
{
PrimarySurface::s_palette = lpDDPalette;
@ -214,7 +219,7 @@ namespace DDraw
template <typename TSurface>
HRESULT PrimarySurfaceImpl<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
{
HRESULT result = SurfaceImpl::Unlock(This, lpRect);
HRESULT result = m_impl.Unlock(This, lpRect);
if (SUCCEEDED(result))
{
RealPrimarySurface::update();

View File

@ -15,6 +15,8 @@ namespace DDraw
class PrimarySurfaceImpl : public SurfaceImpl<TSurface>
{
public:
PrimarySurfaceImpl(SurfaceImpl& impl);
virtual HRESULT Blt(TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
DWORD dwFlags, LPDDBLTFX lpDDBltFx) override;
virtual HRESULT BltFast(TSurface* This, DWORD dwX, DWORD dwY,
@ -31,5 +33,8 @@ namespace DDraw
virtual HRESULT SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper) override;
virtual HRESULT SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette) override;
virtual HRESULT Unlock(TSurface* This, TUnlockParam lpRect) override;
private:
SurfaceImpl& m_impl;
};
}

View File

@ -43,13 +43,21 @@ namespace DDraw
ULONG STDMETHODCALLTYPE Surface::AddRef()
{
return 0;
return ++m_refCount;
}
ULONG STDMETHODCALLTYPE Surface::Release()
{
delete this;
return 0;
DWORD refCount = --m_refCount;
if (0 == refCount)
{
delete this;
}
return refCount;
}
Surface::Surface() : m_refCount(0)
{
}
Surface::~Surface()
@ -124,28 +132,6 @@ namespace DDraw
m_impl7.reset(new SurfaceImpl<IDirectDrawSurface7>());
}
template <typename TSurface>
SurfaceImpl<TSurface>* Surface::getImpl(CompatRef<TSurface> dds)
{
Surface* surface = nullptr;
DWORD surfacePtrSize = sizeof(surface);
CompatVtableBase<IDirectDrawSurface7>::s_origVtable.GetPrivateData(
reinterpret_cast<IDirectDrawSurface7*>(&dds),
IID_CompatSurfacePrivateData, &surface, &surfacePtrSize);
if (!surface)
{
return nullptr;
}
return surface->getImpl<TSurface>();
}
template SurfaceImpl<IDirectDrawSurface>* Surface::getImpl(CompatRef<IDirectDrawSurface> dds);
template SurfaceImpl<IDirectDrawSurface2>* Surface::getImpl(CompatRef<IDirectDrawSurface2> dds);
template SurfaceImpl<IDirectDrawSurface3>* Surface::getImpl(CompatRef<IDirectDrawSurface3> dds);
template SurfaceImpl<IDirectDrawSurface4>* Surface::getImpl(CompatRef<IDirectDrawSurface4> dds);
template SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl(CompatRef<IDirectDrawSurface7> dds);
template <>
SurfaceImpl<IDirectDrawSurface>* Surface::getImpl<IDirectDrawSurface>() const { return m_impl.get(); }
template <>
@ -156,4 +142,24 @@ namespace DDraw
SurfaceImpl<IDirectDrawSurface4>* Surface::getImpl<IDirectDrawSurface4>() const { return m_impl4.get(); }
template <>
SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl<IDirectDrawSurface7>() const { return m_impl7.get(); }
template <typename TSurface>
Surface* Surface::getSurface(TSurface& dds)
{
Surface* surface = nullptr;
DWORD surfacePtrSize = sizeof(surface);
// This can get called during surface release so a proper QueryInterface would be dangerous
CompatVtableBase<IDirectDrawSurface7>::s_origVtable.GetPrivateData(
reinterpret_cast<IDirectDrawSurface7*>(&dds),
IID_CompatSurfacePrivateData, &surface, &surfacePtrSize);
return surface;
}
template Surface* Surface::getSurface(IDirectDrawSurface& dds);
template Surface* Surface::getSurface(IDirectDrawSurface2& dds);
template Surface* Surface::getSurface(IDirectDrawSurface3& dds);
template Surface* Surface::getSurface(IDirectDrawSurface4& dds);
template Surface* Surface::getSurface(IDirectDrawSurface7& dds);
}

View File

@ -26,12 +26,14 @@ namespace DDraw
static HRESULT create(CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface);
template <typename TSurface>
static SurfaceImpl<TSurface>* getImpl(CompatRef<TSurface> dds);
static Surface* getSurface(TSurface& dds);
template <typename TSurface>
SurfaceImpl<TSurface>* getImpl() const;
protected:
Surface();
static void attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface>& privateData);
std::unique_ptr<SurfaceImpl<IDirectDrawSurface>> m_impl;
@ -44,5 +46,7 @@ namespace DDraw
static HRESULT WINAPI attachToLinkedSurfaces(
IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface);
virtual void createImpl();
DWORD m_refCount;
};
}