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

Create repository surfaces on the appropriate device

This change assigns a different DirectDraw repository object for each original
DirectDraw object that requires temporary surfaces, ensuring that video memory
surfaces are created on the appropriate device on a multi-GPU system.
This commit is contained in:
narzoul 2016-09-24 23:02:48 +02:00
parent 7220b80999
commit e8f987eb05
8 changed files with 98 additions and 46 deletions

View File

@ -26,6 +26,13 @@ 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)
{ {

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Common/CompatPtr.h"
#include "Common/CompatRef.h" #include "Common/CompatRef.h"
#include "Common/CompatVtable.h" #include "Common/CompatVtable.h"
#include "DDraw/Visitors/DirectDrawSurfaceVtblVisitor.h" #include "DDraw/Visitors/DirectDrawSurfaceVtblVisitor.h"
@ -7,6 +8,8 @@
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>>
{ {

View File

@ -1,8 +1,10 @@
#include <algorithm> #include <algorithm>
#include <map>
#include <vector> #include <vector>
#include "Common/CompatPtr.h" #include "Common/CompatPtr.h"
#include "Common/Log.h" #include "Common/Log.h"
#include "DDraw/DirectDraw.h"
#include "DDraw/Repository.h" #include "DDraw/Repository.h"
#include "Dll/Procs.h" #include "Dll/Procs.h"
@ -10,16 +12,23 @@ namespace
{ {
using DDraw::Repository::Surface; using DDraw::Repository::Surface;
static std::vector<Surface> g_sysMemSurfaces; struct Repository
static std::vector<Surface> g_vidMemSurfaces; {
CompatWeakPtr<IDirectDraw7> dd;
std::vector<Surface> surfaces;
};
Repository g_sysMemRepo;
std::map<void*, Repository> g_vidMemRepos;
CompatPtr<IDirectDraw7> createDirectDraw(); CompatPtr<IDirectDraw7> createDirectDraw();
Surface createSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps); Surface createSurface(CompatRef<IDirectDraw7> dd,
DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps);
std::vector<Surface>::iterator findSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, std::vector<Surface>::iterator findSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf,
std::vector<Surface>& cachedSurfaces); std::vector<Surface>& cachedSurfaces);
void destroySmallerSurfaces(DWORD width, DWORD height, const DDPIXELFORMAT& pf, void destroySmallerSurfaces(DWORD width, DWORD height, const DDPIXELFORMAT& pf,
std::vector<Surface>& cachedSurfaces); std::vector<Surface>& cachedSurfaces);
Surface getSurface(const DDSURFACEDESC2& desc); Surface getSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc);
void normalizePixelFormat(DDPIXELFORMAT& pf); void normalizePixelFormat(DDPIXELFORMAT& pf);
void returnSurface(const Surface& surface); void returnSurface(const Surface& surface);
@ -30,21 +39,22 @@ namespace
reinterpret_cast<void**>(&dd.getRef()), IID_IDirectDraw7, nullptr); reinterpret_cast<void**>(&dd.getRef()), IID_IDirectDraw7, nullptr);
if (FAILED(result)) if (FAILED(result))
{ {
Compat::Log() << "Failed to create a DirectDraw object in the repository: " << result; LOG_ONCE("Failed to create a DirectDraw object in the repository: " << result);
return nullptr; return nullptr;
} }
result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL); result = dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
if (FAILED(result)) if (FAILED(result))
{ {
Compat::Log() << "Failed to set the cooperative level in the repository: " << result; LOG_ONCE("Failed to set the cooperative level in the repository: " << result);
return nullptr; return nullptr;
} }
return dd; return dd;
} }
Surface createSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps) Surface createSurface(CompatRef<IDirectDraw7> dd,
DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps)
{ {
Surface surface = {}; Surface surface = {};
@ -55,8 +65,7 @@ namespace
surface.desc.ddpfPixelFormat = pf; surface.desc.ddpfPixelFormat = pf;
surface.desc.ddsCaps.dwCaps = caps; surface.desc.ddsCaps.dwCaps = caps;
auto dd(DDraw::Repository::getDirectDraw()); dd.get().lpVtbl->CreateSurface(&dd, &surface.desc, &surface.surface.getRef(), nullptr);
dd->CreateSurface(dd, &surface.desc, &surface.surface.getRef(), nullptr);
return surface; return surface;
} }
@ -103,27 +112,52 @@ namespace
return cachedSurfaces.end(); return cachedSurfaces.end();
} }
Surface getSurface(const DDSURFACEDESC2& desc) Repository& getRepository(CompatRef<IDirectDraw7> dd, DWORD caps)
{ {
std::vector<Surface>& cachedSurfaces = if (caps & DDSCAPS_SYSTEMMEMORY)
(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ? g_sysMemSurfaces : g_vidMemSurfaces; {
g_sysMemRepo.dd = DDraw::Repository::getDirectDraw();
return g_sysMemRepo;
}
void* ddObject = DDraw::getDdObject(dd.get());
auto it = g_vidMemRepos.find(ddObject);
if (it == g_vidMemRepos.end())
{
Repository repo = {};
repo.dd = createDirectDraw().detach();
return g_vidMemRepos[ddObject] = repo;
}
return it->second;
}
Surface getSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc)
{
Repository& repo = getRepository(dd, desc.ddsCaps.dwCaps);
if (!repo.dd)
{
return Surface();
}
DDPIXELFORMAT pf = desc.ddpfPixelFormat; DDPIXELFORMAT pf = desc.ddpfPixelFormat;
normalizePixelFormat(pf); normalizePixelFormat(pf);
auto it = findSurface(desc.dwWidth, desc.dwHeight, pf, cachedSurfaces); auto it = findSurface(desc.dwWidth, desc.dwHeight, pf, repo.surfaces);
if (it != cachedSurfaces.end()) if (it != repo.surfaces.end())
{ {
Surface cachedSurface = *it; Surface cachedSurface = *it;
cachedSurfaces.erase(it); repo.surfaces.erase(it);
return cachedSurface; return cachedSurface;
} }
Surface newSurface = createSurface(desc.dwWidth, desc.dwHeight, pf, const DWORD memFlag = (desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
DDSCAPS_OFFSCREENPLAIN | (desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)); ? DDSCAPS_SYSTEMMEMORY : DDSCAPS_VIDEOMEMORY;
Surface newSurface = createSurface(*repo.dd, desc.dwWidth, desc.dwHeight, pf,
DDSCAPS_OFFSCREENPLAIN | memFlag);
if (newSurface.surface) if (newSurface.surface)
{ {
destroySmallerSurfaces(desc.dwWidth, desc.dwHeight, pf, cachedSurfaces); newSurface.ddObject = DDraw::getDdObject(dd.get());
destroySmallerSurfaces(desc.dwWidth, desc.dwHeight, pf, repo.surfaces);
} }
return newSurface; return newSurface;
} }
@ -149,11 +183,11 @@ namespace
if (surface.desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) if (surface.desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{ {
g_sysMemSurfaces.push_back(surface); g_sysMemRepo.surfaces.push_back(surface);
} }
else else
{ {
g_vidMemSurfaces.push_back(surface); g_vidMemRepos[surface.ddObject].surfaces.push_back(surface);
} }
} }
} }
@ -162,8 +196,8 @@ namespace DDraw
{ {
namespace Repository namespace Repository
{ {
ScopedSurface::ScopedSurface(const DDSURFACEDESC2& desc) ScopedSurface::ScopedSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc)
: Surface(getSurface(desc)) : Surface(getSurface(dd, desc))
{ {
} }
@ -177,5 +211,18 @@ namespace DDraw
static auto dd = new CompatPtr<IDirectDraw7>(createDirectDraw()); static auto dd = new CompatPtr<IDirectDraw7>(createDirectDraw());
return *dd; return *dd;
} }
void onRelease(void* ddObject)
{
auto it = g_vidMemRepos.find(ddObject);
if (it != g_vidMemRepos.end())
{
for (auto& surface : it->second.surfaces)
{
surface.surface->Release(surface.surface);
}
g_vidMemRepos.erase(it);
}
}
} }
} }

