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:
parent
7220b80999
commit
e8f987eb05
@ -26,6 +26,13 @@ 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)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "Common/CompatRef.h"
|
||||
#include "Common/CompatVtable.h"
|
||||
#include "DDraw/Visitors/DirectDrawSurfaceVtblVisitor.h"
|
||||
@ -7,6 +8,8 @@
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
CompatPtr<IDirectDraw7> getDirectDraw(CompatRef<IDirectDrawSurface7> surface);
|
||||
|
||||
template <typename TSurface>
|
||||
class DirectDrawSurface : public CompatVtable<Vtable<TSurface>>
|
||||
{
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "Common/Log.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "Dll/Procs.h"
|
||||
|
||||
@ -10,16 +12,23 @@ namespace
|
||||
{
|
||||
using DDraw::Repository::Surface;
|
||||
|
||||
static std::vector<Surface> g_sysMemSurfaces;
|
||||
static std::vector<Surface> g_vidMemSurfaces;
|
||||
struct Repository
|
||||
{
|
||||
CompatWeakPtr<IDirectDraw7> dd;
|
||||
std::vector<Surface> surfaces;
|
||||
};
|
||||
|
||||
Repository g_sysMemRepo;
|
||||
std::map<void*, Repository> g_vidMemRepos;
|
||||
|
||||
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>& cachedSurfaces);
|
||||
void destroySmallerSurfaces(DWORD width, DWORD height, const DDPIXELFORMAT& pf,
|
||||
std::vector<Surface>& cachedSurfaces);
|
||||
Surface getSurface(const DDSURFACEDESC2& desc);
|
||||
Surface getSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc);
|
||||
void normalizePixelFormat(DDPIXELFORMAT& pf);
|
||||
void returnSurface(const Surface& surface);
|
||||
|
||||
@ -30,21 +39,22 @@ namespace
|
||||
reinterpret_cast<void**>(&dd.getRef()), IID_IDirectDraw7, nullptr);
|
||||
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;
|
||||
}
|
||||
|
||||
result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
|
||||
result = dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
|
||||
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 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 = {};
|
||||
|
||||
@ -55,8 +65,7 @@ namespace
|
||||
surface.desc.ddpfPixelFormat = pf;
|
||||
surface.desc.ddsCaps.dwCaps = caps;
|
||||
|
||||
auto dd(DDraw::Repository::getDirectDraw());
|
||||
dd->CreateSurface(dd, &surface.desc, &surface.surface.getRef(), nullptr);
|
||||
dd.get().lpVtbl->CreateSurface(&dd, &surface.desc, &surface.surface.getRef(), nullptr);
|
||||
return surface;
|
||||
}
|
||||
|
||||
@ -103,27 +112,52 @@ namespace
|
||||
return cachedSurfaces.end();
|
||||
}
|
||||
|
||||
Surface getSurface(const DDSURFACEDESC2& desc)
|
||||
Repository& getRepository(CompatRef<IDirectDraw7> dd, DWORD caps)
|
||||
{
|
||||
std::vector<Surface>& cachedSurfaces =
|
||||
(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ? g_sysMemSurfaces : g_vidMemSurfaces;
|
||||
if (caps & DDSCAPS_SYSTEMMEMORY)
|
||||
{
|
||||
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;
|
||||
normalizePixelFormat(pf);
|
||||
|
||||
auto it = findSurface(desc.dwWidth, desc.dwHeight, pf, cachedSurfaces);
|
||||
if (it != cachedSurfaces.end())
|
||||
auto it = findSurface(desc.dwWidth, desc.dwHeight, pf, repo.surfaces);
|
||||
if (it != repo.surfaces.end())
|
||||
{
|
||||
Surface cachedSurface = *it;
|
||||
cachedSurfaces.erase(it);
|
||||
repo.surfaces.erase(it);
|
||||
return cachedSurface;
|
||||
}
|
||||
|
||||
Surface newSurface = createSurface(desc.dwWidth, desc.dwHeight, pf,
|
||||
DDSCAPS_OFFSCREENPLAIN | (desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY));
|
||||
const DWORD memFlag = (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)
|
||||
{
|
||||
destroySmallerSurfaces(desc.dwWidth, desc.dwHeight, pf, cachedSurfaces);
|
||||
newSurface.ddObject = DDraw::getDdObject(dd.get());
|
||||
destroySmallerSurfaces(desc.dwWidth, desc.dwHeight, pf, repo.surfaces);
|
||||
}
|
||||
return newSurface;
|
||||
}
|
||||
@ -149,11 +183,11 @@ namespace
|
||||
|
||||
if (surface.desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
|
||||
{
|
||||
g_sysMemSurfaces.push_back(surface);
|
||||
g_sysMemRepo.surfaces.push_back(surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_vidMemSurfaces.push_back(surface);
|
||||
g_vidMemRepos[surface.ddObject].surfaces.push_back(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -162,8 +196,8 @@ namespace DDraw
|
||||
{
|
||||
namespace Repository
|
||||
{
|
||||
ScopedSurface::ScopedSurface(const DDSURFACEDESC2& desc)
|
||||
: Surface(getSurface(desc))
|
||||
ScopedSurface::ScopedSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc)
|
||||
: Surface(getSurface(dd, desc))
|
||||
{
|
||||
}
|
||||
|
||||
@ -177,5 +211,18 @@ namespace DDraw
|
||||
static auto dd = new CompatPtr<IDirectDraw7>(createDirectDraw());
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "Common/CompatRef.h"
|
||||
#include "Common/CompatWeakPtr.h"
|
||||
|
||||
namespace DDraw
|
||||
@ -12,6 +13,7 @@ namespace DDraw
|
||||
{
|
||||
struct Surface
|
||||
{
|
||||
void* ddObject;
|
||||
DDSURFACEDESC2 desc;
|
||||
CompatWeakPtr<IDirectDrawSurface7> surface;
|
||||
};
|
||||
@ -19,10 +21,11 @@ namespace DDraw
|
||||
class ScopedSurface : public Surface
|
||||
{
|
||||
public:
|
||||
ScopedSurface(const DDSURFACEDESC2& desc);
|
||||
ScopedSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc);
|
||||
~ScopedSurface();
|
||||
};
|
||||
|
||||
CompatWeakPtr<IDirectDraw7> getDirectDraw();
|
||||
void onRelease(void* ddObject);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
@ -79,9 +80,9 @@ namespace DDraw
|
||||
}
|
||||
|
||||
Surface::Surface()
|
||||
: m_dds(nullptr)
|
||||
: m_ddObject(nullptr)
|
||||
, m_dds(nullptr)
|
||||
, m_ddId()
|
||||
, m_ddObject(nullptr)
|
||||
, m_refCount(0)
|
||||
{
|
||||
}
|
||||
@ -96,8 +97,7 @@ namespace DDraw
|
||||
privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER)))
|
||||
{
|
||||
CompatPtr<IUnknown> dd;
|
||||
CompatVtable<IDirectDrawSurface7Vtbl>::s_origVtable.GetDDInterface(
|
||||
&dds, reinterpret_cast<void**>(&dd.getRef()));
|
||||
dds->GetDDInterface(&dds, reinterpret_cast<void**>(&dd.getRef()));
|
||||
|
||||
privateData->createImpl();
|
||||
privateData->m_impl->m_data = privateData.get();
|
||||
@ -187,10 +187,7 @@ namespace DDraw
|
||||
|
||||
CompatPtr<IDirectDraw7> Surface::getDirectDraw() const
|
||||
{
|
||||
auto dds(getDirectDrawSurface());
|
||||
CompatPtr<IUnknown> dd;
|
||||
m_impl7->GetDDInterface(dds, reinterpret_cast<void**>(&dd.getRef()));
|
||||
return CompatPtr<IDirectDraw7>(dd);
|
||||
return DDraw::getDirectDraw(*getDirectDrawSurface());
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> Surface::getDirectDrawSurface() const
|
||||
|
@ -40,6 +40,7 @@ namespace DDraw
|
||||
|
||||
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<IDirectDrawSurface2>> m_impl2;
|
||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface3>> m_impl3;
|
||||
@ -56,7 +57,6 @@ namespace DDraw
|
||||
|
||||
IDirectDrawSurface* m_dds;
|
||||
IID m_ddId;
|
||||
void* m_ddObject;
|
||||
DWORD m_refCount;
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
@ -27,17 +28,8 @@ namespace
|
||||
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 };
|
||||
surface->Blt(&surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr);
|
||||
surface->Blt(&surface, &r, &surface, &r, DDBLT_WAIT, nullptr);
|
||||
}
|
||||
|
||||
HRESULT WINAPI fixSurfacePtrEnumCallback(
|
||||
@ -87,7 +79,8 @@ namespace
|
||||
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)
|
||||
{
|
||||
return nullptr;
|
||||
@ -96,7 +89,7 @@ namespace
|
||||
RECT rect = { 0, 0, static_cast<LONG>(desc.dwWidth), static_cast<LONG>(desc.dwHeight) };
|
||||
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 ||
|
||||
!mirrorBlt(*tempMirroredSurface.surface, surface, srcRect ? *srcRect : rect,
|
||||
DDBLTFX_MIRRORLEFTRIGHT) ||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <map>
|
||||
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
#include "DDraw/Surfaces/TagSurface.h"
|
||||
|
||||
@ -16,7 +17,8 @@ namespace DDraw
|
||||
{
|
||||
std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
|
||||
[=](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(),
|
||||
[=](auto& i) { return i.second == this; }));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user