From d1637874379b10099fce0f378a4ae34784c6149a Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 11 Sep 2016 22:44:30 +0200 Subject: [PATCH] Allow PrimarySurface to wrap different surface implementations --- DDrawCompat/DDraw/DirectDrawSurface.cpp | 7 +-- DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp | 17 ++++-- DDrawCompat/DDraw/Surfaces/PrimarySurface.h | 4 ++ .../DDraw/Surfaces/PrimarySurfaceImpl.cpp | 31 +++++----- .../DDraw/Surfaces/PrimarySurfaceImpl.h | 5 ++ DDrawCompat/DDraw/Surfaces/Surface.cpp | 56 ++++++++++--------- DDrawCompat/DDraw/Surfaces/Surface.h | 6 +- 7 files changed, 77 insertions(+), 49 deletions(-) diff --git a/DDrawCompat/DDraw/DirectDrawSurface.cpp b/DDrawCompat/DDraw/DirectDrawSurface.cpp index 35bbb03..ad3fc5c 100644 --- a/DDrawCompat/DDraw/DirectDrawSurface.cpp +++ b/DDrawCompat/DDraw/DirectDrawSurface.cpp @@ -11,13 +11,12 @@ namespace typename TSurface, typename... Params> HRESULT STDMETHODCALLTYPE callImpl(TSurface* This, Params... params) { - DDraw::SurfaceImpl* surfaceImpl = - This ? DDraw::Surface::getImpl(*This) : nullptr; - if (!surfaceImpl) + DDraw::Surface* surface = This ? DDraw::Surface::getSurface(*This) : nullptr; + if (!surface) { return (CompatVtableBase::s_origVtable.*origMethod)(This, params...); } - return (surfaceImpl->*compatMethod)(This, params...); + return (surface->getImpl()->*compatMethod)(This, params...); } } diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp index 5cf1dd4..413be66 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp @@ -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 surface7(Compat::queryInterface(surface)); - std::unique_ptr privateData(new PrimarySurface()); + std::unique_ptr privateData(new PrimarySurface(Surface::getSurface(*surface))); attach(*surface7, privateData); CompatPtr surface1(Compat::queryInterface(surface)); @@ -77,11 +82,11 @@ namespace DDraw void PrimarySurface::createImpl() { - m_impl.reset(new PrimarySurfaceImpl()); - m_impl2.reset(new PrimarySurfaceImpl()); - m_impl3.reset(new PrimarySurfaceImpl()); - m_impl4.reset(new PrimarySurfaceImpl()); - m_impl7.reset(new PrimarySurfaceImpl()); + m_impl.reset(new PrimarySurfaceImpl(*m_surface->getImpl())); + m_impl2.reset(new PrimarySurfaceImpl(*m_surface->getImpl())); + m_impl3.reset(new PrimarySurfaceImpl(*m_surface->getImpl())); + m_impl4.reset(new PrimarySurfaceImpl(*m_surface->getImpl())); + m_impl7.reset(new PrimarySurfaceImpl(*m_surface->getImpl())); } const DDSURFACEDESC2& PrimarySurface::getDesc() diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.h b/DDrawCompat/DDraw/Surfaces/PrimarySurface.h index 339b39e..8e4a677 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.h +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.h @@ -20,6 +20,10 @@ namespace DDraw static PALETTEENTRY s_paletteEntries[256]; private: + PrimarySurface(Surface* surface); + virtual void createImpl() override; + + std::unique_ptr m_surface; }; } diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp index 909d4af..58f9d0a 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp @@ -15,6 +15,11 @@ namespace namespace DDraw { + template + PrimarySurfaceImpl::PrimarySurfaceImpl(SurfaceImpl& impl) : m_impl(impl) + { + } + template HRESULT PrimarySurfaceImpl::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 HRESULT PrimarySurfaceImpl::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 HRESULT PrimarySurfaceImpl::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 HRESULT PrimarySurfaceImpl::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 HRESULT PrimarySurfaceImpl::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 HRESULT PrimarySurfaceImpl::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 HRESULT PrimarySurfaceImpl::Unlock(TSurface* This, TUnlockParam lpRect) { - HRESULT result = SurfaceImpl::Unlock(This, lpRect); + HRESULT result = m_impl.Unlock(This, lpRect); if (SUCCEEDED(result)) { RealPrimarySurface::update(); diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.h b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.h index 75db33a..2cac65e 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.h +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.h @@ -15,6 +15,8 @@ namespace DDraw class PrimarySurfaceImpl : public SurfaceImpl { 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; }; } diff --git a/DDrawCompat/DDraw/Surfaces/Surface.cpp b/DDrawCompat/DDraw/Surfaces/Surface.cpp index d1bb721..f5f0bab 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.cpp +++ b/DDrawCompat/DDraw/Surfaces/Surface.cpp @@ -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()); } - template - SurfaceImpl* Surface::getImpl(CompatRef dds) - { - Surface* surface = nullptr; - DWORD surfacePtrSize = sizeof(surface); - CompatVtableBase::s_origVtable.GetPrivateData( - reinterpret_cast(&dds), - IID_CompatSurfacePrivateData, &surface, &surfacePtrSize); - if (!surface) - { - return nullptr; - } - - return surface->getImpl(); - } - - template SurfaceImpl* Surface::getImpl(CompatRef dds); - template SurfaceImpl* Surface::getImpl(CompatRef dds); - template SurfaceImpl* Surface::getImpl(CompatRef dds); - template SurfaceImpl* Surface::getImpl(CompatRef dds); - template SurfaceImpl* Surface::getImpl(CompatRef dds); - template <> SurfaceImpl* Surface::getImpl() const { return m_impl.get(); } template <> @@ -156,4 +142,24 @@ namespace DDraw SurfaceImpl* Surface::getImpl() const { return m_impl4.get(); } template <> SurfaceImpl* Surface::getImpl() const { return m_impl7.get(); } + + template + 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::s_origVtable.GetPrivateData( + reinterpret_cast(&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); } diff --git a/DDrawCompat/DDraw/Surfaces/Surface.h b/DDrawCompat/DDraw/Surfaces/Surface.h index 15ab0a4..71c1951 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.h +++ b/DDrawCompat/DDraw/Surfaces/Surface.h @@ -26,12 +26,14 @@ namespace DDraw static HRESULT create(CompatRef dd, TSurfaceDesc desc, TSurface*& surface); template - static SurfaceImpl* getImpl(CompatRef dds); + static Surface* getSurface(TSurface& dds); template SurfaceImpl* getImpl() const; protected: + Surface(); + static void attach(CompatRef dds, std::unique_ptr& privateData); std::unique_ptr> m_impl; @@ -44,5 +46,7 @@ namespace DDraw static HRESULT WINAPI attachToLinkedSurfaces( IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface); virtual void createImpl(); + + DWORD m_refCount; }; }