View File

@ -4,6 +4,7 @@
#include <ddraw.h> #include <ddraw.h>
#include "Common/CompatRef.h"
#include "Common/CompatWeakPtr.h" #include "Common/CompatWeakPtr.h"
namespace DDraw namespace DDraw
@ -12,6 +13,7 @@ namespace DDraw
{ {
struct Surface struct Surface
{ {
void* ddObject;
DDSURFACEDESC2 desc; DDSURFACEDESC2 desc;
CompatWeakPtr<IDirectDrawSurface7> surface; CompatWeakPtr<IDirectDrawSurface7> surface;
}; };
@ -19,10 +21,11 @@ namespace DDraw
class ScopedSurface : public Surface class ScopedSurface : public Surface
{ {
public: public:
ScopedSurface(const DDSURFACEDESC2& desc); ScopedSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc);
~ScopedSurface(); ~ScopedSurface();
}; };
CompatWeakPtr<IDirectDraw7> getDirectDraw(); CompatWeakPtr<IDirectDraw7> getDirectDraw();
void onRelease(void* ddObject);
} }
} }

View File

@ -2,6 +2,7 @@
#include "Common/CompatPtr.h" #include "Common/CompatPtr.h"
#include "DDraw/DirectDraw.h" #include "DDraw/DirectDraw.h"
#include "DDraw/DirectDrawSurface.h"
#include "DDraw/DisplayMode.h" #include "DDraw/DisplayMode.h"
#include "DDraw/Surfaces/Surface.h" #include "DDraw/Surfaces/Surface.h"
#include "DDraw/Surfaces/SurfaceImpl.h" #include "DDraw/Surfaces/SurfaceImpl.h"
@ -79,9 +80,9 @@ namespace DDraw
} }
Surface::Surface() Surface::Surface()
: m_dds(nullptr) : m_ddObject(nullptr)
, m_dds(nullptr)
, m_ddId() , m_ddId()
, m_ddObject(nullptr)
, m_refCount(0) , m_refCount(0)
{ {
} }
@ -96,8 +97,7 @@ namespace DDraw
privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER))) privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER)))
{ {
CompatPtr<IUnknown> dd; CompatPtr<IUnknown> dd;
CompatVtable<IDirectDrawSurface7Vtbl>::s_origVtable.GetDDInterface( dds->GetDDInterface(&dds, reinterpret_cast<void**>(&dd.getRef()));
&dds, reinterpret_cast<void**>(&dd.getRef()));
privateData->createImpl(); privateData->createImpl();
privateData->m_impl->m_data = privateData.get(); privateData->m_impl->m_data = privateData.get();
@ -187,10 +187,7 @@ namespace DDraw
CompatPtr<IDirectDraw7> Surface::getDirectDraw() const CompatPtr<IDirectDraw7> Surface::getDirectDraw() const
{ {
auto dds(getDirectDrawSurface()); return DDraw::getDirectDraw(*getDirectDrawSurface());
CompatPtr<IUnknown> dd;
m_impl7->GetDDInterface(dds, reinterpret_cast<void**>(&dd.getRef()));
return CompatPtr<IDirectDraw7>(dd);
} }
CompatPtr<IDirectDrawSurface7> Surface::getDirectDrawSurface() const CompatPtr<IDirectDrawSurface7> Surface::getDirectDrawSurface() const

View File

@ -40,6 +40,7 @@ namespace DDraw
static void attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface>& privateData); static void attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface>& privateData);
void* m_ddObject;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface>> m_impl; std::unique_ptr<SurfaceImpl<IDirectDrawSurface>> m_impl;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface2>> m_impl2; std::unique_ptr<SurfaceImpl<IDirectDrawSurface2>> m_impl2;
std::unique_ptr<SurfaceImpl<IDirectDrawSurface3>> m_impl3; std::unique_ptr<SurfaceImpl<IDirectDrawSurface3>> m_impl3;
@ -56,7 +57,6 @@ namespace DDraw
IDirectDrawSurface* m_dds; IDirectDrawSurface* m_dds;
IID m_ddId; IID m_ddId;
void* m_ddObject;
DWORD m_refCount; DWORD m_refCount;
}; };
} }

