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

Tagged all DirectDraw objects for tracking lifetime

This commit is contained in:
narzoul 2016-09-22 23:10:00 +02:00
parent 3746362528
commit 7220b80999
11 changed files with 145 additions and 94 deletions

View File

@ -4,7 +4,6 @@
#include "DDraw/ActivateAppHandler.h"
#include "DDraw/DirectDraw.h"
#include "DDraw/DisplayMode.h"
#include "DDraw/Surfaces/FullScreenTagSurface.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "DDraw/Surfaces/SurfaceImpl.h"
#include "Gdi/Gdi.h"
@ -93,7 +92,7 @@ namespace
Gdi::disableEmulation();
}
auto dd(DDraw::FullScreenTagSurface::getFullScreenDirectDraw());
auto dd(DDraw::getFullScreenDirectDraw());
if (dd)
{
if (isActivated)

View File

@ -4,12 +4,38 @@
#include "DDraw/DirectDraw.h"
#include "DDraw/DirectDrawSurface.h"
#include "DDraw/DisplayMode.h"
#include "DDraw/Surfaces/FullScreenTagSurface.h"
#include "DDraw/Surfaces/TagSurface.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "DDraw/Surfaces/Surface.h"
namespace DDraw
{
TagSurface* g_fullScreenTagSurface = nullptr;
template <typename TDirectDraw>
void* getDdObject(TDirectDraw& dd)
{
return reinterpret_cast<void**>(&dd)[1];
}
template void* getDdObject(IDirectDraw&);
template void* getDdObject(IDirectDraw2&);
template void* getDdObject(IDirectDraw4&);
template void* getDdObject(IDirectDraw7&);
CompatPtr<IDirectDraw7> getFullScreenDirectDraw()
{
return g_fullScreenTagSurface ? g_fullScreenTagSurface->getDirectDraw() : nullptr;
}
void onRelease(TagSurface& dd)
{
if (&dd == g_fullScreenTagSurface)
{
g_fullScreenTagSurface = nullptr;
}
}
template <typename TDirectDraw>
void DirectDraw<TDirectDraw>::setCompatVtable(Vtable<TDirectDraw>& vtable)
{
@ -85,16 +111,26 @@ namespace DDraw
HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags);
if (SUCCEEDED(result))
{
if (dwFlags & DDSCL_FULLSCREEN)
void* ddObject = getDdObject(*This);
TagSurface* tagSurface = TagSurface::get(ddObject);
if (!tagSurface)
{
CompatPtr<IDirectDraw> dd(Compat::queryInterface<IDirectDraw>(This));
DDraw::FullScreenTagSurface::create(*dd);
ActivateAppHandler::setFullScreenCooperativeLevel(hWnd, dwFlags);
TagSurface::create(*dd);
tagSurface = TagSurface::get(ddObject);
}
else if (CompatPtr<IDirectDraw7>(Compat::queryInterface<IDirectDraw7>(This)).get() ==
DDraw::FullScreenTagSurface::getFullScreenDirectDraw().get())
if (tagSurface)
{
DDraw::FullScreenTagSurface::destroy();
if (dwFlags & DDSCL_FULLSCREEN)
{
g_fullScreenTagSurface = tagSurface;
ActivateAppHandler::setFullScreenCooperativeLevel(hWnd, dwFlags);
}
else if ((dwFlags & DDSCL_NORMAL) && tagSurface == g_fullScreenTagSurface)
{
g_fullScreenTagSurface = nullptr;
}
}
}
return result;

View File

@ -1,11 +1,20 @@
#pragma once
#include "Common/CompatPtr.h"
#include "Common/CompatVtable.h"
#include "DDraw/Visitors/DirectDrawVtblVisitor.h"
#include "DDraw/Types.h"
namespace DDraw
{
class TagSurface;
template <typename TDirectDraw>
void* getDdObject(TDirectDraw& dd);
CompatPtr<IDirectDraw7> getFullScreenDirectDraw();
void onRelease(TagSurface& dd);
template <typename TDirectDraw>
class DirectDraw: public CompatVtable<Vtable<TDirectDraw>>
{

View File

@ -1,62 +0,0 @@
#include "DDraw/Surfaces/SurfaceImpl.h"
#include "DDraw/Surfaces/FullScreenTagSurface.h"
namespace
{
CompatWeakPtr<IDirectDrawSurface> g_surface = nullptr;
}
namespace DDraw
{
FullScreenTagSurface::~FullScreenTagSurface()
{
g_surface = nullptr;
}
HRESULT FullScreenTagSurface::create(CompatRef<IDirectDraw> dd)
{
destroy();
DDSURFACEDESC desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
desc.dwWidth = 1;
desc.dwHeight = 1;
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
IDirectDrawSurface* surface = nullptr;
HRESULT result = Surface::create(dd, desc, surface);
if (SUCCEEDED(result))
{
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(surface));
std::unique_ptr<Surface> privateData(new FullScreenTagSurface());
attach(*surface7, privateData);
g_surface = surface;
}
return result;
}
void FullScreenTagSurface::destroy()
{
g_surface.release();
}
CompatPtr<IDirectDraw7> FullScreenTagSurface::getFullScreenDirectDraw()
{
if (!g_surface)
{
return nullptr;
}
CompatPtr<IUnknown> dd = nullptr;
auto tagSurface(getFullScreenTagSurface());
tagSurface.get()->lpVtbl->GetDDInterface(tagSurface, reinterpret_cast<void**>(&dd.getRef()));
return CompatPtr<IDirectDraw7>(Compat::queryInterface<IDirectDraw7>(dd.get()));
}
CompatPtr<IDirectDrawSurface7> FullScreenTagSurface::getFullScreenTagSurface()
{
return CompatPtr<IDirectDrawSurface7>(
Compat::queryInterface<IDirectDrawSurface7>(g_surface.get()));
}
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "DDraw/Surfaces/Surface.h"
namespace DDraw
{
class FullScreenTagSurface : public Surface
{
public:
virtual ~FullScreenTagSurface();
static HRESULT create(CompatRef<IDirectDraw> dd);
static void destroy();
static CompatPtr<IDirectDraw7> getFullScreenDirectDraw();
static CompatPtr<IDirectDrawSurface7> getFullScreenTagSurface();
};
}

View File

@ -1,6 +1,7 @@
#include <initguid.h>
#include "Common/CompatPtr.h"
#include "DDraw/DirectDraw.h"
#include "DDraw/DisplayMode.h"
#include "DDraw/Surfaces/Surface.h"
#include "DDraw/Surfaces/SurfaceImpl.h"
@ -78,7 +79,8 @@ namespace DDraw
}
Surface::Surface()
: m_ddId()
: m_dds(nullptr)
, m_ddId()
, m_ddObject(nullptr)
, m_refCount(0)
{
@ -104,8 +106,10 @@ 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 = reinterpret_cast<void**>(dd.get())[1];
privateData->m_ddObject = DDraw::getDdObject(*CompatPtr<IDirectDraw>(dd));
privateData.release();
}
@ -181,6 +185,19 @@ namespace DDraw
template <>
SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl<IDirectDrawSurface7>() const { return m_impl7.get(); }
CompatPtr<IDirectDraw7> Surface::getDirectDraw() const
{
auto dds(getDirectDrawSurface());
CompatPtr<IUnknown> dd;
m_impl7->GetDDInterface(dds, reinterpret_cast<void**>(&dd.getRef()));
return CompatPtr<IDirectDraw7>(dd);
}
CompatPtr<IDirectDrawSurface7> Surface::getDirectDrawSurface() const
{
return CompatPtr<IDirectDrawSurface7>(Compat::queryInterface<IDirectDrawSurface7>(m_dds));
}
template <typename TSurface>
Surface* Surface::getSurface(TSurface& dds)
{

View File

@ -29,6 +29,9 @@ 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;
@ -51,6 +54,7 @@ namespace DDraw
IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface);
virtual void createImpl();
IDirectDrawSurface* m_dds;
IID m_ddId;
void* m_ddObject;
DWORD m_refCount;

View File

@ -0,0 +1,50 @@
#include <algorithm>
#include <map>
#include "DDraw/DirectDraw.h"
#include "DDraw/Surfaces/SurfaceImpl.h"
#include "DDraw/Surfaces/TagSurface.h"
namespace
{
std::map<void*, DDraw::TagSurface*> g_tagSurfaces;
}
namespace DDraw
{
TagSurface::~TagSurface()
{
std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
[=](auto& i) { return i.second == this; })->second;
DDraw::onRelease(*this);
g_tagSurfaces.erase(std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
[=](auto& i) { return i.second == this; }));
}
HRESULT TagSurface::create(CompatRef<IDirectDraw> dd)
{
DDSURFACEDESC desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
desc.dwWidth = 1;
desc.dwHeight = 1;
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
IDirectDrawSurface* surface = nullptr;
HRESULT result = Surface::create(dd, desc, surface);
if (SUCCEEDED(result))
{
std::unique_ptr<Surface> privateData(new TagSurface());
g_tagSurfaces[getDdObject(dd.get())] = static_cast<TagSurface*>(privateData.get());
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(surface));
attach(*surface7, privateData);
}
return result;
}
TagSurface* TagSurface::get(void* ddObject)
{
auto it = g_tagSurfaces.find(ddObject);
return it != g_tagSurfaces.end() ? it->second : nullptr;
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "DDraw/Surfaces/Surface.h"
namespace DDraw
{
class TagSurface : public Surface
{
public:
virtual ~TagSurface();
static HRESULT create(CompatRef<IDirectDraw> dd);
static TagSurface* get(void* ddObject);
};
}

View File

@ -182,7 +182,7 @@
<ClInclude Include="DDraw\Hooks.h" />
<ClInclude Include="DDraw\Repository.h" />
<ClInclude Include="DDraw\ScopedThreadLock.h" />
<ClInclude Include="DDraw\Surfaces\FullScreenTagSurface.h" />
<ClInclude Include="DDraw\Surfaces\TagSurface.h" />
<ClInclude Include="DDraw\Surfaces\PrimarySurface.h" />
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h" />
<ClInclude Include="DDraw\Surfaces\Surface.h" />
@ -234,7 +234,7 @@
<ClCompile Include="DDraw\Repository.cpp" />
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
<ClCompile Include="DDraw\RealPrimarySurface.cpp" />
<ClCompile Include="DDraw\Surfaces\FullScreenTagSurface.cpp" />
<ClCompile Include="DDraw\Surfaces\TagSurface.cpp" />
<ClCompile Include="DDraw\Surfaces\PrimarySurface.cpp" />
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp" />
<ClCompile Include="DDraw\Surfaces\Surface.cpp" />

View File

@ -255,7 +255,7 @@
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h">
<Filter>Header Files\DDraw\Surfaces</Filter>
</ClInclude>
<ClInclude Include="DDraw\Surfaces\FullScreenTagSurface.h">
<ClInclude Include="DDraw\Surfaces\TagSurface.h">
<Filter>Header Files\DDraw\Surfaces</Filter>
</ClInclude>
</ItemGroup>
@ -386,7 +386,7 @@
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp">
<Filter>Source Files\DDraw\Surfaces</Filter>
</ClCompile>
<ClCompile Include="DDraw\Surfaces\FullScreenTagSurface.cpp">
<ClCompile Include="DDraw\Surfaces\TagSurface.cpp">
<Filter>Source Files\DDraw\Surfaces</Filter>
</ClCompile>
</ItemGroup>