View File

@ -1,6 +1,7 @@
#include <set> #include <set>
#include "Common/CompatPtr.h" #include "Common/CompatPtr.h"
#include "DDraw/DirectDrawSurface.h"
#include "DDraw/Repository.h" #include "DDraw/Repository.h"
#include "DDraw/Surfaces/Surface.h" #include "DDraw/Surfaces/Surface.h"
#include "DDraw/Surfaces/SurfaceImpl.h" #include "DDraw/Surfaces/SurfaceImpl.h"
@ -27,17 +28,8 @@ namespace
return; return;
} }
DDSURFACEDESC2 tempSurfaceDesc = desc;
tempSurfaceDesc.dwWidth = 1;
tempSurfaceDesc.dwHeight = 1;
DDraw::Repository::ScopedSurface tempSurface(desc);
if (!tempSurface.surface)
{
return;
}
RECT r = { 0, 0, 1, 1 }; RECT r = { 0, 0, 1, 1 };
surface->Blt(&surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr); surface->Blt(&surface, &r, &surface, &r, DDBLT_WAIT, nullptr);
} }
HRESULT WINAPI fixSurfacePtrEnumCallback( HRESULT WINAPI fixSurfacePtrEnumCallback(
@ -87,7 +79,8 @@ namespace
desc.dwHeight = srcRect->bottom - srcRect->top; desc.dwHeight = srcRect->bottom - srcRect->top;
} }
DDraw::Repository::ScopedSurface mirroredSurface(desc); auto dd(DDraw::getDirectDraw(surface));
DDraw::Repository::ScopedSurface mirroredSurface(*dd, desc);
if (!mirroredSurface.surface) if (!mirroredSurface.surface)
{ {
return nullptr; return nullptr;
@ -96,7 +89,7 @@ namespace
RECT rect = { 0, 0, static_cast<LONG>(desc.dwWidth), static_cast<LONG>(desc.dwHeight) }; RECT rect = { 0, 0, static_cast<LONG>(desc.dwWidth), static_cast<LONG>(desc.dwHeight) };
if ((mirrorFx & DDBLTFX_MIRRORLEFTRIGHT) && (mirrorFx & DDBLTFX_MIRRORUPDOWN)) if ((mirrorFx & DDBLTFX_MIRRORLEFTRIGHT) && (mirrorFx & DDBLTFX_MIRRORUPDOWN))
{ {
DDraw::Repository::Surface tempMirroredSurface = DDraw::Repository::ScopedSurface(desc); DDraw::Repository::Surface tempMirroredSurface = DDraw::Repository::ScopedSurface(*dd, desc);
if (!tempMirroredSurface.surface || if (!tempMirroredSurface.surface ||
!mirrorBlt(*tempMirroredSurface.surface, surface, srcRect ? *srcRect : rect, !mirrorBlt(*tempMirroredSurface.surface, surface, srcRect ? *srcRect : rect,
DDBLTFX_MIRRORLEFTRIGHT) || DDBLTFX_MIRRORLEFTRIGHT) ||

View File

@ -2,6 +2,7 @@
#include <map> #include <map>
#include "DDraw/DirectDraw.h" #include "DDraw/DirectDraw.h"
#include "DDraw/Repository.h"
#include "DDraw/Surfaces/SurfaceImpl.h" #include "DDraw/Surfaces/SurfaceImpl.h"
#include "DDraw/Surfaces/TagSurface.h" #include "DDraw/Surfaces/TagSurface.h"
@ -16,7 +17,8 @@ namespace DDraw
{ {
std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(), std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
[=](auto& i) { return i.second == this; })->second; [=](auto& i) { return i.second == this; })->second;
DDraw::onRelease(*this); onRelease(*this);
Repository::onRelease(m_ddObject);
g_tagSurfaces.erase(std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(), g_tagSurfaces.erase(std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
[=](auto& i) { return i.second == this; })); [=](auto& i) { return i.second == this; }));
} }